FS2_Open
Open source remastering of the Freespace 2 engine
multiui.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #ifdef _WIN32
14 #include <winsock.h> // for inet_addr()
15 #else
16 #include <arpa/inet.h>
17 #include <netinet/in.h>
18 #endif
19 
20 #include "network/multiui.h"
21 #include "freespace2/freespace.h"
22 #include "network/multi.h"
23 #include "network/multiutil.h"
24 #include "network/multimsgs.h"
25 #include "io/key.h"
26 #include "io/timer.h"
28 #include "gamehelp/contexthelp.h"
29 #include "playerman/player.h"
30 #include "network/multi_xfer.h"
31 #include "cmdline/cmdline.h"
32 #include "network/stand_gui.h"
35 #include "graphics/font.h"
36 #include "io/mouse.h"
37 #include "gamesnd/gamesnd.h"
38 #include "missionui/chatbox.h"
39 #include "popup/popup.h"
41 #include "network/multi_ingame.h"
42 #include "network/multi_kick.h"
43 #include "network/multi_data.h"
44 #include "network/multi_campaign.h"
45 #include "network/multi_team.h"
46 #include "network/multi_pinfo.h"
47 #include "network/multi_observer.h"
48 #include "network/multi_voice.h"
49 #include "network/multi_endgame.h"
50 #include "playerman/managepilot.h"
51 #include "pilotfile/pilotfile.h"
52 #include "stats/stats.h"
53 #include "network/multi_pmsg.h"
54 #include "network/multi_obj.h"
55 #include "network/multi_log.h"
56 #include "globalincs/alphacolors.h"
57 #include "anim/animplay.h"
58 #include "network/multi_dogfight.h"
59 #include "missionui/missionpause.h"
60 #include "ship/ship.h"
61 #include "osapi/osregistry.h"
63 #include "parse/parselo.h"
64 #include "cfile/cfile.h"
65 #include "fs2netd/fs2netd_client.h"
66 #include "menuui/mainhallmenu.h"
67 #include "debugconsole/console.h"
68 
69 #include <algorithm>
70 
71 
72 // -------------------------------------------------------------------------------------------------------------
73 //
74 // MULTIPLAYER COMMON interface controls
75 //
76 
77 // the common text info box stuff. This is lifted almost directly from Alans briefing code (minus the spiffy colored, scrolling
78 // text crap :)
80  { // GR_640
81  29, 396, 393, 76
82  },
83  { // GR_1024
84  47, 634, 630, 122
85  }
86 };
87 
89  8, // GR_640
90  12, // GR_1024
91 };
92 
93 #define MULTI_COMMON_TEXT_META_CHAR '$'
94 #define MULTI_COMMON_TEXT_MAX_LINE_LENGTH 200
95 #define MULTI_COMMON_TEXT_MAX_LINES 20
96 #define MULTI_COMMON_MAX_TEXT (MULTI_COMMON_TEXT_MAX_LINES * MULTI_COMMON_TEXT_MAX_LINE_LENGTH)
97 
100 
101 int Multi_common_top_text_line = -1; // where to start displaying from
102 int Multi_common_num_text_lines = 0; // how many lines we have
103 
109 
110 #define MAX_IP_STRING 255 // maximum length for ip string
111 
113 {
115  if ( Multi_common_top_text_line < 0 ) {
119 
120  } else {
122  }
123 }
124 
126 {
130  if ( !mouse_down(MOUSE_LEFT_BUTTON) ){
132  }
133  } else {
135  }
136 }
137 
139 {
140  // if there's nowhere to scroll down, do nothing
142  return;
143  }
144 
146 }
147 
148 void multi_common_set_text(const char *str,int auto_scroll)
149 {
150  // make sure it fits
151  // store the entire string as well
152  if(strlen(str) >= MULTI_COMMON_MAX_TEXT){
153  return ;
154  } else {
156  }
157 
158  // split the whole thing up
160 
161  // scroll to the bottom if we're supposed to
162  if(auto_scroll){
164  }
165 }
166 
167 void multi_common_add_text(const char *str,int auto_scroll)
168 {
169  // make sure it fits
170  // store the entire string as well
171  if((strlen(str) + strlen(Multi_common_all_text)) >= MULTI_COMMON_MAX_TEXT){
172  return ;
173  } else {
175  }
176 
177  // split the whole thing up
179 
180  // scroll to the bottom if we're supposed to
181  if(auto_scroll){
183  }
184 }
185 
187 {
188  int n_lines, i;
189  int n_chars[MAX_BRIEF_LINES];
190  const char *p_str[MAX_BRIEF_LINES];
191 
193  Assert(n_lines != -1);
194 
195  for ( i = 0; i < n_lines; i++ ) {
196  //The E -- This check is unnecessary, and will break when fonts that aren't bank gothic are used
197  //split_str already ensured that everything will fit in the text window for us already.
198  //Assert(n_chars[i] < MULTI_COMMON_TEXT_MAX_LINE_LENGTH);
199  strncpy(Multi_common_text[i], p_str[i], n_chars[i]);
200  Multi_common_text[i][n_chars[i]] = 0;
202  }
203 
205  Multi_common_num_text_lines = n_lines;
206 }
207 
209 {
210  int i, fh, line_count;
211 
212  fh = gr_get_font_height();
213 
214  line_count = 0;
217  if ( line_count >= Multi_common_text_max_display[gr_screen.res] ){
218  break;
219  }
221  line_count++;
222  }
223 
224  if ( (Multi_common_num_text_lines - Multi_common_top_text_line) > Multi_common_text_max_display[gr_screen.res] ) {
227  }
228 }
229 
230 // common notification messaging stuff
231 #define MULTI_COMMON_NOTIFY_TIME 3500
233  375, // GR_640
234  605 // GR_1024
235 };
237  380, // GR_640
238  610 // GR_1024
239 };
240 
242  380, // GR_640
243  610 // GR_1024
244 };
245 
247  380, // GR_640
248  610 // GR_1024
249 };
250 
253 
255 {
258 }
259 
260 // add a notification string, drawing appropriately depending on the state/screen we're in
261 void multi_common_add_notify(const char *str)
262 {
263  if(str){
266  }
267 }
268 
269 // process/display notification messages
271 {
272  if(Multi_common_notify_stamp != -1){
275  } else {
276  int w,h,y;
279 
280  // determine where it should be placed based upon which screen we're on
281  y = -1;
282  switch(gameseq_get_state()){
285  break;
288  break;
291  break;
294  break;
295  }
296  if(y != -1){
298  }
299  }
300  }
301 }
302 
303 // common icon stuff
305 //XSTR:OFF
307  "DotRed", // voice denied
308  "DotGreen", // voice recording
309  "OvalGreen", // team 0
310  "OvalGreen01", // team 0 select
311  "OvalRed", // team 1
312  "OvalRed01", // team 1 select
313  "mp_coop", // coop mission
314  "mp_teams", // TvT mission
315  "mp_furball", // furball mission
316  "icon-volition", // volition mission
317  "icon-valid", // mission is valid
318  "cd" // cd icon
319 };
320 //XSTR:ON
321 // width and height of the icons
323  {11, 11}, // voice denied
324  {11, 11}, // voice recording
325  {11, 11}, // team 0
326  {11, 11}, // team 0 select
327  {11, 11}, // team 1
328  {11, 11}, // team 1 select
329  {18, 11}, // mp coop
330  {18, 11}, // mp TvT
331  {18, 11}, // mp furball
332  {9, 9}, // volition mission
333  {8, 8}, // mission is valid
334  {8, 8} // cd icon
335 };
336 
338 {
339  int idx;
340 
341  if (Is_standalone)
342  return;
343 
344  // load all icons
345  for(idx=0; idx<MULTI_NUM_COMMON_ICONS; idx++){
346  Multi_common_icons[idx] = -1;
348  }
349 }
350 
352 {
353  int idx;
354 
355  if (Is_standalone)
356  return;
357 
358  // unload all icons
359  for(idx=0; idx<MULTI_NUM_COMMON_ICONS; idx++){
360  if(Multi_common_icons[idx] != -1){
361  // don't bm_release() here, used in multiple places - taylor
363  Multi_common_icons[idx] = -1;
364  }
365  }
366 }
367 
368 // display any relevant voice status icons
370 {
371  switch(multi_voice_status()){
372  // i have been denied the voice token
377  }
378  break;
379 
380  // i am currently recording
385  }
386  break;
387 
388  // i am currently playing back sound
390  break;
391 
392  // the system is currently idle
394  break;
395  }
396 }
397 
398 //XSTR:OFF
399 // palette initialization stuff
400 #define MULTI_COMMON_PALETTE_FNAME "InterfacePalette"
401 //XSTR:ON
402 
404 
408 
409 // load in the palette if it doesn't already exist
411 {
413  return;
414  }
415 
418  nprintf(("Network","Error loading multiplayer common palette!\n"));
419  }
420 }
421 
422 // set the common palette to be the active one
424 {
425  // if the palette is not loaded yet, do so now
428  }
429 
431 #ifndef HARDWARE_ONLY
433 #endif
434  }
435 }
436 
437 // unload the bitmap palette
439 {
443  }
444 }
445 
447 {
448 #ifdef GAME_CD_CHECK
449  // otherwise, call the freespace function to determine if we have a cd
450  Multi_has_cd = 0;
452  Multi_has_cd = 1;
453  }
454 #else
455  Multi_has_cd = 1;
456 #endif
457 }
458 
459 
460 // -------------------------------------------------------------------------------------------------------------
461 //
462 // MULTIPLAYER JOIN SCREEN
463 //
464 
465 #define MULTI_JOIN_NUM_BUTTONS 11
466 
467 //XSTR:OFF
468 // bitmaps defs
469 #define MULTI_JOIN_PALETTE "InterfacePalette"
470 
471 static char *Multi_join_bitmap_fname[GR_NUM_RESOLUTIONS] = {
472  "MultiJoin", // GR_640
473  "2_MultiJoin" // GR_1024
474 };
475 
476 static char *Multi_join_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
477  "MultiJoin-M", // GR_640
478  "2_MultiJoin-M" // GR_1024
479 };
480 //XSTR:ON
481 
482 // slider
484  "slider",
485  "2_slider"
486 };
488  { // GR_640
489  2, 91, 15, 202
490  },
491  { // GR_1024
492  8, 147, 30, 322
493  }
494 };
495 
496 // button defs
497 #define MJ_SCROLL_UP 0
498 #define MJ_SCROLL_DOWN 1
499 #define MJ_REFRESH 2
500 #define MJ_SCROLL_INFO_UP 3
501 #define MJ_SCROLL_INFO_DOWN 4
502 #define MJ_JOIN_OBSERVER 5
503 #define MJ_START_GAME 6
504 #define MJ_CANCEL 7
505 #define MJ_HELP 8
506 #define MJ_OPTIONS 9
507 #define MJ_ACCEPT 10
508 
509 // uses MULTI_JOIN_REFRESH_TIME as its timestamp
511 
512 #define MULTI_JOIN_PING_TIME 15000 // how often we ping all the known servers
514 UI_WINDOW Multi_join_window; // the window object for the join screen
515 UI_BUTTON Multi_join_select_button; // for selecting list items
516 UI_SLIDER2 Multi_join_slider; // handy dandy slider
517 int Multi_join_bitmap; // the background bitmap
518 
520  { // GR_640
521  ui_button_info( "MJ_00", 1, 57, -1, -1, 0 ), // scroll up
522  ui_button_info( "MJ_02", 1, 297, -1, -1, 2 ), // scroll down
523  ui_button_info( "MJ_03", 10, 338, 65, 364, 3 ), // refresh
524  ui_button_info( "MJ_04", 1, 405, -1, -1, 4 ), // scroll info up
525  ui_button_info( "MJ_05", 1, 446, -1, -1, 5 ), // scroll info down
526  ui_button_info( "MJ_06", 489, 339, -1, -1, 6 ), // join as observer
527  ui_button_info( "MJ_07", 538, 339, -1, -1, 7 ), // create game
528  ui_button_info( "MJ_08", 583, 339, 588, 376, 8 ), // cancel
529  ui_button_info( "MJ_09", 534, 426, -1, -1, 9 ), // help
530  ui_button_info( "MJ_10", 534, 454, -1, -1, 10 ), // options
531  ui_button_info( "MJ_11", 571, 426, 589, 416, 11 ), // join
532  },
533  { // GR_1024
534  ui_button_info( "2_MJ_00", 2, 92, -1, -1, 0 ), // scroll up
535  ui_button_info( "2_MJ_02", 2, 475, -1, -1, 2 ), // scroll down
536  ui_button_info( "2_MJ_03", 16, 541, 104, 582, 3 ), // refresh
537  ui_button_info( "2_MJ_04", 2, 648, -1, -1, 4 ), // scroll info up
538  ui_button_info( "2_MJ_05", 2, 713, -1, -1, 5 ), // scroll info down
539  ui_button_info( "2_MJ_06", 783, 542, -1, -1, 6 ), // join as observer
540  ui_button_info( "2_MJ_07", 861, 542, -1, -1, 7 ), // create game
541  ui_button_info( "2_MJ_08", 933, 542, 588, 376, 8 ), // cancel
542  ui_button_info( "2_MJ_09", 854, 681, -1, -1, 9 ), // help
543  ui_button_info( "2_MJ_10", 854, 727, -1, -1, 10 ), // options
544  ui_button_info( "2_MJ_11", 914, 681, 937, 668, 11 ), // join
545  }
546 };
547 
548 #define MULTI_JOIN_NUM_TEXT 13
549 
551  { // GR_640
552  {"Refresh", 1299, 65, 364, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_REFRESH].button},
553  {"Join as", 1300, 476, 376, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_JOIN_OBSERVER].button},
554  {"Observer", 1301, 467, 385, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_JOIN_OBSERVER].button},
555  {"Create", 1408, 535, 376, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_START_GAME].button},
556  {"Game", 1302, 541, 385, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_START_GAME].button},
557  {"Cancel", 387, 588, 376, UI_XSTR_COLOR_PINK, -1, &Multi_join_buttons[0][MJ_CANCEL].button},
558  {"Help", 928, 496, 436, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_HELP].button},
559  {"Options", 1036, 479, 460, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[0][MJ_OPTIONS].button},
560  {"Join", 1303, 589, 416, UI_XSTR_COLOR_PINK, -1, &Multi_join_buttons[0][MJ_ACCEPT].button},
561  {"Status", 1304, 37, 37, UI_XSTR_COLOR_GREEN, -1, NULL},
562  {"Server", 1305, 116, 37, UI_XSTR_COLOR_GREEN, -1, NULL},
563  {"Players", 1306, 471, 37, UI_XSTR_COLOR_GREEN, -1, NULL},
564  {"Ping", 1307, 555, 37, UI_XSTR_COLOR_GREEN, -1, NULL}
565  },
566  { // GR_1024
567  {"Refresh", 1299, 104, 582, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_REFRESH].button},
568  {"Join as", 1300, 783, 602, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_JOIN_OBSERVER].button},
569  {"Observer", 1301, 774, 611, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_JOIN_OBSERVER].button},
570  {"Create", 1408, 868, 602, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_START_GAME].button},
571  {"Game", 1302, 872, 611, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_START_GAME].button},
572  {"Cancel", 387, 941, 602, UI_XSTR_COLOR_PINK, -1, &Multi_join_buttons[1][MJ_CANCEL].button},
573  {"Help", 928, 806, 699, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_HELP].button},
574  {"Options", 1036, 782, 736, UI_XSTR_COLOR_GREEN, -1, &Multi_join_buttons[1][MJ_OPTIONS].button},
575  {"Join", 1303, 937, 668, UI_XSTR_COLOR_PINK, -1, &Multi_join_buttons[1][MJ_ACCEPT].button},
576  {"Status", 1304, 60, 60, UI_XSTR_COLOR_GREEN, -1, NULL},
577  {"Server", 1305, 186, 60, UI_XSTR_COLOR_GREEN, -1, NULL},
578  {"Players", 1306, 753, 60, UI_XSTR_COLOR_GREEN, -1, NULL},
579  {"Ping", 1307, 888, 60, UI_XSTR_COLOR_GREEN, -1, NULL}
580  }
581 };
582 
583 // constants for coordinate look ups
584 #define MJ_X_COORD 0
585 #define MJ_Y_COORD 1
586 #define MJ_W_COORD 2
587 #define MJ_H_COORD 3
588 
589 #define MULTI_JOIN_SENT_WAIT 10000 // wait this long since a join was sent to allow another
591 
592 // game information text areas
594  28, // GR_640
595  46 // GR_1024
596 };
597 
599  53, // GR_640
600  77 // GR_1024
601 };
602 
604  { // GR_640
605  34, 53, 55, 287
606  },
607  { // GR_1024
608  53, 77, 57, 459
609  }
610 };
611 
613  { // GR_640
614  98, 53, 28
615  },
616  { // GR_1024
617  124, 77, 28
618  }
619 };
620 
622  { // GR_640
623  122, 53, 56, 261
624  },
625  { // GR_1024
626  152, 77, 56, 261
627  }
628 };
629 
631  { // GR_640
632  186, 53, 280, 261
633  },
634  { // GR_1024
635  206, 77, 311, 261
636  }
637 };
638 
640  { // GR_640
641  473, 53, 50, 261
642  },
643  { // GR_1024
644  748, 77, 67, 459
645  }
646 };
647 
649  { // GR_640
650  551, 53, 47, 261
651  },
652  { // GR_1024
653  880, 77, 48, 459
654  }
655 };
656 
657 // game speed labels
658 #define MJ_NUM_SPEED_LABELS 5
660  "< 56k",
661  "56k",
662  "isdn",
663  "cable",
664  "t1/adsl+"
665 };
671  &Color_bright_green
672 };
673 
675  20, 30
676 };
677 
678 //XSTR:OFF
679 #define IP_CONFIG_FNAME "tcp.cfg" // name of the file which contains known TCP addresses
680 
681 // extents of the entire boundable game info region
682 // NOTE : these numbers are completely empirical
683 #define MJ_PING_GREEN 160
684 #define MJ_PING_YELLOW 300
685 #define MJ_PING_RED 700
686 #define MJ_PING_ONE_SECOND 1000
687 
689  { // GR_640
690  23, 53, 565, 279
691  },
692  { // GR_1024
693  53, 76, 887, 461
694  }
695 };
696 
697 // PXO channel filter
698 #define MJ_PXO_FILTER_Y 0
699 
700 // special chars to indicate various status modes for servers
701 #define MJ_CHAR_STANDALONE "*"
702 #define MJ_CHAR_CAMPAIGN "c"
703 //XSTR:ON
704 
705 // various interface indices
706 int Multi_join_list_start; // where to start displaying from
707 active_game *Multi_join_list_start_item; // a pointer to the corresponding active_game
708 int Multi_join_list_selected; // which item we have selected
709 active_game *Multi_join_selected_item; // a pointer to the corresponding active_game
710 
711 // use this macro to modify the list start
712 #define MJ_LIST_START_INC() do { Multi_join_list_start++; } while(0);
713 #define MJ_LIST_START_DEC() do { Multi_join_list_start--; } while(0);
714 #define MJ_LIST_START_SET(vl) do { Multi_join_list_start = vl; } while(0);
715 
716 // if we should be sending a join request at the end of the frame
718 
719 // master tracker details
720 int Multi_join_frame_count; // keep a count of frames displayed
721 int Multi_join_mt_tried_verify; // already tried verifying the pilot with the tracker
722 
723 // data stuff for auto joining a game
724 #define MULTI_AUTOJOIN_JOIN_STAMP 2000
725 #define MULTI_AUTOJOIN_QUERY_STAMP 2000
726 
731 
732 // our join request
734 
736 
737 // LOCAL function definitions
739 void multi_join_button_pressed(int n);
741 void multi_join_blit_game_status(active_game *game, int y);
744 void multi_join_ping_all();
752 void multi_join_handle_item_cull(active_game *item, int item_index);
753 void multi_join_send_join_request(int as_observer);
757 int multi_join_warn_pxo();
759 
760 DCF(mj_make, "Makes a multijoin game? (Multiplayer)")
761 {
762  active_game ag, *newitem;
763  int idx;
764  int idx_max;
765 
766  if (dc_optional_string_either("help", "--help")) {
767  dc_printf("Usage: mj_make <num_games>\n");
768  return;
769  }
770 
771  dc_stuff_int(&idx_max);
772 
773  for(idx = 0; idx < idx_max; idx++){
774  // stuff some fake info
775  memset(&ag, 0, sizeof(active_game));
776  sprintf(ag.name, "Game %d", idx);
779  ag.server_addr.addr[0] = (char)idx;
781 
782  // add the game
783  newitem = multi_update_active_games(&ag);
784 
785  // timestamp it so we get random timeouts
786  if(newitem != NULL){
787  // newitem->heard_from_timer = timestamp((int)frand_range(500.0f, 10000.0f));
788  }
789  }
790 }
791 
793 {
794  // reset the # of items
796  Multi_join_slider.force_currentItem(Multi_join_list_start);
797 }
798 
800 {
801  // if we have an active game on the list, then return a positive value so that we
802  // can join the game
803  if ( Active_game_head && (Active_game_count > 0) ) {
804  Multi_join_selected_item = Active_game_head;
805  return 1;
806  }
807 
808  // send out a server_query again
810  send_server_query(&Multi_autojoin_addr);
812  }
813 
814  return -1;
815 }
816 
818 {
819  int idx;
820 
821  // do the multiplayer init stuff - multi_level_init() now does all net_player zeroing.
822  // setup various multiplayer things
824  Assert( Net_player != NULL );
825 
826  switch (Multi_options_g.protocol) {
827  case NET_TCP:
830  break;
831 
832  default :
833  Int3();
834  } // end switch
835 
836  HEADER_LENGTH = 1;
837 
838  memset( &Netgame, 0, sizeof(Netgame) );
839 
840  multi_level_init();
843  memcpy(&Net_player->p_info.addr,&Psnet_my_addr,sizeof(net_addr));
844 
845  // check for the existence of a CD
847 
848  // load my local netplayer options
850 
851  game_flush();
852 
853  // destroy any chatbox contents which previously existed (from another game)
854  chatbox_clear();
855 
856  // create the interface window
857  Multi_join_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
858  Multi_join_window.set_mask_bmap(Multi_join_bitmap_mask_fname[gr_screen.res]);
859 
860  // load the background bitmap
861  Multi_join_bitmap = bm_load(Multi_join_bitmap_fname[gr_screen.res]);
862  if(Multi_join_bitmap < 0){
863  // we failed to load the bitmap - this is very bad
864  Int3();
865  }
866 
867  // intialize the endgame system
869 
870  // initialize the common notification messaging
872 
873  // initialize the common text area
875 
876  // load and use the common interface palette
879 
880  // load the help overlay
883 
884  // try to login to the tracker
885  if (MULTI_IS_TRACKER_GAME) {
886  if ( !fs2netd_login() ) {
887  // failed! go back to the main hall
889  return;
890  }
891  }
892 
893  // do TCP and VMT specific initialization
895  // if this is a TCP (non tracker) game, we'll load up our default address list right now
897  }
898 
899  // initialize any and all timestamps
903 
904  // reset frame count
906 
907  // haven't tried to verify on the tracker yet.
909 
910  // clear our all game lists to save hassles
912 
913  // create the interface buttons
914  for(idx=0; idx<MULTI_JOIN_NUM_BUTTONS; idx++){
915  // create the object
916  Multi_join_buttons[gr_screen.res][idx].button.create(&Multi_join_window,"", Multi_join_buttons[gr_screen.res][idx].x, Multi_join_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
917 
918  // set the sound to play when highlighted
920 
921  // set the ani for the button
922  Multi_join_buttons[gr_screen.res][idx].button.set_bmaps(Multi_join_buttons[gr_screen.res][idx].filename);
923 
924  // set the hotspot
925  Multi_join_buttons[gr_screen.res][idx].button.link_hotspot(Multi_join_buttons[gr_screen.res][idx].hotspot);
926  }
927 
928  // create all xstrs
929  for(idx=0; idx<MULTI_JOIN_NUM_TEXT; idx++){
930  Multi_join_window.add_XSTR(&Multi_join_text[gr_screen.res][idx]);
931  }
932 
934 
935  // close any previously open chatbox
936  chatbox_close();
937 
938  // create the list item select button
940  Multi_join_select_button.hide();
941 
942  // slider
943  Multi_join_slider.create(&Multi_join_window, Mj_slider_coords[gr_screen.res][MJ_X_COORD], Mj_slider_coords[gr_screen.res][MJ_Y_COORD], Mj_slider_coords[gr_screen.res][MJ_W_COORD], Mj_slider_coords[gr_screen.res][MJ_H_COORD], 0, Mj_slider_name[gr_screen.res], &multi_join_list_scroll_up, &multi_join_list_scroll_down, NULL);
944 
945  // make sure that we turn music/sounds back on (will be disabled after playing a mission)
947 
948  // if starting a network game, then go to the create game screen
949  if ( Cmdline_start_netgame ) {
951  } else if ( Cmdline_connect_addr != NULL ) {
952  char *p;
953  short port_num;
954  int ip_addr;
955 
956  // joining a game. Send a join request to the given IP address, and wait for the return.
957  memset( &Multi_autojoin_addr, 0, sizeof(net_addr) );
958  Multi_autojoin_addr.type = NET_TCP;
959 
960  // create the address, looking out for port number at the end
961  port_num = DEFAULT_GAME_PORT;
962  p = strrchr(Cmdline_connect_addr, ':');
963  if ( p ) {
964  *p = '\0';
965  p++;
966  port_num = (short)atoi(p);
967  }
968  ip_addr = inet_addr(Cmdline_connect_addr);
969  memcpy(Multi_autojoin_addr.addr, &ip_addr, 4);
970  Multi_autojoin_addr.port = port_num;
971 
972  send_server_query(&Multi_autojoin_addr);
974  Multi_did_autojoin = 0;
975  }
976 }
977 
979 {
980  // misc data
982  Multi_join_selected_item = NULL;
983  MJ_LIST_START_SET(-1);
984  Multi_join_list_start_item = NULL;
985 
986  // free up the active game list
988 
989  // initialize the active game list
990  Active_game_head = NULL;
991  Active_game_count = 0;
992 }
993 
995 {
996  // check the status of our reliable socket. If not valid, popup error and return to main menu
997  // I put this code here to avoid nasty gameseq issues with states. Also, we will have nice
998  // background for the popup
999  if ( !psnet_rel_check() ) {
1000  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("Network Error. Try exiting and restarting FreeSpace to clear the error. Otherwise, please reboot your machine.",756));
1002  return;
1003  }
1004 
1005  // return here since we will be moving to the next stage anyway -- I don't want to see the backgrounds of
1006  // all the screens for < 1 second for every screen we automatically move to.
1007  if ( Cmdline_start_netgame ) {
1008  return;
1009  }
1010 
1011  // when joining a network game, wait for the server query to come back, and then join the game
1012  if ( Cmdline_connect_addr != NULL ) {
1013  int rval;
1014 
1015  if ( !Multi_did_autojoin ) {
1016  rval = popup_till_condition(multi_join_autojoin_do, XSTR("&Cancel", 779), XSTR("Joining netgame", 1500) );
1017  if ( rval == 0 ) {
1018  // cancel was hit. Send the user back to the main hall
1020  Cmdline_connect_addr = NULL; // reset this value.
1021  }
1022 
1023  // when we get here, we have the data -- join the game.
1026  Multi_did_autojoin = 1;
1027  }
1028 
1032  }
1033  return;
1034 
1035  }
1036 
1037  // reset the should send var
1039 
1040  int k = Multi_join_window.process();
1041 
1042  // process any keypresses
1043  switch(k){
1044  case KEY_ESC :
1047  } else {
1048  if (MULTI_IS_TRACKER_GAME) {
1050  } else {
1052  }
1054  }
1055  break;
1056 
1057  // page up the game list
1058  case KEY_PAGEUP:
1060  Multi_join_slider.force_currentItem(Multi_join_list_start);
1061  break;
1062 
1063  case KEY_T:
1065  break;
1066 
1067  // page down the game list
1068  case KEY_PAGEDOWN:
1070  Multi_join_slider.force_currentItem(Multi_join_list_start);
1071  break;
1072 
1073  // send out a ping-all
1074  case KEY_P :
1077  break;
1078 
1079  // shortcut to start a game
1080  case KEY_S :
1082  break;
1083 
1084  // scroll the game list up
1085  case KEY_UP:
1087  Multi_join_slider.force_currentItem(Multi_join_list_start);
1088  break;
1089 
1090  // scroll the game list down
1091  case KEY_DOWN:
1093  Multi_join_slider.force_currentItem(Multi_join_list_start);
1094  break;
1095  }
1096 
1097  if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
1099  }
1100 
1101  // do any network related stuff
1103 
1104  // process any button clicks
1106 
1107  // process any list selection stuff
1109 
1110  // draw the background, etc
1111  gr_reset_clip();
1113  if(Multi_join_bitmap != -1){
1116  }
1117  Multi_join_window.draw();
1118 
1119  // display the active games
1121 
1122  // display any text in the info area
1124 
1125  // display any pending notification messages
1127 
1128  // blit the CD icon and any PXO filter stuff
1130 
1131  // draw the help overlay
1133 
1134  // flip the buffer
1135  gr_flip();
1136 
1137  // if we are supposed to be sending a join request
1138  if(Multi_join_should_send != -1){
1140  }
1142 
1143  // increment the frame count
1145 }
1146 
1148 {
1149  // unload any bitmaps
1151  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_join_bitmap_fname[gr_screen.res]));
1152  }
1153 
1154  // free up the active game list
1156 
1157  // destroy the UI_WINDOW
1158  Multi_join_window.destroy();
1159 }
1160 
1162 {
1163  int idx;
1164  for(idx=0;idx<MULTI_JOIN_NUM_BUTTONS;idx++){
1165  // we only really need to check for one button pressed at a time, so we can break after
1166  // finding one.
1167  if(Multi_join_buttons[gr_screen.res][idx].button.pressed()){
1169  break;
1170  }
1171  }
1172 }
1173 
1175 {
1176 
1177  switch(n){
1178  case MJ_CANCEL :
1179  // if we're player PXO, go back there
1180  if (MULTI_IS_TRACKER_GAME) {
1182  } else {
1184  }
1186  break;
1187  case MJ_ACCEPT :
1188  if(Active_game_count <= 0){
1189  multi_common_add_notify(XSTR("No games found!",757));
1191  } else if(Multi_join_list_selected == -1){
1192  multi_common_add_notify(XSTR("No game selected!",758));
1195  multi_common_add_notify(XSTR("Still waiting on previous join request!",759));
1197  } else {
1198  // otherwise, if he's already played PXO games, warn him
1199 
1201  if(!multi_join_warn_pxo()){
1202  break;
1203  }
1204  }
1205 
1206 
1207  // send the join request here
1208  Assert(Multi_join_selected_item != NULL);
1209 
1210  // send a join request packet
1212 
1214  }
1215  break;
1216 
1217  // help overlay
1218  case MJ_HELP:
1221  } else {
1223  }
1224  break;
1225 
1226  // scroll the game list up
1227  case MJ_SCROLL_UP:
1229  Multi_join_slider.force_currentItem(Multi_join_list_start);
1230  break;
1231 
1232  // scroll the game list down
1233  case MJ_SCROLL_DOWN:
1235  Multi_join_slider.force_currentItem(Multi_join_list_start);
1236  break;
1237 
1238  // scroll the info text box up
1239  case MJ_SCROLL_INFO_UP:
1241  break;
1242 
1243  // scroll the info text box down
1244  case MJ_SCROLL_INFO_DOWN:
1246  break;
1247 
1248  // go to the options screen
1249  case MJ_OPTIONS:
1251  break;
1252 
1253  // go to the start game screen
1254  case MJ_START_GAME:
1256  break;
1257 
1258  // refresh the game/server list
1259  case MJ_REFRESH:
1262  break;
1263 
1264  // join a game as an observer
1265  case MJ_JOIN_OBSERVER:
1266  if(Active_game_count <= 0){
1267  multi_common_add_notify(XSTR("No games found!",757));
1269  } else if(Multi_join_list_selected == -1){
1270  multi_common_add_notify(XSTR("No game selected!",758));
1273  multi_common_add_notify(XSTR("Still waiting on previous join request!",759));
1275  } else {
1276  // send the join request here
1277  Assert(Multi_join_selected_item != NULL);
1278 
1280 
1282  }
1283  break;
1284 
1285  default :
1286  multi_common_add_notify(XSTR("Not implemented yet!",760));
1288  break;
1289  }
1290 }
1291 
1292 // display all relevant info for active games
1294 {
1296  char str[200];
1297  int w,h;
1298  int con_type;
1299  int y_start = Mj_list_y[gr_screen.res];
1300  int line_height = gr_get_font_height() + 1;
1301  int count = 0;
1302 
1303  if(moveup != NULL){
1304  do {
1305  // blit the game status (including text and type icon)
1306  multi_join_blit_game_status(moveup,y_start);
1307 
1308  // get the connection type
1310  if((con_type > 4) || (con_type < 0)){
1311  con_type = 0;
1312  }
1313 
1314  // display the connection speed
1315  str[0] = '\0';
1316  strcpy_s(str, Multi_join_speed_labels[con_type]);
1317  gr_set_color_fast(Multi_join_speed_colors[con_type]);
1319 
1320  // we'll want to have different colors for highlighted items, etc.
1321  if(moveup == Multi_join_selected_item){
1323  } else {
1325  }
1326 
1327  // display the game name, adding appropriate status chars
1328  str[0] = '\0';
1329  if(moveup->flags & AG_FLAG_STANDALONE){
1331  }
1332  if(moveup->flags & AG_FLAG_CAMPAIGN){
1334  }
1335 
1336  // tack on the actual server name
1337  strcat_s(str," ");
1338  strcat_s(str,moveup->name);
1339  if(moveup->mission_name[0] != '\0'){
1340  strcat_s(str, " / ");
1341  strcat_s(str,moveup->mission_name);
1342  }
1343 
1344  // make sure the string fits in the display area and draw it
1346  gr_string(Mj_game_name_coords[gr_screen.res][MJ_X_COORD],y_start,str,GR_RESIZE_MENU);
1347 
1348  // display the ping time
1349  if(moveup->ping.ping_avg > 0){
1350  if(moveup->ping.ping_avg > MJ_PING_ONE_SECOND){
1352  strcpy_s(str,XSTR("> 1 sec",761));
1353  } else {
1354  // set the appropriate ping time color indicator
1355  if(moveup->ping.ping_avg > MJ_PING_RED){
1357  } else if(moveup->ping.ping_avg > MJ_PING_YELLOW){
1359  } else {
1361  }
1362 
1363  sprintf(str,"%d",moveup->ping.ping_avg);
1364  strcat_s(str,XSTR(" ms",762)); // [[ Milliseconds ]]
1365  }
1366 
1367  gr_string(Mj_ping_coords[gr_screen.res][MJ_X_COORD],y_start,str,GR_RESIZE_MENU);
1368  }
1369 
1370  // display the number of players (be sure to center it)
1371  if(moveup == Multi_join_selected_item){
1373  } else {
1375  }
1376  sprintf(str,"%d",moveup->num_players);
1377  gr_get_string_size(&w,&h,str);
1378  gr_string(Mj_players_coords[gr_screen.res][MJ_X_COORD] + (Mj_players_coords[gr_screen.res][MJ_W_COORD] - w)/2,y_start,str,GR_RESIZE_MENU);
1379 
1380  count++;
1381  y_start += line_height;
1382  moveup = moveup->next;
1383  } while((moveup != Active_game_head) && (count < Mj_max_game_items[gr_screen.res]));
1384  }
1385  // if there are no items on the list, display this info
1386  else {
1388  gr_string(Mj_game_name_coords[gr_screen.res][MJ_X_COORD] - 30,y_start,XSTR("<No game servers found>",763),GR_RESIZE_MENU);
1389  }
1390 }
1391 
1393 {
1394  int draw,str_w;
1395  char status_text[25];
1396 
1397  // blit the proper icon
1398  draw = 0;
1399  switch( game->flags & AG_FLAG_TYPE_MASK ){
1400  // coop game
1401  case AG_FLAG_COOP:
1402  if(Multi_common_icons[MICON_COOP] != -1){
1404  draw = 1;
1405  }
1406  break;
1407 
1408  // team vs. team game
1409  case AG_FLAG_TEAMS:
1410  if(Multi_common_icons[MICON_TVT] != -1){
1412  draw = 1;
1413  }
1414  break;
1415 
1416  // dogfight game
1417  case AG_FLAG_DOGFIGHT:
1420  draw = 1;
1421  }
1422  break;
1423  }
1424  // if we're supposed to draw a bitmap
1425  if(draw){
1427  }
1428 
1429  // blit the proper status text
1430  memset(status_text,0,25);
1431 
1432  switch( game->flags & AG_FLAG_STATE_MASK ){
1433  case AG_FLAG_FORMING:
1435  strcpy_s(status_text,XSTR("Forming",764));
1436  break;
1437  case AG_FLAG_BRIEFING:
1439  strcpy_s(status_text,XSTR("Briefing",765));
1440  break;
1441  case AG_FLAG_DEBRIEF:
1443  strcpy_s(status_text,XSTR("Debrief",766));
1444  break;
1445  case AG_FLAG_PAUSE:
1447  strcpy_s(status_text,XSTR("Paused",767));
1448  break;
1449  case AG_FLAG_IN_MISSION:
1451  strcpy_s(status_text,XSTR("Playing",768));
1452  break;
1453  default:
1455  strcpy_s(status_text,XSTR("Unknown",769));
1456  break;
1457  }
1458  gr_get_string_size(&str_w,NULL,status_text);
1460 }
1461 
1463 {
1464  char line[MAX_IP_STRING];
1465  net_addr addr;
1466  server_item *item;
1467  CFILE *file = NULL;
1468 
1469  // attempt to open the ip list file
1471  if(file == NULL){
1472  nprintf(("Network","Error loading tcp.cfg file!\n"));
1473  return;
1474  }
1475 
1476  // free up any existing server list
1478 
1479  // read in all the strings in the file
1480  while(!cfeof(file)){
1481  line[0] = '\0';
1482  cfgets(line,MAX_IP_STRING,file);
1483 
1484  // strip off any newline character
1485  if(line[strlen(line) - 1] == '\n'){
1486  line[strlen(line) - 1] = '\0';
1487  }
1488 
1489  // empty lines don't get processed
1490  if( (line[0] == '\0') || (line[0] == '\n') ){
1491  continue;
1492  }
1493 
1494  if ( !psnet_is_valid_ip_string(line) ) {
1495  nprintf(("Network","Invalid ip string (%s)\n",line));
1496  } else {
1497  // copy the server ip address
1498  memset(&addr,0,sizeof(net_addr));
1499  addr.type = NET_TCP;
1500  psnet_string_to_addr(&addr,line);
1501  if ( addr.port == 0 ){
1502  addr.port = DEFAULT_GAME_PORT;
1503  }
1504 
1505  // create a new server item on the list
1506  item = multi_new_server_item();
1507  if(item != NULL){
1508  memcpy(&item->server_addr,&addr,sizeof(net_addr));
1509  }
1510  }
1511  }
1512 
1513  cfclose(file);
1514 }
1515 
1516 // do stuff like pinging servers, sending out requests, etc
1518 {
1519  // handle game query stuff
1520  if (Multi_join_glr_stamp == -1) {
1522 
1525  } else {
1527  }
1528  }
1529  // otherwise send out game query and restamp
1530  else if ( timestamp_elapsed(Multi_join_glr_stamp) ) {
1532 
1535  } else {
1537  }
1538  }
1539 
1540  // check to see if we've been accepted. If so, put up message saying so
1542  multi_common_add_notify(XSTR("Accepted. Waiting for player data.",770));
1543  }
1544 
1545  // check to see if any join packets we have sent have timed out
1547  Multi_join_sent_stamp = -1;
1548  multi_common_add_notify(XSTR("Join request timed out!",771));
1549  }
1550 
1551  // check to see if we should be pinging everyone
1555  }
1556 
1557  // cull timeouts
1559 }
1560 
1561 // evaluate a returned pong.
1563 {
1564  active_game *moveup = Active_game_head;
1565 
1566  if(moveup != NULL){
1567  do {
1568  if(psnet_same(&moveup->server_addr,addr)){
1569  multi_ping_eval_pong(&moveup->ping);
1570 
1571  break;
1572  } else {
1573  moveup = moveup->next;
1574  }
1575  } while(moveup != Active_game_head);
1576  }
1577 }
1578 
1579 // ping all the server on the list
1581 {
1582  active_game *moveup = Active_game_head;
1583 
1584  if(moveup != NULL){
1585  do {
1586  /*
1587  moveup->ping_start = timer_get_fixed_seconds();
1588  moveup->ping_end = -1;
1589  send_ping(&moveup->server_addr);
1590  */
1591 
1592  send_server_query(&moveup->server_addr);
1593  multi_ping_send(&moveup->server_addr,&moveup->ping);
1594 
1595  moveup = moveup->next;
1596  } while(moveup != Active_game_head);
1597  }
1598 }
1599 
1601 {
1602  int line_height = gr_get_font_height() + 1;
1603 
1604  // if we don't have anything selected and there are items on the list - select the first one
1605  if((Multi_join_list_selected == -1) && (Active_game_count > 0)){
1607  Multi_join_selected_item = multi_join_get_game(0);
1608  MJ_LIST_START_SET(0);
1609  Multi_join_list_start_item = Multi_join_selected_item;
1610 
1611  // send a mission description request to this guy
1612  send_netgame_descript_packet(&Multi_join_selected_item->server_addr,0);
1614 
1615  // I sure hope this doesn't happen
1616  Assert(Multi_join_selected_item != NULL);
1617  return;
1618  }
1619  // otherwise see if he's clicked on an item
1620  else if(Multi_join_select_button.pressed() && (Active_game_count > 0)){
1621  int y,item;
1622  Multi_join_select_button.get_mouse_pos(NULL,&y);
1623  item = y / line_height;
1626 
1628  Multi_join_selected_item = multi_join_get_game(Multi_join_list_selected);
1629 
1630  // I sure hope this doesn't happen
1631  Assert(Multi_join_selected_item != NULL);
1632 
1633  // send a mission description request to this guy
1634  send_netgame_descript_packet(&Multi_join_selected_item->server_addr,0);
1635  multi_common_set_text("");
1636  }
1637  }
1638 
1639  // if he's double clicked, then select it and accept
1640  if(Multi_join_select_button.double_clicked()){
1641  int y,item;
1642  Multi_join_select_button.get_mouse_pos(NULL,&y);
1643  item = y / line_height;
1644  if(item == Multi_join_list_selected){
1646  }
1647  }
1648 }
1649 
1650 // return game n (0 based index)
1652 {
1653  active_game *moveup = Active_game_head;
1654 
1655  if(moveup != NULL){
1656  if(n == 0){
1657  return moveup;
1658  } else {
1659  int count = 1;
1660  moveup = moveup->next;
1661  while((moveup != Active_game_head) && (count != n)){
1662  moveup = moveup->next;
1663  count++;
1664  }
1665  if(moveup == Active_game_head){
1666  nprintf(("Network","Warning, couldn't find game item %d!\n",n));
1667  return NULL;
1668  } else {
1669  return moveup;
1670  }
1671  }
1672  }
1673  return NULL;
1674 }
1675 
1676 // scroll through the game list
1678 {
1679  // if we're not at the beginning of the list, scroll up
1680  if(Multi_join_list_start_item != Active_game_head){
1681  Multi_join_list_start_item = Multi_join_list_start_item->prev;
1682 
1683  MJ_LIST_START_DEC();
1684 
1686  } else {
1688  }
1689 }
1690 
1691 // scroll through the game list
1693 {
1695  Multi_join_list_start_item = Multi_join_list_start_item->next;
1696 
1697  MJ_LIST_START_INC();
1698 
1700  } else {
1702  }
1703 }
1704 
1706 {
1707  // in this case, just set us to the beginning of the list
1709  Multi_join_list_start_item = Active_game_head;
1710 
1711  MJ_LIST_START_SET(0);
1712 
1714  } else {
1715  // otherwise page the whole thing up
1716  int idx;
1717  for(idx=0; idx<Mj_max_game_items[gr_screen.res]; idx++){
1718  Multi_join_list_start_item = Multi_join_list_start_item->prev;
1719 
1720  MJ_LIST_START_DEC();
1721  }
1723  }
1724 }
1725 
1727 {
1728  int count = 0;
1729 
1730  // page the whole thing down
1732  Multi_join_list_start_item = Multi_join_list_start_item->next;
1733  MJ_LIST_START_INC();
1734 
1735  // next
1736  count++;
1737  }
1739 }
1740 
1742 {
1743  active_game *backup;
1744  int count;
1745  active_game *moveup = Active_game_head;
1746 
1747  // traverse through the entire list if any items exist
1748  count = 0;
1749  if(moveup != NULL){
1750  do {
1751  if((moveup->heard_from_timer != -1) && (timestamp_elapsed(moveup->heard_from_timer))){
1753 
1754  // if this is the head of the list
1755  if(moveup == Active_game_head){
1756  // if this is the _only_ item on the list
1757  if(moveup->next == Active_game_head){
1758  // handle any gui details related to deleting this item
1760 
1762  Active_game_head = NULL;
1763  return;
1764  }
1765  // if there are other items on the list
1766  else {
1767  // handle any gui details related to deleting this item
1768  multi_join_handle_item_cull(moveup, count);
1769 
1770  Active_game_head = moveup->next;
1771  Active_game_head->prev = moveup->prev;
1773  vm_free(moveup);
1774  moveup = Active_game_head;
1775  }
1776  }
1777  // if its somewhere else on the list
1778  else {
1779  // handle any gui details related to deleting this item
1780  multi_join_handle_item_cull(moveup, count);
1781 
1782  // if its the last item on the list
1783  moveup->next->prev = moveup->prev;
1784  moveup->prev->next = moveup->next;
1785 
1786  // if it was the last element on the list, return
1787  if(moveup->next == Active_game_head){
1788  vm_free(moveup);
1789  return;
1790  } else {
1791  backup = moveup->next;
1792  vm_free(moveup);
1793  moveup = backup;
1794  }
1795  }
1796  } else {
1797  moveup = moveup->next;
1798  count++;
1799  }
1800  } while(moveup != Active_game_head);
1801  }
1802 }
1803 
1804 // deep magic begins here.
1805 void multi_join_handle_item_cull(active_game *item, int item_index)
1806 {
1807  // if this is the only item on the list, unset everything
1808  if(item->next == item){
1810  Multi_join_selected_item = NULL;
1811 
1812  Multi_join_slider.set_numberItems(0);
1813  MJ_LIST_START_SET(-1);
1814  Multi_join_list_start_item = NULL;
1815 
1816  // return
1817  return;
1818  }
1819 
1820  // see if we should be adjusting our currently selected item
1821  if(item_index <= Multi_join_list_selected){
1822  // the selected item is the head of the list
1823  if(Multi_join_selected_item == Active_game_head){
1824  // move the pointer up since this item is about to be destroyed
1825  Multi_join_selected_item = Multi_join_selected_item->next;
1826  } else {
1827  // if this is the item being deleted, select the previous one
1828  if(item == Multi_join_selected_item){
1829  // previous item
1830  Multi_join_selected_item = Multi_join_selected_item->prev;
1831 
1832  // decrement the selected index by 1
1834  }
1835  // now we know its a previous item, so our pointer stays the same but our index goes down by one, since there will be
1836  // 1 less item on the list
1837  else {
1838  // decrement the selected index by 1
1840  }
1841  }
1842  }
1843 
1844  // see if we should be adjusting out current start position
1845  if(item_index <= Multi_join_list_start){
1846  // the start position is the head of the list
1847  if(Multi_join_list_start_item == Active_game_head){
1848  // move the pointer up since this item is about to be destroyed
1849  Multi_join_list_start_item = Multi_join_list_start_item->next;
1850  } else {
1851  // if this is the item being deleted, select the previous one
1852  if(item == Multi_join_list_start_item){
1853  Multi_join_list_start_item = Multi_join_list_start_item->prev;
1854 
1855  // decrement the starting index by 1
1856  MJ_LIST_START_DEC();
1857  } else {
1858  // but decrement the starting index by 1
1859  MJ_LIST_START_DEC();
1860  }
1861  }
1862  }
1863 
1864  // maybe go back up a bit so that we always have a full page of items
1867  Multi_join_list_start_item = Multi_join_list_start_item->prev;
1869  }
1870  }
1871 
1872  // set slider location
1874  Multi_join_slider.force_currentItem(Multi_join_list_start);
1875 }
1876 
1877 void multi_join_send_join_request(int as_observer)
1878 {
1879  // don't do anything if we have no items selected
1880  if(Multi_join_selected_item == NULL){
1881  return;
1882  }
1883 
1884  // 5/26/98 -- for team v team games, don't allow ingame joining :-(
1885  if ( (Multi_join_selected_item->flags & AG_FLAG_TEAMS) && (Multi_join_selected_item->flags & (AG_FLAG_PAUSE|AG_FLAG_IN_MISSION)) ) {
1886  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("Joining ingame is currently not allowed for team vs. team games",772));
1887  return;
1888  }
1889 
1890  memset(&Multi_join_request,0,sizeof(join_request));
1891 
1892  // if the netgame is in password mode, put up a request for the password
1893  if(Multi_join_selected_item->flags & AG_FLAG_PASSWD){
1894  if(!multi_passwd_popup(Multi_join_request.passwd)){
1895  return;
1896  }
1897 
1898  nprintf(("Network", "Password : %s\n", Multi_join_request.passwd));
1899  }
1900 
1901  // fill out the join request struct
1902  strcpy_s(Multi_join_request.callsign,Player->callsign);
1903  if(Player->image_filename[0] != '\0'){
1904  strcpy_s(Multi_join_request.image_filename, Player->image_filename);
1905  }
1906  if(Player->m_squad_filename[0] != '\0'){
1907  strcpy_s(Multi_join_request.squad_filename, Player->m_squad_filename);
1908  }
1909 
1910  // tracker id (if any)
1911  Multi_join_request.tracker_id = Multi_tracker_id;
1912 
1913  // player's rank (at least, what he wants you to _believe_)
1914  Multi_join_request.player_rank = (ubyte)Player->stats.rank;
1915 
1916  // misc join flags
1917  Multi_join_request.flags = 0;
1918  if(as_observer){
1919  Multi_join_request.flags |= JOIN_FLAG_AS_OBSERVER;
1920  }
1921 
1922  // if the player has hacked data
1923  if(game_hacked_data()){
1924  Multi_join_request.flags |= JOIN_FLAG_HAXOR;
1925  }
1926 
1927  // pxo squad info
1928  strcpy_s(Multi_join_request.pxo_squad_name, Multi_tracker_squad_name);
1929 
1930  // version of this server
1931  Multi_join_request.version = MULTI_FS_SERVER_VERSION;
1932 
1933  // server compatible version
1934  Multi_join_request.comp_version = MULTI_FS_SERVER_COMPATIBLE_VERSION;
1935 
1936  // his local player options
1937  memcpy(&Multi_join_request.player_options,&Player->m_local_options,sizeof(multi_local_options));
1938 
1939  // set the server address for the netgame
1940  memcpy(&Netgame.server_addr,&Multi_join_selected_item->server_addr,sizeof(net_addr));
1941 
1942  // send a join request to the guy
1943  send_join_packet(&Multi_join_selected_item->server_addr,&Multi_join_request);
1944 
1945  // now we wait
1947 
1948  psnet_flush();
1949  multi_common_add_notify(XSTR("Sending join request...",773));
1950 }
1951 
1953 {
1954  // maybe warn the player about possible crappy server conditions
1955  if(!multi_join_maybe_warn()){
1956  return;
1957  }
1958 
1959  // make sure to flag ourself as being the master
1962 
1963  // if we're in PXO mode, mark it down in our player struct
1967  }
1968  // otherwise, if he's already played PXO games, warn him
1969  else {
1970 
1972  if(!multi_join_warn_pxo()){
1973  return;
1974  }
1975  }
1976 
1977  }
1978 
1981 }
1982 
1984 {
1985  // unset the timestamp here so the user can immediately send another join request
1986  Multi_join_sent_stamp = -1;
1988 }
1989 
1991 {
1992  // blit the cd icon if he has one
1993  if(Multi_has_cd && (Multi_common_icons[MICON_CD] != -1)){
1994  // get bitmap width
1995  int cd_w;
1996  bm_get_info(Multi_common_icons[MICON_CD], &cd_w, NULL, NULL, NULL, NULL);
1997 
1998  gr_set_bitmap(Multi_common_icons[MICON_CD]);
2000  }
2001 }
2002 
2003 #define CW_CODE_CANCEL 0 // cancel the action
2004 #define CW_CODE_OK 1 // continue anyway
2005 #define CW_CODE_INFO 2 // gimme some more information
2006 
2007 #define LOW_WARN_TEXT XSTR("Warning - You have low object updates selected. A server with low object updates will not be able to handle more than 1 client without performance problems",775)
2008 #define LOW_INFO_TEXT XSTR("Low update level caps all bandwidth at ~2000 bytes/second. It is appropriate for clients with 28.8 modems, but is not reccomended for servers. In addition, any clients connecting to this server should use low object updates as well. To change your settings go to the options menu (f2), and select the Multi button",776)
2009 
2010 #define MED_WARN_TEXT XSTR("Warning - You have medium object updates selected. A server with medium object updates will not be able to handle more than 1 or 2 clients without performance problems",777)
2011 #define MED_INFO_TEXT XSTR("Medium update level caps all bandwidth at ~4000 bytes/second. It is appropriate for clients with 56.6 modems, but is not reccomended for servers. In addition, any clients connecting to this server should use low object updates as well. To change your settings go to the options menu (f2), and select the Multi button",778)
2012 
2014 {
2015  switch(code){
2016  case CW_CODE_OK:
2017  return popup(0,3,XSTR("&Cancel",779),XSTR("&Continue",780),XSTR("&More info",781),LOW_WARN_TEXT);
2018 
2019  case CW_CODE_INFO:
2020  return popup(0,3,XSTR("&Cancel",779),XSTR("&Continue",780),XSTR("&More info",781),LOW_INFO_TEXT);
2021  }
2022 
2023  return CW_CODE_CANCEL;
2024 }
2025 
2027 {
2028  switch(code){
2029  case CW_CODE_OK:
2030  return popup(0,3,XSTR("&Cancel",779),XSTR("&Continue",780),XSTR("&More info",781),MED_WARN_TEXT);
2031 
2032  case CW_CODE_INFO:
2033  return popup(0,3,XSTR("&Cancel",779),XSTR("&Continue",780),XSTR("&More info",781),MED_INFO_TEXT);
2034  }
2035 
2036  return CW_CODE_CANCEL;
2037 }
2038 
2040 {
2041  int code;
2042 
2043  // if the player is set for low updates
2045  code = CW_CODE_OK;
2046  do {
2047  code = multi_join_warn_update_low(code);
2048  } while((code != CW_CODE_CANCEL) && (code != CW_CODE_OK));
2049 
2050  return code;
2051  }
2052 
2053  // if the player is set for medium updates
2055  code = CW_CODE_OK;
2056  do {
2057  code = multi_join_warn_update_medium(code);
2058  } while((code != CW_CODE_CANCEL) && (code != CW_CODE_OK));
2059 
2060  return code;
2061  }
2062 
2063  return 1;
2064 }
2065 
2067 {
2068  return popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_TITLE_BIG | PF_TITLE_RED, 2, XSTR("&Back", 995), XSTR("&Continue",780), XSTR("Warning\n\nThis pilot has played PXO games. If you continue and play a non-PXO game, your stats will not be updated", 1006)) <= 0 ? 0 : 1;
2069  //return 1;
2070 }
2071 
2073 {
2075  gr_string(5, 2, "TCP", GR_RESIZE_MENU);
2076 }
2077 
2078 
2079 // -------------------------------------------------------------------------------------------------
2080 //
2081 // MULTIPLAYER START GAME screen
2082 //
2083 
2084 //XSTR:OFF
2085 // bitmap defs
2086 #define MULTI_SG_PALETTE "InterfacePalette"
2087 
2088 static char *Multi_sg_bitmap_fname[GR_NUM_RESOLUTIONS] = {
2089  "MultiStartGame", // GR_640
2090  "2_MultiStartGame" // GR_1024
2091 };
2092 
2093 static char *Multi_sg_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
2094  "MultiStartGame-M", // GR_640
2095  "2_MultiStartGame-M" // GR_1024
2096 };
2097 
2098 //XSTR:ON
2099 
2101  2, // GR_640
2102  4 // GR_1024
2103 };
2104 
2105 // constants for coordinate look ups
2106 #define MSG_X_COORD 0
2107 #define MSG_Y_COORD 1
2108 #define MSG_W_COORD 2
2109 #define MSG_H_COORD 3
2110 
2111 // area definitions
2112 
2113 // input password field
2115  { // GR_640
2116  36, 236, 408, 20
2117  },
2118  { // GR_1024
2119  58, 377, 652, 32
2120  }
2121 };
2122 
2123 // input game title field
2125  { // GR_640
2126  29, 49, 415, 23
2127  },
2128  { // GR_1024
2129  46, 78, 664, 36
2130  }
2131 };
2132 
2133 // rank selected field
2135  { // GR_640
2136  242, 254, 126, 12
2137  },
2138  { // GR_1024
2139  242, 254, 126, 12
2140  }
2141 };
2142 
2143 // rank list field
2145  { // GR_640
2146  37, 297, 131, 16
2147  },
2148  { // GR_1024
2149  60, 469, 652, 32
2150  }
2151 };
2152 
2153 
2154 // button defs
2155 #define MULTI_SG_NUM_BUTTONS 10
2156 //#define MULTI_SG_NUM_BUTTONS 12
2157 
2158 #define MSG_OPEN_GAME 0
2159 //#define MSG_CLOSED_GAME 1
2160 //#define MSG_RESTRICTED_GAME 2
2161 #define MSG_PASSWD_GAME 1
2162 #define MSG_RANK_SET_GAME 2
2163 #define MSG_RANK_SCROLL_UP 3
2164 #define MSG_RANK_SCROLL_DOWN 4
2165 #define MSG_RANK_ABOVE 5
2166 #define MSG_RANK_BELOW 6
2167 #define MSG_HELP 7
2168 #define MSG_OPTIONS 8
2169 #define MSG_ACCEPT 9
2170 
2171 UI_WINDOW Multi_sg_window; // the window object for the join screen
2172 UI_BUTTON Multi_sg_rank_button; // for selecting the rank marker
2173 UI_INPUTBOX Multi_sg_game_name; // for Netgame.name
2174 UI_INPUTBOX Multi_sg_game_passwd; // for Netgame.passwd
2175 int Multi_sg_bitmap; // the background bitmap
2176 
2178  { // GR_640
2179  ui_button_info("MSG_00", 1, 184, 34, 191, 2), // open
2180 //******ui_button_info("MSG_01", 1, 159, 34, 166, 1), // closed
2181 //******ui_button_info("MSG_02", 1, 184, 34, 191, 2), // restricted
2182  ui_button_info("MSG_03", 1, 209, 34, 218, 3), // password
2183  ui_button_info("MSG_04", 1, 257, 34, 266, 4), // rank set
2184  ui_button_info("MSG_05", 1, 282, -1, -1, 5), // rank scroll up
2185  ui_button_info("MSG_06", 1, 307, -1, -1, 6), // rank scroll down
2186  ui_button_info("MSG_07", 177, 282, 210, 290, 7), // rank above
2187  ui_button_info("MSG_08", 177, 307, 210, 315, 8), // rank below
2188  ui_button_info("MSG_09", 536, 429, 500, 440, 9), // help
2189  ui_button_info("MSG_10", 536, 454, 479, 464, 10), // options
2190  ui_button_info("MSG_11", 576, 432, 571, 415, 11), // accept
2191  },
2192  { // GR_1024
2193  ui_button_info("2_MSG_00", 2, 295, 51, 307, 2), // open
2194 //******ui_button_info("2_MSG_01", 2, 254, 51, 267, 1), // closed
2195 //******ui_button_info("2_MSG_02", 2, 295, 51, 307, 2), // restricted
2196  ui_button_info("2_MSG_03", 2, 335, 51, 350, 3), // password
2197  ui_button_info("2_MSG_04", 2, 412, 51, 426, 4), // rank set
2198  ui_button_info("2_MSG_05", 2, 452, -1, -1, 5), // rank scroll up
2199  ui_button_info("2_MSG_06", 2, 492, -1, -1, 6), // rank scroll down
2200  ui_button_info("2_MSG_07", 284, 452, 335, 465, 7), // rank above
2201  ui_button_info("2_MSG_08", 284, 492, 335, 505, 8), // rank below
2202  ui_button_info("2_MSG_09", 858, 687, 817, 706, 9), // help
2203  ui_button_info("2_MSG_10", 858, 728, 797, 743, 10), // options
2204  ui_button_info("2_MSG_11", 921, 692, 921, 664, 11), // accept
2205  },
2206 };
2207 
2208 //#define MULTI_SG_NUM_TEXT 13
2209 #define MULTI_SG_NUM_TEXT 11
2211  { // GR_640
2212  {"Open", 1322, 34, 191, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_OPEN_GAME].button},
2213 //******{"Closed", 1323, 34, 166, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_CLOSED_GAME].button},
2214 //******{"Restricted", 1324, 34, 191, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_RESTRICTED_GAME].button},
2215  {"Password Protected", 1325, 34, 218, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_PASSWD_GAME].button},
2216  {"Allow Rank", 1326, 34, 266, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_RANK_SET_GAME].button},
2217  {"Above", 1327, 210, 290, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_RANK_ABOVE].button},
2218  {"Below", 1328, 210, 315, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_RANK_BELOW].button},
2219  {"Help", 928, 500, 440, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_HELP].button},
2220  {"Options", 1036, 479, 464, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[0][MSG_OPTIONS].button},
2221  {"Accept", 1035, 571, 415, UI_XSTR_COLOR_PINK, -1, &Multi_sg_buttons[0][MSG_ACCEPT].button},
2222  {"Start Game", 1329, 26, 10, UI_XSTR_COLOR_GREEN, -1, NULL},
2223  {"Title", 1330, 26, 31, UI_XSTR_COLOR_GREEN, -1, NULL},
2224  {"Game Type", 1331, 12, 165, UI_XSTR_COLOR_GREEN, -1, NULL},
2225  },
2226  { // GR_1024
2227  {"Open", 1322, 51, 307, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_OPEN_GAME].button},
2228 //******{"Closed", 1323, 51, 267, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_CLOSED_GAME].button},
2229 //******{"Restricted", 1324, 51, 307, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_RESTRICTED_GAME].button},
2230  {"Password Protected", 1325, 51, 350, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_PASSWD_GAME].button},
2231  {"Allow Rank", 1326, 51, 426, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_RANK_SET_GAME].button},
2232  {"Above", 1327, 335, 465, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_RANK_ABOVE].button},
2233  {"Below", 1328, 335, 505, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_RANK_BELOW].button},
2234  {"Help", 928, 817, 706, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_HELP].button},
2235  {"Options", 1036, 797, 743, UI_XSTR_COLOR_GREEN, -1, &Multi_sg_buttons[1][MSG_OPTIONS].button},
2236  {"Accept", 1035, 921, 664, UI_XSTR_COLOR_PINK, -1, &Multi_sg_buttons[1][MSG_ACCEPT].button},
2237  {"Start Game", 1329, 42, 22, UI_XSTR_COLOR_GREEN, -1, NULL},
2238  {"Title", 1330, 42, 50, UI_XSTR_COLOR_GREEN, -1, NULL},
2239  {"Game Type", 1331, 20, 264, UI_XSTR_COLOR_GREEN, -1, NULL},
2240  }
2241 };
2242 
2243 // starting index for displaying ranks
2246 
2247 // netgame pointer to indirect through
2249 
2250 // hold temporary values in this structure when on a standalone server
2252 
2254 
2255 // forward declarations
2256 void multi_sg_check_buttons();
2257 void multi_sg_button_pressed(int n);
2258 void multi_sg_init_gamenet();
2264 void multi_sg_rank_build_name(char *in,char *out);
2265 void multi_sg_check_passwd();
2266 void multi_sg_check_name();
2268 int multi_sg_rank_select_valid(int rank);
2270 
2271 // function which takes a rank name and returns the index. Useful for commandline options
2272 // for above and below rank. We return the index of the rank in the Ranks[] array. If
2273 // the rank isn't found, we return -1
2275  int i;
2276 
2277  for ( i = 0; i <= MAX_FREESPACE2_RANK; i++ ) {
2278  if ( !stricmp(Ranks[i].name, rank) ) {
2279  return i;
2280  }
2281  }
2282 
2283  return -1;
2284 }
2285 
2287 {
2288  int idx;
2289 
2290  // initialize the gamenet
2292 
2293  // create the interface window
2294  Multi_sg_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
2295  Multi_sg_window.set_mask_bmap(Multi_sg_bitmap_mask_fname[gr_screen.res]);
2296 
2297  // load the background bitmap
2298  Multi_sg_bitmap = bm_load(Multi_sg_bitmap_fname[gr_screen.res]);
2299  if(Multi_sg_bitmap < 0){
2300  // we failed to load the bitmap - this is very bad
2301  Int3();
2302  }
2303 
2304  // initialize the common notification messaging
2306 
2307  // initialize the common text area
2309 
2310  // use the common interface palette
2312 
2313  // create the interface buttons
2314  for(idx=0; idx<MULTI_SG_NUM_BUTTONS; idx++){
2315  // create the object
2316  Multi_sg_buttons[gr_screen.res][idx].button.create(&Multi_sg_window, "", Multi_sg_buttons[gr_screen.res][idx].x, Multi_sg_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
2317 
2318  // set the sound to play when highlighted
2320 
2321  // set the ani for the button
2322  Multi_sg_buttons[gr_screen.res][idx].button.set_bmaps(Multi_sg_buttons[gr_screen.res][idx].filename);
2323 
2324  // set the hotspot
2325  Multi_sg_buttons[gr_screen.res][idx].button.link_hotspot(Multi_sg_buttons[gr_screen.res][idx].hotspot);
2326  }
2327 
2328  // add all xstrs
2329  for(idx=0; idx<MULTI_SG_NUM_TEXT; idx++){
2330  Multi_sg_window.add_XSTR(&Multi_sg_text[gr_screen.res][idx]);
2331  }
2332 
2333  // load the help overlay
2334  Multi_sg_overlay_id = help_overlay_get_index(MULTI_START_OVERLAY);
2335  help_overlay_set_state(Multi_sg_overlay_id,gr_screen.res,0);
2336 
2337  // intiialize the rank selection items
2339  Multi_sg_rank_start = Multi_sg_rank_select;
2340 
2341  // create the rank select button
2342  Multi_sg_rank_button.create(&Multi_sg_window,"",Msg_rank_list_coords[gr_screen.res][MSG_X_COORD],Msg_rank_list_coords[gr_screen.res][MSG_Y_COORD],Msg_rank_list_coords[gr_screen.res][MSG_W_COORD],Msg_rank_list_coords[gr_screen.res][MSG_H_COORD],0,1);
2343  Multi_sg_rank_button.hide();
2344 
2345  // create the netgame name input box
2346  Multi_sg_game_name.create(&Multi_sg_window,Msg_title_coords[gr_screen.res][MSG_X_COORD],Msg_title_coords[gr_screen.res][MSG_Y_COORD],Msg_title_coords[gr_screen.res][MSG_W_COORD],MAX_GAMENAME_LEN,"",UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_INVIS,-1,&Color_normal);
2347 
2348  // create the netgame password input box, and disable it by default
2349  Multi_sg_game_passwd.create(&Multi_sg_window,Msg_passwd_coords[gr_screen.res][MSG_X_COORD],Msg_passwd_coords[gr_screen.res][MSG_Y_COORD],Msg_passwd_coords[gr_screen.res][MSG_W_COORD],16,"",UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_PASSWD | UI_INPUTBOX_FLAG_INVIS,-1,&Color_normal);
2350  Multi_sg_game_passwd.hide();
2351  Multi_sg_game_passwd.disable();
2352 
2353  // set the netgame text to this gadget and make it have focus
2354  Multi_sg_game_name.set_text(Multi_sg_netgame->name);
2355  Multi_sg_game_name.set_focus();
2356 
2357  // if starting a netgame, set the name of the game and any other options that are appropriate
2358  if ( Cmdline_start_netgame ) {
2359  if ( Cmdline_game_name != NULL ) {
2360  strcpy_s( Multi_sg_netgame->name, Cmdline_game_name );
2361  Multi_sg_game_name.set_text(Multi_sg_netgame->name);
2362  }
2363 
2364  // deal with the different game types -- only one should even be active, so we will just go down
2365  // the line. Last one wins.
2366  if ( Cmdline_closed_game ) {
2367  Multi_sg_netgame->mode = NG_MODE_CLOSED;
2368  } else if ( Cmdline_restricted_game ) {
2369  Multi_sg_netgame->mode = NG_MODE_RESTRICTED;
2370  } else if ( Cmdline_game_password != NULL ) {
2371  Multi_sg_netgame->mode = NG_MODE_PASSWORD;
2372  strcpy_s(Multi_sg_netgame->passwd, Cmdline_game_password);
2373  Multi_sg_game_passwd.set_text(Multi_sg_netgame->passwd);
2374  }
2375 
2376  // deal with rank above and rank below
2377  if ( (Cmdline_rank_above != NULL) || (Cmdline_rank_below != NULL) ) {
2378  int rank;
2379  char *rank_str;
2380 
2381  if ( Cmdline_rank_above != NULL ) {
2382  rank_str = Cmdline_rank_above;
2383  } else {
2384  rank_str = Cmdline_rank_below;
2385  }
2386 
2387  // try and get the rank index from the name -- if found, then set the rank base
2388  // and the game type. apparently we only support either above or below, not both
2389  // together, so I make a random choice
2390  rank = multi_start_game_rank_from_name( rank_str );
2391  if ( rank != -1 ) {
2392  Multi_sg_netgame->rank_base = Multi_sg_rank_select;
2393 
2394  // now an arbitrary decision
2395  if ( Cmdline_rank_above != NULL ) {
2396  Multi_sg_netgame->mode = NG_MODE_RANK_ABOVE;
2397  } else {
2398  Multi_sg_netgame->mode = NG_MODE_RANK_BELOW;
2399  }
2400  }
2401  }
2402 
2404  }
2405 }
2406 
2408 {
2409  // return here since we will be moving to the next stage anyway -- I don't want to see the backgrounds of
2410  // all the screens for < 1 second for every screen we automatically move to.
2411  if ( Cmdline_start_netgame ) {
2412  Cmdline_start_netgame = 0; // DTP no quit fix; by using -startgame Quit was sort of out of function
2413  return;
2414  }
2415 
2416  int k = Multi_sg_window.process();
2417 
2418  // process any keypresses
2419  switch(k){
2420  case KEY_ESC :
2421  if(help_overlay_active(Multi_sg_overlay_id)){
2422  help_overlay_set_state(Multi_sg_overlay_id,gr_screen.res,0);
2423  } else {
2426  }
2427  break;
2428 
2429  // same as ACCEPT
2430  case KEY_LCTRL + KEY_ENTER :
2431  case KEY_RCTRL + KEY_ENTER :
2434  break;
2435  }
2436 
2437  if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
2438  help_overlay_set_state(Multi_sg_overlay_id, gr_screen.res, 0);
2439  }
2440 
2441  // check to see if the user has selected a different rank
2443 
2444  // check any button presses
2446 
2447  // check to see if any of the input boxes have changed, and update the appropriate Netgame fields if necessary
2450 
2451  // draw the background, etc
2452  gr_reset_clip();
2453  GR_MAYBE_CLEAR_RES(Multi_sg_bitmap);
2454  if(Multi_sg_bitmap != -1){
2455  gr_set_bitmap(Multi_sg_bitmap);
2457  }
2458  Multi_sg_window.draw();
2459 
2460  // display rank stuff
2462 
2463  // display any pending notification messages
2465 
2466  // draw all radio button
2468 
2469  // draw the help overlay
2470  help_overlay_maybe_blit(Multi_sg_overlay_id, gr_screen.res);
2471 
2472  // flip the buffer
2473  gr_flip();
2474 }
2475 
2477 {
2478  // if i'm the host on a standalone server, send him my start game options (passwd, mode, etc)
2480  multi_options_update_start_game(Multi_sg_netgame);
2481  }
2482 
2483  // unload any bitmaps
2484  if(!bm_unload(Multi_sg_bitmap)){
2485  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_sg_bitmap_fname[gr_screen.res]));
2486  }
2487 
2488  // destroy the UI_WINDOW
2489  Multi_sg_window.destroy();
2490 }
2491 
2493 {
2494  int idx;
2495  for(idx=0;idx<MULTI_SG_NUM_BUTTONS;idx++){
2496  // we only really need to check for one button pressed at a time, so we can break after
2497  // finding one.
2498  if(Multi_sg_buttons[gr_screen.res][idx].button.pressed()){
2500  break;
2501  }
2502  }
2503 }
2504 
2506 {
2507  switch(n){
2508  // go to the options screen
2509  case MSG_OPTIONS:
2511  break;
2512 
2513  // help overlay
2514  case MSG_HELP:
2515  if(!help_overlay_active(Multi_sg_overlay_id)){
2516  help_overlay_set_state(Multi_sg_overlay_id,gr_screen.res,1);
2517  } else {
2518  help_overlay_set_state(Multi_sg_overlay_id,gr_screen.res,0);
2519  }
2520  break;
2521 
2522  // the open button was pressed
2523  case MSG_OPEN_GAME:
2524  // if the closed option is selected
2525  if(Multi_sg_netgame->mode != NG_MODE_OPEN){
2526  Multi_sg_netgame->mode = NG_MODE_OPEN;
2527 
2529 
2530  // release the password control if necessary
2532  }
2533  // if its already selected
2534  else {
2536  }
2537  break;
2538 
2539 /*
2540  // the open button was pressed
2541  case MSG_CLOSED_GAME:
2542  // if the closed option is selected
2543  if(Multi_sg_netgame->mode != NG_MODE_CLOSED){
2544  Multi_sg_netgame->mode = NG_MODE_CLOSED;
2545 
2546  gamesnd_play_iface(SND_USER_SELECT);
2547 
2548  // release the password control if necessary
2549  multi_sg_release_passwd();
2550  }
2551  // if its already selected
2552  else {
2553  gamesnd_play_iface(SND_GENERAL_FAIL);
2554  }
2555  break;
2556 */
2557  // toggle password protection
2558  case MSG_PASSWD_GAME:
2559  // if we selected it
2560  if(Multi_sg_netgame->mode != NG_MODE_PASSWORD){
2562 
2563  Multi_sg_game_passwd.enable();
2564  Multi_sg_game_passwd.unhide();
2565  Multi_sg_game_passwd.set_focus();
2566 
2567  Multi_sg_netgame->mode = NG_MODE_PASSWORD;
2568 
2569  // copy in the current network password
2570  Multi_sg_game_passwd.set_text(Multi_sg_netgame->passwd);
2571  } else {
2573  }
2574  break;
2575 
2576 /*
2577  // toggle "restricted" on or off
2578  case MSG_RESTRICTED_GAME:
2579  if(Multi_sg_netgame->mode != NG_MODE_RESTRICTED){
2580  gamesnd_play_iface(SND_USER_SELECT);
2581  Multi_sg_netgame->mode = NG_MODE_RESTRICTED;
2582 
2583  // release the password control if necessary
2584  multi_sg_release_passwd();
2585  } else {
2586  gamesnd_play_iface(SND_GENERAL_FAIL);
2587  }
2588  break;
2589 */
2590  // turn off all rank requirements
2591  case MSG_RANK_SET_GAME:
2592  // if either is set, then turn then both off
2593  if((Multi_sg_netgame->mode != NG_MODE_RANK_BELOW) && (Multi_sg_netgame->mode != NG_MODE_RANK_ABOVE)){
2595 
2596  // set it to the default case if we're turning it off
2598  Multi_sg_rank_start = Multi_sg_rank_select;
2599 
2600  Multi_sg_netgame->mode = NG_MODE_RANK_ABOVE;
2601 
2602  // release the password control if necessary
2604  } else {
2606  }
2607  break;
2608 
2609  // rank above was pressed
2610  case MSG_RANK_ABOVE :
2611  if((Multi_sg_netgame->mode == NG_MODE_RANK_ABOVE) || (Multi_sg_netgame->mode == NG_MODE_RANK_BELOW)){
2612  Multi_sg_netgame->mode = NG_MODE_RANK_ABOVE;
2613 
2614  // select the first item
2616  Multi_sg_rank_start = Multi_sg_rank_select;
2617 
2618  // play a sound
2620  } else {
2622  }
2623  break;
2624 
2625  // rank below was pressed
2626  case MSG_RANK_BELOW :
2627  if((Multi_sg_netgame->mode == NG_MODE_RANK_ABOVE) || (Multi_sg_netgame->mode == NG_MODE_RANK_BELOW)){
2628  Multi_sg_netgame->mode = NG_MODE_RANK_BELOW;
2629 
2630  // select the first item
2632  Multi_sg_rank_start = Multi_sg_rank_select;
2633 
2634  // play a sound
2636  } else {
2638  }
2639  break;
2640 
2641  // scroll the rank list up
2642  case MSG_RANK_SCROLL_UP:
2644  break;
2645 
2646  // scroll the rank list down
2647  case MSG_RANK_SCROLL_DOWN:
2649  break;
2650 
2651  // move to the create game screen
2652  case MSG_ACCEPT:
2655  break;
2656 
2657  default :
2659  multi_common_add_notify(XSTR("Not implemented yet!",760));
2660  break;
2661  }
2662 }
2663 
2664 // NOTE : this is where all Netgame initialization should take place on the host
2666 {
2667  char buf[128],out_name[128];
2668  net_addr save;
2669  net_player *server_save;
2670 
2671  // back this data up in case we are already connected to a standalone
2672  memcpy(&save,&Netgame.server_addr,sizeof(net_addr));
2673  server_save = Netgame.server;
2674 
2675  // remove campaign flags
2677 
2678  // clear out the Netgame structure and start filling in the values
2679  memset( &Netgame, 0, sizeof(Netgame) );
2680  memset( &Multi_sg_netgame_temp, 0, sizeof(netgame_info) );
2681 
2682  // if we're on the standalone, we're not the server, so we don't care about setting the netgame state
2685  Multi_sg_netgame = &Netgame;
2686 
2687  // NETLOG
2688  ml_string(NOX("Starting netgame as Host/Server"));
2689  } else {
2690  Multi_sg_netgame = &Multi_sg_netgame_temp;
2691 
2692  // NETLOG
2693  in_addr temp_addr;
2694  memcpy(&temp_addr.s_addr, &Netgame.server_addr, 4);
2695  char *server_addr = inet_ntoa(temp_addr);
2696  ml_printf(NOX("Starting netgame as Host on Standalone server : %s"), (server_addr == NULL) ? NOX("Unknown") : server_addr);
2697  }
2698 
2700 
2701  Multi_sg_netgame->security = (rand() % 32766) + 1; // get some random security number
2702  Multi_sg_netgame->mode = NG_MODE_OPEN;
2703  Multi_sg_netgame->rank_base = RANK_ENSIGN;
2704  if(Multi_sg_netgame->security < 16){
2705  Multi_sg_netgame->security += 16;
2706  }
2707 
2708  // set the version_info field
2709  Multi_sg_netgame->version_info = NG_VERSION_ID;
2710 
2713  }
2714 
2715  // set the default netgame flags
2716  Multi_sg_netgame->flags = 0;
2717 
2718  // intialize endgame stuff
2720 
2721  // load in my netgame options
2723 
2724  // load my local netplayer options
2726 
2727  // setup the default game name, taking care of string length and player callsigns
2728  memset(out_name,0,128);
2729  memset(buf,0,128);
2731  sprintf(buf, XSTR("%s game",782), out_name); // [[ %s will be a pilot's name ]]
2732  if ( strlen(buf) > MAX_GAMENAME_LEN ){
2733  strcpy_s(buf, XSTR("Temporary name",783));
2734  }
2735  strcpy_s(Multi_sg_netgame->name, buf);
2736 
2737  // set the default qos and duration
2739 
2740  // make sure to set the server correctly (me or the standalone)
2742  memcpy(&Netgame.server_addr, &Psnet_my_addr,sizeof(net_addr));
2745 
2746  // setup debug flags
2747  Netgame.debug_flags = 0;
2748  } else {
2749  memcpy(&Netgame.server_addr,&save,sizeof(net_addr));
2750  Netgame.server = server_save;
2751  }
2752 
2753  // if I have a cd or not
2754  if(Multi_has_cd){
2756  }
2757 
2758  // if I have hacked data
2759  if(game_hacked_data()){
2761  }
2762 
2763  // assign my player struct and other data
2766 
2767  // if we're supposed to flush our cache directory, do so now
2770 
2771  // NETLOG
2772  ml_string(NOX("Flushing multi-data cache"));
2773  }
2774 
2775  game_flush();
2776 }
2777 
2779 {
2780  // draw the appropriate radio button
2781  switch(Multi_sg_netgame->mode){
2782  case NG_MODE_OPEN:
2783  Multi_sg_buttons[gr_screen.res][MSG_OPEN_GAME].button.draw_forced(2);
2784  break;
2785 /*
2786  case NG_MODE_CLOSED:
2787  Multi_sg_buttons[gr_screen.res][MSG_CLOSED_GAME].button.draw_forced(2);
2788  break;
2789 */
2790  case NG_MODE_PASSWORD:
2791  Multi_sg_buttons[gr_screen.res][MSG_PASSWD_GAME].button.draw_forced(2);
2792  break;
2793 /*
2794  case NG_MODE_RESTRICTED:
2795  Multi_sg_buttons[gr_screen.res][MSG_RESTRICTED_GAME].button.draw_forced(2);
2796  break;
2797 */
2798  case NG_MODE_RANK_ABOVE:
2799  Multi_sg_buttons[gr_screen.res][MSG_RANK_SET_GAME].button.draw_forced(2);
2800  Multi_sg_buttons[gr_screen.res][MSG_RANK_ABOVE].button.draw_forced(2);
2801  break;
2802  case NG_MODE_RANK_BELOW:
2803  Multi_sg_buttons[gr_screen.res][MSG_RANK_SET_GAME].button.draw_forced(2);
2804  Multi_sg_buttons[gr_screen.res][MSG_RANK_BELOW].button.draw_forced(2);
2805  break;
2806  }
2807 }
2808 
2810 {
2811  // if he doesn't have either of the rank flags set, then ignore this
2812  if((Multi_sg_netgame->mode != NG_MODE_RANK_ABOVE) && (Multi_sg_netgame->mode != NG_MODE_RANK_BELOW)){
2813  return;
2814  }
2815 
2816  if(Multi_sg_rank_start > 0){
2817  Multi_sg_rank_start--;
2819  } else {
2821  }
2822 }
2823 
2825 {
2826  // if he doesn't have either of the rank flags set, then ignore this
2827  if((Multi_sg_netgame->mode != NG_MODE_RANK_ABOVE) && (Multi_sg_netgame->mode != NG_MODE_RANK_BELOW)){
2828  return;
2829  }
2830 
2831  if((NUM_RANKS - Multi_sg_rank_start) > Multi_sg_rank_max_display[gr_screen.res]){
2832  Multi_sg_rank_start++;
2834  } else {
2836  }
2837 }
2838 
2840 {
2841  int y,line_height,idx,count;
2842  char rank_name[40];
2843 
2844  // if he doesn't have either of the rank flags set, then ignore this
2845  if((Multi_sg_netgame->mode != NG_MODE_RANK_ABOVE) && (Multi_sg_netgame->mode != NG_MODE_RANK_BELOW)){
2846  return;
2847  }
2848 
2849  // display the list of ranks
2850  y = Msg_rank_list_coords[gr_screen.res][MSG_Y_COORD];
2851  line_height = gr_get_font_height() + 1;
2852  idx = Multi_sg_rank_start;
2853  count = 0;
2854  while((count < NUM_RANKS) && (count < Multi_sg_rank_max_display[gr_screen.res]) && (idx < NUM_RANKS)){
2855  // if its the selected item, then color it differently
2856  if(idx == Multi_sg_rank_select){
2858  } else {
2860  }
2861 
2862  // print the text
2863  multi_sg_rank_build_name(Ranks[idx].name,rank_name);
2864  gr_string(Msg_rank_list_coords[gr_screen.res][MSG_X_COORD],y,rank_name,GR_RESIZE_MENU);
2865 
2866  // increment stuff
2867  y+=line_height;
2868  idx++;
2869  count++;
2870  }
2871 
2872  // display the selected rank
2873 
2875  multi_sg_rank_build_name(Ranks[Multi_sg_netgame->rank_base].name,rank_name);
2876  gr_string(Msg_rank_sel_coords[gr_screen.res][MSG_X_COORD],Msg_rank_sel_coords[gr_screen.res][MSG_Y_COORD],rank_name,GR_RESIZE_MENU);
2877 
2878 }
2879 
2881 {
2882  char string[255];
2883 
2884  // if he doesn't have either of the rank flags set, then ignore this
2885  if((Multi_sg_netgame->mode != NG_MODE_RANK_ABOVE) && (Multi_sg_netgame->mode != NG_MODE_RANK_BELOW)){
2886  return;
2887  }
2888 
2889  // see if he's clicked on an item on the rank list
2890  if(Multi_sg_rank_button.pressed()){
2891  int y,item;
2892  Multi_sg_rank_button.get_mouse_pos(NULL,&y);
2893  item = y / (gr_get_font_height() + 1);
2894 
2895  if(item + Multi_sg_rank_start < NUM_RANKS){
2896  // evaluate whether this rank is valid for the guy to pick
2897  if(multi_sg_rank_select_valid(item + Multi_sg_rank_start)){
2899 
2900  Multi_sg_rank_select = item + Multi_sg_rank_start;
2901 
2902  // set the Netgame rank
2903  Multi_sg_netgame->rank_base = Multi_sg_rank_select;
2904  } else {
2906 
2907  memset(string,0,255);
2908  sprintf(string,XSTR("Illegal value for a host of your rank (%s)\n",784),Ranks[Net_player->m_player->stats.rank].name);
2909  multi_common_add_notify(string);
2910  }
2911  }
2912  }
2913 }
2914 
2915 void multi_sg_rank_build_name(char *in,char *out)
2916 {
2917  char use[100];
2918  char *first;
2919 
2920  strcpy_s(use,in);
2921  first = strtok(use," ");
2922 
2923  // just copy the string
2924  if(first == NULL){
2925  strcpy(out,in);
2926  }
2927 
2928  // if the first part of the string is lieutenant, then abbreivate it and tack on the rest of the string
2929  if (stricmp(first,XSTR("lieutenant",785)) == 0) {
2930  first = strtok(NULL, NOX("\n"));
2931 
2932  // if he's not just a plain lieutenant
2933  if(first != NULL){
2934  strcpy(out,XSTR("Lt. ",786)); // [[ lieutenant ]]
2935  strcat(out,first);
2936  }
2937  // if he _is_ just a plain lieutenant
2938  else {
2939  strcpy(out,in);
2940  }
2941  } else {
2942  strcpy(out,in);
2943  }
2944 }
2945 
2947 {
2948  // check to see if the password input box has been pressed
2949  if(Multi_sg_game_passwd.changed()){
2950  Multi_sg_game_passwd.get_text(Multi_sg_netgame->passwd);
2951  }
2952 }
2953 
2955 {
2956  // check to see if the game name input box has been pressed
2957  if(Multi_sg_game_name.changed()){
2958  Multi_sg_game_name.get_text(Multi_sg_netgame->name);
2959  }
2960 }
2961 
2963 {
2964  // hide and disable the password input box
2965  Multi_sg_game_passwd.hide();
2966  Multi_sg_game_passwd.disable();
2967 
2968  // set the focus back to the name input box
2969  Multi_sg_game_name.set_focus();
2970 }
2971 
2973 {
2974  // rank above mode
2975  if(Multi_sg_netgame->mode == NG_MODE_RANK_ABOVE){
2976  if(Net_player->m_player->stats.rank >= rank){
2977  return 1;
2978  }
2979  }
2980  // rank below mode
2981  else {
2982  if(Net_player->m_player->stats.rank <= rank){
2983  return 1;
2984  }
2985  }
2986 
2987  return 0;
2988 }
2989 
2991 {
2992  // pick our rank for now
2993  Multi_sg_rank_select = Net_player->m_player->stats.rank;
2994 
2995  // set the Netgame rank
2996  Multi_sg_netgame->rank_base = Multi_sg_rank_select;
2997 }
2998 
2999 // -------------------------------------------------------------------------------------------------
3000 //
3001 // MULTIPLAYER CREATE GAME screen
3002 //
3003 
3004 //XSTR:OFF
3005 // bitmaps defs
3007  "MultiCreate", // GR_640
3008  "2_MultiCreate" // GR_1024
3009 };
3010 
3012  "MultiCreate-M", // GR_640
3013  "2_MultiCreate-M" // GR_1024
3014 };
3015 
3017  "PleaseWait", // GR_640
3018  "2_PleaseWait" // GR_1024
3019 };
3020 //XSTR:ON
3021 
3022 #define MULTI_CREATE_NUM_BUTTONS 23
3023 
3024 // button defs
3025 #define MC_SHOW_ALL 0
3026 #define MC_SHOW_COOP 1
3027 #define MC_SHOW_TEAM 2
3028 #define MC_SHOW_DOGFIGHT 3
3029 #define MC_PXO_REFRESH 4
3030 #define MC_PILOT_INFO 5
3031 #define MC_SCROLL_LIST_UP 6
3032 #define MC_SCROLL_LIST_DOWN 7
3033 #define MC_SCROLL_PLAYERS_UP 8
3034 #define MC_SCROLL_PLAYERS_DOWN 9
3035 #define MC_MISSION_FILTER 10
3036 #define MC_CAMPAIGN_FILTER 11
3037 #define MC_CANCEL 12
3038 #define MC_TEAM0 13
3039 #define MC_TEAM1 14
3040 #define MC_KICK 15
3041 #define MC_CLOSE 16
3042 #define MC_SCROLL_INFO_UP 17
3043 #define MC_SCROLL_INFO_DOWN 18
3044 #define MC_HOST_OPTIONS 19
3045 #define MC_HELP 20
3046 #define MC_OPTIONS 21
3047 #define MC_ACCEPT 22
3048 
3049 
3050 UI_WINDOW Multi_create_window; // the window object for the create screen
3052 UI_BUTTON Multi_create_list_select_button; // for selecting missions/campaigns
3053 int Multi_create_bitmap = -1; // the background bitmap
3054 UI_SLIDER2 Multi_create_slider; // for create list
3055 
3056 // constants for coordinate look ups
3057 #define MC_X_COORD 0
3058 #define MC_Y_COORD 1
3059 #define MC_W_COORD 2
3060 #define MC_H_COORD 3
3061 
3063  { // GR_640
3064  ui_button_info("MC_00", 32, 129, 36, 158, 0), // show all missions
3065  ui_button_info("MC_01", 76, 129, 71, 158, 1), // show coop missions
3066  ui_button_info("MC_02", 121, 129, 119, 158, 2), // show team missions
3067  ui_button_info("MC_03", 164, 129, 166, 158, 3), // show dogfight missions
3068  ui_button_info("MC_04", 399, 129, 229, 130, 4), // pxo mission refresh
3069  ui_button_info("MC_05", 567, 123, 467, 132, 5), // pilot info
3070  ui_button_info("MC_06", 1, 161, -1, -1, 6), // scroll mission info up
3071  ui_button_info("MC_08", 1, 304, -1, -1, 8), // scroll mission info down
3072  ui_button_info("MC_09", 613, 160, -1, -1, 9), // scroll players up
3073  ui_button_info("MC_10", 613, 202, -1, -1, 10), // scroll players down
3074  ui_button_info("MC_11", 22, 346, 27, 376, 11), // mission filter
3075  ui_button_info("MC_12", 104, 346, 110, 376, 12), // campaign filter
3076  ui_button_info("MC_13", 392, 341, 328, 364, 13), // cancel
3077  ui_button_info("MC_14", 472, 352, 482, 381, 14), // team 0
3078  ui_button_info("MC_15", 506, 352, 514, 381, 15), // team 1
3079  ui_button_info("MC_16", 539, 346, 539, 381, 16), // kick
3080  ui_button_info("MC_17", 589, 346, 582, 381, 17), // close
3081  ui_button_info("MC_18", 1, 406, -1, -1, 18), // scroll list up
3082  ui_button_info("MC_19", 1, 447, -1, -1, 19), // scroll list down
3083  ui_button_info("MC_20", 499, 434, 436, 423, 20), // host options
3084  ui_button_info("MC_21", 534, 426, -1, -1, 21), // help
3085  ui_button_info("MC_22", 534, 452, -1, -1, 22), // options
3086  ui_button_info("MC_23", 571, 426, 572, 413, 23), // commit
3087  },
3088  { // GR_1024
3089  ui_button_info("2_MC_00", 51, 207, 61, 253, 0), // show all missions
3090  ui_button_info("2_MC_01", 122, 207, 124, 253, 1), // show coop missions
3091  ui_button_info("2_MC_02", 193, 207, 194, 253, 2), // show team missions
3092  ui_button_info("2_MC_03", 263, 207, 261, 253, 3), // show dogfight missions
3093  ui_button_info("2_MC_04", 639, 207, 479, 218, 4), // pxo mission refresh
3094  ui_button_info("2_MC_05", 907, 197, 748, 216, 5), // pilot info
3095  ui_button_info("2_MC_06", 1, 258, -1, -1, 6), // scroll mission info up
3096  ui_button_info("2_MC_08", 1, 487, -1, -1, 8), // scroll mission info down
3097  ui_button_info("2_MC_09", 981, 256, -1, -1, 9), // scroll players up
3098  ui_button_info("2_MC_10", 981, 323, -1, -1, 10), // scroll players down
3099  ui_button_info("2_MC_11", 35, 554, 46, 601, 11), // mission filter
3100  ui_button_info("2_MC_12", 166, 554, 174, 601, 12), // campaign filter
3101  ui_button_info("2_MC_13", 628, 545, 559, 582, 13), // cancel
3102  ui_button_info("2_MC_14", 756, 564, 772, 610, 14), // team 0
3103  ui_button_info("2_MC_15", 810, 564, 826, 610, 15), // team 1
3104  ui_button_info("2_MC_16", 862, 554, 872, 610, 16), // kick
3105  ui_button_info("2_MC_17", 943, 554, 949, 610, 17), // close
3106  ui_button_info("2_MC_18", 1, 649, -1, -1, 18), // scroll list up
3107  ui_button_info("2_MC_19", 1, 716, -1, -1, 19), // scroll list down
3108  ui_button_info("2_MC_20", 798, 695, 726, 667, 20), // host options
3109  ui_button_info("2_MC_21", 854, 681, -1, -1, 21), // help
3110  ui_button_info("2_MC_22", 854, 724, -1, -1, 22), // options
3111  ui_button_info("2_MC_23", 914, 681, 932, 667, 23), // commit
3112  },
3113 };
3114 
3115 #define MULTI_CREATE_NUM_TEXT 15
3117  { // GR_640
3118  {"All", 1256, 36, 158, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_SHOW_ALL].button},
3119  {"Coop", 1257, 71, 158, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_SHOW_COOP].button},
3120  {"Team", 1258, 119, 158, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_SHOW_TEAM].button},
3121  {"Dogfight", 1259, 166, 158, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_SHOW_DOGFIGHT].button},
3122  {"Refresh Missions", 1260, 229, 130, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_PXO_REFRESH].button},
3123  {"Pilot Info", 1261, 467, 132, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_PILOT_INFO].button},
3124  {"Missions", 1262, 27, 376, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_MISSION_FILTER].button},
3125  {"Campaigns", 1263, 110, 376, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_CAMPAIGN_FILTER].button},
3126  {"Cancel", 387, 328, 364, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[0][MC_CANCEL].button},
3127  {"1", 1264, 482, 381, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_TEAM0].button},
3128  {"2", 1265, 514, 381, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_TEAM1].button},
3129  {"Kick", 1266, 539, 381, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[0][MC_KICK].button},
3130  {"Close", 1508, 582, 381, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[0][MC_CLOSE].button},
3131  {"Host Options", 1267, 436, 423, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[0][MC_HOST_OPTIONS].button},
3132  {"Commit", 1062, 572, 413, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[0][MC_ACCEPT].button}
3133  },
3134  { // GR_1024
3135  {"All", 1256, 61, 253, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_SHOW_ALL].button},
3136  {"Coop", 1257, 124, 253, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_SHOW_COOP].button},
3137  {"Team", 1258, 194, 253, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_SHOW_TEAM].button},
3138  {"Dogfight", 1259, 261, 253, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_SHOW_DOGFIGHT].button},
3139  {"Refresh Missions", 1260, 501, 218, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_PXO_REFRESH].button},
3140  {"Pilot Info", 1261, 814, 216, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_PILOT_INFO].button},
3141  {"Missions", 1262, 46, 601, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_MISSION_FILTER].button},
3142  {"Campaigns", 1263, 174, 601, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_CAMPAIGN_FILTER].button},
3143  {"Cancel", 387, 559, 582, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[1][MC_CANCEL].button},
3144  {"1", 1264, 772, 610, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_TEAM0].button},
3145  {"2", 1265, 826, 610, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_TEAM1].button},
3146  {"Kick", 1266, 872, 610, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[1][MC_KICK].button},
3147  {"Close", 1508, 949, 610, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[1][MC_CLOSE].button},
3148  {"Host Options", 1267, 755, 683, UI_XSTR_COLOR_GREEN, -1, &Multi_create_buttons[1][MC_HOST_OPTIONS].button},
3149  {"Commit", 1062, 932, 667, UI_XSTR_COLOR_PINK, -1, &Multi_create_buttons[1][MC_ACCEPT].button}
3150  },
3151 };
3152 
3153 // squad war checkbox
3156  "MC_SW_00",
3157  "MC_SW_00",
3158 };
3160  { // GR_640
3161  6, 75
3162  },
3163  { // GR_1024
3164  18, 135
3165  }
3166 };
3168  { // GR_640
3169  6, 95
3170  },
3171  { // GR_640
3172  18, 155
3173  },
3174 };
3175 
3176 // game information text areas
3178  { // GR_640
3179  105, 173, 311, 152
3180  },
3181  { // GR_1024
3182  62, 275, 600, 262
3183  }
3184 };
3185 
3187  { // GR_640
3188  463, 164, 144, 180
3189  },
3190  { // GR_1024
3191  741, 262, 144, 180
3192  }
3193 };
3194 
3196  { // GR_640
3197  47, 405, 363, 59
3198  },
3199  { // GR_1024
3200  75, 648, 363, 59
3201  }
3202 };
3203 
3204 // mission icon stuff
3206  { // GR_640
3207  38, -2 // y is an offset
3208  },
3209  { // GR_1024
3210  61, -2 // y is an offset
3211  }
3212 };
3213 
3215  { // GR_640
3216  61, -1 // y is an offset
3217  },
3218  { // GR_1024
3219  98, 1 // y is an offset
3220  }
3221 };
3222 
3224  { // GR_640
3225  72, 0 // y is an offset
3226  },
3227  { // GR_1024
3228  115, 0 // y is an offset
3229  }
3230 };
3231 
3233  { // GR_640
3234  91, 0 // y is an offset
3235  },
3236  { // GR_1024
3237  146, 0 // y is an offset
3238  }
3239 };
3240 
3241 // mission/campaign list column areas
3243  194, // GR_640
3244  310 // GR_1024
3245 };
3246 
3248  38, // GR_640
3249  61 // GR_1024
3250 };
3251 
3253  77, // GR_640
3254  123 // GR_1024
3255 };
3256 
3258  105, // GR_640
3259  168 // GR_1024
3260 };
3261 
3263  314, // GR_640
3264  502 // GR_1024
3265 };
3266 
3268  337, // GR_640
3269  539 // GR_1024
3270 };
3271 
3273  {13, 116}, // GR_640
3274  {21, 186} // GR_1024
3275 };
3276 
3278  {467, 150}, // GR_640
3279  {747, 240} // GR_1024
3280 };
3281 
3283  {484, 342}, // GR_640
3284  {774, 547} // GR_1024
3285 };
3286 
3288  {
3289  3, 197, 13, 105 // GR_640
3290  },
3291  {
3292  5, 316, 20, 168 // GR_1024
3293  }
3294 };
3295 
3297  "slider",
3298  "2_slider"
3299 };
3300 
3301 // player list control thingie defs
3302 #define MULTI_CREATE_PLIST_MAX_DISPLAY 20
3303 int Multi_create_plist_select_flag; // flag indicating if we have a play selected
3304 short Multi_create_plist_select_id; // the net address of the currently selected player (for lookup)
3305 
3306 // master tracker details
3307 int Multi_create_frame_count; // framecount
3308 int Multi_create_mt_tried_login; // attempted to login this server on the MT
3309 
3310 // mission filter settings
3311 int Multi_create_filter; // what mode we're in
3312 
3313 // game/campaign list control defs
3315  15, // GR_640
3316  26 // GR_1024
3317 };
3318 
3319 
3321 int Multi_create_list_mode; // 0 == mission mode, 1 == campaign mode
3322 int Multi_create_list_start; // where to start displaying from
3323 int Multi_create_list_select; // which item is currently highlighted
3325 
3328 
3330 
3331 // LOCAL function definitions
3333 void multi_create_button_pressed(int n);
3344 void multi_create_list_do();
3346 void multi_create_list_blit_icons(int list_index, int y_start);
3355 
3356 // since we can selectively filter out mission/campaign types we always need to map a selected index (which is relative
3357 // to the displayed list), to an absolute index (which is relative to the total file list - some of which may filtered out)
3358 void multi_create_select_to_filename(int select_index,char *filename);
3359 int multi_create_select_to_index(int select_index);
3360 
3362 
3363 bool Multi_create_sort_mode = false; // default to mission name sorting, "true" is mission filename sorting
3364 
3365 
3366 // sorting function to sort mission lists.. Basic sorting on mission name
3368 {
3369  if (Multi_create_filter != MISSION_TYPE_MULTI) {
3370  if ( (m1.flags & Multi_create_filter) && !(m2.flags & Multi_create_filter) ) {
3371  return false;
3372  } else if ( (m2.flags & Multi_create_filter) && !(m1.flags & Multi_create_filter) ) {
3373  return true;
3374  }
3375  }
3376 
3377  int test = 0;
3378 
3379  if (Multi_create_sort_mode) {
3380  test = stricmp(m1.filename, m2.filename);
3381  } else {
3382  test = stricmp(m1.name, m2.name);
3383  }
3384 
3385  if (test < 0) {
3386  return true;
3387  } else if (test > 0) {
3388  return false;
3389  } else {
3390  return true;
3391  }
3392 }
3393 
3395 {
3396  bool sort_missions = false;
3397  bool sort_campaigns = false;
3398  char selected_name[255];
3399  int new_index = -1;
3400 
3401  if (Multi_create_list_count < 0) {
3402  return;
3403  }
3404 
3405  switch (mode) {
3407  sort_missions = true;
3408  break;
3409 
3411  sort_campaigns = true;
3412  break;
3413 
3414  default:
3415  sort_missions = true;
3416  sort_campaigns = true;
3417  break;
3418  }
3419 
3420  // save our current selected item so that we can restore that one after sorting
3421  multi_create_select_to_filename(Multi_create_list_select, selected_name);
3422 
3423  if (sort_missions) {
3424  std::sort( Multi_create_mission_list.begin(), Multi_create_mission_list.end(), multi_create_sort_func);
3425 
3426  for (size_t idx = 0; idx < Multi_create_mission_list.size(); idx++) {
3427  if ( !strcmp(selected_name, Multi_create_mission_list[idx].filename) ) {
3428  new_index = (int)idx;
3429  break;
3430  }
3431  }
3432  }
3433 
3434  if (sort_campaigns) {
3435  std::sort( Multi_create_campaign_list.begin(), Multi_create_campaign_list.end(), multi_create_sort_func);
3436 
3437  for (size_t idx = 0; idx < Multi_create_campaign_list.size(); idx++) {
3438  if ( !strcmp(selected_name, Multi_create_campaign_list[idx].filename) ) {
3439  new_index = (int)idx;
3440  break;
3441  }
3442  }
3443  }
3444 
3445  multi_create_list_select_item(new_index);
3446 }
3447 
3449 {
3450  int idx,should_sort,switched_modes;
3451 
3452  // set the current mode
3453  should_sort = 0;
3454  switched_modes = 0;
3455  if ( (Multi_create_list_mode != mode) && (mode != -1) ) {
3456  Multi_create_list_mode = mode;
3457  switched_modes = 1;
3458  } else if (mode == -1) {
3459  switched_modes = 1;
3460  }
3461 
3462  // get the mission count based upon the filter selected
3463  if(Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS){
3464  switch (Multi_create_filter) {
3465  case MISSION_TYPE_MULTI:
3466  Multi_create_list_count = (int)Multi_create_mission_list.size();
3467 
3468  // if we switched modes and we have more than 0 items, sort them
3469  if (switched_modes && (Multi_create_list_count > 0)){
3470  should_sort = 1;
3471  }
3472  break;
3473 
3474  default :
3475  Multi_create_list_count = 0;
3476 
3477  // find all missions which match
3478  for (idx = 0; idx < (int)Multi_create_mission_list.size(); idx++) {
3479  if(Multi_create_mission_list[idx].flags & Multi_create_filter){
3480  Multi_create_list_count++;
3481  }
3482  }
3483 
3484  // if we switched modes and we have more than 0 items, sort them
3485  if (switched_modes && (Multi_create_list_count > 0)){
3486  should_sort = 1;
3487  }
3488 
3489  break;
3490  }
3491  } else if(Multi_create_list_mode == MULTI_CREATE_SHOW_CAMPAIGNS){
3492  switch (Multi_create_filter) {
3493  case MISSION_TYPE_MULTI:
3494  Multi_create_list_count = (int)Multi_create_campaign_list.size();
3495 
3496  // if we switched modes and we have more than 0 items, sort them
3497  if (switched_modes && (Multi_create_list_count > 0)){
3498  should_sort = 1;
3499  }
3500  break;
3501 
3502  default :
3503  Multi_create_list_count = 0;
3504 
3505  // find all missions which match
3506  for (idx = 0; idx < (int)Multi_create_campaign_list.size(); idx++) {
3507  if(Multi_create_campaign_list[idx].flags & Multi_create_filter){
3508  Multi_create_list_count++;
3509  }
3510  }
3511 
3512  // if we switched modes and we have more than 0 items, sort them
3513  if(switched_modes && (Multi_create_list_count > 0)){
3514  should_sort = 1;
3515  }
3516  break;
3517  }
3518  }
3519 
3520  // reset the list start and selected indices
3521  Multi_create_list_start = 0;
3522  Multi_create_list_select = -1;
3523  multi_create_list_select_item(Multi_create_list_start);
3524 
3525  // sort the list of missions if necessary
3526  if (should_sort) {
3527  multi_create_list_sort(mode);
3528  }
3529 
3530  // reset the slider
3531  Multi_create_slider.set_numberItems(Multi_create_list_count > Multi_create_list_max_display[gr_screen.res] ? Multi_create_list_count-Multi_create_list_max_display[gr_screen.res] : 0);
3532 }
3533 
3535 {
3536  int idx;
3537  ui_button_info *b;
3538 
3539  // now make sure to initialze various netgame stuff based upon whether we're on a standalone or not
3542  } else {
3544  }
3545 
3546  // initialize the player list data
3547  Multi_create_plist_select_flag = 0;
3548  Multi_create_plist_select_id = -1;
3549 
3550  // create the interface window
3551  Multi_create_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
3552  Multi_create_window.set_mask_bmap(Multi_create_bitmap_mask_fname[gr_screen.res]);
3553 
3554  // load the background bitmap
3555  Multi_create_bitmap = bm_load(Multi_create_bitmap_fname[gr_screen.res]);
3556  if(Multi_create_bitmap < 0){
3557  // we failed to load the bitmap - this is very bad
3558  Int3();
3559  }
3560 
3561  // close any previous existing instances of the chatbox and create a new one
3562  chatbox_close();
3563  chatbox_create();
3564 
3565  // load the help overlay
3566  Multi_create_overlay_id = help_overlay_get_index(MULTI_CREATE_OVERLAY);
3567  help_overlay_set_state(Multi_create_overlay_id, gr_screen.res, 0);
3568 
3569  // initialize the common notification messaging
3571 
3572  // use the common interface palette
3574 
3575  // create the interface buttons
3576  for(idx=0; idx<MULTI_CREATE_NUM_BUTTONS; idx++){
3577  b = &Multi_create_buttons[gr_screen.res][idx];
3578 
3579  // create the object
3580  b->button.create(&Multi_create_window, "", b->x, b->y, 1, 1, ((idx == MC_SCROLL_LIST_UP) || (idx == MC_SCROLL_LIST_DOWN)), 1);
3581 
3582  // set the sound to play when highlighted
3584 
3585  // set the ani for the button
3586  b->button.set_bmaps(b->filename);
3587 
3588  // set the hotspot
3589  b->button.link_hotspot(b->hotspot);
3590 
3591  // some special case stuff for the pxo refresh button
3592  if(idx == MC_PXO_REFRESH){
3593  // if not a PXO game, or if I'm not a server disable and hide the button
3595  b->button.hide();
3596  b->button.disable();
3597  }
3598  }
3599  }
3600 
3601  // create xstrs
3602  for(idx=0; idx<MULTI_CREATE_NUM_TEXT; idx++){
3603  Multi_create_window.add_XSTR(&Multi_create_text[gr_screen.res][idx]);
3604  }
3605 
3606  // if this is a PXO game, enable the squadwar checkbox
3607  Multi_create_sw_checkbox.create(&Multi_create_window, "", Multi_create_sw_checkbox_coords[gr_screen.res][0], Multi_create_sw_checkbox_coords[gr_screen.res][1], 0);
3608  Multi_create_sw_checkbox.set_bmaps(Multi_create_sw_checkbox_fname[gr_screen.res], 6, 0);
3609  if(!MULTI_IS_TRACKER_GAME){
3610  Multi_create_sw_checkbox.hide();
3611  Multi_create_sw_checkbox.disable();
3612  }
3613 
3614  // initialize the mission type filtering mode
3615  Multi_create_filter = MISSION_TYPE_MULTI;
3616 
3617  // initialize the list mode, and load in a list
3618  Multi_create_mission_list.clear();
3619  Multi_create_campaign_list.clear();
3620 
3621  Multi_create_list_mode = MULTI_CREATE_SHOW_MISSIONS;
3622  Multi_create_list_start = -1;
3623  Multi_create_list_select = -1;
3624  Multi_create_list_count = 0;
3625 
3626  Multi_create_slider.create(&Multi_create_window, Mc_slider_coords[gr_screen.res][MC_X_COORD], Mc_slider_coords[gr_screen.res][MC_Y_COORD], Mc_slider_coords[gr_screen.res][MC_W_COORD],Mc_slider_coords[gr_screen.res][MC_H_COORD], -1, Mc_slider_bitmap[gr_screen.res], &multi_create_list_scroll_up, &multi_create_list_scroll_down, NULL);
3627 
3628  // create the player list select button
3629  Multi_create_player_select_button.create(&Multi_create_window, "", Mc_players_coords[gr_screen.res][MC_X_COORD], Mc_players_coords[gr_screen.res][MC_Y_COORD], Mc_players_coords[gr_screen.res][MC_W_COORD], Mc_players_coords[gr_screen.res][MC_H_COORD], 0, 1);
3630  Multi_create_player_select_button.hide();
3631 
3632  // create the mission/campaign list select button
3633  Multi_create_list_select_button.create(&Multi_create_window, "", Mc_list_coords[gr_screen.res][MC_X_COORD], Mc_list_coords[gr_screen.res][MC_Y_COORD], Mc_list_coords[gr_screen.res][MC_W_COORD], Mc_list_coords[gr_screen.res][MC_H_COORD], 0, 1);
3634  Multi_create_list_select_button.hide();
3635 
3636  // set hotkeys for a couple of things.
3637  Multi_create_buttons[gr_screen.res][MC_ACCEPT].button.set_hotkey(KEY_CTRLED+KEY_ENTER);
3638 
3639  // init some master tracker stuff
3640  Multi_create_frame_count = 0;
3641  Multi_create_mt_tried_login = 0;
3642 
3643  // remove campaign flags
3645 
3646  // send any pilots as appropriate
3648 
3649  Multi_create_files_loaded = 0;
3650 }
3651 
3653 {
3654  //DTP CHECK ALMISSION FLAG HERE AND SKIP THE BITMAP LOADING PROGRESS
3655  //SINCE WE ALREADY HAVE A MISSION SELECTED IF THIS MISSION IS A VALID MULTIPLAYER MISSION
3656  //IF NOT A VALID MULTIPLAYER MISSION CONTINUE LOADING, MAYBE CALL POPUP.
3658  multi_create_list_do(); //uhm here because off, hehe, my mind is failing right now
3659 
3660  // DTP Var section for the is mission multi player Check.
3661 
3662  char mission_name[NAME_LENGTH+1];
3663  int flags;
3664  char *filename;
3665  filename = cf_add_ext( Cmdline_almission, FS_MISSION_FILE_EXT ); //DTP ADD EXTENSION needed next line
3666  flags = mission_parse_is_multi(filename, mission_name); //DTP flags will set if mission is multi
3667 
3668  if (flags) { //only continue if mission is multiplayer mission
3669  netgame_info *ng;
3670  ng = &Netgame;
3671 
3672  char almissionname[256]; // needed, for the strncpy below
3673  strncpy(almissionname, Cmdline_almission,MAX_FILENAME_LEN); //DTP; copying name from cmd_almission line
3674 
3675  Netgame.options.respawn = 99; //override anything //for debugging, i often forget this.
3677 
3678  Netgame.campaign_mode = MP_SINGLE_MISSION; //multiplayer single mission. meaning Single mission, not single player
3679 
3680  strcpy_s(Game_current_mission_filename,almissionname); // copying almissionname to Game_current_mission_filename
3681  strcpy_s(Netgame.mission_name,almissionname);// copying almission name to netgame.mission_name
3682 
3683  Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING; //DTP must be set before a call to gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC) is done as it is below.
3685 
3686  Cmdline_almission = NULL; // we don't want to autoload anymore do we, we will be able to quit. halleluja. Startgame has already been disabled, so no need to turn of "Cmdline_start_netgame"
3687  return; // we don't need to check or set regarding ships/weapons anything as we are already progressing into mission so return
3688  }
3689  else {
3690  popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR(" Not a multi player-mission",9999)); //DTP startgame popup pilot error
3692  Cmdline_almission = NULL; //DTP make sure this gets nullified.
3693 
3694  }
3695  }
3696 
3697  int player_index;
3698  const char *loading_str = XSTR("Loading", 1336);
3699  int str_w, str_h;
3700 
3701  // set this if we want to show the pilot info popup
3702  Multi_create_should_show_popup = 0;
3703 
3704  // first thing is to load the files
3705  if ( !Multi_create_files_loaded ) {
3706  // if I am a client, send a list request to the server for the missions
3707  if ( MULTIPLAYER_CLIENT ) {
3709  } else {
3710  int loading_bitmap;
3711 
3712  loading_bitmap = bm_load(Multi_create_loading_fname[gr_screen.res]);
3713 
3714  // draw the background, etc
3715  gr_reset_clip();
3716  GR_MAYBE_CLEAR_RES(Multi_create_bitmap);
3717  if(Multi_create_bitmap != -1){
3718  gr_set_bitmap(Multi_create_bitmap);
3719  gr_bitmap(0, 0, GR_RESIZE_MENU);
3720  }
3721  chatbox_render();
3722  if ( loading_bitmap > -1 ){
3723  gr_set_bitmap(loading_bitmap);
3724  }
3726 
3727  // draw "Loading" on it
3729  gr_set_font(FONT2);
3730  gr_get_string_size(&str_w, &str_h, loading_str);
3731  gr_string((gr_screen.max_w_unscaled - str_w) / 2, (gr_screen.max_h_unscaled - str_h) / 2, loading_str, GR_RESIZE_MENU);
3732  gr_set_font(FONT1);
3733 
3734  gr_flip();
3735 
3738 
3739  // if this is a tracker game, validate missions
3740  if (MULTI_IS_TRACKER_GAME) {
3743  }
3744 
3745  // update the file list
3747  // the above function doesn't sort initially, so we need this to take care of it
3749  // the sort function probably changed our selection, but here we always need it to zero
3751  }
3752 
3753  // don't bother setting netgame state if ont the server
3757 
3758  // tell FS2NetD about our game as well
3759  if (MULTI_IS_TRACKER_GAME) {
3761  }
3762  }
3763 
3764  // if we're on the standalone we have to tell him that we're now in the host setup screen
3767 
3768  Multi_create_files_loaded = 1;
3769  }
3770 
3771  int k = chatbox_process();
3772  k = Multi_create_window.process(k,0);
3773 
3774  switch(k){
3775  // same as the cancel button
3776  case KEY_ESC: {
3777  if ( help_overlay_active(Multi_create_overlay_id) ) {
3778  help_overlay_set_state(Multi_create_overlay_id, gr_screen.res, 0);
3779  } else {
3782  }
3783 
3784  break;
3785  }
3786 
3787  case KEY_CTRLED | KEY_SHIFTED | KEY_S:
3788  Multi_create_sort_mode = !Multi_create_sort_mode;
3789  multi_create_list_sort(Multi_create_list_mode);
3790  break;
3791  }
3792 
3793  if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
3794  help_overlay_set_state(Multi_create_overlay_id, gr_screen.res, 0);
3795  }
3796 
3797  // process any button clicks
3799 
3800  // do any network related stuff
3802 
3803  // draw the background, etc
3804  gr_reset_clip();
3805  GR_MAYBE_CLEAR_RES(Multi_create_bitmap);
3806  if(Multi_create_bitmap != -1){
3807  gr_set_bitmap(Multi_create_bitmap);
3809  }
3810 
3811  // if we're not in team vs. team mode, don't draw the team buttons
3812  if(!(Netgame.type_flags & NG_TYPE_TEAM)){
3813  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.hide();
3814  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.hide();
3815  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.disable();
3816  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.disable();
3817  } else {
3818  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.enable();
3819  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.enable();
3820  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.unhide();
3821  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.unhide();
3822  }
3823 
3824  // draw the window itself
3825  Multi_create_window.draw();
3826 
3828 
3829  // draw Create Game text
3830  gr_string(Mc_create_game_text[gr_screen.res][MC_X_COORD], Mc_create_game_text[gr_screen.res][MC_Y_COORD], XSTR("Create Game", 1268), GR_RESIZE_MENU);
3831 
3832  // draw players text
3833  gr_string(Mc_players_text[gr_screen.res][MC_X_COORD], Mc_players_text[gr_screen.res][MC_Y_COORD], XSTR("Players", 1269), GR_RESIZE_MENU);
3834 
3835  // draw players text
3836  gr_string(Mc_team_text[gr_screen.res][MC_X_COORD], Mc_team_text[gr_screen.res][MC_Y_COORD], XSTR("Team", 1258), GR_RESIZE_MENU);
3837 
3838  // process and display the player list
3839  // NOTE : this must be done before the buttons are checked to insure that a player hasn't dropped
3843  } else {
3845  }
3846 
3847  // process and display the game/campaign list
3849 
3850  // draw the correct mission filter button
3852 
3853  // display any text in the info area
3855 
3856  // display any pending notification messages
3858 
3859  // force the correct mission/campaign button to light up
3860  if( Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS ){
3861  Multi_create_buttons[gr_screen.res][MC_MISSION_FILTER].button.draw_forced(2);
3862  } else {
3863  Multi_create_buttons[gr_screen.res][MC_CAMPAIGN_FILTER].button.draw_forced(2);
3864  }
3865 
3866  // force draw the closed button if it is toggled on
3868  Multi_create_buttons[gr_screen.res][MC_CLOSE].button.draw_forced(2);
3869  }
3870 
3871  // process and show the chatbox thingie
3872  chatbox_render();
3873 
3874  // draw tooltips
3875  Multi_create_window.draw_tooltip();
3876 
3877  // display the voice status indicator
3879 
3880  // blit the help overlay if necessary
3881  help_overlay_maybe_blit(Multi_create_overlay_id, gr_screen.res);
3882 
3883  // test code
3887  } else {
3889  }
3890  gr_string(Multi_create_sw_checkbox_text[gr_screen.res][0], Multi_create_sw_checkbox_text[gr_screen.res][1], "SquadWar", GR_RESIZE_MENU);
3891  }
3892 
3893  // flip the buffer
3894  gr_flip();
3895 
3896  // if we're supposed to show the pilot info popup, do it now
3897  if(Multi_create_should_show_popup){
3898  // get the player index and address of the player item the mouse is currently over
3899  if(Multi_create_plist_select_flag){
3900  player_index = find_player_id(Multi_create_plist_select_id);
3901  if(player_index != -1){
3902  multi_pinfo_popup(&Net_players[player_index]);
3903  }
3904  }
3905  }
3906 
3907  // increment the frame count
3908  Multi_create_frame_count++;
3909 }
3910 
3912 {
3913  // unload any bitmaps
3914  if(!bm_unload(Multi_create_bitmap)){
3915  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_create_bitmap_fname[gr_screen.res]));
3916  }
3917 
3918  // destroy the chatbox
3919  // chatbox_close();
3920 
3921  // destroy the UI_WINDOW
3922  Multi_create_window.destroy();
3923 }
3924 
3926 {
3927  int idx;
3928  for(idx=0;idx<MULTI_CREATE_NUM_BUTTONS;idx++){
3929  // we only really need to check for one button pressed at a time, so we can break after
3930  // finding one.
3931  if(Multi_create_buttons[gr_screen.res][idx].button.pressed()){
3933  break;
3934  }
3935  }
3936 
3937  // if the squad war checkbox was clicked
3938  if(Multi_create_sw_checkbox.changed()){
3940  }
3941 }
3942 
3944 {
3945  int idx;
3946 
3947  switch(n){
3948  case MC_CANCEL :
3951  break;
3952  case MC_ACCEPT :
3953  // if valid commit conditions have not been met
3955  break;
3956  }
3957 
3958  // commit
3960  break;
3961 
3962  // help button
3963  case MC_HELP :
3964  if(!help_overlay_active(Multi_create_overlay_id)){
3965  help_overlay_set_state(Multi_create_overlay_id,gr_screen.res,1);
3966  } else {
3967  help_overlay_set_state(Multi_create_overlay_id,gr_screen.res,0);
3968  }
3969  break;
3970 
3971  // scroll the info text box up
3972  case MC_SCROLL_INFO_UP:
3974  break;
3975 
3976  // scroll the info text box down
3977  case MC_SCROLL_INFO_DOWN:
3979  break;
3980 
3981  // scroll the player list up
3982  case MC_SCROLL_PLAYERS_UP:
3984  break;
3985 
3986  // scroll the player list down
3989  break;
3990 
3991  // scroll the game/campaign list up
3992  case MC_SCROLL_LIST_UP:
3994  Multi_create_slider.forceUp(); // move slider up
3995  break;
3996 
3997  // scroll the game/campaign list down
3998  case MC_SCROLL_LIST_DOWN:
4000  Multi_create_slider.forceDown(); // move slider down
4001  break;
4002 
4003  // go to the options screen
4004  case MC_OPTIONS:
4007  break;
4008 
4009  // show all missions
4010  case MC_SHOW_ALL:
4011  if(Multi_create_filter != MISSION_TYPE_MULTI){
4013  Multi_create_filter = MISSION_TYPE_MULTI;
4014  multi_create_setup_list_data(Multi_create_list_mode); // update the file list
4015  } else {
4017  }
4018  break;
4019 
4020  // show cooperative missions
4021  case MC_SHOW_COOP:
4022  if(Multi_create_filter != MISSION_TYPE_MULTI_COOP){
4024  Multi_create_filter = MISSION_TYPE_MULTI_COOP;
4025  multi_create_setup_list_data(Multi_create_list_mode); // update the file list
4026  } else {
4028  }
4029  break;
4030 
4031  // show team vs. team missions
4032  case MC_SHOW_TEAM:
4033  if(Multi_create_filter != MISSION_TYPE_MULTI_TEAMS){
4035  Multi_create_filter = MISSION_TYPE_MULTI_TEAMS;
4036  multi_create_setup_list_data(Multi_create_list_mode); // update the file list
4037  } else {
4039  }
4040  break;
4041 
4042  // show dogfight missions
4043  case MC_SHOW_DOGFIGHT:
4044  if (Multi_create_filter != MISSION_TYPE_MULTI_DOGFIGHT){
4046  Multi_create_filter = MISSION_TYPE_MULTI_DOGFIGHT;
4047  multi_create_setup_list_data(Multi_create_list_mode); // update the file list
4048  } else {
4050  }
4051  break;
4052 
4053  // toggle temporary netgame closed on/off
4054  case MC_CLOSE:
4057  } else {
4060  }
4062  break;
4063 
4064  // kick the currently selected player (if possible)
4065  case MC_KICK:
4066  // lookup the player at the specified index
4067  if(Multi_create_plist_select_flag){
4068  idx = find_player_id(Multi_create_plist_select_id);
4069  // kick him - but don't ban him
4070  if(idx != -1){
4071  multi_kick_player(idx,0);
4072  }
4073  }
4074  break;
4075 
4076  // switch to individual mission mode and load in a list
4077  case MC_MISSION_FILTER:
4078  if(Multi_create_list_mode != MULTI_CREATE_SHOW_MISSIONS){
4080 
4082 
4083  // update the file list
4085  } else {
4087  }
4088  break;
4089 
4090  // switch to campaign mode and load in a list
4091  case MC_CAMPAIGN_FILTER:
4092  // switch off squad war
4093  Multi_create_sw_checkbox.set_state(0);
4095 
4096  if(Multi_create_list_mode != MULTI_CREATE_SHOW_CAMPAIGNS){
4098 
4100 
4101  // update the file list
4103  } else {
4105  }
4106  break;
4107 
4108  // attempt to set the selected player's team
4109  case MC_TEAM0:
4113  }
4114  break;
4115 
4116  // attempt to set the selected player's team
4117  case MC_TEAM1:
4121  }
4122  break;
4123 
4124  // popup the pilot info dialog for the currently selected pilot (will occur at the end of the frame)
4125  case MC_PILOT_INFO:
4126  Multi_create_should_show_popup = 1;
4127  break;
4128 
4129  // go to the host options screen
4130  case MC_HOST_OPTIONS:
4133  break;
4134 
4135  // refresh PXO file list
4136  case MC_PXO_REFRESH:
4137  if(!MULTI_IS_TRACKER_GAME){
4138  break;
4139  }
4141  break;
4142 
4143  default :
4145  multi_common_add_notify(XSTR("Not implemented yet!",760));
4146  break;
4147  }
4148 }
4149 
4150 // do stuff like pinging servers, sending out requests, etc
4151 // # Kazan # -- This apparently DOES NOT Apply to Standalones
4153 {
4154 
4155 }
4156 
4157 // if not on a standalone
4159 {
4160  // set me up as the host and master
4162 }
4163 
4164 // if on a standalone
4166 {
4168 }
4169 
4170 // scroll up through the player list
4172 {
4174 }
4175 
4176 // scroll down through the player list
4178 {
4180 }
4181 
4183 {
4184  int test_count,idx,player_index;
4185 
4186  // first determine if there are 0 players in the game. This should never happen since the host is _always_ in the game
4187  test_count = 0;
4188  for(idx=0;idx<MAX_PLAYERS;idx++){
4189  // count anyone except the standalone server (if applicable)
4191  test_count++;
4192  }
4193  }
4194  if(test_count <= 0){
4195  return;
4196  }
4197 
4198  // if we had a selected item but that player has left, select myself instead
4199  if(Multi_create_plist_select_flag){
4200  player_index = find_player_id(Multi_create_plist_select_id);
4201  if(player_index == -1){
4202  Multi_create_plist_select_id = Net_player->player_id;
4203  }
4204  } else {
4205  Multi_create_plist_select_flag = 1;
4206  Multi_create_plist_select_id = Net_player->player_id;
4207  }
4208 
4209  // if the player has clicked somewhere in the player list area
4210  if(Multi_create_player_select_button.pressed()){
4211  short player_id;
4212 
4213  // get the player index and address of the player item the mouse is currently over
4214  player_id = multi_create_get_mouse_id();
4215  player_index = find_player_id(player_id);
4216  if(player_index != -1){
4217  Multi_create_plist_select_flag = 1;
4218  Multi_create_plist_select_id = player_id;
4219  }
4220  }
4221 }
4222 
4224 {
4225  int idx;
4226  char str[CALLSIGN_LEN+5];
4227  int y_start = Mc_players_coords[gr_screen.res][MC_Y_COORD];
4228  int line_height = gr_get_font_height() + 1;
4229  int total_offset;
4230 
4231  // display all the players
4232  for(idx=0;idx<MAX_PLAYERS;idx++){
4233  // count anyone except the standalone server (if applicable)
4235  // total x offset
4236  total_offset = 0;
4237 
4238  // highlight him if he's the host
4240  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4242  } else {
4244  }
4245  } else {
4246  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4248  } else {
4250  }
4251  }
4252 
4253  // optionally draw his CD status
4256  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start - 1,GR_RESIZE_MENU);
4257 
4258  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
4259  }
4260 
4261  // make sure the string will fit, then display it
4262  strcpy_s(str,Net_players[idx].m_player->callsign);
4264  strcat_s(str,XSTR("(O)",787)); // [[ Observer ]]
4265  }
4266  gr_force_fit_string(str,CALLSIGN_LEN,Mc_players_coords[gr_screen.res][MC_W_COORD] - total_offset);
4267  gr_string(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
4268 
4269  y_start += line_height;
4270  }
4271  }
4272 }
4273 
4275 {
4276  int idx;
4277  char str[CALLSIGN_LEN+1];
4278  int y_start = Mc_players_coords[gr_screen.res][MC_Y_COORD];
4279  int line_height = gr_get_font_height() + 1;
4280  int total_offset;
4281 
4282  // display all the red players first
4283  for(idx=0;idx<MAX_PLAYERS;idx++){
4284  // count anyone except the standalone server (if applicable)
4285  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_players[idx].p_info.team == 0)){
4286  // reset total offset
4287  total_offset = 0;
4288 
4289  // highlight him if he's the host
4291  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4293 
4294  // be sure to blit the correct team button
4295  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.draw_forced(2);
4296  } else {
4298  }
4299  } else {
4300  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4302 
4303  // be sure to blit the correct team button
4304  Multi_create_buttons[gr_screen.res][MC_TEAM0].button.draw_forced(2);
4305  } else {
4307  }
4308  }
4309 
4310  // optionally draw his CD status
4313  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start - 1,GR_RESIZE_MENU);
4314 
4315  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
4316  }
4317 
4318  // blit the red team indicator
4322  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset, y_start-2, GR_RESIZE_MENU);
4323 
4324  total_offset += Multi_common_icon_dims[MICON_TEAM0_SELECT][0] + 1;
4325  }
4326  } else {
4327  if(Multi_common_icons[MICON_TEAM0] != -1){
4329  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset, y_start-2, GR_RESIZE_MENU);
4330 
4331  total_offset += Multi_common_icon_dims[MICON_TEAM0][0] + 1;
4332  }
4333  }
4334 
4335  // make sure the string will fit
4336  strcpy_s(str,Net_players[idx].m_player->callsign);
4338  strcat_s(str,XSTR("(O)",787));
4339  }
4340  gr_force_fit_string(str,CALLSIGN_LEN,Mc_players_coords[gr_screen.res][MC_W_COORD] - total_offset);
4341 
4342  // display him in the correct half of the list depending on his team
4343  gr_string(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
4344  y_start += line_height;
4345  }
4346  }
4347 
4348  // display all the green players next
4349  for(idx=0;idx<MAX_PLAYERS;idx++){
4350  // count anyone except the standalone server (if applicable)
4351  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_players[idx].p_info.team == 1)){
4352  // reset total offset
4353  total_offset = 0;
4354 
4355  // highlight him if he's the host
4357  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4359 
4360  // be sure to blit the correct team button
4361  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.draw_forced(2);
4362  } else {
4364  }
4365  } else {
4366  if(Multi_create_plist_select_id == Net_players[idx].player_id){
4368 
4369  // be sure to blit the correct team button
4370  Multi_create_buttons[gr_screen.res][MC_TEAM1].button.draw_forced(2);
4371  } else {
4373  }
4374  }
4375 
4376  // optionally draw his CD status
4379  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start - 1,GR_RESIZE_MENU);
4380 
4381  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
4382  }
4383 
4384  // blit the red team indicator
4388  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset, y_start-2, GR_RESIZE_MENU);
4389 
4390  total_offset += Multi_common_icon_dims[MICON_TEAM1_SELECT][0] + 1;
4391  }
4392  } else {
4393  if(Multi_common_icons[MICON_TEAM1] != -1){
4395  gr_bitmap(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset, y_start-2, GR_RESIZE_MENU);
4396 
4397  total_offset += Multi_common_icon_dims[MICON_TEAM1][0] + 1;
4398  }
4399  }
4400 
4401  // make sure the string will fit
4402  strcpy_s(str,Net_players[idx].m_player->callsign);
4404  strcat_s(str,XSTR("(O)",787));
4405  }
4406  gr_force_fit_string(str,CALLSIGN_LEN,Mc_players_coords[gr_screen.res][MC_W_COORD] - total_offset);
4407 
4408  // display him in the correct half of the list depending on his team
4409  gr_string(Mc_players_coords[gr_screen.res][MC_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
4410  y_start += line_height;
4411  }
4412  }
4413 }
4414 
4416 {
4417  if(Multi_create_list_start > 0){
4418  Multi_create_list_start--;
4419 
4421  } else {
4423  }
4424 }
4425 
4427 {
4428  if((Multi_create_list_count - Multi_create_list_start) > Multi_create_list_max_display[gr_screen.res]){
4429  Multi_create_list_start++;
4430 
4432  } else {
4434  }
4435 }
4436 
4437 // gets a list of multiplayer misisons
4439 {
4440  char *fname, mission_name[NAME_LENGTH+1];
4441  char wild_card[10];
4442  int file_count, idx;
4443  char **file_list = NULL;
4444 
4445  Multi_create_mission_list.clear();
4446 
4447  memset( wild_card, 0, sizeof(wild_card) );
4448  snprintf(wild_card, sizeof(wild_card) - 1, "*%s", FS_MISSION_FILE_EXT);
4449 
4450  file_list = (char**) vm_malloc( sizeof(char*) * 1024 );
4451 
4452  if (file_list == NULL) {
4453  return;
4454  }
4455 
4456  file_count = cf_get_file_list(1024, file_list, CF_TYPE_MISSIONS, wild_card);
4457 
4458  // maybe create a standalone dialog
4460  std_create_gen_dialog("Loading missions");
4461  std_gen_set_text("Mission:", 1);
4462  }
4463 
4464  for (idx = 0; idx < file_count; idx++) {
4465  int flags,max_players;
4466  char *filename;
4467  uint m_respawn;
4468 
4469  fname = file_list[idx];
4470 
4471  // tack on any necessary file extension
4472  filename = cf_add_ext( fname, FS_MISSION_FILE_EXT );
4473 
4474  if (Game_mode & GM_STANDALONE_SERVER) {
4475  std_gen_set_text(filename, 2);
4476  }
4477 
4478  flags = mission_parse_is_multi(filename, mission_name);
4479 
4480  // if the mission is a multiplayer mission, then add it to the mission list
4481  if ( flags ) {
4482  max_players = mission_parse_get_multi_mission_info( filename );
4483  m_respawn = The_mission.num_respawns;
4484 
4485  multi_create_info mcip;
4486 
4487  strcpy_s(mcip.filename, filename );
4488  strcpy_s(mcip.name, mission_name );
4489  mcip.flags = flags;
4490  mcip.respawn = m_respawn;
4491  mcip.max_players = (ubyte)max_players;
4492 
4493  // get any additional information for possibly builtin missions
4495  if(fb != NULL){
4496  }
4497 
4498  Multi_create_mission_list.push_back( mcip );
4499  }
4500  }
4501 
4502  if (file_list) {
4503  for (idx = 0; idx < file_count; idx++) {
4504  if (file_list[idx]) {
4505  vm_free(file_list[idx]);
4506  file_list[idx] = NULL;
4507  }
4508  }
4509 
4510  vm_free(file_list);
4511  file_list = NULL;
4512  }
4513 
4514  Multi_create_slider.set_numberItems(int(Multi_create_mission_list.size()) > Multi_create_list_max_display[gr_screen.res] ? int(Multi_create_mission_list.size())-Multi_create_list_max_display[gr_screen.res] : 0);
4515 
4516  // maybe create a standalone dialog
4517  if (Game_mode & GM_STANDALONE_SERVER) {
4519  }
4520 }
4521 
4523 {
4524  char *fname;
4525  int idx, file_count;
4526  int campaign_type,max_players;
4527  char title[255];
4528  char wild_card[10];
4529  char **file_list = NULL;
4530 
4531  Multi_create_campaign_list.clear();
4532 
4533  memset( wild_card, 0, sizeof(wild_card) );
4534  snprintf(wild_card, sizeof(wild_card) - 1, "*%s", FS_CAMPAIGN_FILE_EXT);
4535 
4536  file_list = (char**) vm_malloc( sizeof(char*) * 1024 );
4537 
4538  if (file_list == NULL) {
4539  return;
4540  }
4541 
4542  file_count = cf_get_file_list(1024, file_list, CF_TYPE_MISSIONS, wild_card);
4543 
4544  // maybe create a standalone dialog
4546  std_create_gen_dialog("Loading campaigns");
4547  std_gen_set_text("Campaign:", 1);
4548  }
4549 
4550  for (idx = 0; idx < file_count; idx++) {
4551  int flags;
4552  char *filename, name[NAME_LENGTH];
4553 
4554  fname = file_list[idx];
4555 
4556  // tack on any necessary file extension
4557  filename = cf_add_ext( fname, FS_CAMPAIGN_FILE_EXT );
4558 
4559  if (Game_mode & GM_STANDALONE_SERVER) {
4560  std_gen_set_text(filename, 2);
4561  }
4562 
4563  // if the campaign is a multiplayer campaign, then add the data to the campaign list items
4564  flags = mission_campaign_parse_is_multi( filename, name );
4565  if( flags != CAMPAIGN_TYPE_SINGLE && mission_campaign_get_info(filename,title,&campaign_type,&max_players)) {
4566  multi_create_info mcip;
4567 
4568  strcpy_s(mcip.filename, filename );
4569  strcpy_s(mcip.name, name );
4570 
4571  // setup various flags
4572  if ( flags == CAMPAIGN_TYPE_MULTI_COOP ){
4574  } else if ( flags == CAMPAIGN_TYPE_MULTI_TEAMS ) {
4576  } else {
4577  Int3(); // bogus campaign multi type -- find allender
4578  }
4579 
4580  // 0 respawns for campaign files (should be contained within the mission files themselves)
4581  mcip.respawn = 0;
4582 
4583  // 0 max players for campaign files
4584  mcip.max_players = (unsigned char)max_players;
4585 
4586  // get any additional information for possibly builtin missions
4588  if(fb != NULL){
4589  }
4590 
4591  Multi_create_campaign_list.push_back( mcip );
4592  }
4593  }
4594 
4595  if (file_list) {
4596  for (idx = 0; idx < file_count; idx++) {
4597  if (file_list[idx]) {
4598  vm_free(file_list[idx]);
4599  file_list[idx] = NULL;
4600  }
4601  }
4602 
4603  vm_free(file_list);
4604  file_list = NULL;
4605  }
4606 
4607  // maybe create a standalone dialog
4608  if (Game_mode & GM_STANDALONE_SERVER) {
4610  }
4611 }
4612 
4614 {
4615  int idx;
4616  int start_index,stop_index;
4617  int line_height = gr_get_font_height() + 1;
4618  char selected_name[255];
4619 
4620  // bail early if there aren't any selectable items
4621  if(Multi_create_list_count == 0){
4622  return;
4623  }
4624 
4625  // first check to see if the user has clicked on an item
4626  if(Multi_create_list_select_button.pressed()){
4627  int y,item;
4628  Multi_create_list_select_button.get_mouse_pos(NULL,&y);
4629  item = (y / line_height);
4630 
4631  // make sure we are selectedin valid indices
4632  if((item < Multi_create_list_max_display[gr_screen.res]) && (item >= 0)){
4633  item += Multi_create_list_start;
4634 
4635  if(item < Multi_create_list_count){
4638  }
4639  }
4640  }
4641 
4642  // bail early if we don't have a start position
4643  if(Multi_create_list_start == -1){
4644  return;
4645  }
4646 
4647  // display the list of individual campaigns/missions
4648  int count = 0;
4649  int y_start = Mc_list_coords[gr_screen.res][MC_Y_COORD];
4650 
4651  start_index = multi_create_select_to_index(Multi_create_list_start);
4652  stop_index = (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) ? Multi_create_mission_list.size() : Multi_create_campaign_list.size();
4653 
4654  for (idx = start_index; idx < stop_index; idx++) {
4655  multi_create_info *mcip;
4656 
4657  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
4658  mcip = &Multi_create_mission_list[idx];
4659  } else {
4660  mcip = &Multi_create_campaign_list[idx];
4661  }
4662 
4663  // see if we should drop out
4664  if(count == Multi_create_list_max_display[gr_screen.res]){
4665  break;
4666  }
4667 
4668  // see if we should filter out this mission
4669  if ( !(mcip->flags & Multi_create_filter) ) {
4670  continue;
4671  }
4672 
4673  // highlight the selected item
4674  multi_create_select_to_filename(Multi_create_list_select, selected_name);
4675 
4676  if ( !strcmp(selected_name, mcip->filename) ) {
4678  } else {
4680  }
4681 
4682  // draw the type icon
4683  multi_create_list_blit_icons(idx, y_start);
4684 
4685  // force fit the mission name string
4686  strcpy_s(selected_name, mcip->name);
4687  gr_force_fit_string(selected_name, 255, Mc_column1_w[gr_screen.res]);
4688  gr_string(Mc_mission_name_x[gr_screen.res], y_start, selected_name, GR_RESIZE_MENU);
4689 
4690  // draw the max players if in mission mode
4691  sprintf(selected_name, "%d", (int)mcip->max_players);
4692  gr_string(Mc_mission_count_x[gr_screen.res], y_start, selected_name, GR_RESIZE_MENU);
4693 
4694  // force fit the mission filename string
4695  strcpy_s(selected_name, mcip->filename);
4696  gr_force_fit_string(selected_name, 255, Mc_column3_w[gr_screen.res]);
4697  gr_string(Mc_mission_fname_x[gr_screen.res], y_start, selected_name, GR_RESIZE_MENU);
4698 
4699  y_start += line_height;
4700  count++;
4701  }
4702 }
4703 
4704 // takes care of stuff like changing indices around and setting up the netgame structure
4706 {
4707  int abs_index,campaign_type,max_players;
4708  char title[NAME_LENGTH+1];
4709  netgame_info ng_temp;
4710  netgame_info *ng;
4711  multi_create_info *mcip = NULL;
4712 
4713  char *campaign_desc;
4714 
4715  // if not on the standalone server
4717  ng = &Netgame;
4718  }
4719  // on the standalone
4720  else {
4721  memset(&ng_temp,0,sizeof(netgame_info));
4722  ng = &ng_temp;
4723  }
4724 
4725  if ( n != Multi_create_list_select ) {
4726  // check to see if this is a valid index, and bail if it is not
4727  abs_index = multi_create_select_to_index(n);
4728  if(abs_index == -1){
4729  return;
4730  }
4731 
4732  Multi_create_list_select = n;
4733 
4734  // set the mission name
4735  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
4737  } else {
4739  }
4740 
4741  // make sure the netgame type is properly set
4742  int old_type = Netgame.type_flags;
4743  abs_index = multi_create_select_to_index(n);
4744 
4745  if (abs_index != -1) {
4746  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
4747  mcip = &Multi_create_mission_list[abs_index];
4748  } else {
4749  mcip = &Multi_create_campaign_list[abs_index];
4750  }
4751 
4752  if (mcip->flags & MISSION_TYPE_MULTI_TEAMS) {
4753  // if we're in squad war mode, leave it as squad war
4754  if(old_type & NG_TYPE_SW){
4755  ng->type_flags = NG_TYPE_SW;
4756  } else {
4757  ng->type_flags = NG_TYPE_TVT;
4758  }
4759  } else if (mcip->flags & MISSION_TYPE_MULTI_COOP) {
4760  ng->type_flags = NG_TYPE_COOP;
4761  } else if (mcip->flags & MISSION_TYPE_MULTI_DOGFIGHT) {
4763  }
4764  }
4765 
4766  // if we're no longer in a TvT game, just uncheck the squadwar checkbox
4767  if(!(ng->type_flags & NG_TYPE_TEAM)){
4768  Multi_create_sw_checkbox.set_state(0);
4769  }
4770 
4771  // if we switched from something else to team vs. team mode, do some special processing
4772  if((ng->type_flags & NG_TYPE_TEAM) && (ng->type_flags != old_type) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
4773  multi_team_reset();
4774  }
4775 
4776  switch(Multi_create_list_mode){
4778  // don't forget to update the info box window thingie
4780  ship_level_init(); // mwa -- 10/15/97. Call this function to reset number of ships in mission
4782 
4783  Assert(ng->max_players > 0);
4785 
4786  // set the information area text
4788  }
4789  // if we're on the standalone, send a request for the description
4790  else {
4793  }
4794 
4795  // set the respawns as appropriate
4796  if (mcip) {
4797  if(Netgame.options.respawn <= mcip->respawn){
4799  nprintf(("Network", "Using netgame options for respawn count (%d %d)\n", Netgame.options.respawn, mcip->respawn));
4800  } else {
4801  ng->respawn = mcip->respawn;
4802  nprintf(("Network", "Using mission settings for respawn count (%d %d)\n", Netgame.options.respawn, mcip->respawn));
4803  }
4804  }
4805  break;
4807  // if not on the standalone server
4809  // get the campaign info
4810  memset(title,0,NAME_LENGTH+1);
4811  if(!mission_campaign_get_info(ng->campaign_name,title,&campaign_type,&max_players, &campaign_desc)) {
4812  memset(ng->campaign_name,0,NAME_LENGTH+1);
4813  ng->max_players = 0;
4814  }
4815  // if we successfully got the # of players
4816  else {
4817  memset(ng->title,0,NAME_LENGTH+1);
4818  strcpy_s(ng->title,title);
4819  ng->max_players = max_players;
4820  }
4821 
4822  nprintf(("Network","MC MAX PLAYERS : %d\n",ng->max_players));
4823 
4824  // set the information area text
4825  // multi_common_set_text(ng->title);
4826  if (campaign_desc != NULL)
4827  {
4828  multi_common_set_text(campaign_desc);
4829  }
4830  else
4831  {
4833  }
4834  }
4835  // if on the standalone server, send a request for the description
4836  else {
4837  // no descriptions currently kept for campaigns
4838  }
4839 
4840  // netgame respawns are always 0 for campaigns (until the first mission is loaded)
4841  ng->respawn = 0;
4842  break;
4843  }
4844 
4846  // update players
4848 
4849  // update all machines about stuff like respawns, etc.
4851 
4852  // send update to FS2NetD as well
4853  if (MULTI_IS_TRACKER_GAME) {
4855  }
4856  } else {
4857  multi_options_update_mission(ng, Multi_create_list_mode == MULTI_CREATE_SHOW_CAMPAIGNS ? 1 : 0);
4858  }
4859  }
4860 }
4861 
4862 void multi_create_list_blit_icons(int list_index, int y_start)
4863 {
4864  multi_create_info *mcip;
4865  fs_builtin_mission *fb;
4866  int max_index;
4867 
4868  // get a pointer to the list item
4869  max_index = (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) ? Multi_create_mission_list.size() - 1 : Multi_create_campaign_list.size() - 1;
4870 
4871  if ( (list_index < 0) || (list_index > max_index) ) {
4872  return;
4873  }
4874 
4875  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
4876  mcip = &Multi_create_mission_list[list_index];
4877  } else {
4878  mcip = &Multi_create_campaign_list[list_index];
4879  }
4880 
4881  // blit the multiplayer type icons
4882  if(mcip->flags & MISSION_TYPE_MULTI_COOP){
4883  if(Multi_common_icons[MICON_COOP] >= 0){
4885  gr_bitmap(Mc_icon_type_coords[gr_screen.res][MC_X_COORD],y_start + Mc_icon_type_coords[gr_screen.res][MC_Y_COORD],GR_RESIZE_MENU);
4886  }
4887  } else if(mcip->flags & MISSION_TYPE_MULTI_TEAMS){
4888  if(Multi_common_icons[MICON_TVT] >= 0){
4890  gr_bitmap(Mc_icon_type_coords[gr_screen.res][MC_X_COORD],y_start + Mc_icon_type_coords[gr_screen.res][MC_Y_COORD],GR_RESIZE_MENU);
4891  }
4892  } else if(mcip->flags & MISSION_TYPE_MULTI_DOGFIGHT){
4895  gr_bitmap(Mc_icon_type_coords[gr_screen.res][MC_X_COORD],y_start + Mc_icon_type_coords[gr_screen.res][MC_Y_COORD],GR_RESIZE_MENU);
4896  }
4897  }
4898 
4899  // if its a valid mission, blit the valid mission icon
4901  if(Multi_common_icons[MICON_VALID] >= 0){
4903  gr_bitmap(Mc_icon_valid_coords[gr_screen.res][MC_X_COORD],y_start + Mc_icon_valid_coords[gr_screen.res][MC_Y_COORD],GR_RESIZE_MENU);
4904  }
4905  }
4906 
4907  // now see if its a builtin mission
4908  fb = game_find_builtin_mission(mcip->filename);
4909  // if the mission is from volition, blit the volition icon
4910  if((fb != NULL) && (fb->flags & FSB_FROM_VOLITION)){
4913  gr_bitmap(Mc_icon_volition_coords[gr_screen.res][MC_X_COORD],y_start + Mc_icon_volition_coords[gr_screen.res][MC_Y_COORD],GR_RESIZE_MENU);
4914  }
4915  }
4916 }
4917 
4919 {
4920  char selected_name[255];
4921  int start_campaign = 0;
4922  int popup_choice = 0;
4923 
4924  // make sure all players have finished joining
4926  popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("Please wait until all clients have finished joining",788));
4928  return;
4929  } else {
4931  }
4932 
4933  // do single mission stuff
4934  switch(Multi_create_list_mode){
4936  if(Multi_create_list_select != -1){
4937  // set the netgame mode
4939 
4940  // setup various filenames and mission names
4941  multi_create_select_to_filename(Multi_create_list_select,selected_name);
4942  strcpy_s( Game_current_mission_filename, selected_name);
4943  strcpy_s(Netgame.mission_name,selected_name);
4944 
4945  // NETLOG
4946  ml_printf(NOX("Starting single mission %s, with %d players"), Game_current_mission_filename, multi_num_players());
4947  } else {
4948  multi_common_add_notify(XSTR("No mission selected!",789));
4949  return ;
4950  }
4951  break;
4952 
4954  // do campaign related stuff
4955  if(Multi_create_list_select != -1){
4956  // set the netgame mode
4958 
4959  // start a campaign instead of a single mission
4960  multi_create_select_to_filename(Multi_create_list_select,selected_name);
4961  multi_campaign_start(selected_name);
4962  start_campaign = 1;
4963 
4964  // NETLOG
4965  ml_printf(NOX("Starting campaign %s, with %d players"), selected_name, multi_num_players());
4966  } else {
4967  multi_common_add_notify(XSTR("No campaign selected!",790));
4968  return ;
4969  }
4970  break;
4971  }
4972 
4973  // if this is a team vs team situation, lock the players send a final team update
4977  }
4978 
4979  // coop game option validation checks
4981  // check for time limit
4982  if (Netgame.options.mission_time_limit != i2f(-1)) {
4983  popup_choice = popup(0, 3, POPUP_CANCEL, POPUP_YES, XSTR( " &No", 506 ),
4984  XSTR("A time limit is being used in a co-op game.\r\n"
4985  " Select \'Cancel\' to go back to the mission select screen.\r\n"
4986  " Select \'Yes\' to continue with this time limit.\r\n"
4987  " Select \'No\' to continue without this time limit.", -1));
4988 
4989  if (popup_choice == 0) {
4990  return;
4991  } else if (popup_choice == 2) {
4993  }
4994  }
4995 
4996  // check kill limit (NOTE: <= 0 is considered no limit)
4997  if ( (Netgame.options.kill_limit > 0) && (Netgame.options.kill_limit != 9999) ) {
4998  popup_choice = popup(0, 3, POPUP_CANCEL, POPUP_YES, XSTR( " &No", 506 ),
4999  XSTR("A kill limit is being used in a co-op game.\r\n"
5000  " Select \'Cancel\' to go back to the mission select screen.\r\n"
5001  " Select \'Yes\' to continue with this kill limit.\r\n"
5002  " Select \'No\' to continue without this kill limit.", -1));
5003 
5004  if (popup_choice == 0) {
5005  return;
5006  } else if (popup_choice == 2) {
5007  Netgame.options.kill_limit = 9999;
5008  }
5009  }
5010  }
5011 
5012  // if not on the standalone, move to the mission sync state which will take care of everything
5016  }
5017  // otherwise tell the standalone to do so
5018  else {
5019  // when the standalone receives this, he'll do the mission syncing himself
5021  }
5022 }
5023 
5025 {
5026  // highlight the correct filter button
5027  if ( Multi_create_filter == MISSION_TYPE_MULTI ){
5028  Multi_create_buttons[gr_screen.res][MC_SHOW_ALL].button.draw_forced(2);
5029  } else if ( Multi_create_filter == MISSION_TYPE_MULTI_COOP ) {
5030  Multi_create_buttons[gr_screen.res][MC_SHOW_ALL + 1].button.draw_forced(2);
5031  } else if ( Multi_create_filter == MISSION_TYPE_MULTI_TEAMS ) {
5032  Multi_create_buttons[gr_screen.res][MC_SHOW_ALL + 2].button.draw_forced(2);
5033  } else if ( Multi_create_filter == MISSION_TYPE_MULTI_DOGFIGHT ){
5034  Multi_create_buttons[gr_screen.res][MC_SHOW_ALL + 3].button.draw_forced(2);
5035  } else {
5036  Int3();
5037  }
5038 }
5039 
5041 {
5042  int player_index;
5043 
5044  // if we don't currently have a player selected, don't do anything
5045  if(!Multi_create_plist_select_flag){
5047  return;
5048  }
5050 
5051  // otherwise attempt to set the team for this guy
5052  player_index = find_player_id(Multi_create_plist_select_id);
5053  if(player_index != -1){
5054  multi_team_set_team(&Net_players[player_index],team);
5055  }
5056 }
5057 
5059 {
5060  // for now just play a bloop sound
5062 }
5063 
5064 // fill in net address of player the mouse is over, return player index (or -1 if none)
5066 {
5067  // determine where he clicked (y pixel value)
5068  int y,nth,idx;
5069  Multi_create_player_select_button.get_mouse_pos(NULL,&y);
5070 
5071  // select things a little differently if we're in team vs. team or non-team vs. team mode
5072  nth = (y / (gr_get_font_height() + 1));
5074  int player_index = -1;
5075 
5076  // look through all of team red first
5077  for(idx=0;idx<MAX_PLAYERS;idx++){
5079  nth--;
5080 
5081  // if this is the _nth_ guy
5082  if(nth < 0){
5083  player_index = idx;
5084  break;
5085  }
5086  }
5087  }
5088 
5089  // if we still haven't found him yet, look through the green team
5090  if(player_index == -1){
5091  for(idx=0;idx<MAX_PLAYERS;idx++){
5093  nth--;
5094  // if this is the _nth_ guy
5095  if(nth < 0){
5096  player_index = idx;
5097  break;
5098  }
5099  }
5100  }
5101  }
5102 
5103  if(player_index != -1){
5104  return Net_players[player_index].player_id;
5105  }
5106  } else {
5107  // select the nth active player if possible, disregarding the standalone server
5108  for(idx=0;idx<MAX_PLAYERS;idx++){
5110  nth--;
5111 
5112  // if this is the _nth_ guy
5113  if(nth < 0){
5114  return Net_players[idx].player_id;
5115  }
5116  }
5117  }
5118  }
5119 
5120  return -1;
5121 }
5122 
5123 void multi_create_select_to_filename(int select_index,char *filename)
5124 {
5125  uint idx;
5126 
5127  // look through the mission list
5128  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
5129  for (idx = 0; idx < Multi_create_mission_list.size(); idx++) {
5130  if (Multi_create_mission_list[idx].flags & Multi_create_filter) {
5131  select_index--;
5132  }
5133 
5134  // if we found the item
5135  if (select_index < 0) {
5136  strcpy(filename, Multi_create_mission_list[idx].filename);
5137  return;
5138  }
5139  }
5140  }
5141  // look through the campaign list
5142  else if (Multi_create_list_mode == MULTI_CREATE_SHOW_CAMPAIGNS) {
5143  for (idx = 0; idx < Multi_create_campaign_list.size(); idx++) {
5144  select_index--;
5145 
5146  // if we found the item
5147  if (select_index < 0) {
5148  strcpy(filename, Multi_create_campaign_list[idx].filename);
5149  return;
5150  }
5151  }
5152  }
5153 
5154  strcpy(filename,"");
5155 }
5156 
5157 int multi_create_select_to_index(int select_index)
5158 {
5159  uint idx;
5160  int lookup_index = 0;
5161 
5162  // look through the mission list
5163  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
5164  for (idx = 0; idx < Multi_create_mission_list.size(); idx++) {
5165  if (Multi_create_mission_list[idx].flags & Multi_create_filter) {
5166  lookup_index++;
5167  }
5168 
5169  // if we found the item
5170  if (select_index < lookup_index) {
5171  return idx;
5172  }
5173  }
5174  }
5175  // look through the campaign list
5176  else if (Multi_create_list_mode == MULTI_CREATE_SHOW_CAMPAIGNS) {
5177  for (idx = 0; idx < Multi_create_campaign_list.size(); idx++) {
5178  select_index--;
5179 
5180  // if we found the item
5181  if (select_index < 0) {
5182  return idx;
5183  }
5184  }
5185  }
5186 
5187  return -1;
5188 }
5189 
5191 {
5192  int player_count, observer_count, idx;
5193  int notify_of_hacked_ships_tbl = 0;
5194  int notify_of_hacked_weapons_tbl = 0;
5195  char err_string[255];
5196  int abs_index;
5197  int found_hack;
5198 
5199  // make sure we have a valid mission selected
5200  if(Multi_create_list_select < 0){
5201  return 0;
5202  }
5203 
5204  // if this is not a valid mission, let the player know
5205  abs_index = multi_create_select_to_index(Multi_create_list_select);
5206  if(abs_index < 0){
5207  return 0;
5208  }
5209 
5210  // if we're playing with a hacked ships.tbl (on PXO)
5211  notify_of_hacked_ships_tbl = 0;
5213  if(!Game_ships_tbl_valid){
5214  notify_of_hacked_ships_tbl = 1;
5215  }
5216  } else {
5218  notify_of_hacked_ships_tbl = 1;
5219  }
5220  }
5221  if(!MULTI_IS_TRACKER_GAME){
5222  notify_of_hacked_ships_tbl = 0;
5223  }
5224  if(notify_of_hacked_ships_tbl){
5225  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("You or the server you are playing on has a hacked ships.tbl. Your stats will not be updated on PXO", 1051)) <= 0){
5226  return 0;
5227  }
5228  }
5229 
5230  // if we're playing with a hacked weapons.tbl (on PXO)
5231  notify_of_hacked_weapons_tbl = 0;
5234  notify_of_hacked_weapons_tbl = 1;
5235  }
5236  } else {
5238  notify_of_hacked_weapons_tbl = 1;
5239  }
5240  }
5241  if(!MULTI_IS_TRACKER_GAME){
5242  notify_of_hacked_weapons_tbl = 0;
5243  }
5244  if(notify_of_hacked_weapons_tbl){
5245  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("You or the server you are playing on has a hacked weapons.tbl. Your stats will not be updated on PXO", 1052)) <= 0){
5246  return 0;
5247  }
5248  }
5249 
5250  // if any of the players have hacked data
5251  found_hack = 0;
5252  for(idx=0; idx<MAX_PLAYERS; idx++){
5253  // look for hacked players
5255  // we found a hack
5256  found_hack = 1;
5257 
5258  // message everyone - haha
5259  if(Net_players[idx].m_player != NULL){
5260  sprintf(err_string, "%s %s", Net_players[idx].m_player->callsign, XSTR("has hacked tables/data", 1271));
5261  } else {
5262  sprintf(err_string, "somebody %s", XSTR("has hacked tables/data", 1271));
5263  }
5264  send_game_chat_packet(Net_player, err_string, MULTI_MSG_ALL, NULL, NULL, 1);
5265  }
5266  }
5267  // if we found a hacked set of data
5268  if(found_hack){
5269  // if we're on PXO
5271  // don't allow squad war matches to continue
5273  // if this is squad war, don't allow it to continue
5274  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("One or more players has hacked data files. You cannot play a SquadWar match unless all clients have legal data", 1272));
5275 
5276  return 0;
5277  }
5278  // otherwise, warn the players that stats will not saved
5279  else {
5280  // if this is squad war, don't allow it to continue
5281  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("One or more players has hacked data files. If you continue, stats will not be stored at the end of the mission", 1273)) <= 0){
5282  return 0;
5283  }
5284  }
5285  }
5286  // non-pxo, just give a notice
5287  else {
5288  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("One or more players has hacked data files", 1274)) <= 0){
5289  return 0;
5290  }
5291  }
5292  }
5293 
5294  // check to see that we don't have too many observers
5295  observer_count = multi_num_observers();
5296  if(observer_count > Netgame.options.max_observers){
5297  // print up the error string
5298  sprintf(err_string,XSTR("There are too many observers in the game\n\nMax : %d\nCurrently %d\n\nPlease dump a few",791),Netgame.options.max_observers,observer_count);
5299 
5300  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, err_string);
5301  return 0;
5302  }
5303 
5304  // check to see that we have a valid # of players for the the # of ships in the game
5305  player_count = multi_num_players();
5306  if(player_count > Netgame.max_players){
5307  // print up the error string
5308  sprintf(err_string,XSTR("There are too many players in the game\n\nMax : %d\nCurrently %d\n\nPlease dump a few", 792), Netgame.max_players,player_count);
5309 
5310  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, err_string);
5311  return 0;
5312  }
5313 
5314  // check to see if teams are assigned properly in a team vs. team situation
5316  if(!multi_team_ok_to_commit()){
5318  popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("Teams and/or team captains are not assigned properly", 793));
5319  return 0;
5320  }
5321  }
5322 
5323  // verify cd's
5324  if(!multi_create_verify_cds()){
5326 
5327  popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("You need 1 CD for every 4 players!", 794));
5328 
5329  return 0;
5330  }
5331 
5332  // if we're playing on the tracker
5334 //#ifdef PXO_CHECK_VALID_MISSIONS
5335  if ( (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) && (Multi_create_mission_list[abs_index].valid_status != MVALID_STATUS_VALID) ) {
5336  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("You have selected a mission which is either invalid or unknown to PXO. Your stats will not be saved if you continue",996)) <= 0){
5337  return 0;
5338  }
5339  }
5340 //#endif
5341 
5342  // non-squad war
5343  if(!(Netgame.type_flags & NG_TYPE_SW)){
5344  // if he is playing by himself, tell him stats will not be accepted
5345  if(multi_num_players() == 1){
5346  if(popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_TITLE_RED | PF_TITLE_BIG, 2, XSTR("&Back", 995), XSTR("&Continue", 780), XSTR("Warning\n\nIf you start a PXO mission by yourself, your stats will not be updated", 997)) <= 0){
5347  return 0;
5348  }
5349  }
5350  }
5351  // squad war
5352  else {
5353  }
5354  }
5355 
5356  return 1;
5357 }
5358 
5360 {
5361  int player_count = multi_num_players();
5362  int multi_cd_count;
5363  int idx;
5364 
5365  // count how many cds we have
5366  multi_cd_count = 0;
5367  for(idx=0;idx<MAX_PLAYERS;idx++){
5369  multi_cd_count++;
5370  }
5371  }
5372 
5373  // determine if we have enough
5374  float ratio = (float)player_count / (float)multi_cd_count;
5375  // greater than a 4 to 1 ratio
5376  if(ratio > 4.0f){
5377  return 0;
5378  }
5379 
5380  // we meet the conditions
5381  return 1;
5382 }
5383 
5384 // returns an index into Multi_create_mission_list
5386 {
5387  uint idx;
5388 
5389  for (idx = 0; idx < Multi_create_mission_list.size(); idx++) {
5390  if ( !stricmp(fname, Multi_create_mission_list[idx].filename) ) {
5391  return idx;
5392  }
5393  }
5394 
5395  // couldn't find the mission
5396  return -1;
5397 }
5398 
5399 // returns an index into Multi_create_campaign_list
5401 {
5402  uint idx;
5403 
5404  for (idx = 0; idx < Multi_create_campaign_list.size(); idx++) {
5405  if ( !stricmp(fname, Multi_create_campaign_list[idx].filename) ) {
5406  return idx;
5407  }
5408  }
5409 
5410  // couldn't find the campaign
5411  return -1;
5412 }
5413 
5414 
5416 {
5417  // delete mvalid.cfg if it exists
5419 
5420  // refresh missions from the tracker
5422 }
5423 
5425 {
5426  netgame_info ng_temp;
5427  netgame_info *ng;
5428  multi_create_info *mcip;
5429 
5430  int file_index = multi_create_select_to_index(Multi_create_list_select);
5431 
5432  if (file_index < 0) {
5433  Int3();
5434 
5435  if ( Multi_create_sw_checkbox.checked() ) {
5436  Multi_create_sw_checkbox.set_state(0);
5437  }
5438 
5439  return;
5440  }
5441 
5442  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
5443  mcip = &Multi_create_mission_list[file_index];
5444  } else {
5445  mcip = &Multi_create_campaign_list[file_index];
5446  }
5447 
5448  // either a temporary netgame or the real one
5449  if(MULTIPLAYER_MASTER){
5450  ng = &Netgame;
5451  } else {
5452  ng_temp = Netgame;
5453  ng = &ng_temp;
5454  }
5455 
5456  // maybe switch squad war off
5457  if(!Multi_create_sw_checkbox.checked()){
5458  // if the mission selected is a coop mission, go back to coop mode
5459 
5460  if (mcip->flags & MISSION_TYPE_MULTI_TEAMS) {
5461  ng->type_flags = NG_TYPE_TVT;
5462  } else if (mcip->flags & MISSION_TYPE_MULTI_DOGFIGHT) {
5464  } else {
5465  ng->type_flags = NG_TYPE_COOP;
5466  }
5467  }
5468  // switch squad war on
5469  else {
5470  // at this point we know its safe to switch squad war on
5471  ng->type_flags = NG_TYPE_SW;
5472  }
5473 
5474  // update
5476  // update players
5478 
5479  // update all machines about stuff like respawns, etc.
5481  }
5482  // on the standalone
5483  else {
5484  // standalone will take care of polling the usertracker
5485  multi_options_update_mission(ng, Multi_create_list_mode == MULTI_CREATE_SHOW_CAMPAIGNS ? 1 : 0);
5486  }
5487 }
5488 
5489 
5490 // -------------------------------------------------------------------------------------------------------------
5491 //
5492 // MULTIPLAYER HOST OPTIONS SCREEN
5493 //
5494 
5495 #define MULTI_HO_NUM_BUTTONS 12
5496 #define MULTI_HO_NUM_RADIO_BUTTONS 10
5497 
5498 //XSTR:OFF
5499 // bitmaps defs
5500 #define MULTI_HO_PALETTE "InterfacePalette"
5501 
5502 static char *Multi_ho_bitmap_fname[GR_NUM_RESOLUTIONS] = {
5503  "MultiHost", // GR_640
5504  "2_MultiHost" // GR_1024
5505 };
5506 
5507 static char *Multi_ho_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
5508  "MultiHost-M", // GR_640
5509  "2_MultiHost-M" // GR_1024
5510 };
5511 
5512 //XSTR:ON
5513 UI_WINDOW Multi_ho_window; // the window object for the join screen
5514 UI_INPUTBOX Multi_ho_respawns; // the # of respawns allowed in the game
5515 UI_INPUTBOX Multi_ho_time_limit; // mission time limit
5516 UI_INPUTBOX Multi_ho_voice_wait; // wait time between tokens
5517 UI_INPUTBOX Multi_ho_kill_limit; // kill limit in a furball mission
5518 UI_INPUTBOX Multi_ho_obs; // # of observers we'll allow
5519 int Multi_ho_bitmap; // the background bitmap
5520 
5521 // constants for coordinate lookup
5522 #define MULTI_HO_X_COORD 0
5523 #define MULTI_HO_Y_COORD 1
5524 #define MULTI_HO_W_COORD 2
5525 #define MULTI_HO_H_COORD 3
5526 #define MULTI_HO_TEXT_X_COORD 4
5527 #define MULTI_HO_TEXT_Y_COORD 5
5528 
5529 // button defs
5530 #define MULTI_HO_MSG_RANK 0 // highest ranking players can do messaging
5531 #define MULTI_HO_MSG_LEADER 1 // wing/team leaders can do messaging
5532 #define MULTI_HO_MSG_ANY 2 // any player can do messaging
5533 #define MULTI_HO_MSG_HOST 3 // only the host can do messaging
5534 #define MULTI_HO_END_RANK 4 // highest rank can and host can end mission
5535 #define MULTI_HO_END_LEADER 5 // wing/team leaders and host can end the mission
5536 #define MULTI_HO_END_ANY 6 // any player can end the mission
5537 #define MULTI_HO_END_HOST 7 // only host can end the mission
5538 #define MULTI_HO_VOICE_ON 8 // voice toggled on
5539 #define MULTI_HO_VOICE_OFF 9 // voice toggled off
5540 #define MULTI_HO_HOST_MODIFIES 10 // only the host or team captains can modify ships/weapons in briefing
5541 #define MULTI_HO_ACCEPT 11 // accept button
5542 
5544  { // GR_640
5545  // who is allowed to message
5546  ui_button_info("MH_00", 3, 160, 46, 166, 0), // highest rank
5547  ui_button_info("MH_01", 3, 179, 46, 185, 1), // team/wing leader
5548  ui_button_info("MH_02", 3, 196, 46, 203, 2), // any
5549  ui_button_info("MH_03", 3, 214, 46, 220, 3), // host
5550 
5551  // who is allowed to end the mission
5552  ui_button_info("MH_04", 3, 257, 46, 265, 4), // highest rank
5553  ui_button_info("MH_05", 3, 276, 46, 283, 5), // team/wing leader
5554  ui_button_info("MH_06", 3, 294, 46, 300, 6), // any
5555  ui_button_info("MH_07", 3, 311, 46, 317, 7), // host
5556 
5557  // voice on/off button
5558  ui_button_info("MH_09", 542, 158, 545, 185, 9),
5559  ui_button_info("MH_10", 598, 158, 604, 185, 10),
5560 
5561  // host modifies ships
5562  ui_button_info("MH_13", 542, 377, 437, 363, 13),
5563 
5564  // exit
5565  ui_button_info("MH_14", 572, 428, 580, 414, 14),
5566  },
5567  { // GR_1024
5568  // who is allowed to message
5569  ui_button_info("2_MH_00", 5, 256, 73, 269, 0), // highest rank
5570  ui_button_info("2_MH_01", 5, 286, 73, 297, 1), // team/wing leader
5571  ui_button_info("2_MH_02", 5, 314, 73, 325, 2), // any
5572  ui_button_info("2_MH_03", 5, 341, 73, 352, 3), // host
5573 
5574  // who is allowed to end the mission
5575  ui_button_info("2_MH_04", 5, 412, 73, 425, 4), // highest rank
5576  ui_button_info("2_MH_05", 5, 442, 73, 452, 5), // team/wing leader
5577  ui_button_info("2_MH_06", 5, 470, 73, 480, 6), // any
5578  ui_button_info("2_MH_07", 5, 497, 73, 508, 7), // host
5579 
5580  // voice on/off button
5581  ui_button_info("2_MH_09", 867, 253, 872, 296, 9),
5582  ui_button_info("2_MH_10", 957, 253, 966, 296, 10),
5583 
5584  // host modifies ships
5585  ui_button_info("2_MH_13", 867, 603, 784, 581, 13),
5586 
5587  // exit
5588  ui_button_info("2_MH_14", 916, 685, 925, 665, 14),
5589  },
5590 };
5592  { // GR_640
5593  {"Highest rank", 1280, 46, 166, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_MSG_RANK].button},
5594  {"Team / wing-leader", 1281, 46, 185, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_MSG_LEADER].button},
5595  {"Any", 1282, 46, 203, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_MSG_ANY].button},
5596  {"Host", 1283, 46, 220, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_MSG_HOST].button},
5597  {"Highest rank", 1280, 46, 265, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_END_RANK].button},
5598  {"Team / wing-leader", 1281, 46, 283, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_END_LEADER].button},
5599  {"Any", 1282, 46, 300, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_END_ANY].button},
5600  {"Host", 1283, 46, 317, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_END_HOST].button},
5601  {"On", 1285, 545, 185, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_VOICE_ON].button},
5602  {"Off", 1286, 604, 185, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_VOICE_OFF].button},
5603  {"Host modifies ships", 1287, 437, 363, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[0][MULTI_HO_HOST_MODIFIES].button},
5604  {"Exit", 1417, 572, 418, UI_XSTR_COLOR_PINK, -1, &Multi_ho_buttons[0][MULTI_HO_ACCEPT].button},
5605  },
5606  { // GR_1024
5607  {"Highest rank", 1280, 62, 269, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_MSG_RANK].button},
5608  {"Team / wing-leader", 1281, 62, 297, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_MSG_LEADER].button},
5609  {"Any", 1282, 62, 325, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_MSG_ANY].button},
5610  {"Host", 1283, 62, 352, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_MSG_HOST].button},
5611  {"Highest rank", 1280, 62, 425, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_END_RANK].button},
5612  {"Team / wing-leader", 1281, 62, 452, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_END_LEADER].button},
5613  {"Any", 1282, 62, 480, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_END_ANY].button},
5614  {"Host", 1283, 62, 508, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_END_HOST].button},
5615  {"On", 1285, 877, 294, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_VOICE_ON].button},
5616  {"Off", 1286, 967, 293, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_VOICE_OFF].button},
5617  {"Host modifies ships", 1287, 869, 589, UI_XSTR_COLOR_GREEN, -1, &Multi_ho_buttons[1][MULTI_HO_HOST_MODIFIES].button},
5618  {"Exit", 1417, 953, 672, UI_XSTR_COLOR_PINK, -1, &Multi_ho_buttons[1][MULTI_HO_ACCEPT].button},
5619  }
5620 };
5621 
5622 // radio button controls
5623 #define MULTI_HO_NUM_RADIO_GROUPS 3
5624 #define MULTI_HO_MSG_GROUP 0 // group dealing with squadmate messaging
5625 #define MULTI_HO_END_GROUP 1 // group dealing with ending the mission
5626 #define MULTI_HO_VOICE_GROUP 2 // group dealing with voice stuff
5627 int Multi_ho_radio_groups[MULTI_HO_NUM_RADIO_GROUPS] = { // currently selected button in the radio button group
5628  0,0,0
5629 };
5630 int Multi_ho_radio_info[MULTI_HO_NUM_RADIO_BUTTONS][3] = { // info related to each of the radio buttons themselves
5631  // { group #, value, button id# }
5632  {0, 0, 0}, // highest ranking players can do messaging
5633  {0, 1, 1}, // wing/team leaders can do messaging
5634  {0, 2, 2}, // any player can do messaging
5635  {0, 3, 3}, // only host can do messaging
5636  {1, 0, 4}, // highest rank and host can end the mission
5637  {1, 1, 5}, // team/wing leader can end the mission
5638  {1, 2, 6}, // any player can end the mission
5639  {1, 3, 7}, // only the host can end the mission
5640  {2, 0, 8}, // voice toggled on
5641  {2, 1, 9} // voice toggled off
5642 };
5643 
5644 // slider controls
5645 #define MULTI_HO_NUM_SLIDERS 3
5646 #define MULTI_HO_SLIDER_VOICE_QOS 0 // voice quality of sound
5647 #define MULTI_HO_SLIDER_VOICE_DUR 1 // max duration of voice recording
5648 #define MULTI_HO_SLIDER_SKILL 2 // skill level
5649 struct ho_sliders {
5650  char *filename;
5651  int x, y, xt, yt;
5652  int hotspot;
5653  int dot_w;
5654  int dots;
5655  UI_DOT_SLIDER_NEW slider; // because we have a class inside this struct, we need the constructor below..
5656 
5657  ho_sliders(char *name, int x1, int y1, int xt1, int yt1, int h, int _dot_w, int _dots) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), dot_w(_dot_w), dots(_dots){}
5658 };
5660  { // GR_640
5661  ho_sliders("MH_11", 428, 214, 437, 199, 11, 19, 10), // voice qos
5662  ho_sliders("MH_12", 428, 261, 437, 246, 12, 19, 10), // voice duration
5663  ho_sliders("MH_08", 237, 454, 230, 411, 8, 36, 5), // skill level
5664  },
5665  { // GR_1024
5666  ho_sliders("2_MH_11", 684, 343, 690, 323, 11, 32, 10), // voice qos
5667  ho_sliders("2_MH_12", 685, 418, 837, 468, 12, 32, 10), // voice duration
5668  ho_sliders("2_MH_08", 379, 727, 369, 663, 8, 60, 5), // skill level
5669  }
5670 };
5671 
5673 
5675 
5676 // whether or not any of the inputboxes on this screen had focus last frame
5678 
5679 // game information text areas
5680 
5681 // ho titles
5682 #define MULTI_HO_NUM_TITLES 14
5684  { // GR_640
5685  { "AI Orders", 1289, 32, 144, UI_XSTR_COLOR_GREEN, -1, NULL },
5686  { "End Mission", 1290, 32, 242, UI_XSTR_COLOR_GREEN, -1, NULL },
5687  { "Time Limit", 1291, 32, 347, UI_XSTR_COLOR_GREEN, -1, NULL },
5688  { "Min", 1292, 74, 362, UI_XSTR_COLOR_GREEN, -1, NULL },
5689  { "Respawn Limit", 1288, 32, 378, UI_XSTR_COLOR_GREEN, -1, NULL },
5690  { "Kill Limit", 1293, 32, 409, UI_XSTR_COLOR_GREEN, -1, NULL },
5691  { "Observers", 1294, 32, 441, UI_XSTR_COLOR_GREEN, -1, NULL },
5692  { "Skill Level", 1284, 230, 411, UI_XSTR_COLOR_GREEN, -1, NULL },
5693  { "Voice Transmission", 1295, 437, 144, UI_XSTR_COLOR_GREEN, -1, NULL },
5694  { "Voice Quality", 1296, 437, 199, UI_XSTR_COLOR_GREEN, -1, NULL },
5695  { "Message Duration", 1297, 437, 246, UI_XSTR_COLOR_GREEN, -1, NULL },
5696  { "sec", 1522, 523, 292, UI_XSTR_COLOR_GREEN, -1, NULL },
5697  { "sec", 1523, 523, 332, UI_XSTR_COLOR_GREEN, -1, NULL },
5698  { "Voice Wait", 1298, 437, 313, UI_XSTR_COLOR_GREEN, -1, NULL },
5699  },
5700  { // GR_1024
5701  { "AI Orders", 1289, 48, 238, UI_XSTR_COLOR_GREEN, -1, NULL },
5702  { "End Mission", 1290, 48, 394, UI_XSTR_COLOR_GREEN, -1, NULL },
5703  { "Time Limit", 1291, 50, 568, UI_XSTR_COLOR_GREEN, -1, NULL },
5704  { "Min", 1292, 119, 581, UI_XSTR_COLOR_GREEN, -1, NULL },
5705  { "Respawn Limit", 1288, 50, 618, UI_XSTR_COLOR_GREEN, -1, NULL },
5706  { "Kill Limit", 1293, 50, 668, UI_XSTR_COLOR_GREEN, -1, NULL },
5707  { "Observers", 1294, 50, 718, UI_XSTR_COLOR_GREEN, -1, NULL },
5708  { "Skill Level", 1284, 398, 670, UI_XSTR_COLOR_GREEN, -1, NULL },
5709  { "Voice Transmission", 1295, 869, 239, UI_XSTR_COLOR_GREEN, -1, NULL },
5710  { "Voice Quality", 1296, 690, 331, UI_XSTR_COLOR_GREEN, -1, NULL },
5711  { "Message Duration", 1297, 690, 405, UI_XSTR_COLOR_GREEN, -1, NULL },
5712  { "sec", 1522, 837, 467, UI_XSTR_COLOR_GREEN, -1, NULL },
5713  { "sec", 1523, 837, 534, UI_XSTR_COLOR_GREEN, -1, NULL },
5714  { "Voice Wait", 1298, 742, 510, UI_XSTR_COLOR_GREEN, -1, NULL },
5715  }
5716 };
5717 
5718 // mission time limit input box
5720  { // GR_640
5721  36, 362, 36, 17
5722  },
5723  { // GR_1024
5724  58, 581, 57, 27
5725  }
5726 };
5727 
5728 // furball kill limit input box
5730  { // GR_640
5731  36, 425, 45, 17
5732  },
5733  { // GR_1024
5734  58, 684, 72, 27
5735  }
5736 };
5737 
5738 // voice recording duration text display area
5740  { // GR_640
5741  467, 292, 55, 15
5742  },
5743  { // GR_1024
5744  750, 467, 85, 28
5745  }
5746 };
5747 
5748 // voice token wait input box
5750  { // GR_640
5751  467, 332, 55, 15
5752  },
5753  { // GR_1024
5754  750, 534, 85, 28
5755  }
5756 };
5757 
5758 // observer count input box
5760  { // GR_640
5761  36, 457, 45, 17
5762  },
5763  { // GR_1024
5764  58, 733, 72, 27
5765  }
5766 };
5767 
5768 // skill text description area
5770  { // GR_640
5771  249, 435, 172, 10
5772  },
5773  { // GR_1024
5774  403, 699, 172, 10
5775  }
5776 };
5777 
5778 // respawn input box
5780  { // GR_640
5781  36, 394, 45, 17,
5782  },
5783  { // GR_1024
5784  58, 632, 72, 27
5785  }
5786 };
5787 
5788 // respawn max text area
5790  { // GR_640
5791  150, 378
5792  },
5793  { // GR_1024
5794  190, 618
5795  }
5796 };
5797 
5798 // maximum values for various input boxes (to notify user of overruns)
5799 #define MULTI_HO_MAX_TIME_LIMIT 500
5800 #define MULTI_HO_MAX_TOKEN_WAIT 5
5801 #define MULTI_HO_MAX_KILL_LIMIT 9999
5802 #define MULTI_HO_MAX_OBS 4
5803 
5804 // LOCAL function definitions
5805 void multi_ho_check_buttons();
5806 void multi_ho_button_pressed(int n);
5808 void multi_ho_accept_hit();
5809 void multi_ho_get_options();
5810 void multi_ho_apply_options();
5812 int multi_ho_check_values();
5813 void multi_ho_check_focus();
5816 
5818 {
5819  int idx;
5820 
5821  // create the interface window
5822  Multi_ho_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
5823  Multi_ho_window.set_mask_bmap(Multi_ho_bitmap_mask_fname[gr_screen.res]);
5824 
5825  // load the background bitmap
5826  Multi_ho_bitmap = bm_load(Multi_ho_bitmap_fname[gr_screen.res]);
5827  if(Multi_ho_bitmap < 0){
5828  // we failed to load the bitmap - this is very bad
5829  Int3();
5830  }
5831 
5832  // initialize the common notification messaging
5834 
5835  // use the common interface palette
5837 
5838  // create the interface buttons
5839  for(idx=0;idx<MULTI_HO_NUM_BUTTONS;idx++){
5840  // create the object
5841  Multi_ho_buttons[gr_screen.res][idx].button.create(&Multi_ho_window, "", Multi_ho_buttons[gr_screen.res][idx].x, Multi_ho_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
5842 
5843  // set the sound to play when highlighted
5845 
5846  // set the ani for the button
5847  Multi_ho_buttons[gr_screen.res][idx].button.set_bmaps(Multi_ho_buttons[gr_screen.res][idx].filename);
5848 
5849  // set the hotspot, ignoring the skill level button
5850  Multi_ho_buttons[gr_screen.res][idx].button.link_hotspot(Multi_ho_buttons[gr_screen.res][idx].hotspot);
5851 
5852  // add xstr text
5853  Multi_ho_window.add_XSTR(&Multi_ho_text[gr_screen.res][idx]);
5854  }
5855 
5856  // create misc text
5857  for(idx=0; idx<MULTI_HO_NUM_TITLES; idx++){
5858  Multi_ho_window.add_XSTR(&Multi_ho_titles[gr_screen.res][idx]);
5859  }
5860 
5861  // create the interface sliders
5862  for(idx=0; idx<MULTI_HO_NUM_SLIDERS; idx++){
5863  // create the object
5864  Multi_ho_sliders[gr_screen.res][idx].slider.create(&Multi_ho_window, Multi_ho_sliders[gr_screen.res][idx].x, Multi_ho_sliders[gr_screen.res][idx].y, Multi_ho_sliders[gr_screen.res][idx].dots, Multi_ho_sliders[gr_screen.res][idx].filename, Multi_ho_sliders[gr_screen.res][idx].hotspot, NULL, -1, -1, -1, NULL, -1, -1, -1, Multi_ho_sliders[gr_screen.res][idx].dot_w);
5865  }
5866 
5867  // create the respawn count input box
5868  Multi_ho_respawns.create(&Multi_ho_window,Ho_rsp_coords[gr_screen.res][MULTI_HO_X_COORD],Ho_rsp_coords[gr_screen.res][MULTI_HO_Y_COORD],Ho_rsp_coords[gr_screen.res][MULTI_HO_W_COORD],6,"",UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_NO_LETTERS,-1,&Color_bright);
5869  // if we're in campaign mode, disable it
5871  Multi_ho_respawns.set_text(XSTR("NA",795)); // [[ Not applicable ]]
5872  Multi_ho_respawns.disable();
5873  } else {
5874  Multi_ho_respawns.set_valid_chars("0123456789");
5875  }
5876 
5877  // create the time limit input box
5878  Multi_ho_time_limit.create(&Multi_ho_window, Ho_time_coords[gr_screen.res][MULTI_HO_X_COORD], Ho_time_coords[gr_screen.res][MULTI_HO_Y_COORD], Ho_time_coords[gr_screen.res][MULTI_HO_W_COORD], 3, "", UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_NO_LETTERS, -1, &Color_bright);
5879  Multi_ho_time_limit.set_valid_chars("-0123456789");
5880 
5881  // create the voice token wait input box
5882  Multi_ho_voice_wait.create(&Multi_ho_window, Ho_vw_coords[gr_screen.res][MULTI_HO_X_COORD], Ho_vw_coords[gr_screen.res][MULTI_HO_Y_COORD], Ho_vw_coords[gr_screen.res][MULTI_HO_W_COORD], 1, "", UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_NO_LETTERS, -1, &Color_bright);
5883  Multi_ho_voice_wait.set_valid_chars("01243456789");
5884 
5885  // create the furball kill limit input box
5886  Multi_ho_kill_limit.create(&Multi_ho_window, Ho_kill_coords[gr_screen.res][MULTI_HO_X_COORD], Ho_kill_coords[gr_screen.res][MULTI_HO_Y_COORD], Ho_kill_coords[gr_screen.res][MULTI_HO_W_COORD], 4, "", UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_NO_LETTERS, -1, &Color_bright);
5887  Multi_ho_kill_limit.set_valid_chars("0123456789");
5888 
5889  // create the observer limit input box
5890  Multi_ho_obs.create(&Multi_ho_window, Ho_obs_coords[gr_screen.res][MULTI_HO_X_COORD], Ho_obs_coords[gr_screen.res][MULTI_HO_Y_COORD], Ho_obs_coords[gr_screen.res][MULTI_HO_W_COORD], 1, "", UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_NO_LETTERS, -1, &Color_bright);
5891  Multi_ho_obs.set_valid_chars("01234");
5892 
5893  // load in the current netgame defaults
5895 
5896  // whether or not any of the inputboxes on this screen had focus last frame
5897  Multi_ho_lastframe_input = 0;
5898 
5899  // get the # of respawns for the currently selected mission (if any)
5900  if(Multi_create_list_select != -1){
5901  int abs_index = multi_create_select_to_index(Multi_create_list_select);
5902 
5903  // if he has a valid mission selected
5904  if(abs_index >= 0){
5905  if (Multi_create_list_mode == MULTI_CREATE_SHOW_MISSIONS) {
5906  Multi_ho_mission_respawn = (int)Multi_create_mission_list[abs_index].respawn;
5907  } else {
5908  Multi_ho_mission_respawn = (int)Multi_create_campaign_list[abs_index].respawn;
5909  }
5910  } else {
5911  Multi_ho_mission_respawn = -1;
5912  }
5913  } else {
5914  Multi_ho_mission_respawn = -1;
5915  }
5916 }
5917 
5919 {
5920  // game skill slider
5921  if (Game_skill_level != Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_SKILL].slider.pos) {
5922  if ( !(Netgame.type_flags & NG_TYPE_TEAM) ){
5925  } else {
5927  }
5928  }
5929 
5930  // get the voice qos options
5931  if (Netgame.options.voice_qos != (ubyte)(Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_QOS].slider.pos + 1)) {
5934  }
5935 
5936  // get the voice duration options
5937  if (Netgame.options.voice_record_time != (int)(0.5f * (float)(Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos + 1) * 1000.0f)) {
5938  Netgame.options.voice_record_time = (int)(0.5f * (float)(Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos + 1) * 1000.0f);
5940  }
5941 
5942 }
5943 
5945 {
5946  int k;
5947 
5948  // process stuff
5949  k = Multi_ho_window.process();
5950  chatbox_process(k);
5951 
5952  // process any keypresses
5953  switch(k){
5954  case KEY_ESC :
5956  break;
5957  // same as ACCEPT
5958  case KEY_CTRLED + KEY_ENTER :
5961  break;
5962  }
5963 
5964  // process any button clicks
5966 
5967  // update the sliders
5969 
5970  // make sure that the chatbox inputbox and any inputbox on this screen are mutually exclusive in terms of focus
5972 
5973  // draw the background, etc
5974  gr_reset_clip();
5975  GR_MAYBE_CLEAR_RES(Multi_ho_bitmap);
5976  if(Multi_ho_bitmap != -1){
5977  gr_set_bitmap(Multi_ho_bitmap);
5979  }
5980  Multi_ho_window.draw();
5981 
5982  // draw all the radio buttons properly
5984 
5985  // display any pending notification messages
5987 
5988  // display the voice record time settings
5990 
5991  // maybe display the max # of respawns next to the respawn input box
5993 
5994  // blit the proper skill level
5996 
5997  // blit the "host modifies button"
5998  if(Multi_ho_host_modifies){
5999  Multi_ho_buttons[gr_screen.res][MULTI_HO_HOST_MODIFIES].button.draw_forced(2);
6000  }
6001 
6002  // process and show the chatbox thingie
6003  chatbox_render();
6004 
6005  // draw tooltips
6006  Multi_ho_window.draw_tooltip();
6007 
6008  // display the voice status indicator
6010 
6011  // flip the buffer
6012  gr_flip();
6013 }
6014 
6016 {
6017  // unload any bitmaps
6018  if(!bm_unload(Multi_ho_bitmap)){
6019  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_ho_bitmap_fname[gr_screen.res]));
6020  }
6021 
6022  // destroy the UI_WINDOW
6023  Multi_ho_window.destroy();
6024 }
6025 
6027 {
6028  int idx;
6029  for(idx=0;idx<MULTI_HO_NUM_BUTTONS;idx++){
6030  // we only really need to check for one button pressed at a time, so we can break after
6031  // finding one.
6032  if(Multi_ho_buttons[gr_screen.res][idx].button.pressed()){
6034  break;
6035  }
6036  }
6037 }
6038 
6040 {
6041  int radio_index,idx;
6042  int x_pixel,y_pixel;
6043 
6044  // get the pixel position of the click
6045  Multi_ho_buttons[gr_screen.res][n].button.get_mouse_pos(&x_pixel,&y_pixel);
6046 
6047  switch(n){
6048  // clicked on the accept button
6049  case MULTI_HO_ACCEPT:
6052  return;
6053 
6054  // clicked on the host/captains only modify button
6056  // toggle it on or off
6057  Multi_ho_host_modifies = !Multi_ho_host_modifies;
6059  return;
6060  }
6061 
6062  // look through the radio buttons and see which one this corresponds to
6063  radio_index = -1;
6064  for(idx=0;idx<MULTI_HO_NUM_RADIO_BUTTONS;idx++){
6065  if(Multi_ho_radio_info[idx][2] == n){
6066  radio_index = idx;
6067  break;
6068  }
6069  }
6070  Assert(radio_index != -1);
6071 
6072  // check to see if a radio button was pressed
6073  if(radio_index < MULTI_HO_NUM_RADIO_BUTTONS){
6074  // see if this value is already picked for this radio group
6075  if(Multi_ho_radio_groups[Multi_ho_radio_info[radio_index][0]] != Multi_ho_radio_info[radio_index][1]){
6077  Multi_ho_radio_groups[Multi_ho_radio_info[radio_index][0]] = Multi_ho_radio_info[radio_index][1];
6078  } else {
6080  }
6081  }
6082 }
6083 
6085 {
6086  int idx;
6087 
6088  // go through each item and draw it if it is the selected button in its respective group
6089  for(idx=0;idx<MULTI_HO_NUM_RADIO_BUTTONS;idx++){
6091  if(Multi_ho_radio_info[idx][1] == Multi_ho_radio_groups[Multi_ho_radio_info[idx][0]]){
6092  Multi_ho_buttons[gr_screen.res][Multi_ho_radio_info[idx][2]].button.draw_forced(2);
6093  }
6094  }
6095 }
6096 
6098 {
6099  char resp_str[10];
6100 
6101  // check the values in the input boxes
6102  if(!multi_ho_check_values()){
6103  return;
6104  }
6105 
6106  // zero out the netgame flags
6107  Netgame.flags = 0;
6108 
6109  // set default options
6111 
6112  // set the squadmate messaging flags
6113  switch(Multi_ho_radio_groups[MULTI_HO_MSG_GROUP]){
6114  case 0 :
6116  break;
6117  case 1 :
6119  break;
6120  case 2 :
6122  break;
6123  case 3 :
6125  break;
6126  default :
6127  Int3();
6128  }
6129 
6130  // set the end mission flags
6131  switch(Multi_ho_radio_groups[MULTI_HO_END_GROUP]){
6132  case 0 :
6134  break;
6135  case 1 :
6137  break;
6138  case 2 :
6140  break;
6141  case 3 :
6143  break;
6144  default :
6145  Int3();
6146  }
6147 
6148  // set the voice toggle
6149  switch(Multi_ho_radio_groups[MULTI_HO_VOICE_GROUP]){
6150  case 0 :
6152  break;
6153  case 1 :
6155  break;
6156  default :
6157  Int3();
6158  }
6159 
6160  // get the voice qos options
6162 
6163  // get the voice duration options
6164  Netgame.options.voice_record_time = (int)(0.5f * (float)(Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos + 1) * 1000.0f);
6165 
6166  // set the skill level. If in team vs. team mode, preserve the old setting before saving
6167  // the pilot file. I'll bet that this doesn't work though because the pilot file gets
6168  // written in a bunch of locations....sigh.
6169  if ( !(Netgame.type_flags & NG_TYPE_TEAM) ){
6171  } else {
6173  }
6174 
6175  // set the netgame respawn count
6176  // maybe warn the user that respawns will not be used for a campaign mission
6178  Multi_ho_respawns.get_text(resp_str);
6179  uint temp_respawn = (uint)atoi(resp_str);
6180  // if he currently has no mission selected, let the user set any # of respawns
6181  if((int)temp_respawn > Multi_ho_mission_respawn){
6182  if(Multi_ho_mission_respawn == -1){
6183  Netgame.respawn = temp_respawn;
6184  Netgame.options.respawn = temp_respawn;
6185  }
6186  // this should have been taken care of by the interface code
6187  else {
6188  Int3();
6189  }
6190  } else {
6191  Netgame.options.respawn = temp_respawn;
6192  Netgame.respawn = temp_respawn;
6193  }
6194  }
6195 
6196  // get the mission time limit
6197  Multi_ho_time_limit.get_text(resp_str);
6198  int temp_time = atoi(resp_str);
6199  if(temp_time <= 0){
6201  } else if(temp_time > MULTI_HO_MAX_TIME_LIMIT){
6202  Int3();
6203  } else {
6204  Netgame.options.mission_time_limit = fl2f(60.0f * (float)temp_time);
6205  }
6206 
6207  // get observer count options
6208  Multi_ho_obs.get_text(resp_str);
6209  int temp_obs = atoi(resp_str);
6210  if(temp_obs > MULTI_HO_MAX_OBS){
6211  Int3();
6212  }
6213  Netgame.options.max_observers = (ubyte)temp_obs;
6214 
6215  // get the furball kill limit
6216  Multi_ho_kill_limit.get_text(resp_str);
6217  int temp_kills = atoi(resp_str);
6218  if(temp_kills > MULTI_HO_MAX_KILL_LIMIT){
6219  Int3();
6220  }
6221  Netgame.options.kill_limit = temp_kills;
6222 
6223  // get the token wait limit
6224  Multi_ho_voice_wait.get_text(resp_str);
6225  int temp_wait = atoi(resp_str);
6226  if(temp_wait > MULTI_HO_MAX_TOKEN_WAIT){
6227  Int3();
6228  }
6229  Netgame.options.voice_token_wait = (temp_wait * 1000);
6230 
6231  // set the netgame option
6233 
6234  // get whether we're in host/captains only modify mode
6236  if(Multi_ho_host_modifies){
6238  }
6239 
6240  // store these values locally
6244 
6245  // apply any changes in settings (notify everyone of voice qos changes, etc)
6247 
6248  // move back to the create game screen
6250 }
6251 
6253 {
6254  char resp_str[10];
6255 
6256  // set the squadmate messaging buttons
6257  switch(Netgame.options.squad_set){
6258  case MSO_SQUAD_RANK :
6259  Multi_ho_radio_groups[MULTI_HO_MSG_GROUP] = 0;
6260  break;
6261  case MSO_SQUAD_LEADER:
6262  Multi_ho_radio_groups[MULTI_HO_MSG_GROUP] = 1;
6263  break;
6264  case MSO_SQUAD_ANY:
6265  Multi_ho_radio_groups[MULTI_HO_MSG_GROUP] = 2;
6266  break;
6267  case MSO_SQUAD_HOST:
6268  Multi_ho_radio_groups[MULTI_HO_MSG_GROUP] = 3;
6269  break;
6270  default :
6271  Int3();
6272  }
6273 
6274  // set the mission end buttons
6275  switch(Netgame.options.endgame_set){
6276  case MSO_END_RANK:
6277  Multi_ho_radio_groups[MULTI_HO_END_GROUP] = 0;
6278  break;
6279  case MSO_END_LEADER:
6280  Multi_ho_radio_groups[MULTI_HO_END_GROUP] = 1;
6281  break;
6282  case MSO_END_ANY:
6283  Multi_ho_radio_groups[MULTI_HO_END_GROUP] = 2;
6284  break;
6285  case MSO_END_HOST:
6286  Multi_ho_radio_groups[MULTI_HO_END_GROUP] = 3;
6287  break;
6288  default :
6289  Int3();
6290  }
6291 
6292  // set the voice toggle buttons
6294  Multi_ho_radio_groups[MULTI_HO_VOICE_GROUP] = 1;
6295  } else {
6296  Multi_ho_radio_groups[MULTI_HO_VOICE_GROUP] = 0;
6297  }
6298 
6299  // get the voice qos options
6302 
6303  // get the voice duration options
6305  Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos = ((int)((float)Netgame.options.voice_record_time / 500.0f)) - 1;
6306 
6307  // get the current skill level
6310 
6311  // get the # of observers
6312  memset(resp_str,0,10);
6313  sprintf(resp_str,"%d",Netgame.options.max_observers);
6314  Multi_ho_obs.set_text(resp_str);
6315 
6316  // set the respawn count
6318  memset(resp_str,0,10);
6319  sprintf(resp_str,"%u",Netgame.respawn);
6320  Multi_ho_respawns.set_text(resp_str);
6321  }
6322 
6323  // set the mission time limit
6324  memset(resp_str,0,10);
6325  float tl = f2fl(Netgame.options.mission_time_limit);
6326  sprintf(resp_str,"%d",(int)(tl / 60.0f));
6327  Multi_ho_time_limit.set_text(resp_str);
6328 
6329  // set the furball kill limit
6330  memset(resp_str,0,10);
6331  sprintf(resp_str,"%d",Netgame.options.kill_limit);
6332  Multi_ho_kill_limit.set_text(resp_str);
6333 
6334  // set the token wait time
6335  memset(resp_str,0,10);
6336  sprintf(resp_str,"%d",Netgame.options.voice_token_wait / 1000);
6337  Multi_ho_voice_wait.set_text(resp_str);
6338 
6339  // get whether we're in host/captains only modify mode
6341  Multi_ho_host_modifies = 1;
6342  } else {
6343  Multi_ho_host_modifies = 0;
6344  }
6345 }
6346 
6348 {
6349  // if the voice qos or duration has changed, apply the change
6351 
6352  // send an options update
6354 }
6355 
6356 // display the voice record time settings
6358 {
6359  char time_str[30];
6360  int full_seconds, half_seconds;
6361 
6362  // clear the string
6363  memset(time_str,0,30);
6364 
6365  // get the seconds
6366  full_seconds = (((Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos + 1) * 500) / 1000);
6367 
6368  // get the half-seconds
6369  half_seconds = ((((Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_VOICE_DUR].slider.pos + 1) * 500) % 1000) / 500) * 5;
6370 
6371  // format the string
6372  sprintf(time_str,"%d.%d",full_seconds,half_seconds);
6374  gr_string(Ho_vd_coords[gr_screen.res][MULTI_HO_X_COORD],Ho_vd_coords[gr_screen.res][MULTI_HO_Y_COORD],time_str,GR_RESIZE_MENU);
6375 }
6376 
6378 {
6379  char val_txt[255];
6380 
6381  memset(val_txt,0,255);
6382 
6383  // check against respawn settings
6384  if(Multi_ho_mission_respawn != -1){
6385  Multi_ho_respawns.get_text(val_txt);
6386  // if the value is invalid, let the user know
6387  if(atoi(val_txt) > Multi_ho_mission_respawn){
6388  memset(val_txt,0,255);
6389  sprintf(val_txt,XSTR("Warning\nRespawn count in greater than mission specified max (%d)",796),Multi_ho_mission_respawn);
6391  return 0;
6392  }
6393  }
6394 
6395  // check against mission time limit max
6396  Multi_ho_time_limit.get_text(val_txt);
6397  // if the value is invalid, force it to be valid
6398  if(atoi(val_txt) > MULTI_HO_MAX_TIME_LIMIT){
6399  memset(val_txt,0,255);
6400  sprintf(val_txt,XSTR("Warning\nMission time limit is greater than max allowed (%d)",797),MULTI_HO_MAX_TIME_LIMIT);
6402  return 0;
6403  }
6404 
6405  // check against max observer limit
6406  Multi_ho_obs.get_text(val_txt);
6407  // if the value is invalid, force it to be valid
6408  if(atoi(val_txt) > MULTI_HO_MAX_OBS){
6409  memset(val_txt,0,255);
6410  sprintf(val_txt,XSTR("Warning\nObserver count is greater than max allowed (%d)",798),MULTI_HO_MAX_OBS);
6412  return 0;
6413  }
6414 
6415  // check against furball kill limit
6416  Multi_ho_kill_limit.get_text(val_txt);
6417  // if the value is invalid, force it to be valid
6418  if(atoi(val_txt) > MULTI_HO_MAX_KILL_LIMIT){
6419  memset(val_txt,0,255);
6420  sprintf(val_txt,XSTR("Warning\nMission kill limit is greater than max allowed (%d)",799),MULTI_HO_MAX_KILL_LIMIT);
6422  return 0;
6423  }
6424 
6425  // check against the token wait limit
6426  Multi_ho_voice_wait.get_text(val_txt);
6427  if(atoi(val_txt) > MULTI_HO_MAX_TOKEN_WAIT){
6428  memset(val_txt,0,255);
6429  sprintf(val_txt,XSTR("Warning\nvoice wait time is greater than max allowed (%d)",800),MULTI_HO_MAX_TOKEN_WAIT);
6431  return 0;
6432  }
6433 
6434  // all values are valid
6435  return 1;
6436 }
6437 
6439 {
6440  // if an inputbox has been pressed (hit enter), lose its focus
6441  if (Multi_ho_respawns.pressed() || Multi_ho_time_limit.pressed() || Multi_ho_voice_wait.pressed() || Multi_ho_kill_limit.pressed() || Multi_ho_obs.pressed()) {
6442  Multi_ho_respawns.clear_focus();
6443  Multi_ho_time_limit.clear_focus();
6444  Multi_ho_voice_wait.clear_focus();
6445  Multi_ho_kill_limit.clear_focus();
6446  Multi_ho_obs.clear_focus();
6449  Multi_ho_lastframe_input = 0;
6450 
6451  } else if(!Multi_ho_lastframe_input) {
6452  // if we didn't have focus last frame
6453  if(Multi_ho_respawns.has_focus() || Multi_ho_time_limit.has_focus() || Multi_ho_kill_limit.has_focus() || Multi_ho_voice_wait.has_focus() ){
6455 
6456  Multi_ho_lastframe_input = 1;
6457  }
6458  }
6459  // if we _did_ have focus last frame
6460  else {
6461  // if we no longer have focus on any of the input boxes, set the focus on the chatbox
6462  if(!Multi_ho_respawns.has_focus() && !Multi_ho_time_limit.has_focus() && !Multi_ho_kill_limit.has_focus() && !Multi_ho_voice_wait.has_focus() && !chatbox_has_focus()){
6464  }
6465  // if the chatbox now has focus, clear all focus from our inputboxes
6466  else if (chatbox_has_focus()) {
6467  Multi_ho_respawns.clear_focus();
6468  Multi_ho_time_limit.clear_focus();
6469  Multi_ho_kill_limit.clear_focus();
6470  Multi_ho_voice_wait.clear_focus();
6471 
6472  Multi_ho_lastframe_input = 0;
6473  }
6474  }
6475 }
6476 
6478 {
6479  char string[50];
6480 
6481  // if we're in campaign mode, do nothing
6483  return;
6484  }
6485 
6486  // otherwise blit the max as specified by the current mission file
6487  sprintf(string,"(%d)",Multi_ho_mission_respawn);
6489  gr_string(Ho_max_rsp_coords[gr_screen.res][MULTI_HO_X_COORD], Ho_max_rsp_coords[gr_screen.res][MULTI_HO_Y_COORD], string, GR_RESIZE_MENU);
6490 }
6491 
6493 {
6494  int skill_level = Multi_ho_sliders[gr_screen.res][MULTI_HO_SLIDER_SKILL].slider.pos;
6495 
6496  // sanity
6497  Assert((skill_level >= 0) && (skill_level < NUM_SKILL_LEVELS));
6498  if((skill_level < 0) || (skill_level >= NUM_SKILL_LEVELS)){
6499  skill_level = 0;
6500  }
6501 
6503  gr_string(Ho_st_coords[gr_screen.res][0], Ho_st_coords[gr_screen.res][1], Skill_level_names(skill_level, 1), GR_RESIZE_MENU);
6504 }
6505 
6506 // -------------------------------------------------------------------------------------------------------------
6507 //
6508 // MULTIPLAYER JOIN SCREEN
6509 //
6510 
6511 #define MULTI_JW_NUM_BUTTONS 8
6512 
6513 //XSTR:OFF
6514 // bitmaps defs
6515 #define MULTI_JW_PALETTE "InterfacePalette"
6516 
6517 static char *Multi_jw_bitmap_fname[GR_NUM_RESOLUTIONS] = {
6518  "MultiJoinWait", // GR_640
6519  "2_MultiJoinWait" // GR_1024
6520 };
6521 
6522 static char *Multi_jw_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
6523  "MultiJoinWait-M", // GR_640
6524  "2_MultiJoinWait-M" // GR_1024
6525 };
6526 
6527 //XSTR:ON
6528 
6529 // button defs
6530 #define MJW_SCROLL_PLAYERS_UP 0
6531 #define MJW_SCROLL_PLAYERS_DOWN 1
6532 #define MJW_TEAM0 2
6533 #define MJW_TEAM1 3
6534 #define MJW_PILOT_INFO 4
6535 #define MJW_SCROLL_INFO_UP 5
6536 #define MJW_SCROLL_INFO_DOWN 6
6537 #define MJW_CANCEL 7
6538 
6539 UI_WINDOW Multi_jw_window; // the window object for the join screen
6540 int Multi_jw_bitmap; // the background bitmap
6541 
6542 // constants for coordinate lookup
6543 #define MJW_X_COORD 0
6544 #define MJW_Y_COORD 1
6545 #define MJW_W_COORD 2
6546 #define MJW_H_COORD 3
6547 
6549  { // GR_640
6550  ui_button_info("MJW_00", 1, 24, -1, -1, 0),
6551  ui_button_info("MJW_01", 1, 66, -1, -1, 1),
6552  ui_button_info("MJW_02", 30, 244, 20, 272, 2),
6553  ui_button_info("MJW_03", 84, 244, 73, 272, 3),
6554  ui_button_info("MJW_04", 139, 242, 134, 272, 4),
6555  ui_button_info("MJW_05", 1, 406, -1, -1, 5),
6556  ui_button_info("MJW_06", 1, 447, -1, -1, 6),
6557  ui_button_info("MJW_07", 577, 428, 570, 414, 7),
6558  },
6559  { // GR_1024
6560  ui_button_info("2_MJW_00", 2, 38, -1, -1, 0),
6561  ui_button_info("2_MJW_01", 2, 106, -1, -1, 1),
6562  ui_button_info("2_MJW_02", 48, 390, 47, 435, 2),
6563  ui_button_info("2_MJW_03", 134, 390, 133, 435, 3),
6564  ui_button_info("2_MJW_04", 223, 388, 225, 435, 4),
6565  ui_button_info("2_MJW_05", 2, 649, -1, -1, 5),
6566  ui_button_info("2_MJW_06", 2, 715, -1, -1, 6),
6567  ui_button_info("2_MJW_07", 923, 685, 931, 667, 7),
6568  }
6569 };
6570 
6571 #define MULTI_JW_NUM_TEXT 7
6572 
6574  { // GR_640
6575  { "Team 1", 1308, 20, 272, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[0][MJW_TEAM0].button },
6576  { "Team 2", 1309, 73, 272, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[0][MJW_TEAM1].button },
6577  { "Pilot", 1310, 134, 272, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[0][MJW_PILOT_INFO].button },
6578  { "Info", 1311, 134, 283, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[0][MJW_PILOT_INFO].button },
6579  { "Cancel", 387, 570, 414, UI_XSTR_COLOR_PINK, -1, &Multi_jw_buttons[0][MJW_CANCEL].button },
6580  { "Players", 1269, 38, 8, UI_XSTR_COLOR_GREEN, -1, NULL },
6581  { "Choose Team", 1312, 27, 231, UI_XSTR_COLOR_GREEN, -1, NULL },
6582  },
6583  { // GR_1024
6584  { "Team 1", 1308, 47, 435, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[1][MJW_TEAM0].button },
6585  { "Team 2", 1309, 133, 435, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[1][MJW_TEAM1].button },
6586  { "Pilot", 1310, 225, 435, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[1][MJW_PILOT_INFO].button },
6587  { "Info", 1311, 225, 446, UI_XSTR_COLOR_GREEN, -1, &Multi_jw_buttons[1][MJW_PILOT_INFO].button },
6588  { "Cancel", 387, 931, 667, UI_XSTR_COLOR_PINK, -1, &Multi_jw_buttons[1][MJW_CANCEL].button },
6589  { "Players", 1269, 165, 12, UI_XSTR_COLOR_GREEN, -1, NULL },
6590  { "Choose Team", 1312, 45, 373, UI_XSTR_COLOR_GREEN, -1, NULL },
6591  }
6592 };
6593 
6595  { // GR_640
6596  29, 18, 153, 210
6597  },
6598  { // GR_1024
6599  46, 29, 254, 336
6600  }
6601 };
6602 
6604  { // GR_640
6605  5, 380
6606  },
6607  { // GR_1024
6608  47, 618
6609  }
6610 };
6611 
6612 // squad war checkbox
6615  "MC_SW_00",
6616  "MC_SW_00",
6617 };
6619  { // GR_640
6620  6, 285
6621  },
6622  { // GR_1024
6623  18, 450
6624  }
6625 };
6627  { // GR_640
6628  6, 305
6629  },
6630  { // GR_640
6631  18, 470
6632  },
6633 };
6634 
6635 
6636 // player list control thingie defs
6637 #define MULTI_JW_PLIST_MAX_DISPLAY 19
6638 int Multi_jw_plist_select_flag; // indicates whether we currently have a selected player
6639 short Multi_jw_plist_select_id; // id of the current selected player
6640 UI_BUTTON Multi_jw_plist_select_button; // for selecting a player
6641 
6643 
6644 // LOCAL function definitions
6645 void multi_jw_check_buttons();
6646 void multi_jw_button_pressed(int n);
6647 void multi_jw_do_netstuff();
6650 void multi_jw_plist_process();
6653 short multi_jw_get_mouse_id();
6654 
6656 {
6657  int idx;
6658 
6659  // create the interface window
6660  Multi_jw_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
6661  Multi_jw_window.set_mask_bmap(Multi_jw_bitmap_mask_fname[gr_screen.res]);
6662 
6663  // load the background bitmap
6664  Multi_jw_bitmap = bm_load(Multi_jw_bitmap_fname[gr_screen.res]);
6665  if(Multi_jw_bitmap < 0){
6666  // we failed to load the bitmap - this is very bad
6667  Int3();
6668  }
6669 
6670  // initialize the player list data
6671  Multi_jw_plist_select_flag = 0;
6672  Multi_jw_plist_select_id = -1;
6673 
6674  // kill any old instances of the chatbox and create a new one
6675  chatbox_close();
6677 
6678  // initialize the common notification messaging
6680 
6681  // initialize the common mission info display area.
6682  multi_common_set_text("");
6683 
6684  // use the common interface palette
6686 
6687  // create the interface buttons
6688  for(idx=0; idx<MULTI_JW_NUM_BUTTONS; idx++){
6689  // create the object
6690  Multi_jw_buttons[gr_screen.res][idx].button.create(&Multi_jw_window, "", Multi_jw_buttons[gr_screen.res][idx].x, Multi_jw_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
6691 
6692  // set the sound to play when highlighted
6694 
6695  // set the ani for the button
6696  Multi_jw_buttons[gr_screen.res][idx].button.set_bmaps(Multi_jw_buttons[gr_screen.res][idx].filename);
6697 
6698  // set the hotspot
6699  Multi_jw_buttons[gr_screen.res][idx].button.link_hotspot(Multi_jw_buttons[gr_screen.res][idx].hotspot);
6700  }
6701 
6702  // if this is a PXO game, enable the squadwar checkbox
6703  Multi_jw_sw_checkbox.create(&Multi_jw_window, "", Multi_jw_sw_checkbox_coords[gr_screen.res][0], Multi_jw_sw_checkbox_coords[gr_screen.res][1], 0);
6704  Multi_jw_sw_checkbox.set_bmaps(Multi_jw_sw_checkbox_fname[gr_screen.res], 6, 0);
6705  Multi_jw_sw_checkbox.disable();
6706  if(!MULTI_IS_TRACKER_GAME){
6707  Multi_jw_sw_checkbox.hide();
6708  }
6709 
6710  // create all xstrs
6711  for(idx=0; idx<MULTI_JW_NUM_TEXT; idx++){
6712  Multi_jw_window.add_XSTR(&Multi_jw_text[gr_screen.res][idx]);
6713  }
6714 
6715  // create the player select list button and hide it
6716  Multi_jw_plist_select_button.create(&Multi_jw_window, "", Mjw_players_coords[gr_screen.res][MJW_X_COORD], Mjw_players_coords[gr_screen.res][MJW_Y_COORD], Mjw_players_coords[gr_screen.res][MJW_W_COORD], Mjw_players_coords[gr_screen.res][MJW_H_COORD], 0, 1);
6717  Multi_jw_plist_select_button.hide();
6718 
6719  // set hotkeys
6720  Multi_jw_buttons[gr_screen.res][MJW_CANCEL].button.set_hotkey(KEY_ESC);
6721 
6722  // remove campaign flags
6724 
6725  // tell the server we have finished joining
6728 
6729  // NETLOG
6730  ml_printf(NOX("Joined netgame %s"), Netgame.name);
6731 
6732  // send any appropriate files
6734 }
6735 
6737 {
6738  int player_index;
6739  int k = chatbox_process();
6740  char mission_text[255];
6741  k = Multi_jw_window.process(k,0);
6742 
6743  Multi_jw_should_show_popup = 0;
6744 
6745  // process any button clicks
6747 
6748  // do any network related stuff
6750 
6751  // draw the background, etc
6752  gr_reset_clip();
6753  GR_MAYBE_CLEAR_RES(Multi_jw_bitmap);
6754  if(Multi_jw_bitmap != -1){
6755  gr_set_bitmap(Multi_jw_bitmap);
6757  }
6758 
6759  // if we're not in team vs. team mode, don't draw the team buttons
6760  if(!(Netgame.type_flags & NG_TYPE_TEAM)){
6761  Multi_jw_buttons[gr_screen.res][MJW_TEAM0].button.hide();
6762  Multi_jw_buttons[gr_screen.res][MJW_TEAM1].button.hide();
6763  Multi_jw_buttons[gr_screen.res][MJW_TEAM0].button.disable();
6764  Multi_jw_buttons[gr_screen.res][MJW_TEAM1].button.disable();
6765  } else {
6766  Multi_jw_buttons[gr_screen.res][MJW_TEAM0].button.enable();
6767  Multi_jw_buttons[gr_screen.res][MJW_TEAM1].button.enable();
6768  Multi_jw_buttons[gr_screen.res][MJW_TEAM0].button.unhide();
6769  Multi_jw_buttons[gr_screen.res][MJW_TEAM1].button.unhide();
6770  }
6771 
6773  // maybe check the squadwar button
6775  Multi_jw_sw_checkbox.set_state(1);
6777  } else {
6778  Multi_jw_sw_checkbox.set_state(0);
6780  }
6781 
6782  gr_string(Multi_jw_sw_checkbox_text[gr_screen.res][0], Multi_jw_sw_checkbox_text[gr_screen.res][1], "SquadWar", GR_RESIZE_MENU);
6783  }
6784 
6785  // draw the UI window
6786  Multi_jw_window.draw();
6787 
6788  // process and display the player list
6789  // NOTE : this must be done before the buttons are checked to insure that a player hasn't dropped
6793  } else {
6795  }
6796 
6797  // display any text in the info area
6799 
6800  // display any pending notification messages
6802 
6803  // blit the mission filename if possible
6804  if(Netgame.campaign_mode){
6805  if(Netgame.campaign_name[0] != '\0'){
6806  strcpy_s(mission_text,Netgame.campaign_name);
6807 
6808  if(Netgame.title[0] != '\0'){
6809  strcat_s(mission_text,", ");
6810  strcat_s(mission_text,Netgame.title);
6811  }
6812 
6814  gr_string(Mjw_mission_name_coords[gr_screen.res][MJW_X_COORD],Mjw_mission_name_coords[gr_screen.res][MJW_Y_COORD],mission_text,GR_RESIZE_MENU);
6815  }
6816  } else {
6817  if(Netgame.mission_name[0] != '\0'){
6818  strcpy_s(mission_text,Netgame.mission_name);
6819 
6820  if(Netgame.title[0] != '\0'){
6821  strcat_s(mission_text,", ");
6822  strcat_s(mission_text,Netgame.title);
6823  }
6824 
6826  gr_string(Mjw_mission_name_coords[gr_screen.res][MJW_X_COORD],Mjw_mission_name_coords[gr_screen.res][MJW_Y_COORD],mission_text,GR_RESIZE_MENU);
6827  }
6828  }
6829 
6830  // process and show the chatbox thingie
6831  chatbox_render();
6832 
6833  // draw tooltips
6834  Multi_jw_window.draw_tooltip();
6835 
6836  // display the voice status indicator
6838 
6839  // flip the buffer
6840  gr_flip();
6841 
6842  // if we're supposed to be displaying a pilot info popup
6843  if(Multi_jw_should_show_popup){
6844  player_index = find_player_id(Multi_jw_plist_select_id);
6845  if(player_index != -1){
6846  multi_pinfo_popup(&Net_players[player_index]);
6847  }
6848  }
6849 }
6850 
6852 {
6853  // unload any bitmaps
6854  if(!bm_unload(Multi_jw_bitmap)){
6855  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_jw_bitmap_fname[gr_screen.res]));
6856  }
6857 
6858  // destroy the chatbox
6859  // chatbox_close();
6860 
6861  // destroy the UI_WINDOW
6862  Multi_jw_window.destroy();
6863 
6864  // play a sound.
6867  }
6868 }
6869 
6870 
6872 {
6873  int idx;
6874  for(idx=0;idx<MULTI_JW_NUM_BUTTONS;idx++){
6875  // we only really need to check for one button pressed at a time, so we can break after
6876  // finding one.
6877  if(Multi_jw_buttons[gr_screen.res][idx].button.pressed()){
6879  break;
6880  }
6881  }
6882 }
6883 
6885 {
6886  switch(n){
6887  case MJW_CANCEL:
6890  break;
6891  case MJW_SCROLL_PLAYERS_UP:
6893  break;
6896  break;
6897  case MJW_SCROLL_INFO_UP:
6899  break;
6900  case MJW_SCROLL_INFO_DOWN:
6902  break;
6903 
6904  // request to set myself to team 0
6905  case MJW_TEAM0:
6908  break;
6909 
6910  // request to set myself to team 1
6911  case MJW_TEAM1:
6914  break;
6915 
6916  // pilot info popup
6917  case MJW_PILOT_INFO:
6918  Multi_jw_should_show_popup = 1;
6919  break;
6920 
6921  default :
6922  multi_common_add_notify(XSTR("Not implemented yet!",760));
6923  break;
6924  }
6925 }
6926 
6927 // do stuff like pinging servers, sending out requests, etc
6929 {
6930 }
6931 
6933 {
6935 }
6936 
6937 // scroll down through the player list
6939 {
6941 }
6942 
6944 {
6945  int test_count,player_index,idx;
6946 
6947  // first determine if there are 0 players in the game. This should never happen since the host is _always_ in the game
6948  test_count = 0;
6949  for(idx=0;idx<MAX_PLAYERS;idx++){
6950  // count anyone except the standalone server (if applicable)
6952  test_count++;
6953  }
6954  }
6955  if(test_count <= 0){
6956  return;
6957  }
6958 
6959  // if we had a selected item but that player has left, select myself instead
6960  if(Multi_jw_plist_select_flag){
6961  player_index = find_player_id(Multi_jw_plist_select_id);
6962  if(player_index == -1){
6963  Multi_jw_plist_select_id = Net_player->player_id;
6964  }
6965  } else {
6966  Multi_jw_plist_select_flag = 1;
6967  Multi_jw_plist_select_id = Net_player->player_id;
6968  }
6969 
6970  // if the player has clicked somewhere in the player list area
6971  if(Multi_jw_plist_select_button.pressed()){
6972  short player_id;
6973 
6974  player_id = multi_jw_get_mouse_id();
6975  player_index = find_player_id(player_id);
6976  if(player_index != -1){
6977  Multi_jw_plist_select_id = player_id;
6978  Multi_jw_plist_select_flag = 1;
6979  }
6980  }
6981 }
6982 
6984 {
6985  int idx;
6986  char str[CALLSIGN_LEN+1];
6987  int y_start = Mjw_players_coords[gr_screen.res][MJW_Y_COORD];
6988  int line_height = gr_get_font_height() + 1;
6989  int total_offset;
6990 
6991  // display all the players
6992  for(idx=0;idx<MAX_PLAYERS;idx++){
6993  // reset total offset
6994  total_offset = 0;
6995 
6996  // count anyone except the standalone server (if applicable)
6998  // highlight him if he's the host
7000  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7002  } else {
7004  }
7005  } else {
7006  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7008  } else {
7010  }
7011  }
7012 
7013  // optionally draw his CD status
7016  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start - 1,GR_RESIZE_MENU);
7017 
7018  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
7019  }
7020 
7021  // make sure the string will fit, then display it
7022  strcpy_s(str,Net_players[idx].m_player->callsign);
7024  strcat_s(str,"(0)");
7025  }
7026  gr_force_fit_string(str,CALLSIGN_LEN,Mjw_players_coords[gr_screen.res][MJW_W_COORD] - total_offset);
7027  gr_string(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
7028 
7029  y_start += line_height;
7030  }
7031  }
7032 }
7033 
7035 {
7036  int idx;
7037  char str[CALLSIGN_LEN+1];
7038  int y_start = Mjw_players_coords[gr_screen.res][MJW_Y_COORD];
7039  int line_height = gr_get_font_height() + 1;
7040  int total_offset;
7041 
7042  // always blit the proper team button based on _my_ team status
7043  if(Net_player->p_info.team == 0){
7044  Multi_jw_buttons[gr_screen.res][MJW_TEAM0].button.draw_forced(2);
7045  } else {
7046  Multi_jw_buttons[gr_screen.res][MJW_TEAM1].button.draw_forced(2);
7047  }
7048 
7049  // display all the red players first
7050  for(idx=0;idx<MAX_PLAYERS;idx++){
7051  // reset total offset
7052  total_offset = 0;
7053 
7054  // count anyone except the standalone server (if applicable)
7055  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_players[idx].p_info.team == 0)){
7056  // highlight him if he's the host
7058  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7060  } else {
7062  }
7063  } else {
7064  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7066  } else {
7068  }
7069  }
7070 
7071  // optionally draw his CD status
7074  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start - 1, GR_RESIZE_MENU);
7075 
7076  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
7077  }
7078 
7079  // blit the red team indicator
7083  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start-2,GR_RESIZE_MENU);
7084 
7085  total_offset += Multi_common_icon_dims[MICON_TEAM0_SELECT][0] + 1;
7086  }
7087  } else {
7088  if(Multi_common_icons[MICON_TEAM0] != -1){
7090  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start-2,GR_RESIZE_MENU);
7091 
7092  total_offset += Multi_common_icon_dims[MICON_TEAM0][0] + 1;
7093  }
7094  }
7095 
7096  // make sure the string will fit
7097  strcpy_s(str,Net_players[idx].m_player->callsign);
7098  gr_force_fit_string(str,CALLSIGN_LEN,Mjw_players_coords[gr_screen.res][MJW_W_COORD] - total_offset);
7099 
7100  // display him in the correct half of the list depending on his team
7101  gr_string(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
7102  y_start += line_height;
7103  }
7104  }
7105 
7106  // display all the green players next
7107  for(idx=0;idx<MAX_PLAYERS;idx++){
7108  // reset total offset
7109  total_offset = 0;
7110 
7111  // count anyone except the standalone server (if applicable)
7112  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_players[idx].p_info.team == 1)){
7113  // highlight him if he's the host
7115  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7117  } else {
7119  }
7120  } else {
7121  if(Multi_jw_plist_select_id == Net_players[idx].player_id){
7123  } else {
7125  }
7126  }
7127 
7128  // optionally draw his CD status
7131  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start - 1,GR_RESIZE_MENU);
7132 
7133  total_offset += Multi_common_icon_dims[MICON_CD][0] + 1;
7134  }
7135 
7136  // blit the red team indicator
7140  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start-2,GR_RESIZE_MENU);
7141 
7142  total_offset += Multi_common_icon_dims[MICON_TEAM1_SELECT][0] + 1;
7143  }
7144  } else {
7145  if(Multi_common_icons[MICON_TEAM1] != -1){
7147  gr_bitmap(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start-2,GR_RESIZE_MENU);
7148 
7149  total_offset += Multi_common_icon_dims[MICON_TEAM1][0] + 1;
7150  }
7151  }
7152 
7153  // make sure the string will fit
7154  strcpy_s(str,Net_players[idx].m_player->callsign);
7156  strcat_s(str,"(0)");
7157  }
7158  gr_force_fit_string(str,CALLSIGN_LEN,Mjw_players_coords[gr_screen.res][MJW_W_COORD] - total_offset);
7159 
7160  // display him in the correct half of the list depending on his team
7161  gr_string(Mjw_players_coords[gr_screen.res][MJW_X_COORD] + total_offset,y_start,str,GR_RESIZE_MENU);
7162  y_start += line_height;
7163  }
7164  }
7165 }
7166 
7168 {
7169  // for now just play a bloop sound
7171 }
7172 
7174 {
7175  // determine where he clicked (y pixel value)
7176  int y,nth,idx;
7177  Multi_jw_plist_select_button.get_mouse_pos(NULL,&y);
7178 
7179  // select things a little differently if we're in team vs. team or non-team vs. team mode
7180  nth = (y / (gr_get_font_height() + 1));
7182  int player_index = -1;
7183 
7184  // look through all of team red first
7185  for(idx=0;idx<MAX_PLAYERS;idx++){
7187  nth--;
7188 
7189  // if this is the _nth_ guy
7190  if(nth < 0){
7191  player_index = idx;
7192  break;
7193  }
7194  }
7195  }
7196 
7197  // if we still haven't found him yet, look through the green team
7198  if(player_index == -1){
7199  for(idx=0;idx<MAX_PLAYERS;idx++){
7201  nth--;
7202  // if this is the _nth_ guy
7203  if(nth < 0){
7204  player_index = idx;
7205  break;
7206  }
7207  }
7208  }
7209  }
7210  if(player_index != -1){
7211  return Net_players[idx].player_id;
7212  }
7213  } else {
7214  // select the nth active player if possible, disregarding the standalone server
7215  for(idx=0;idx<MAX_PLAYERS;idx++){
7217  nth--;
7218 
7219  // if this is the _nth_ guy
7220  if(nth < 0){
7221  return Net_players[idx].player_id;
7222  }
7223  }
7224  }
7225  return -1;
7226  }
7227 
7228  return -1;
7229 }
7230 
7231 
7232 // -------------------------------------------------------------------------------------------------------------
7233 //
7234 // MULTIPLAYER WAIT/SYNCH SCREEN
7235 //
7236 
7237 #define MULTI_SYNC_HOST_COUNT 4 // host uses 4 buttons (and sometimes 5)
7238 #define MULTI_SYNC_CLIENT_COUNT 3 // client only uses 3 buttons
7239 
7241  "MultiSynch", // GR_640
7242  "2_MultiSynch" // GR_1024
7243 };
7244 
7246  "MultiSynch-M", // GR_640
7247  "2_MultiSynch-M" // GR_1024
7248 };
7249 
7250 //XSTR:ON
7251 
7252 // constants for coordinate lookup
7253 #define MS_X_COORD 0
7254 #define MS_Y_COORD 1
7255 #define MS_W_COORD 2
7256 #define MS_H_COORD 3
7257 
7258 UI_WINDOW Multi_sync_window; // the window object for the join screen
7259 int Multi_sync_button_count; // the # of buttons to use for this instance of mission sync
7260 int Multi_sync_bitmap; // the background bitmap
7261 
7262 // button defs
7263 #define MULTI_SYNC_NUM_BUTTONS 5
7264 #define MS_SCROLL_INFO_UP 0
7265 #define MS_SCROLL_INFO_DOWN 1
7266 #define MS_CANCEL 2
7267 #define MS_KICK 3
7268 #define MS_LAUNCH 4
7270  { // GR_640
7271  ui_button_info("MS_00", 1, 404, -1, -1, 0),
7272  ui_button_info("MS_01", 1, 446, -1, -1, 1),
7273  ui_button_info("MS_03", 518, 426, 519, 416, 3),
7274  ui_button_info("MS_02", 469, 426, 479, 416, 2),
7275  ui_button_info("MS_04", 571, 420, 577, 416, 4),
7276  },
7277  { // GR_1024
7278  ui_button_info("2_MS_00", 2, 647, -1, -1, 0),
7279  ui_button_info("2_MS_01", 2, 713, -1, -1, 1),
7280  ui_button_info("2_MS_03", 829, 682, 831, 667, 3),
7281  ui_button_info("2_MS_02", 751, 682, 766, 667, 2),
7282  ui_button_info("2_MS_04", 914, 672, 924, 667, 4),
7283  }
7284 };
7285 
7286 // text
7287 #define MULTI_SYNC_NUM_TEXT 5
7288 #define MST_KICK 0
7289 #define MST_LAUNCH 2
7291  { // GR_640
7292  { "Kick", 1266, 479, 416, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[0][MS_KICK].button },
7293  { "Cancel", 387, 519, 416, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[0][MS_CANCEL].button },
7294  { "Launch", 801, 577, 416, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[0][MS_LAUNCH].button },
7295  { "Players", 1269, 23, 133, UI_XSTR_COLOR_GREEN, -1, NULL },
7296  { "Status", 1304, 228, 133, UI_XSTR_COLOR_GREEN, -1, NULL }
7297  },
7298  { // GR_1024
7299  { "Kick", 1266, 766, 667, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[1][MS_KICK].button },
7300  { "Cancel", 387, 831, 667, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[1][MS_CANCEL].button },
7301  { "Launch", 801, 924, 667, UI_XSTR_COLOR_PINK, -1, &Multi_sync_buttons[1][MS_LAUNCH].button },
7302  { "Players", 1269, 38, 214, UI_XSTR_COLOR_GREEN, -1, NULL },
7303  { "Status", 1304, 366, 214, UI_XSTR_COLOR_GREEN, -1, NULL }
7304  }
7305 };
7306 
7307 // player name
7309  { // GR_640
7310  38, 150, 581, 220
7311  },
7312  { // GR_1024
7313  38, 228, 958, 367
7314  }
7315 };
7316 
7317 // player status coords
7319  { // GR_640
7320  228, 150, 391, 220
7321  },
7322  { // GR_1024
7323  370, 228, 626, 367
7324  }
7325 };
7326 
7328  10, // GR_640
7329  10 // GR_1024
7330 };
7331 
7333  38, // GR_640
7334  38 // GR_1024
7335 };
7336 
7337 // player currently selected, index into Net_players[]
7339 
7340 // player list control thingie defs
7341 #define MULTI_SYNC_PLIST_MAX_DISPLAY 15
7342 int Multi_sync_plist_start; // where to start displaying from
7343 int Multi_sync_plist_count; // how many we have
7344 
7345 // list select button
7347 
7349 
7350 #define MULTI_SYNC_COUNTDOWN_TIME 5 // in seconds
7353 
7355 
7356 //XSTR:OFF
7357 // countdown animation timer
7359  "Count", // GR_640
7360  "2_Count" // GR_1024
7361 };
7362 
7364  {
7365  0, 0 // GR_640
7366  },
7367  {
7368  0, 0 // GR_1024
7369  }
7370 };
7371 
7372 //XSTR:ON
7373 
7374 static generic_anim Multi_sync_countdown_anim;
7375 
7376 
7377 // PREBRIEFING STUFF
7378 // syncing flags used by the server
7380 #define MS_FLAG_SENT_FILESIG (1<<0) // sent filesig requests
7381 #define MS_FLAG_SENT_LOAD (1<<1) // sent load packets
7382 #define MS_FLAG_PUSHED_BRIEFING (1<<2) // pushed everyone else into the briefing
7383 #define MS_FLAG_POST_DATA (1<<3) // sent the post data block
7384 #define MS_FLAG_WSS_SLOTS (1<<4) // all players have received wss slot data
7385 #define MS_FLAG_PSETTINGS (1<<5) // send the player settings packet
7386 #define MS_FLAG_MT_STATS_START (1<<6) // server has started getting player stats from the tracker
7387 #define MS_FLAG_MT_STATS_DONE (1<<7) // server has finished getting player stats from the tracker (success or fail)
7388 #define MS_FLAG_TS_SLOTS (1<<8) // team/ship slots have been sent
7389 #define MS_FLAG_DATA_DONE (1<<9) // done transferring all necessary data
7390 #define MS_FLAG_CAMP_DONE (1<<10) // send campaign pool/goal/event stuff
7391 
7392 // POSTBRIEFING STUFF
7395 
7396 // LOCAL function definitions
7398 void multi_sync_button_pressed(int n);
7401 void multi_sync_display_name(const char *name,int index,int np_index); // display info on the left hand portion of the status window thingie
7402 void multi_sync_display_status(const char *status,int index); // display info on the right hand portion of the status window thingie
7405 void multi_sync_launch();
7409 
7410 void multi_sync_common_init();
7411 void multi_sync_common_do();
7413 
7414 void multi_sync_pre_init();
7415 void multi_sync_pre_do();
7416 void multi_sync_pre_close();
7417 
7418 void multi_sync_post_init();
7419 void multi_sync_post_do();
7420 void multi_sync_post_close();
7421 
7422 int Sync_test = 1;
7423 
7424 
7425 // perform the correct init functions
7427 {
7428  Multi_sync_countdown = -1;
7429 
7430  Sync_test = 1;
7431 
7432  // reset all timestamp
7434 
7437  }
7438 
7439  switch(Multi_sync_mode){
7442  break;
7445  break;
7446  case MULTI_SYNC_INGAME:
7448  break;
7449  }
7450 }
7451 
7452 // perform the correct do frame functions
7454 {
7457  }
7458 
7459  // if the netgame is ending, don't do any sync processing
7460  if(multi_endgame_ending()){
7461  return;
7462  }
7463 
7464  // process appropriateliy
7465  switch(Multi_sync_mode){
7467  multi_sync_pre_do();
7468  break;
7471  break;
7472  case MULTI_SYNC_INGAME:
7474 
7475  gr_reset_clip();
7476  GR_MAYBE_CLEAR_RES(Multi_sync_bitmap);
7477  if(Multi_sync_bitmap != -1){
7478  gr_set_bitmap(Multi_sync_bitmap);
7480  }
7481  Multi_sync_window.draw();
7482 
7484 
7485  gr_flip();
7486  break;
7487  }
7488 }
7489 
7490 // perform the correct close functions
7492 {
7493  switch(Multi_sync_mode){
7496  break;
7499  break;
7500  case MULTI_SYNC_INGAME:
7502  break;
7503  }
7504 
7507  }
7508 }
7509 
7510 const char *multi_sync_tooltip_handler(const char *str)
7511 {
7512  if (!stricmp(str, NOX("@launch"))) {
7513  if (Multi_launch_button_created){
7514  return XSTR("Launch",801);
7515  }
7516  }
7517 
7518  return NULL;
7519 }
7520 
7522 {
7523  int idx;
7524 
7525  // create the interface window
7526  Multi_sync_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
7527  Multi_sync_window.set_mask_bmap(Multi_sync_bitmap_mask_fname[gr_screen.res]);
7528  Multi_sync_window.tooltip_handler = multi_sync_tooltip_handler;
7529 
7530  // load the background bitmap
7531  Multi_sync_bitmap = bm_load(Multi_sync_bitmap_fname[gr_screen.res]);
7532  if (Multi_sync_bitmap < 0) {
7533  // we failed to load the bitmap - this is very bad
7534  Int3();
7535  }
7536 
7537  // initialize the player list data
7538  Multi_sync_plist_start = 0;
7539  Multi_sync_plist_count = 1; // we can pretty safely assume that there's one player in the game - me.
7540 
7541  Multi_launch_button_created = 0;
7542 
7543  // create the chatbox thingie (shouldn't be necesary to do this, but we'll put it in for good measure)
7544  chatbox_create();
7545 
7546  // force the chatbox to be small
7548 
7549  // initialize the common notification messaging
7551 
7552  // initialize the common mission info display area.
7553  multi_common_set_text("");
7554 
7555  // use the common interface palette
7557 
7558  // don't select any player yet.
7559  Multi_sync_player_select = -1;
7560 
7561  // determine how many of the 5 buttons to create
7563  Multi_sync_button_count = MULTI_SYNC_HOST_COUNT;
7564  } else {
7565  Multi_sync_button_count = MULTI_SYNC_CLIENT_COUNT;
7566  }
7567  // create the interface buttons
7568  for(idx=0; idx<Multi_sync_button_count; idx++){
7569  // create the object
7570  Multi_sync_buttons[gr_screen.res][idx].button.create(&Multi_sync_window, "", Multi_sync_buttons[gr_screen.res][idx].x, Multi_sync_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
7571 
7572  // set the sound to play when highlighted
7574 
7575  // set the ani for the button
7576  // this wierdness is necessary because cancel and kick buttons aren't drawn on the background bitmap,
7577  // so we have to load in frame 0, too (the file should exist)
7578  if ((idx == MS_CANCEL) || (idx == MS_KICK) || (idx == MS_LAUNCH)) {
7579  Multi_sync_buttons[gr_screen.res][idx].button.set_bmaps(Multi_sync_buttons[gr_screen.res][idx].filename, 3, 0);
7580  } else {
7581  Multi_sync_buttons[gr_screen.res][idx].button.set_bmaps(Multi_sync_buttons[gr_screen.res][idx].filename);
7582  }
7583 
7584  // set the hotspot
7585  Multi_sync_buttons[gr_screen.res][idx].button.link_hotspot(Multi_sync_buttons[gr_screen.res][idx].hotspot);
7586  }
7587 
7588  // add xstrs
7589  for(idx=0; idx<MULTI_SYNC_NUM_TEXT; idx++) {
7590  // don't create the "launch" button text just yet
7591  if(idx == MST_LAUNCH) {
7592  continue;
7593  }
7594  // multiplayer clients should ignore the kick button
7595  if(!MULTIPLAYER_MASTER && !MULTIPLAYER_HOST && (idx == MST_KICK)) {
7596  continue;
7597  }
7598 
7599  Multi_sync_window.add_XSTR(&Multi_sync_text[gr_screen.res][idx]);
7600  }
7601 
7602  // create the player list select button and hide it
7603  Multi_sync_plist_button.create(&Multi_sync_window, "", Ms_status_coords[gr_screen.res][MS_X_COORD], Ms_status_coords[gr_screen.res][MS_Y_COORD], Ms_status_coords[gr_screen.res][MS_W_COORD], Ms_status_coords[gr_screen.res][MS_H_COORD], 0, 1);
7604  Multi_sync_plist_button.hide();
7605 
7606  // set up hotkeys for certain common functions
7607  Multi_sync_buttons[gr_screen.res][MS_CANCEL].button.set_hotkey(KEY_ESC);
7608 }
7609 
7611 {
7612  int k = chatbox_process();
7613  k = Multi_sync_window.process(k);
7614 
7615  // process the player list
7617 
7618  // process any button clicks
7620 
7621  // process any keypresses
7622  switch(k){
7623  case KEY_ESC :
7624  // Sync_test = 1;
7627  break;
7628  }
7629 }
7630 
7632 {
7633  // unload any bitmaps
7634  if(!bm_unload(Multi_sync_bitmap)){
7635  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_sync_bitmap_fname[gr_screen.res]));
7636  }
7637 
7638  // destroy the UI_WINDOW
7639  Multi_sync_window.destroy();
7640 }
7641 
7643 {
7644  int count,idx;
7645  int state;
7646  float pct_complete;
7647  char txt[255];
7648 
7649  // display any text in the info area
7651 
7652  // display any pending notification messages
7654 
7655  // display any info about visible players
7656  count = 0;
7657  for(idx=0;idx<MAX_PLAYERS;idx++){
7659  // display his name and status
7660  multi_sync_display_name(Net_players[idx].m_player->callsign,count,idx);
7661 
7662  // get the player state
7663  state = Net_players[idx].state;
7664 
7665  // if we're ingame joining, show all other players except myself as "playing"
7666  if((Net_player != NULL) && (&Net_players[idx] != Net_player) && ((Multi_sync_mode == MULTI_SYNC_INGAME) || (Net_player->flags & NETINFO_FLAG_INGAME_JOIN)) ){
7668  }
7669 
7670  switch(state){
7672  multi_sync_display_status(XSTR("Mission Loading",802),count);
7673  break;
7674  case NETPLAYER_STATE_INGAME_SHIP_SELECT: // I don't think its possible to see this state, but...
7675  multi_sync_display_status(XSTR("Ingame Ship Select",803),count);
7676  break;
7678  multi_sync_display_status(XSTR("Debriefing",804),count);
7679  break;
7681  multi_sync_display_status(XSTR("Mission Sync",805),count);
7682  break;
7684  multi_sync_display_status(XSTR("Joining",806),count);
7685  break;
7686  case NETPLAYER_STATE_JOINED:
7687  multi_sync_display_status(XSTR("Joined",807),count);
7688  break;
7689  case NETPLAYER_STATE_SLOT_ACK :
7690  multi_sync_display_status(XSTR("Slot Ack",808),count);
7691  break;
7693  multi_sync_display_status(XSTR("Briefing",765),count);
7694  break;
7696  multi_sync_display_status(XSTR("Ship Select",809),count);
7697  break;
7699  multi_sync_display_status(XSTR("Weapon Select",810),count);
7700  break;
7702  multi_sync_display_status(XSTR("Waiting",811),count);
7703  break;
7705  multi_sync_display_status(XSTR("In Mission",812),count);
7706  break;
7708  multi_sync_display_status(XSTR("Mission Loaded",813),count);
7709  break;
7711  multi_sync_display_status(XSTR("Data loading",814),count);
7712  break;
7714  multi_sync_display_status(XSTR("Ready To Enter Mission",815),count);
7715  break;
7717  multi_sync_display_status(XSTR("Ingame Ships Packet Ack",816),count);
7718  break;
7720  multi_sync_display_status(XSTR("Ingame Wings Packet Ack",817),count);
7721  break;
7723  multi_sync_display_status(XSTR("Ingame Respawn Points Ack",818),count);
7724  break;
7726  multi_sync_display_status(XSTR("Ingame Weapon Slots Ack",819),count);
7727  break;
7729  multi_sync_display_status(XSTR("Post Briefing Data Block Ack",820),count);
7730  break;
7732  multi_sync_display_status(XSTR("Flags Ack",821),count);
7733  break;
7735  multi_sync_display_status(XSTR("Parallax Online Stats Updating",822),count);
7736  break;
7738  multi_sync_display_status(XSTR("Weapon Slots Ack",823),count);
7739  break;
7741  multi_sync_display_status(XSTR("Host setup",824),count);
7742  break;
7744  multi_sync_display_status(XSTR("Debrief accept",825),count);
7745  break;
7747  multi_sync_display_status(XSTR("Debrief replay",826),count);
7748  break;
7750  multi_sync_display_status(XSTR("Campaign ship/weapon ack",827),count);
7751  break;
7753  memset(txt,0,255);
7754  // server should display the pct completion of all clients
7756  if(Net_players[idx].s_info.xfer_handle != -1){
7757  pct_complete = multi_xfer_pct_complete(Net_players[idx].s_info.xfer_handle);
7758 
7759  // if we've got a valid xfer handle
7760  if((pct_complete >= 0.0) && (pct_complete <= 1.0)){
7761  sprintf(txt,XSTR("Mission file xfer %d%%",828),(int)(pct_complete * 100.0f));
7762  }
7763  // otherwise
7764  else {
7765  strcpy_s(txt,XSTR("Mission file xfer",829));
7766  }
7767  } else {
7768  strcpy_s(txt,XSTR("Mission file xfer",829));
7769  }
7770  }
7771  // clients should display only for themselves (which is the only thing they know)
7772  else {
7773  // if we've got a valid file xfer handle
7774  if((&Net_players[idx] == Net_player) && (Net_player->s_info.xfer_handle != -1)){
7776 
7777  // if we've got a valid xfer handle
7778  if((pct_complete >= 0.0) && (pct_complete <= 1.0)){
7779  sprintf(txt,XSTR("Mission file xfer %d%%",828),(int)(pct_complete * 100.0f));
7780  }
7781  // otherwise
7782  else {
7783  strcpy_s(txt,XSTR("Mission file xfer",829));
7784  }
7785  }
7786  // otherwise
7787  else {
7788  strcpy_s(txt,XSTR("Mission file xfer",829));
7789  }
7790  }
7791 
7792  // display the text
7793  multi_sync_display_status(txt,count);
7794  break;
7795  default :
7796  nprintf(("Network","Unhandled player state : %d !\n",Net_players[idx].state));
7797  break;
7798  }
7799  count++;
7800  }
7801  }
7802 
7803  // display the mission start countdown timer (if any)
7804  //anim_render_all(GS_STATE_MULTI_MISSION_SYNC,flFrametime);
7805  if((gameseq_get_state() == GS_STATE_MULTI_MISSION_SYNC && Multi_sync_countdown_timer > -1.0f) || (Multi_sync_countdown != -1))
7806  generic_anim_render(&Multi_sync_countdown_anim, flFrametime, Multi_sync_countdown_coords[gr_screen.res][MS_X_COORD], Multi_sync_countdown_coords[gr_screen.res][MS_Y_COORD], true);
7807 
7808 
7809  // process and show the chatbox thingie
7810  chatbox_render();
7811 
7812  // draw tooltips
7813  Multi_sync_window.draw_tooltip();
7814 
7815  // display the voice status indicator
7817 }
7818 
7820 {
7821  int idx;
7822  for(idx=0;idx<Multi_sync_button_count;idx++){
7823  // we only really need to check for one button pressed at a time, so we can break after
7824  // finding one.
7825  if(Multi_sync_buttons[gr_screen.res][idx].button.pressed()){
7827  break;
7828  }
7829  }
7830 }
7831 
7833 {
7834  switch(n){
7835  // exit the game
7836  case MS_CANCEL:
7839  break;
7840 
7841  // scroll the info box up
7842  case MS_SCROLL_INFO_UP:
7844  break;
7845 
7846  // scroll the info box down
7847  case MS_SCROLL_INFO_DOWN:
7849  break;
7850 
7851  // KICK (host only)
7852  case MS_KICK:
7853  // if we have a currently selected player, kick him
7854  if(Multi_sync_player_select >= 0){
7855  multi_kick_player(Multi_sync_player_select);
7856  }
7857  break;
7858 
7859  // start the final launch countdown (post-sync only)
7860  case MS_LAUNCH:
7862  break;
7863 
7864  // doesn't do anything
7865  default :
7866  Int3();
7867  }
7868 }
7869 
7871 {
7872  int idx;
7873 
7875 
7876  /* if we're in teamplay mode, always force skill level to be medium
7877  Karajorma - disabling cause it's just plain idiotic! if people want to play on insane let them
7878 
7879  if((Netgame.type_flags & NG_TYPE_TEAM) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){
7880  Netgame.options.skill_level = NUM_SKILL_LEVELS / 2;
7881  Game_skill_level = NUM_SKILL_LEVELS / 2;
7882  multi_options_update_netgame();
7883  }
7884  */
7885 
7886  // notify everyone of when we get here
7890  }
7891 
7893  // NETLOG
7894  ml_string(NOX("Server performing pre-briefing data sync"));
7895 
7896  if(!(Game_mode & GM_STANDALONE_SERVER)){
7897  multi_common_set_text(XSTR("Server performing sync\n",830),1);
7898  }
7899 
7900  // maybe initialize tvt and squad war stuff
7903  }
7904 
7905  // force everyone into this state
7907 
7908  if(!(Game_mode & GM_STANDALONE_SERVER)){
7909  multi_common_add_text(XSTR("Send update packet\n",831),1);
7910  }
7911 
7912  // setup some of my own data
7914 
7915  // do any output stuff
7916  if (Game_mode & GM_STANDALONE_SERVER) {
7917  std_debug_set_standalone_state_string("Mission Sync");
7918  }
7919 
7920  // do this here to insure we have the most up to date file checksum info
7922  // parse_get_file_signature(Game_current_mission_filename);
7923 
7924  if(!(Game_mode & GM_STANDALONE_SERVER)){
7925  multi_common_add_text(XSTR("Got file signatures\n",832),1);
7926  }
7927  } else {
7928  if(!(Game_mode & GM_STANDALONE_SERVER)){
7929  multi_common_add_text(XSTR("Sending update state packet\n",833),1);
7930  }
7931  }
7932 
7933  // if we're not in team vs. team mode - set all player teams to be 0, and unset all captaincy bits
7934  if(!(Netgame.type_flags & NG_TYPE_TEAM)){
7935  for(idx=0;idx<MAX_PLAYERS;idx++){
7936  Net_players[idx].p_info.team = 0;
7938  }
7939  }
7940 
7941  // we aren't necessarily xferring the mission file yet
7943 
7944  // always call this for good measure
7946 
7947  Mission_sync_flags = 0;
7949 }
7950 
7952 {
7953  int idx;
7954 
7955  // If I'm the server, wait for everyone to arrive in this state, then begin transferring data, etc.
7956  // all servers (standalone or no, go through this)
7958  // wait for everyone to arrive, then request filesig from all of them
7961  Mission_sync_flags |= MS_FLAG_SENT_FILESIG;
7962 
7964  multi_common_add_text(XSTR("Sent filesig request\n",834),1);
7965  }
7966  }
7967 
7968  // if we're waiting for players to receive files, then check on their status
7969  if((Mission_sync_flags & MS_FLAG_SENT_FILESIG) && !multi_netplayer_flag_check(NETINFO_FLAG_MISSION_OK) && !multi_endgame_ending()){
7970  for(idx=0;idx<MAX_PLAYERS;idx++){
7971  // if this player is in the process of xferring a file
7972  if(MULTI_CONNECTED(Net_players[idx]) && (Net_players[idx].s_info.xfer_handle != -1)){
7973  switch(multi_xfer_get_status(Net_players[idx].s_info.xfer_handle)){
7974  // if it has successfully completed, set his ok flag
7975  case MULTI_XFER_SUCCESS :
7976  // set his ok flag
7978 
7979  // release the xfer instance handle
7980  multi_xfer_release_handle(Net_players[idx].s_info.xfer_handle);
7982  break;
7983  // if it has failed or timed-out, kick the player
7984  case MULTI_XFER_TIMEDOUT:
7985  case MULTI_XFER_FAIL:
7986  // release the xfer handle
7987  multi_xfer_release_handle(Net_players[idx].s_info.xfer_handle);
7989 
7990  // kick the loser
7992  break;
7993  }
7994  }
7995  }
7996  }
7997 
7998  // NOTE : this is now obsolete
7999  // once everyone is verified, do any data transfer necessary
8001  // do nothing for now
8002  Mission_sync_flags |= MS_FLAG_DATA_DONE;
8003 
8004  // send campaign pool data
8006  }
8007 
8008  // wait for everyone to ack on campaign pool data (even in non-campaign situations)
8009  if((Mission_sync_flags & MS_FLAG_DATA_DONE) && !(Mission_sync_flags & MS_FLAG_CAMP_DONE) && !multi_endgame_ending()){
8010  // check to see if everyone has acked the campaign pool data
8012  Mission_sync_flags |= MS_FLAG_CAMP_DONE;
8013  }
8014  }
8015 
8016  // once everyone is verified, tell them to load the mission
8017  // also make sure to load the mission myself _AFTER_ telling everyone to do so. This makes the whole process
8018  // move along faster
8019  if((Mission_sync_flags & MS_FLAG_CAMP_DONE) && !(Mission_sync_flags & MS_FLAG_SENT_LOAD) && !multi_endgame_ending()){
8021  Mission_sync_flags |= MS_FLAG_SENT_LOAD;
8022 
8024  multi_common_add_text(XSTR("Sent load packet\n",835),1);
8025  }
8026 
8027  // load the mission myself, as soon as possible
8028  if(!Multi_mission_loaded){
8029  nprintf(("Network","Server loading mission..."));
8030 
8031  // update everyone about my status
8034 
8036  psnet_flush();
8037  nprintf(("Network","Done\n"));
8038  Multi_mission_loaded = 1;
8039 
8040  // update everyone about my status
8043 
8044  if(!(Game_mode & GM_STANDALONE_SERVER)){
8045  multi_common_add_text(XSTR("Loaded mission locally\n",836),1);
8046  }
8047  }
8048  }
8049 
8050  // if everyone has loaded the mission, randomly assign players to ships
8052  // call the team select function to assign players to their ships, wings, etc
8055 
8056  // mark this flag
8057  Mission_sync_flags |= MS_FLAG_TS_SLOTS;
8058  }
8059 
8060  // if everyone has loaded the mission, move to the team select stage
8061  if(Sync_test && multi_netplayer_state_check(NETPLAYER_STATE_SLOT_ACK) && !(Mission_sync_flags & MS_FLAG_PUSHED_BRIEFING) && !multi_endgame_ending()){
8063  send_netgame_update_packet(); // this will push everyone into the next state
8064 
8065  // the standalone moves to his own wait state, whereas in the normal game mode, the server/host moves in to the
8066  // team select state
8069  } else {
8071  }
8072 
8073  Mission_sync_flags |= MS_FLAG_PUSHED_BRIEFING;
8074 
8075  if(!(Game_mode & GM_STANDALONE_SERVER)){
8076  multi_common_add_text(XSTR("Moving to team select\n",837),1);
8077  }
8078  }
8079  } else {
8080  // clients should detect here if they are doing a file xfer and do error processing
8083  // if it has successfully completed, set his ok flag
8084  case MULTI_XFER_SUCCESS :
8085  // release my xfer handle
8087  Net_player->s_info.xfer_handle = -1;
8088  break;
8089 
8090  // if it has failed or timed-out, kick the player
8091  case MULTI_XFER_TIMEDOUT:
8092  case MULTI_XFER_FAIL:
8093  // release my xfer handle
8096 
8097  // leave the game qith an error code
8099  break;
8100  }
8101  }
8102  }
8103 
8104  // blit stuff
8106  gr_reset_clip();
8107  GR_MAYBE_CLEAR_RES(Multi_sync_bitmap);
8108  if(Multi_sync_bitmap != -1){
8109  gr_set_bitmap(Multi_sync_bitmap);
8111  }
8112  Multi_sync_window.draw();
8113 
8115 
8116  gr_flip();
8117  }
8118 }
8119 
8121 {
8122  // at this point, we should shut down any file xfers...
8123  if(Net_player->s_info.xfer_handle != -1){
8124  nprintf(("Network","WARNING - killing file xfer while leaving mission sync state!!!\n"));
8125 
8128  }
8129 }
8130 
8132 {
8134 
8135  Multi_state_timestamp = timestamp(0);
8136 
8137  // NETLOG
8138  ml_string(NOX("Performing post-briefing data sync"));
8139 
8141  multi_common_add_text(XSTR("Server performing sync\n",830),1);
8142  } else {
8143  multi_common_add_text(XSTR("Client performing sync\n",838),1);
8144  }
8145 
8146  // everyone should re-initialize these
8148 
8149  // reset all sequencing info
8151 
8152  // if I am not the master of the game, then send the firing information for my ship
8153  // to the host
8156  }
8157 
8158  // if I'm not a standalone server, load up the countdown stuff
8160  generic_anim_init(&Multi_sync_countdown_anim, Multi_sync_countdown_fname[gr_screen.res]);
8161  Multi_sync_countdown_anim.ani.bg_type = bm_get_type(Multi_sync_bitmap);
8162  generic_anim_stream(&Multi_sync_countdown_anim);
8163  if(Multi_sync_countdown_anim.num_frames < 1){
8164  nprintf(("General","WARNING!, Could not load countdown animation %s!\n",Multi_sync_countdown_fname[gr_screen.res]));
8165  }
8166  }
8167 
8168  // create objects for all permanent observers
8170 
8171  // clear the game start countdown timer
8172  Multi_sync_countdown_timer = -1.0f;
8173  Multi_sync_countdown = -1;
8174 
8175  // if this is a team vs. team mission, mark all ship teams appropriately
8178  }
8179 
8180  Mission_sync_flags = 0;
8181  Multi_sync_launch_pressed = 0;
8182 }
8183 
8184 #define MULTI_POST_TIMESTAMP 7000
8185 
8186 extern int create_wings();
8187 
8189 {
8190  int idx;
8191 
8192  // only if the host is also the master should he be doing this (non-standalone situation)
8194 
8195  // once everyone gets to this screen, send them the ship classes of all ships.
8196  if(multi_netplayer_state_check(NETPLAYER_STATE_WAITING) && !(Mission_sync_flags & MS_FLAG_POST_DATA)) {
8197  // only the host should ever do this
8199  // at this point we want to delete all necessary ships, change all necessary ship classes, and set all weapons up
8201 
8202  // update player ets settings
8203  for(idx=0;idx<MAX_PLAYERS;idx++){
8204  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].m_player->objnum != -1)){
8206  }
8207  }
8208  }
8209 
8210  // note that this is done a little differently for standalones and nonstandalones
8212 
8213  multi_common_add_text(XSTR("Sending post briefing block information\n",839),1);
8214 
8215  Mission_sync_flags |= MS_FLAG_POST_DATA;
8216  }
8217 
8218  // send weapon slots data
8220  // note that this is done a little differently for standalones and nonstandalones
8224  } else {
8226  }
8227 
8228  multi_common_add_text(XSTR("Sending weapon slots information\n",840),1);
8229 
8230  Mission_sync_flags |= MS_FLAG_WSS_SLOTS;
8231  }
8232 
8233  // once weapon information is received, send player settings info
8234  if ( multi_netplayer_state_check(NETPLAYER_STATE_WSS_ACK) && !(Mission_sync_flags & MS_FLAG_PSETTINGS)) {
8236 
8237  // server (specifically, the standalone), should set this here
8240 
8241  multi_common_add_text(XSTR("Sending player settings packets\n",841),1);
8242 
8243  Mission_sync_flags |= MS_FLAG_PSETTINGS;
8244  }
8245 
8246  // check to see if the countdown timer has started and act appropriately
8247  if( Multi_sync_countdown_timer > -1.0f ) {
8248 
8249  // increment by frametime.
8250  Multi_sync_countdown_timer += flFrametime;
8251 
8252  // if the next second has expired
8253  if( Multi_sync_countdown_timer >= 1.0f ) {
8254 
8255  Multi_sync_countdown--;
8256  Multi_sync_countdown_timer = 0.0f;
8257 
8258  // if the countdown has reached 0, launch the mission
8259  if(Multi_sync_countdown == 0){
8260  Multi_sync_countdown_timer = -1.0f;
8261 
8262  Multi_sync_launch_pressed = 0;
8264  }
8265  // otherwise send a countdown packet
8266  else {
8267  send_countdown_packet(Multi_sync_countdown);
8268  }
8269  }
8270  }
8271 
8272  // jump into the mission myself
8273  if((Multi_sync_countdown == 0) && multi_netplayer_state_check(NETPLAYER_STATE_IN_MISSION)){
8274  if(!((Net_player->flags & NETINFO_FLAG_GAME_HOST) && !Multi_sync_launch_pressed)){
8278 
8279  multi_common_add_text(XSTR("Moving into game\n",842),1);
8280  }
8281  }
8282  }
8283 
8284  // host - specific stuff
8286  // create the launch button so the host can click
8289  }
8290  }
8291 
8292  // blit stuff
8294  gr_reset_clip();
8295  GR_MAYBE_CLEAR_RES(Multi_sync_bitmap);
8296  if(Multi_sync_bitmap != -1){
8297  gr_set_bitmap(Multi_sync_bitmap);
8299  }
8300  Multi_sync_window.draw();
8301 
8303 
8304  gr_flip();
8305  }
8306 }
8307 
8309 {
8310  int idx;
8311 
8312  if(Multi_sync_countdown_anim.num_frames > 0)
8313  generic_anim_unload(&Multi_sync_countdown_anim);
8314 
8315  // all players should reset sequencing
8316  for(idx=0;idx<MAX_PLAYERS;idx++){
8320  }
8321  }
8322 
8323  // multiplayer dogfight
8325 
8326  // clients should clear obj_pair array and add pair for themselves
8327  /*
8328  if ( MULTIPLAYER_CLIENT ) {
8329  obj_reset_pairs();
8330  obj_add_pairs( OBJ_INDEX(Player_obj) );
8331  }
8332  */
8333 }
8334 
8335 void multi_sync_display_name(const char *name,int index,int np_index)
8336 {
8337  char fit[CALLSIGN_LEN];
8338  int line_height = gr_get_font_height() + 1;
8339 
8340  // make sure the string actually fits
8341  strcpy_s(fit,name);
8342 
8343  // if we're in team vs. team mode
8345  gr_force_fit_string(fit,CALLSIGN_LEN, Ms_status2_coords[gr_screen.res][MS_X_COORD] - Ms_status_coords[gr_screen.res][MS_X_COORD] - 20 - Ms_cd_icon_offset[gr_screen.res] - Ms_team_icon_offset[gr_screen.res]);
8346 
8347  // if this is the currently selected player, draw him highlighted
8348  if(np_index == Multi_sync_player_select){
8350  } else {
8352  }
8353 
8354  // blit the string
8355  gr_string(Ms_status_coords[gr_screen.res][0] + Ms_cd_icon_offset[gr_screen.res] + Ms_team_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height),fit,GR_RESIZE_MENU);
8356 
8357  // blit his team icon
8358  // team 0
8359  if(Net_players[np_index].p_info.team == 0){
8360  // blit the team captain icon
8361  if(Net_players[np_index].flags & NETINFO_FLAG_TEAM_CAPTAIN){
8364  gr_bitmap(Ms_status_coords[gr_screen.res][MS_X_COORD] + Ms_cd_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height) - 2, GR_RESIZE_MENU);
8365  }
8366  }
8367  // normal team member icon
8368  else {
8369  if(Multi_common_icons[MICON_TEAM0] != -1){
8371  gr_bitmap(Ms_status_coords[gr_screen.res][MS_X_COORD] + Ms_cd_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height) - 2, GR_RESIZE_MENU);
8372  }
8373  }
8374  }
8375  // team 1
8376  else if(Net_players[np_index].p_info.team == 1){
8377  // blit the team captain icon
8381  gr_bitmap(Ms_status_coords[gr_screen.res][MS_X_COORD] + Ms_cd_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height) - 2, GR_RESIZE_MENU);
8382  }
8383  }
8384  // normal team member icon
8385  else {
8386  if(Multi_common_icons[MICON_TEAM1] != -1){
8388  gr_bitmap(Ms_status_coords[gr_screen.res][MS_X_COORD] + Ms_cd_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height) - 2, GR_RESIZE_MENU);
8389  }
8390  }
8391  }
8392  } else {
8393  gr_force_fit_string(fit, CALLSIGN_LEN, Ms_status2_coords[gr_screen.res][MS_X_COORD] - Ms_status_coords[gr_screen.res][MS_X_COORD] - 20 - Ms_cd_icon_offset[gr_screen.res]);
8394 
8395  // if this is the currently selected player, draw him highlighted
8396  if(np_index == Multi_sync_player_select){
8398  } else {
8400  }
8401 
8402  // blit the string
8403  gr_string(Ms_status_coords[gr_screen.res][MS_X_COORD] + Ms_cd_icon_offset[gr_screen.res], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height),fit,GR_RESIZE_MENU);
8404  }
8405 
8406  // maybe blit his CD status icon
8407  if((Net_players[np_index].flags & NETINFO_FLAG_HAS_CD) && (Multi_common_icons[MICON_CD] != -1)){
8409  gr_bitmap(Ms_status_coords[gr_screen.res][MS_X_COORD], Ms_status_coords[gr_screen.res][MS_Y_COORD] + (index * line_height), GR_RESIZE_MENU);
8410  }
8411 }
8412 
8413 void multi_sync_display_status(const char *status,int index)
8414 {
8415  char fit[250];
8416 
8417  // make sure the string actually fits
8418  strcpy_s(fit, status);
8419  gr_force_fit_string(fit, 250, Ms_status2_coords[gr_screen.res][MS_W_COORD] - 20);
8421  gr_string(Ms_status2_coords[gr_screen.res][MS_X_COORD], Ms_status2_coords[gr_screen.res][MS_Y_COORD] + (index * (gr_get_font_height() + 1)), fit, GR_RESIZE_MENU);
8422 }
8423 
8425 {
8426  int idx;
8427  int want_state = NETPLAYER_STATE_SLOT_ACK; // kick any players who are still in this state
8428 
8429  // go through the player list and boot anyone who isn't in the right state
8430  for(idx=0;idx<MAX_PLAYERS;idx++){
8431  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_player != &Net_players[idx]) && (Net_players[idx].state == want_state)){
8432  multi_kick_player(idx,0);
8433  }
8434  }
8435 }
8436 
8438 {
8439  int idx,idx2;
8440  int kill_state[3];
8441  int num_kill_states;
8442 
8443  // determine the state we want all players in so that we can find those who are not in the state
8444  kill_state[0] = NETPLAYER_STATE_BRIEFING;
8445  kill_state[1] = NETPLAYER_STATE_SHIP_SELECT;
8446  kill_state[2] = NETPLAYER_STATE_WEAPON_SELECT;
8447  num_kill_states = 3;
8448 
8449  // go through the player list and boot anyone who isn't in the right state
8450  for(idx=0;idx<MAX_PLAYERS;idx++){
8452  // check against all kill state
8453  for(idx2 = 0;idx2<num_kill_states;idx2++){
8454  if(Net_players[idx].state == kill_state[idx2]){
8455  multi_kick_player(idx,0);
8456  break;
8457  }
8458  }
8459  }
8460  }
8461 }
8462 
8464 {
8465  // don't allow repeat button presses
8466  if(Multi_sync_launch_pressed){
8467  return;
8468  }
8469 
8470  Multi_sync_launch_pressed = 1;
8471 
8472  // if I'm the server, begin the countdown
8475  Multi_sync_countdown_timer = 0.0f;
8476  Multi_sync_countdown = MULTI_SYNC_COUNTDOWN_TIME;
8477 
8478  // send an initial countdown value
8479  send_countdown_packet(Multi_sync_countdown);
8480  }
8481  // otherwise send the "start countdown" packet to the standalone
8482  else {
8485  }
8486 }
8487 
8489 {
8490  // don't allow repeat button presses
8491  if(Multi_sync_launch_pressed){
8492  return;
8493  }
8494 
8495  Multi_sync_launch_pressed = 1;
8496 
8497  // NETLOG
8498  ml_printf(NOX("Entering mission %s"), Game_current_mission_filename);
8499 
8500  // tell everyone to jump into the mission
8502  Multi_state_timestamp = timestamp(MULTI_POST_TIMESTAMP);
8503 
8504  // set the # of players at the start of the mission
8506  nprintf(("Network","# of players at start of mission : %d\n", Multi_num_players_at_start));
8507 
8508  // initialize datarate limiting for all clients
8510 
8511  multi_common_add_text(XSTR("Sending mission start packet\n",843),1);
8512 }
8513 
8515 {
8516  if (!Multi_launch_button_created) {
8517  // create the object
8518  Multi_sync_buttons[gr_screen.res][MS_LAUNCH].button.create(&Multi_sync_window, "", Multi_sync_buttons[gr_screen.res][MS_LAUNCH].x, Multi_sync_buttons[gr_screen.res][MS_LAUNCH].y, 1, 1, 0, 1);
8519 
8520  // set the sound to play when highlighted
8522 
8523  // set the ani for the button
8524  Multi_sync_buttons[gr_screen.res][MS_LAUNCH].button.set_bmaps(Multi_sync_buttons[gr_screen.res][MS_LAUNCH].filename, 3, 0);
8525 
8526  // set the hotspot
8527  Multi_sync_buttons[gr_screen.res][MS_LAUNCH].button.link_hotspot(Multi_sync_buttons[gr_screen.res][MS_LAUNCH].hotspot);
8528 
8529  // hotkey
8531 
8532  // create the text for the button
8533  Multi_sync_window.add_XSTR(&Multi_sync_text[gr_screen.res][MST_LAUNCH]);
8534 
8535  // increment the button count so we start checking this one
8536  Multi_sync_button_count++;
8537 
8538  Multi_launch_button_created = 1;
8539  }
8540 }
8541 
8543 {
8544  int idx;
8545  int my;
8546  int select_index;
8547 
8548  // if we don't have a currently selected player, select one
8549  if((Multi_sync_player_select < 0) || !MULTI_CONNECTED(Net_players[Multi_sync_player_select])){
8550  for(idx=0;idx<MAX_PLAYERS;idx++){
8552  Multi_sync_player_select = idx;
8553  break;
8554  }
8555  }
8556  }
8557 
8558  // check for button list presses
8559  if(Multi_sync_plist_button.pressed()){
8560  // get the y mouse coords
8561  Multi_sync_plist_button.get_mouse_pos(NULL,&my);
8562 
8563  // get the index of the item selected
8564  select_index = my / (gr_get_font_height() + 1);
8565 
8566  // if the index is greater than the current # connections, do nothing
8567  if(select_index > (multi_num_connections() - 1)){
8568  return;
8569  }
8570 
8571  // translate into an absolute Net_players[] index (get the Nth net player)
8572  Multi_sync_player_select = -1;
8573  for(idx=0;idx<MAX_PLAYERS;idx++){
8575  select_index--;
8576  }
8577 
8578  // if we've found the item we're looking for
8579  if(select_index < 0){
8580  Multi_sync_player_select = idx;
8581  break;
8582  }
8583  }
8584 
8585  // if for some bizarre reason, this is an invalid player, unselect him and wait for the next interation
8586  // of the loop
8587  if((Multi_sync_player_select >= 0) && (!MULTI_CONNECTED(Net_players[Multi_sync_player_select]) || MULTI_STANDALONE(Net_players[Multi_sync_player_select])) ){
8588  Multi_sync_player_select = -1;
8589  }
8590  }
8591 }
8592 
8593 
8594 // -------------------------------------------------------------------------------------------------------------
8595 //
8596 // MULTIPLAYER DEBRIEF SCREEN
8597 //
8598 
8599 // other relevant data
8602 
8603 // set if the server has left the game
8605 
8606 // if we've reported on TvT status all players are in the debrief
8608 
8609 // whether stats are being accepted
8610 // -1 == no decision yet
8611 // 1 == accepted
8612 // 0 == tossed
8613 
8614 // kazan - for internal purposes stats are always accepted by default
8616 
8618 
8619 float Multi_debrief_time = 0.0f;
8621 
8623 {
8624  int idx;
8625 
8626  Multi_debrief_time = 0.0f;
8627  Multi_debrief_resend_time = 10.0f;
8628 
8629  // do this to notify the standalone or the normal server that we're in the debrief state and ready to receive packets
8633  }
8634 
8635  // unflag some stuff
8636  for(idx=0;idx<MAX_PLAYERS;idx++){
8637  if(MULTI_CONNECTED(Net_players[idx])){
8639  }
8640  }
8641 
8642  // if text input mode is active, clear it
8644 
8645  // the server has not left yet
8646  Multi_debrief_server_left = 0;
8647 
8648  // have not hit accept or replay yet
8649  Multi_debrief_accept_hit = 0;
8650  Multi_debrief_replay_hit = 0;
8651 
8652  // stats have not been accepted yet
8653  Multi_debrief_stats_accept_code = -1;
8654 
8655  // mark stats as not being store yet
8657 
8658  // no report on TvT yet
8659  Multi_debrief_reported_tvt = 0;
8660 
8661  Multi_debrief_server_framecount = 0;
8662 }
8663 
8665 {
8666  Multi_debrief_time += flFrametime;
8667 
8668  // set the netgame state to be debriefing when appropriate
8672  }
8673 
8674  // evaluate all server stuff
8677  }
8678 }
8679 
8681 {
8684  }
8685 }
8686 
8687 // handle optional mission loop
8689 {
8690  int cur = Campaign.current_mission;
8693  }
8694  bool require_repeat_mission = (Campaign.current_mission == Campaign.next_mission);
8695 
8696  // check for (1) mission loop available, (2) don't have to repeat last mission
8697  if ( (Campaign.missions[cur].flags & CMISSION_FLAG_HAS_LOOP) && (Campaign.loop_mission != -1) && !require_repeat_mission ) {
8698 
8699  char buffer[512];
8701 
8702  int choice = popup(0 , 2, POPUP_NO, POPUP_YES, buffer);
8703  if (choice == 1) {
8704  Campaign.loop_enabled = 1;
8706  }
8707  }
8708 }
8709 
8710 // handle all cases for when the accept key is hit in a multiplayer debriefing
8712 {
8713  // if we already accepted, do nothing
8714  // but he may need to hit accept again after the server has left the game, so allow this
8715  if(Multi_debrief_accept_hit){
8716  return;
8717  }
8718 
8719  // mark this so that we don't hit it again
8720  Multi_debrief_accept_hit = 1;
8721 
8723 
8724  if (MULTI_IS_TRACKER_GAME) {
8725  int res = popup(PF_TITLE | PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_IGNORE_ESC, 3, XSTR("&Cancel", 779), XSTR("&Accept", 844), XSTR("&Toss", 845), XSTR("(Continue Netgame)\nDo you wish to accept these stats?", 846));
8726 
8727  // evaluate the result
8728  switch (res) {
8729  // undo the accept
8730  case -1:
8731  case 0:
8732  Multi_debrief_accept_hit = 0;
8733  return;
8734 
8735  // toss the stats
8736  case 2 :
8737  break;
8738 
8739  // accept the stats
8740  case 1 :
8742  break;
8743  }
8744  }
8745 
8746  // if the server has left the game, always just end the game.
8747  if(Multi_debrief_server_left){
8749  Multi_debrief_server_left = 1;
8750  Multi_debrief_accept_hit = 0;
8751  } else {
8752  Multi_debrief_server_left = 0;
8753  }
8754  } else {
8755  // query the host and see if he wants to accept stats
8757  // if we're on a tracker game, he gets no choice for storing stats
8758  if (MULTI_IS_TRACKER_GAME) {
8760  } else {
8761  int res = popup(PF_TITLE | PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_IGNORE_ESC,3,XSTR("&Cancel",779),XSTR("&Accept",844),XSTR("&Toss",845),XSTR("(Continue Netgame)\nDo you wish to accept these stats?",846));
8762 
8763  // evaluate the result
8764  switch(res){
8765  // undo the accept
8766  case -1:
8767  case 0:
8768  Multi_debrief_accept_hit = 0;
8769  return;
8770 
8771  // set the accept code to be "not accepting"
8772  case 2 :
8775  break;
8776 
8777  // accept the stats and continue
8778  case 1 :
8781  break;
8782  }
8783  }
8784  }
8785 
8786  // set my netplayer state to be "debrief_accept", and be done with it
8789  }
8790 }
8791 
8792 // handle all cases for when the escape key is hit in a multiplayer debriefing
8794 {
8795  int res;
8796 
8797  if (MULTI_IS_TRACKER_GAME) {
8798  res = popup(PF_TITLE | PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_IGNORE_ESC, 3, XSTR("&Cancel", 779), XSTR("&Accept", 844), XSTR("&Toss", 845), XSTR("(Exit Netgame)\nDo you wish to accept these stats?", 847));
8799 
8800  // evaluate the result
8801  switch (res) {
8802  // undo the accept
8803  case -1:
8804  case 0:
8805  break;
8806 
8807  // toss the stats
8808  case 2 :
8809  break;
8810 
8811  // accept the stats
8812  case 1 :
8814  break;
8815  }
8816  }
8817 
8818  // if the server has left
8819  if(Multi_debrief_server_left){
8821  return;
8822  }
8823 
8824  // display a popup
8826  // if the stats have already been accepted
8827  if((Multi_debrief_stats_accept_code != -1) || (MULTI_IS_TRACKER_GAME)){
8829  } else {
8830  res = popup(PF_TITLE | PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_IGNORE_ESC,3,XSTR("&Cancel",779),XSTR("&Accept",844),XSTR("&Toss",845),XSTR("(Exit Netgame)\nDo you wish to accept these stats?",847));
8831 
8832  // evaluate the result
8833  switch(res){
8834  // undo the accept
8835  case -1:
8836  case 0:
8837  break;
8838 
8839  // set the accept code to be "not accepting"
8840  case 2 :
8843  break;
8844 
8845  // accept the stats and continue
8846  case 1 :
8849  break;
8850  }
8851  }
8852  } else {
8853  // if the stats haven't been accepted yet, or this is a tracker game
8854  if((Multi_debrief_stats_accept_code == -1) && !(MULTI_IS_TRACKER_GAME)){
8855  res = popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON,2,XSTR("&Cancel",779),XSTR("&Leave",848),XSTR("Are you sure you want to leave the netgame before stats are stored?",849));
8856 
8857  // evaluate the result
8858  if(res == 1){
8860  }
8861  }
8862  // otherwise go through the normal endgame channels
8863  else {
8865  }
8866  }
8867 }
8868 
8870 {
8871  // only the host should ever get here
8873 
8874  // if the button was already pressed, do nothing
8875  if(Multi_debrief_accept_hit){
8876  return;
8877  }
8878 
8879  // same as hittin the except button except no stats are kept
8880  Multi_debrief_accept_hit = 1;
8881 
8882  // mark myself as being in the replay state so we know what to do next
8885 }
8886 
8887 // call this when the server has left and we would otherwise be saying "contact lost with server
8889 {
8890  // the server left
8891  Multi_debrief_server_left = 1;
8892 
8893  // undo any "accept" hit so that clients can hit accept again to leave
8894  Multi_debrief_accept_hit = 0;
8895 }
8896 
8898 {
8899  // don't do anything if we've already accepted
8900  if(Multi_debrief_stats_accept_code != -1){
8901  return;
8902  }
8903 
8904  Multi_debrief_stats_accept_code = 1;
8905 
8906  // if we're the host, and we're on a standalone, tell the standalone to begin the stats storing process
8908  // send a packet to the players telling them to store their stats
8910  }
8911 
8912  // add a chat line saying "stats have been accepted"
8913  multi_display_chat_msg(XSTR("<stats have been accepted>",850),0,0);
8914 
8915  // NETLOG
8916  ml_string(NOX("Stats stored"));
8917 }
8918 
8920 {
8921  // don't do anything if we've already accepted
8922  if(Multi_debrief_stats_accept_code != -1){
8923  return;
8924  }
8925 
8926  Multi_debrief_stats_accept_code = 0;
8927 
8928  // if we're the host, and we're on a standalone, tell everyone to "toss" stats
8929  // Kazan - or how about we don't - we tell them we stored them
8931  // send a packet to the players telling them to store their stats
8933  }
8934 
8935  // add a chat line saying "stats have been accepted"
8936  //multi_display_chat_msg(XSTR("<stats have been tossed>",851),0,0);
8937 
8938  // NETLOG
8939  ml_string(NOX("Stats tossed"));
8940 }
8941 
8943 {
8945 }
8946 
8948 {
8949  int idx;
8950  int player_status,other_status;
8951 
8952  Multi_debrief_server_framecount++;
8953 
8954  // if we're > 10 seconds into the debrief and not everyone is here, try warping everyone out again
8955  if((Multi_debrief_time >= Multi_debrief_resend_time) && !multi_netplayer_state_check3(NETPLAYER_STATE_DEBRIEF, NETPLAYER_STATE_DEBRIEF_ACCEPT, NETPLAYER_STATE_DEBRIEF_REPLAY, 1)){
8956  // find all players who are not in the debrief state and hit them with the endgame packet
8957  for(idx=0; idx<MAX_PLAYERS; idx++){
8958  if( MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx]) &&
8959  ( ( Net_players[idx].state != NETPLAYER_STATE_DEBRIEF ) &&
8960  ( Net_players[idx].state != NETPLAYER_STATE_DEBRIEF_ACCEPT ) &&
8961  ( Net_players[idx].state != NETPLAYER_STATE_DEBRIEF_REPLAY ) ) ){
8963  }
8964  }
8965 
8966  // next check time
8967  Multi_debrief_resend_time += 7.0f;
8968  }
8969 
8970  // evaluate the status of all players in the game (0 == not ready, 1 == ready to continue, 2 == ready to replay)
8971  other_status = 1;
8972 
8973  // check all players
8974  for(idx=0;idx<MAX_PLAYERS;idx++){
8976  if(Net_players[idx].state != NETPLAYER_STATE_DEBRIEF_ACCEPT){
8977  other_status = 0;
8978  break;
8979  }
8980  }
8981  }
8982 
8983  // if we haven't already reported TvT results
8984  if(multi_netplayer_state_check3(NETPLAYER_STATE_DEBRIEF, NETPLAYER_STATE_DEBRIEF_ACCEPT, NETPLAYER_STATE_DEBRIEF_REPLAY) && (Netgame.type_flags & NG_TYPE_TEAM) && !Multi_debrief_reported_tvt && (Multi_debrief_server_framecount > 4)){
8986  Multi_debrief_reported_tvt = 1;
8987  }
8988 
8989  // if all other players are good to go, check the host
8990  if(other_status){
8991  // if he is ready to continue
8993  player_status = 1;
8994  }
8995  // if he wants to replay the mission
8997  player_status = 2;
8998  }
8999  // if he is not ready
9000  else {
9001  player_status = 0;
9002  }
9003  }
9004  // if all players are _not_ good to go
9005  else {
9006  player_status = 0;
9007  }
9008 
9009  // if we're in the debriefing state in a campaign mode, process accordingly
9011  multi_campaign_do_debrief(player_status);
9012  }
9013  // otherwise process as normal (looking for all players to be ready to go to the next mission
9014  else {
9015  if(player_status == 1){
9017 
9018  // set the netgame state to be forming and continue
9021 
9022  // move to the proper state
9025  } else {
9027  }
9028 
9030  } else if(player_status == 2){
9032 
9033  // tell everyone to move into the pre-briefing sync state
9036 
9037  // move back to the mission sync screen for the same mission again
9038  Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
9040 
9042  }
9043  }
9044 }
9045 
9046 
9047 // -------------------------------------------------------------------------------------------------------------
9048 //
9049 // MULTIPLAYER PASSWORD POPUP
9050 //
9051 
9052 //XSTR:OFF
9053 // bitmaps defs
9054 static char *Multi_pwd_bitmap_fname[GR_NUM_RESOLUTIONS] = {
9055  "Password", // GR_640
9056  "2_Password" // GR_1024
9057 };
9058 
9059 static char *Multi_pwd_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
9060  "Password-M", // GR_640
9061  "2_Password-M" // GR_1024
9062 };
9063 
9064 //XSTR:ON
9065 
9066 // constants for coordinate lookup
9067 #define MPWD_X_COORD 0
9068 #define MPWD_Y_COORD 1
9069 #define MPWD_W_COORD 2
9070 #define MPWD_H_COORD 3
9071 
9072 // button defs
9073 #define MULTI_PWD_NUM_BUTTONS 2
9074 #define MPWD_CANCEL 0
9075 #define MPWD_COMMIT 1
9076 
9077 // password area defs
9079  { // GR_640
9080  134, 112, 367, 15
9081  },
9082  { // GR_1024
9083  215, 190, 587, 24
9084  }
9085 };
9086 
9087 UI_WINDOW Multi_pwd_window; // the window object for the join screen
9088 UI_INPUTBOX Multi_pwd_passwd; // for Netgame.passwd
9089 int Multi_pwd_bitmap; // the background bitmap
9093 
9094 // password buttons
9096  { // GR_640
9097  ui_button_info("PWB_00", 411, 151, 405, 141, 0),
9098  ui_button_info("PWB_01", 460, 151, 465, 141, 1),
9099  },
9100  { // GR_1024
9101  ui_button_info("2_PWB_00", 659, 242, 649, 225, 0),
9102  ui_button_info("2_PWB_01", 737, 242, 736, 225, 1),
9103  },
9104 };
9105 
9106 // text
9107 #define MULTI_PWD_NUM_TEXT 3
9109  { // GR_640
9110  { "Cancel", 387, 400, 141, UI_XSTR_COLOR_GREEN, -1, &Multi_pwd_buttons[0][MPWD_CANCEL].button},
9111  { "Commit", 1062, 455, 141, UI_XSTR_COLOR_GREEN, -1, &Multi_pwd_buttons[0][MPWD_COMMIT].button},
9112  { "Enter Password", 1332, 149, 92, UI_XSTR_COLOR_GREEN, -1, NULL},
9113  },
9114  { // GR_1024
9115  { "Cancel", 387, 649, 225, UI_XSTR_COLOR_GREEN, -1, &Multi_pwd_buttons[1][MPWD_CANCEL].button},
9116  { "Commit", 1062, 736, 225, UI_XSTR_COLOR_GREEN, -1, &Multi_pwd_buttons[1][MPWD_COMMIT].button},
9117  { "Enter Password", 1332, 239, 148, UI_XSTR_COLOR_GREEN, -1, NULL},
9118  }
9119 };
9120 
9121 // initialize all graphics, etc
9123 {
9124  int idx;
9125 
9126  // store the background as it currently is
9127  Multi_passwd_background = gr_save_screen();
9128 
9129  // create the interface window
9130  Multi_pwd_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
9131  Multi_pwd_window.set_mask_bmap(Multi_pwd_bitmap_mask_fname[gr_screen.res]);
9132 
9133  // load the background bitmap
9134  Multi_pwd_bitmap = bm_load(Multi_pwd_bitmap_fname[gr_screen.res]);
9135  if(Multi_pwd_bitmap < 0){
9136  // we failed to load the bitmap - this is very bad
9137  Int3();
9138  }
9139 
9140  // create the interface buttons
9141  for(idx=0; idx<MULTI_PWD_NUM_BUTTONS; idx++){
9142  // create the object
9143  Multi_pwd_buttons[gr_screen.res][idx].button.create(&Multi_pwd_window, "", Multi_pwd_buttons[gr_screen.res][idx].x, Multi_pwd_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
9144 
9145  // set the sound to play when highlighted
9147 
9148  // set the ani for the button
9149  Multi_pwd_buttons[gr_screen.res][idx].button.set_bmaps(Multi_pwd_buttons[gr_screen.res][idx].filename);
9150 
9151  // set the hotspot
9152  Multi_pwd_buttons[gr_screen.res][idx].button.link_hotspot(Multi_pwd_buttons[gr_screen.res][idx].hotspot);
9153  }
9154 
9155  // add all xstrs
9156  for(idx=0; idx<MULTI_PWD_NUM_TEXT; idx++){
9157  Multi_pwd_window.add_XSTR(&Multi_pwd_text[gr_screen.res][idx]);
9158  }
9159 
9160  // create the password input box
9161  Multi_pwd_passwd.create(&Multi_pwd_window, Mpwd_coords[gr_screen.res][MPWD_X_COORD], Mpwd_coords[gr_screen.res][MPWD_Y_COORD],Mpwd_coords[gr_screen.res][MPWD_W_COORD], MAX_PASSWD_LEN, "", UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_INVIS, -1, &Color_normal);
9162  Multi_pwd_passwd.set_focus();
9163 
9164  // link the enter key to ACCEPT
9165  Multi_pwd_buttons[gr_screen.res][MPWD_COMMIT].button.set_hotkey(KEY_ENTER);
9166 
9167  Multi_passwd_done = -1;
9168  Multi_passwd_running = 1;
9169 }
9170 
9171 // close down all graphics, etc
9173 {
9174  // unload any bitmaps
9175  bm_release(Multi_pwd_bitmap);
9176 
9177  // destroy the UI_WINDOW
9178  Multi_pwd_window.destroy();
9179 
9180  // free up the saved background screen
9181  if(Multi_passwd_background >= 0){
9182  gr_free_screen(Multi_passwd_background);
9183  Multi_passwd_background = -1;
9184  }
9185 
9186  Multi_passwd_running = 0;
9187 }
9188 
9189 // process any button pressed
9191 {
9192  // if the accept button was pressed
9193  if(Multi_pwd_buttons[gr_screen.res][MPWD_COMMIT].button.pressed()){
9195  Multi_passwd_done = 1;
9196  }
9197 
9198  // if the cancel button was pressed
9199  if(Multi_pwd_buttons[gr_screen.res][MPWD_CANCEL].button.pressed()){
9201  Multi_passwd_done = 0;
9202  }
9203 }
9204 
9205 // run the passwd popup
9206 void multi_passwd_do(char *passwd)
9207 {
9208  int k;
9209 
9210  while(Multi_passwd_done == -1){
9211  // set frametime and run background stuff
9212  game_set_frametime(-1);
9214 
9215  k = Multi_pwd_window.process();
9216 
9217  // process any keypresses
9218  switch(k){
9219  case KEY_ESC :
9220  // set this to indicate the user has cancelled for one reason or another
9221  Multi_passwd_done = 0;
9222  break;
9223  }
9224 
9225  // if the input box text has changed
9226  if(Multi_pwd_passwd.changed()){
9227  strcpy(passwd,"");
9228  Multi_pwd_passwd.get_text(passwd);
9229  }
9230 
9231  // process any button pressed
9233 
9234  // draw the background, etc
9235  gr_reset_clip();
9236  gr_clear();
9237  if(Multi_passwd_background >= 0){
9238  gr_restore_screen(Multi_passwd_background);
9239  }
9240  gr_set_bitmap(Multi_pwd_bitmap);
9242  Multi_pwd_window.draw();
9243 
9244  // flip the buffer
9245  gr_flip();
9246  }
9247 }
9248 
9249 // bring up the password string popup, fill in passwd (return 1 if accept was pressed, 0 if cancel was pressed)
9250 int multi_passwd_popup(char *passwd)
9251 {
9252  // if the popup is already running for some reason, don't do anything
9253  if(Multi_passwd_running){
9254  return 0;
9255  }
9256 
9257  // initialize all graphics
9259 
9260  // run the popup
9261  multi_passwd_do(passwd);
9262 
9263  // shut everything down
9265 
9266  return Multi_passwd_done;
9267 }
char * Mj_slider_name[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:483
#define NETINFO_FLAG_WARPING_OUT
Definition: multi.h:618
void multi_sync_force_start_pre()
Definition: multiui.cpp:8424
void game_flush()
Definition: fredstubs.cpp:83
#define NG_MODE_RANK_BELOW
Definition: multi.h:635
#define AG_FLAG_TYPE_MASK
Definition: multi.h:541
UI_WINDOW Multi_jw_window
Definition: multiui.cpp:6539
int Multi_create_sw_checkbox_text[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3167
void create(UI_WINDOW *wnd, int _x, int _y, int _num_pos, char *bm_slider, int slider_mask, char *bm_left=NULL, int left_mask=-1, int left_x=-1, int left_y=-1, char *bm_right=NULL, int right_mask=-1, int right_x=-1, int right_y=-1, int _dot_width=19)
DOT_SLIDER class down here.
Definition: slider.cpp:24
int Multi_common_create_y[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:236
#define KEY_LCTRL
Definition: key.h:140
char * Cmdline_connect_addr
Definition: cmdline.cpp:263
int Multi_join_sent_stamp
Definition: multiui.cpp:590
int multi_create_select_to_index(int select_index)
Definition: multiui.cpp:5157
#define MICON_VOICE_DENIED
Definition: multiui.h:54
uint respawn
Definition: multi.h:507
void multi_ingame_sync_close()
void multi_sync_common_close()
Definition: multiui.cpp:7631
void set_text(const char *in)
Definition: inputbox.cpp:490
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
pilotfile Pilot
Definition: pilotfile.cpp:7
#define NETPLAYER_STATE_DEBRIEF
Definition: multi.h:691
int Multi_create_list_max_display[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3314
int timestamp(int delta_ms)
Definition: timer.cpp:226
void multi_common_split_text()
Definition: multiui.cpp:186
#define NETINFO_FLAG_ACCEPT_INGAME
Definition: multi.h:614
void multi_update_valid_missions()
Definition: multiutil.cpp:3041
int Multi_common_text_max_display[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:88
#define FS_MISSION_FILE_EXT
Definition: missionparse.h:25
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
#define CFILE_NORMAL
Definition: cfile.h:89
#define MULTI_HO_NUM_RADIO_GROUPS
Definition: multiui.cpp:5623
int Mc_icon_silent_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3223
#define CW_CODE_INFO
Definition: multiui.cpp:2005
#define NET_TCP
Definition: psnet2.h:29
#define NETGAME_STATE_DEBRIEF
Definition: multi.h:669
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
uint num_respawns
Definition: missionparse.h:141
int Multi_create_mt_tried_login
Definition: multiui.cpp:3308
int Multi_sync_countdown
Definition: multiui.cpp:7352
#define CAMPAIGN_TYPE_SINGLE
int chatbox_create(int mode_flags)
Definition: chatbox.cpp:495
void multi_team_report()
Definition: multi_team.cpp:572
#define MSO_END_HOST
#define MPWD_COMMIT
Definition: multiui.cpp:9075
void add_XSTR(char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id=-1)
Definition: window.cpp:476
void multi_passwd_close()
Definition: multiui.cpp:9172
#define gr_clear
Definition: 2d.h:749
ushort client_server_seq
Definition: multi.h:468
#define NETPLAYER_STATE_HOST_SETUP
Definition: multi.h:694
char Multi_tracker_squad_name[MULTI_TRACKER_STRING_LEN+1]
Definition: multi.cpp:145
void fs2netd_gameserver_start()
#define NETPLAYER_STATE_IN_MISSION
Definition: multi.h:686
int Multi_create_list_mode
Definition: multiui.cpp:3321
int multi_netplayer_flag_check(int flags, int ignore_standalone)
Definition: multiutil.cpp:1486
#define MC_PXO_REFRESH
Definition: multiui.cpp:3029
#define AG_FLAG_FORMING
Definition: multi.h:524
#define MULTI_COMMON_NOTIFY_TIME
Definition: multiui.cpp:231
void multi_join_load_tcp_addrs()
Definition: multiui.cpp:1462
void multi_debrief_stats_accept()
Definition: multiui.cpp:8897
int Multi_create_frame_count
Definition: multiui.cpp:3307
void multi_campaign_do_debrief(int player_status)
void send_server_query(net_addr *addr)
Definition: multimsgs.cpp:2266
int cf_delete(const char *filename, int path_type)
Delete the specified file.
Definition: cfile.cpp:483
int Multi_join_overlay_id
Definition: multiui.cpp:735
void multi_campaign_flush_data()
#define MULTI_HO_SLIDER_SKILL
Definition: multiui.cpp:5648
void multi_join_create_game()
Definition: multiui.cpp:1952
void multi_options_update_mission(netgame_info *ng, int campaign_mode)
#define MULTI_VOICE_STATUS_IDLE
Definition: multi_voice.h:22
int Multi_sg_bitmap
Definition: multiui.cpp:2175
#define AG_FLAG_PAUSE
Definition: multi.h:527
active_game * Multi_join_list_start_item
Definition: multiui.cpp:707
int Multi_jw_plist_select_flag
Definition: multiui.cpp:6638
#define MSG_RANK_SCROLL_DOWN
Definition: multiui.cpp:2164
#define KEY_DOWN
Definition: key.h:180
void multi_sg_release_passwd()
Definition: multiui.cpp:2962
#define MSG_OPEN_GAME
Definition: multiui.cpp:2158
int flags
Definition: player.h:104
int Multi_create_overlay_id
Definition: multiui.cpp:3329
int Multi_mission_loaded
Definition: multi.cpp:98
void game_do_state_common(int, int)
Definition: fredstubs.cpp:195
void multi_join_handle_item_cull(active_game *item, int item_index)
Definition: multiui.cpp:1805
void game_set_frametime(int)
Definition: fredstubs.cpp:196
active_game * next
Definition: multi.h:545
char image_filename[MAX_FILENAME_LEN+1]
Definition: player.h:95
#define JOIN_FLAG_HAXOR
Definition: multi.h:567
void multi_sg_rank_build_name(char *in, char *out)
Definition: multiui.cpp:2915
int find_freespace_cd(char *)
Definition: fredstubs.cpp:193
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
void multi_join_game_do_frame()
Definition: multiui.cpp:994
int multi_num_connections()
Definition: multiutil.cpp:1832
char name[MAX_GAMENAME_LEN+1]
Definition: multi.h:548
float Multi_sync_countdown_timer
Definition: multiui.cpp:7351
void gr_flip()
Definition: 2d.cpp:2113
commit pressed
Definition: gamesnd.h:294
void multi_sync_post_do()
Definition: multiui.cpp:8188
#define MC_SHOW_TEAM
Definition: multiui.cpp:3027
int Mc_mission_count_x[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3262
#define MC_SHOW_ALL
Definition: multiui.cpp:3025
int x
Definition: ui.h:658
void multi_ho_accept_hit()
Definition: multiui.cpp:6097
#define MULTI_START_OVERLAY
Definition: contexthelp.h:29
net_addr server_addr
Definition: multi.h:552
void multi_join_game_init()
Definition: multiui.cpp:817
#define MJ_CHAR_CAMPAIGN
Definition: multiui.cpp:702
UI_BUTTON Multi_create_list_select_button
Definition: multiui.cpp:3052
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
void send_store_stats_packet(int accept)
Definition: multimsgs.cpp:5249
int Multi_join_list_start
Definition: multiui.cpp:706
#define KEY_PAGEDOWN
Definition: key.h:178
#define NG_FLAG_HACKED_WEAPONS_TBL
Definition: multi.h:644
#define MJ_JOIN_OBSERVER
Definition: multiui.cpp:502
char * Multi_create_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3011
#define MULTI_VOICE_STATUS_RECORDING
Definition: multi_voice.h:24
void multi_team_level_init()
Definition: multi_team.cpp:68
UI_XSTR Multi_jw_text[GR_NUM_RESOLUTIONS][MULTI_JW_NUM_TEXT]
Definition: multiui.cpp:6573
#define MC_CLOSE
Definition: multiui.cpp:3041
#define MISSION_LIST_REQUEST
Definition: multi.h:347
net_player * Net_player
Definition: multi.cpp:94
#define GR_RESIZE_MENU
Definition: 2d.h:684
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
ushort client_cinfo_seq
Definition: multi.h:467
int ADDRESS_LENGTH
Definition: multi.cpp:104
void multi_sg_rank_scroll_up()
Definition: multiui.cpp:2809
#define MJ_SCROLL_DOWN
Definition: multiui.cpp:498
#define NETPLAYER_STATE_MISSION_LOADED
Definition: multi.h:679
#define MULTI_HO_VOICE_ON
Definition: multiui.cpp:5538
#define NETPLAYER_STATE_INGAME_RPTS
Definition: multi.h:689
#define AG_FLAG_IN_MISSION
Definition: multi.h:528
char image_filename[MAX_FILENAME_LEN+1]
Definition: multi.h:572
#define MULTI_HO_VOICE_OFF
Definition: multiui.cpp:5539
server_item * multi_new_server_item(void)
Definition: multiutil.cpp:1758
float flFrametime
Definition: fredstubs.cpp:22
int y
Definition: ui.h:658
char name[NAME_LENGTH]
Definition: missionparse.h:131
void multi_jw_button_pressed(int n)
Definition: multiui.cpp:6884
#define NETINFO_FLAG_DO_NETWORKING
Definition: multi.h:610
#define NETPLAYER_STATE_INGAME_WINGS
Definition: multi.h:688
GLuint index
Definition: Glext.h:5608
multi_server_options m_server_options
Definition: player.h:193
void multi_ts_create_wings()
#define MULTI_AUTOJOIN_JOIN_STAMP
Definition: multiui.cpp:724
int Mjw_players_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:6594
void multi_sg_button_pressed(int n)
Definition: multiui.cpp:2505
UI_WINDOW Multi_join_window
Definition: multiui.cpp:514
player * m_player
Definition: multi.h:459
void multi_campaign_send_pool_status()
#define LOW_WARN_TEXT
Definition: multiui.cpp:2007
#define MAX_BRIEF_LINES
int security
Definition: multi.h:499
#define NETPLAYER_STATE_MISSION_LOADING
Definition: multi.h:678
void multi_sync_button_pressed(int n)
Definition: multiui.cpp:7832
void multi_ho_draw_radio_groups()
Definition: multiui.cpp:6084
drop a ship icon on a wing slot
Definition: gamesnd.h:289
int mode
Definition: multi.h:494
void multi_reset_timestamps()
Definition: multi.cpp:1741
#define MJW_Y_COORD
Definition: multiui.cpp:6544
#define MJ_LIST_START_INC()
Definition: multiui.cpp:712
#define gr_restore_screen
Definition: 2d.h:826
#define MULTI_HO_MAX_KILL_LIMIT
Definition: multiui.cpp:5801
#define NETGAME_STATE_BRIEFING
Definition: multi.h:665
#define MC_SCROLL_INFO_UP
Definition: multiui.cpp:3042
char * mission_branch_desc
ubyte max_players
Definition: multiui.h:41
int Ho_max_rsp_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:5789
#define MULTI_HO_NUM_TITLES
Definition: multiui.cpp:5682
void send_netplayer_update_packet(net_player *pl)
Definition: multimsgs.cpp:2308
void multi_sg_init_gamenet()
Definition: multiui.cpp:2665
int mission_campaign_parse_is_multi(char *filename, char *name)
ubyte flags
Definition: multi.h:575
char * Multi_sync_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:7245
void multi_common_scroll_text_up()
Definition: multiui.cpp:112
#define MULTI_HO_MSG_HOST
Definition: multiui.cpp:5533
void multi_create_list_scroll_up()
Definition: multiui.cpp:4415
#define MULTI_STANDALONE(np)
Definition: multi.h:139
#define MULTI_SYNC_PRE_BRIEFING
Definition: multiui.h:138
#define MICON_TEAM1
Definition: multiui.h:58
virtual void unhide()
Definition: gadget.cpp:217
#define MULTI_HO_END_HOST
Definition: multiui.cpp:5537
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
int double_clicked()
Definition: button.cpp:333
void std_destroy_gen_dialog()
void multi_join_list_scroll_down()
Definition: multiui.cpp:1692
Assert(pm!=NULL)
#define MULTI_COMMON_TEXT_MAX_LINE_LENGTH
Definition: multiui.cpp:94
#define MULTI_HO_X_COORD
Definition: multiui.cpp:5522
#define AG_FLAG_DEBRIEF
Definition: multi.h:526
void multi_ho_check_buttons()
Definition: multiui.cpp:6026
#define NETPLAYER_STATE_SLOT_ACK
Definition: multi.h:685
#define MSG_PASSWD_GAME
Definition: multiui.cpp:2161
void multi_sync_post_init()
Definition: multiui.cpp:8131
void multi_common_verify_cd()
Definition: multiui.cpp:446
int Multi_sync_countdown_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:7363
char * Cmdline_almission
Definition: cmdline.cpp:407
void multi_ho_blit_max_respawns()
Definition: multiui.cpp:6477
int Ho_st_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:5769
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
int Ms_team_icon_offset[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:7332
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
#define CW_CODE_CANCEL
Definition: multiui.cpp:2003
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
#define MULTI_VALID_MISSION_FILE
Definition: multi.h:40
#define NUM_SKILL_LEVELS
Definition: systemvars.h:150
void multi_unload_common_icons()
Definition: multiui.cpp:351
#define MSG_RANK_BELOW
Definition: multiui.cpp:2166
int Multi_ho_host_modifies
Definition: multiui.cpp:5674
int Multi_jw_bitmap
Definition: multiui.cpp:6540
int heard_from_timer
Definition: multi.h:546
general failure sound for any event
Definition: gamesnd.h:297
#define AG_FLAG_DOGFIGHT
Definition: multi.h:523
void multi_sg_select_rank_default()
Definition: multiui.cpp:2990
Definition: 2d.h:95
void multi_create_game_init()
Definition: multiui.cpp:3534
int multi_netplayer_state_check(int state, int ignore_standalone)
Definition: multiutil.cpp:1433
#define MULTI_JOIN_SENT_WAIT
Definition: multiui.cpp:589
int Mc_players_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:3186
int Cmdline_start_netgame
Definition: cmdline.cpp:280
int res
Definition: 2d.h:370
#define MJ_CANCEL
Definition: multiui.cpp:504
int max_h_unscaled
Definition: 2d.h:361
#define MJ_LIST_START_DEC()
Definition: multiui.cpp:713
int bm_get_info(int handle, int *w, int *h, ubyte *flags, int *nframes, int *fps)
Gets info on the bitmap indexed by handle.
Definition: bmpman.cpp:769
void multi_join_blit_game_status(active_game *game, int y)
Definition: multiui.cpp:1392
int Multi_autojoin_query_stamp
Definition: multiui.cpp:730
void clear_focus()
Definition: gadget.cpp:328
void multi_create_plist_scroll_down()
Definition: multiui.cpp:4177
CButton * team
int multi_passwd_popup(char *passwd)
Definition: multiui.cpp:9250
#define KICK_REASON_BAD_XFER
Definition: multi_kick.h:24
void multi_join_blit_top_stuff()
Definition: multiui.cpp:1990
int find_player_id(short player_id)
Definition: multiutil.cpp:465
#define NETPLAYER_STATE_JOINING
Definition: multi.h:676
void ml_string(const char *string, int add_time)
Definition: multi_log.cpp:131
void set_focus()
Definition: gadget.cpp:321
int Mj_list_area_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:688
char * Cmdline_game_name
Definition: cmdline.cpp:264
GLclampf f
Definition: Glext.h:7097
void multi_ho_apply_options()
Definition: multiui.cpp:6347
void multi_jw_plist_blit_normal()
Definition: multiui.cpp:6983
#define PLAYER_FLAGS_HAS_PLAYED_PXO
Definition: player.h:49
#define MC_SCROLL_LIST_UP
Definition: multiui.cpp:3031
void forceUp()
Definition: slider2.cpp:309
#define MULTI_HOST(np)
Definition: multi.h:137
#define MLO_FLAG_TEMP_CLOSED
#define JOIN_FLAG_AS_OBSERVER
Definition: multi.h:566
void multi_ping_send(net_player *p)
Definition: multi_ping.cpp:100
int Mj_list_y[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:598
#define MULTI_HO_NUM_RADIO_BUTTONS
Definition: multiui.cpp:5496
#define MISSION_TYPE_MULTI
Definition: missionparse.h:62
void send_file_sig_request(char *file_name)
Definition: multimsgs.cpp:4448
Definition: cfile.h:28
#define MULTI_HO_NUM_SLIDERS
Definition: multiui.cpp:5645
void multi_create_select_to_filename(int select_index, char *filename)
Definition: multiui.cpp:5123
#define MULTI_HO_MAX_TOKEN_WAIT
Definition: multiui.cpp:5800
int checked()
Definition: checkbox.cpp:186
#define f2fl(fx)
Definition: floating.h:37
int changed()
Definition: inputbox.cpp:474
int Multi_has_cd
Definition: multi.cpp:112
float multi_xfer_pct_complete(int handle)
Definition: multi_xfer.cpp:460
ubyte version
Definition: multi.h:578
void psnet_flush()
Definition: psnet2.cpp:927
int Mjw_mission_name_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:6603
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
char mission_name[NAME_LENGTH+1]
Definition: multi.h:549
void multi_common_set_palette()
Definition: multiui.cpp:423
#define NETPLAYER_STATE_JOINED
Definition: multi.h:677
#define AG_FLAG_BRIEFING
Definition: multi.h:525
net_addr Multi_autojoin_addr
Definition: multiui.cpp:728
#define MICON_VOICE_RECORDING
Definition: multiui.h:55
GLenum mode
Definition: Glext.h:5794
#define CHATBOX_FLAG_BIG
Definition: chatbox.h:22
#define RANK_ENSIGN
Definition: scoring.h:30
int multi_voice_status()
void send_join_packet(net_addr *addr, join_request *jr)
Definition: multimsgs.cpp:888
void multi_oo_reset_sequencing()
Definition: multi_obj.cpp:1820
void help_overlay_set_state(int overlay_id, int resolution_index, int state)
#define NETPLAYER_STATE_SETTINGS_ACK
Definition: multi.h:695
int Multi_ho_mission_respawn
Definition: multiui.cpp:5672
void multi_common_add_notify(const char *str)
Definition: multiui.cpp:261
void multi_passwd_process_buttons()
Definition: multiui.cpp:9190
virtual void hide(int n)
Definition: gadget.cpp:207
void send_netgame_update_packet(net_player *pl)
Definition: multimsgs.cpp:2008
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
#define KEY_PAGEUP
Definition: key.h:175
#define UI_INPUTBOX_FLAG_ESC_FOC
Definition: ui.h:38
color Color_text_active_hi
Definition: alphacolors.cpp:27
Definition: ui.h:195
#define MC_OPTIONS
Definition: multiui.cpp:3046
UI_WINDOW Multi_pwd_window
Definition: multiui.cpp:9087
#define MULTI_SYNC_CLIENT_COUNT
Definition: multiui.cpp:7238
#define MSO_END_ANY
int flags
Definition: multi.h:463
UI_BUTTON Multi_sync_plist_button
Definition: multiui.cpp:7346
float Multi_debrief_resend_time
Definition: multiui.cpp:8620
char * Multi_sync_countdown_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:7358
#define MULTI_JOIN_REFRESH_TIME_LOCAL
Definition: multiui.h:28
int tracker_id
Definition: multi.h:576
#define MULTI_AUTOJOIN_QUERY_STAMP
Definition: multiui.cpp:725
int mission_campaign_get_info(const char *filename, char *name, int *type, int *max_players, char **desc)
ubyte addr[6]
Definition: psnet2.h:41
void multi_start_game_init()
Definition: multiui.cpp:2286
int Multi_debrief_accept_hit
Definition: multiui.cpp:8600
#define MSG_RANK_SCROLL_UP
Definition: multiui.cpp:2163
int Multi_state_timestamp
Definition: multiui.cpp:7393
int Ho_vw_coords[GR_NUM_RESOLUTIONS][6]
Definition: multiui.cpp:5749
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
#define MC_HOST_OPTIONS
Definition: multiui.cpp:3044
int max_w_unscaled
Definition: 2d.h:361
#define Int3()
Definition: pstypes.h:292
int Multi_jw_sw_checkbox_text[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:6626
void multi_common_scroll_text_down()
Definition: multiui.cpp:125
#define MS_FLAG_SENT_LOAD
Definition: multiui.cpp:7381
#define MULTI_POST_TIMESTAMP
Definition: multiui.cpp:8184
void multi_game_client_setup_do_frame()
Definition: multiui.cpp:6736
#define CHATBOX_FLAG_BUTTONS
Definition: chatbox.h:25
void multi_debrief_replay_hit()
Definition: multiui.cpp:8869
#define NETPLAYER_STATE_DATA_LOAD
Definition: multi.h:683
GLuint in
Definition: Glext.h:9087
void multi_team_host_lock_all()
Definition: multi_team.cpp:530
void multi_debrief_stats_toss()
Definition: multiui.cpp:8919
#define AG_FLAG_CONNECTION_SPEED_MASK
Definition: multi.h:535
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
void multi_ts_assign_players_all()
const char *(* tooltip_handler)(const char *text)
Definition: ui.h:649
#define MJ_Y_COORD
Definition: multiui.cpp:585
void multi_msg_text_flush()
Definition: multi_pmsg.cpp:329
int Multi_debrief_server_left
Definition: multiui.cpp:8604
multi_local_options player_options
Definition: multi.h:577
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
char * Multi_create_sw_checkbox_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3155
#define MSG_ACCEPT
Definition: multiui.cpp:2169
char * Mc_slider_bitmap[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3296
void multi_create_handle_join(net_player *pl)
Definition: multiui.cpp:5058
void set_state(int _state)
Definition: checkbox.cpp:191
#define MS_FLAG_POST_DATA
Definition: multiui.cpp:7383
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
void forceDown()
Definition: slider2.cpp:302
int game_state
Definition: multi.h:498
int multi_start_game_rank_from_name(char *rank)
Definition: multiui.cpp:2274
int Mc_mission_name_x[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3257
int psnet_same(net_addr *a1, net_addr *a2)
Definition: psnet2.cpp:785
UI_BUTTON Multi_create_player_select_button
Definition: multiui.cpp:3051
int Multi_sync_launch_pressed
Definition: multiui.cpp:7394
#define MJ_START_GAME
Definition: multiui.cpp:503
#define MJ_ACCEPT
Definition: multiui.cpp:507
#define MC_SHOW_COOP
Definition: multiui.cpp:3026
int multi_xfer_get_status(int handle)
Definition: multi_xfer.cpp:276
int Msg_rank_list_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:2144
#define MISSION_TYPE_MULTI_COOP
Definition: missionparse.h:64
void multi_create_list_load_missions()
Definition: multiui.cpp:4438
void generic_anim_unload(generic_anim *ga)
Definition: generic.cpp:291
char Multi_common_all_text[MULTI_COMMON_MAX_TEXT]
Definition: multiui.cpp:98
#define DCF(function_name, help_text)
The potent DCF macro, used to define new debug commands for the console.
Definition: console.h:60
int Multi_sync_mode
Definition: multiui.cpp:7348
int Multi_join_ping_stamp
Definition: multiui.cpp:513
#define MJ_OPTIONS
Definition: multiui.cpp:506
void multi_debrief_do_frame()
Definition: multiui.cpp:8664
#define MSO_SQUAD_ANY
#define MULTI_HO_MSG_ANY
Definition: multiui.cpp:5532
active_game * prev
Definition: multi.h:545
void multi_passwd_init()
Definition: multiui.cpp:9122
HWND DWORD code
Definition: vddraw.h:425
#define MULTI_CREATE_NUM_BUTTONS
Definition: multiui.cpp:3022
#define MICON_VOLITION
Definition: multiui.h:63
int PORT_LENGTH
Definition: multi.cpp:105
int version_info
Definition: multi.h:492
#define MJW_SCROLL_PLAYERS_DOWN
Definition: multiui.cpp:6531
ho_sliders Multi_ho_sliders[GR_NUM_RESOLUTIONS][MULTI_HO_NUM_SLIDERS]
Definition: multiui.cpp:5659
void draw_forced(int frame_num)
Definition: button.cpp:104
int multi_num_observers()
Definition: multiutil.cpp:1815
int multi_endgame_ending()
#define MPWD_CANCEL
Definition: multiui.cpp:9074
#define MSO_END_RANK
int mouse_down(int btn)
Definition: mouse.cpp:315
void multi_common_render_text()
Definition: multiui.cpp:208
#define MJ_PING_YELLOW
Definition: multiui.cpp:684
void multi_sg_check_buttons()
Definition: multiui.cpp:2492
void multi_sync_scroll_info_down()
#define MICON_COOP
Definition: multiui.h:60
int Multi_create_filter
Definition: multiui.cpp:3311
#define FS_CAMPAIGN_FILE_EXT
Definition: freespace.h:26
int Mj_slider_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:487
int tracker_player_id
Definition: multi.h:461
void send_netplayer_load_packet(net_player *pl)
Definition: multimsgs.cpp:4694
void destroy()
Definition: window.cpp:189
#define MULTI_HO_MAX_TIME_LIMIT
Definition: multiui.cpp:5799
UI_INPUTBOX Multi_ho_time_limit
Definition: multiui.cpp:5515
#define MC_PILOT_INFO
Definition: multiui.cpp:3030
void multi_create_sw_clicked()
Definition: multiui.cpp:5424
int num_frames
Definition: generic.h:20
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
netgame_info Multi_sg_netgame_temp
Definition: multiui.cpp:2251
void multi_data_send_my_junk()
Definition: multi_data.cpp:233
#define gr_reset_clip
Definition: 2d.h:745
int instance
Definition: object.h:150
#define NETPLAYER_STATE_CPOOL_ACK
Definition: multi.h:705
void set_mask_bmap(char *fname)
Definition: window.cpp:75
int Multi_common_join_y[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:232
int multi_num_players()
Definition: multiutil.cpp:1799
int multi_create_verify_cds()
Definition: multiui.cpp:5359
int Multi_join_list_selected
Definition: multiui.cpp:708
#define NG_MODE_RANK_ABOVE
Definition: multi.h:634
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
void multi_display_chat_msg(const char *msg, int player_index, int add_id)
Definition: multiutil.cpp:2895
ubyte comp_version
Definition: multi.h:578
int game_hacked_data()
Definition: fredstubs.cpp:208
void multi_ingame_sync_init()
ui_button_info Multi_join_buttons[GR_NUM_RESOLUTIONS][MULTI_JOIN_NUM_BUTTONS]
Definition: multiui.cpp:519
#define MSG_RANK_SET_GAME
Definition: multiui.cpp:2162
void multi_kick_player(int player_index, int ban, int reason)
Definition: multi_kick.cpp:82
void chatbox_render()
Definition: chatbox.cpp:683
net_player_info p_info
Definition: multi.h:473
UI_WINDOW Multi_create_window
Definition: multiui.cpp:3050
int Multi_ho_lastframe_input
Definition: multiui.cpp:5677
#define MS_FLAG_DATA_DONE
Definition: multiui.cpp:7389
bool fs2netd_login()
int type_flags
Definition: multi.h:493
char * Cmdline_rank_above
Definition: cmdline.cpp:266
void set_numberItems(int _numberItems, int _reset=1)
Definition: slider2.cpp:217
int Multi_sg_rank_start
Definition: multiui.cpp:2244
int Mj_game_name_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:630
UI_XSTR Multi_join_text[GR_NUM_RESOLUTIONS][MULTI_JOIN_NUM_TEXT]
Definition: multiui.cpp:550
int multi_create_lookup_mission(char *fname)
Definition: multiui.cpp:5385
void multi_join_reset_join_stamp()
Definition: multiui.cpp:1983
#define MULTI_VOICE_MAX_TIME
Definition: multi_voice.h:28
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
color Color_bright
Definition: alphacolors.cpp:28
unsigned int uint
Definition: pstypes.h:64
const char * multi_sync_tooltip_handler(const char *str)
Definition: multiui.cpp:7510
int Msg_passwd_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:2114
void multi_start_game_do()
Definition: multiui.cpp:2407
#define MPWD_Y_COORD
Definition: multiui.cpp:9068
void multi_options_update_start_game(netgame_info *ng)
#define MULTI_JOIN_NUM_BUTTONS
Definition: multiui.cpp:465
int Cmdline_closed_game
Definition: cmdline.cpp:270
#define MULTI_SYNC_HOST_COUNT
Definition: multiui.cpp:7237
void ml_printf(const char *format,...)
Definition: multi_log.cpp:112
void multi_sync_pre_close()
Definition: multiui.cpp:8120
void multi_join_check_buttons()
Definition: multiui.cpp:1161
#define cfopen(...)
Definition: cfile.h:134
color Color_bright_green
Definition: alphacolors.cpp:31
int psnet_is_valid_ip_string(char *ip_string, int allow_port)
Definition: psnet2.cpp:938
int ping_avg
Definition: multi_ping.h:32
char Multi_common_notify_text[200]
Definition: multiui.cpp:251
int state
Definition: multi.h:464
void multi_level_init()
Definition: multi.cpp:253
#define MULTI_FS_SERVER_COMPATIBLE_VERSION
Definition: multi.h:67
#define nprintf(args)
Definition: pstypes.h:239
int mission_parse_is_multi(const char *filename, char *mission_name)
multi_server_options options
Definition: multi.h:514
#define UI_INPUTBOX_FLAG_PASSWD
Definition: ui.h:39
#define GM_MULTIPLAYER
Definition: systemvars.h:18
ui_button_info Multi_sync_buttons[GR_NUM_RESOLUTIONS][MULTI_SYNC_NUM_BUTTONS]
Definition: multiui.cpp:7269
#define NETPLAYER_STATE_MISSION_SYNC
Definition: multi.h:692
void multi_jw_plist_process()
Definition: multiui.cpp:6943
#define MSG_W_COORD
Definition: multiui.cpp:2108
int multi_create_ok_to_commit()
Definition: multiui.cpp:5190
#define NG_MODE_OPEN
Definition: multi.h:630
int pressed()
Definition: inputbox.cpp:479
#define NETINFO_FLAG_HAS_CD
Definition: multi.h:619
ui_button_info Multi_create_buttons[GR_NUM_RESOLUTIONS][MULTI_CREATE_NUM_BUTTONS]
Definition: multiui.cpp:3062
void multi_sg_rank_display_stuff()
Definition: multiui.cpp:2839
#define NG_FLAG_HACKED_SHIPS_TBL
Definition: multi.h:643
int Sync_test
Definition: multiui.cpp:7422
char name[MAX_GAMENAME_LEN+1]
Definition: multi.h:487
void multi_flush_multidata_cache()
Definition: multiutil.cpp:2778
void send_game_chat_packet(net_player *from, const char *msg, int msg_mode, net_player *to, const char *expr, int server_msg)
Definition: multimsgs.cpp:615
int Multi_ho_radio_info[MULTI_HO_NUM_RADIO_BUTTONS][3]
Definition: multiui.cpp:5630
#define MSO_FLAG_INGAME_XFER
char * cfgets(char *buf, int n, CFILE *cfile)
Definition: cfile.cpp:1571
void send_countdown_packet(int time)
Definition: multimsgs.cpp:7210
void multi_join_list_page_up()
Definition: multiui.cpp:1705
#define gr_save_screen
Definition: 2d.h:825
void multi_obs_level_init()
#define NETPLAYER_STATE_MT_STATS
Definition: multi.h:700
int Multi_join_should_send
Definition: multiui.cpp:717
void create(UI_WINDOW *wnd, int _x, int _y, int _w, int _h, int _numberItems, char *_bitmapSliderControl, void(*_upCallback)(), void(*_downCallback)(), void(*_captureCallback)())
Definition: slider2.cpp:21
UI_INPUTBOX Multi_sg_game_name
Definition: multiui.cpp:2173
void multi_create_refresh_pxo()
Definition: multiui.cpp:5415
#define MJW_TEAM0
Definition: multiui.cpp:6532
void multi_flush_mission_stuff()
Definition: multiutil.cpp:2787
void multi_create_accept_hit()
Definition: multiui.cpp:4918
#define DEFAULT_GAME_PORT
Definition: psnet2.h:36
#define AG_FLAG_STATE_MASK
Definition: multi.h:542
void multi_common_notify_do()
Definition: multiui.cpp:270
UI_INPUTBOX Multi_ho_obs
Definition: multiui.cpp:5518
char * filename
void multi_pinfo_popup(net_player *np)
int multi_sg_rank_select_valid(int rank)
Definition: multiui.cpp:2972
netgame_info Netgame
Definition: multi.cpp:97
UI_INPUTBOX Multi_ho_kill_limit
Definition: multiui.cpp:5517
void multi_team_reset()
Definition: multi_team.cpp:128
int hotspot
Definition: ui.h:659
int Multi_join_frame_count
Definition: multiui.cpp:720
int Multi_sync_bitmap
Definition: multiui.cpp:7260
int pressed()
Definition: button.cpp:325
#define MJW_SCROLL_INFO_DOWN
Definition: multiui.cpp:6536
void multi_team_send_update()
Definition: multi_team.cpp:696
UI_BUTTON Multi_sg_rank_button
Definition: multiui.cpp:2172
void multi_join_do_netstuff()
Definition: multiui.cpp:1517
int Ho_obs_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:5759
#define KEY_SHIFTED
Definition: key.h:62
int multi_create_lookup_campaign(char *fname)
Definition: multiui.cpp:5400
#define NG_MODE_CLOSED
Definition: multi.h:631
char name[NAME_LENGTH]
Definition: multiui.h:38
#define MC_W_COORD
Definition: multiui.cpp:3059
#define MULTI_SYNC_COUNTDOWN_TIME
Definition: multiui.cpp:7350
#define MULTIPLAYER_HOST
Definition: multi.h:131
int Multi_ho_radio_groups[MULTI_HO_NUM_RADIO_GROUPS]
Definition: multiui.cpp:5627
int Mc_mission_fname_x[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3267
void chatbox_force_small()
Definition: chatbox.cpp:1020
int Multi_sg_overlay_id
Definition: multiui.cpp:2253
ui_button_info Multi_ho_buttons[GR_NUM_RESOLUTIONS][MULTI_HO_NUM_BUTTONS]
Definition: multiui.cpp:5543
#define NG_TYPE_COOP
Definition: multi.h:647
void multi_create_plist_process()
Definition: multiui.cpp:4182
int Multi_sg_rank_max_display[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:2100
#define MULTI_FS_SERVER_VERSION
Definition: multi.h:65
int Mj_max_game_items[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:593
void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool menu)
Definition: generic.cpp:437
#define MP_CAMPAIGN
Definition: multi.h:98
#define w(p)
Definition: modelsinc.h:68
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define NG_TYPE_TEAM
Definition: multi.h:650
void std_gen_set_text(char *str, int field_num)
net_player * host
Definition: multi.h:504
char filename[MAX_FILENAME_LEN]
Definition: multiui.h:37
#define NG_FLAG_STORED_MT_STATS
Definition: multi.h:642
#define MJW_PILOT_INFO
Definition: multiui.cpp:6534
int Multi_num_players_at_start
Definition: multi.cpp:114
void multi_voice_maybe_update_vars(int new_qos, int new_duration)
#define MULTI_XFER_TIMEDOUT
Definition: multi_xfer.h:27
#define KEY_ENTER
Definition: key.h:125
int Multi_common_text_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:79
#define UI_INPUTBOX_FLAG_NO_LETTERS
Definition: ui.h:42
#define MULTI_PWD_NUM_TEXT
Definition: multiui.cpp:9107
#define NETINFO_FLAG_MISSION_OK
Definition: multi.h:608
int Mc_info_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:3195
#define KEY_RCTRL
Definition: key.h:141
#define NG_VERSION_ID
Definition: multi.h:74
int Mission_sync_flags
Definition: multiui.cpp:7379
int idx_max
Definition: multiui.cpp:764
#define NETINFO_FLAG_INGAME_JOIN
Definition: multi.h:604
short multi_jw_get_mouse_id()
Definition: multiui.cpp:7173
#define MSO_SQUAD_RANK
void multi_create_plist_blit_normal()
Definition: multiui.cpp:4223
void multi_common_load_palette()
Definition: multiui.cpp:410
#define MSO_FLAG_SS_LEADERS
ushort flags
Definition: multi.h:553
#define AG_FLAG_STANDALONE
Definition: multi.h:530
multi_local_options m_local_options
Definition: player.h:192
void multi_join_list_scroll_up()
Definition: multiui.cpp:1677
char * Multi_jw_sw_checkbox_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:6614
GLuint buffer
Definition: Glext.h:5492
#define MICON_TVT
Definition: multiui.h:61
#define MJW_CANCEL
Definition: multiui.cpp:6537
short Multi_jw_plist_select_id
Definition: multiui.cpp:6639
#define MULTI_HO_VOICE_GROUP
Definition: multiui.cpp:5626
int multi_join_warn_update_medium(int code)
Definition: multiui.cpp:2026
void multi_options_netgame_load(multi_server_options *options)
net_player_server_info s_info
Definition: multi.h:472
#define MULTI_CREATE_SHOW_MISSIONS
Definition: multiui.h:122
#define NETGAME_STATE_MISSION_SYNC
Definition: multi.h:670
ubyte version
Definition: multi.h:554
#define NETINFO_FLAG_TEAM_CAPTAIN
Definition: multi.h:612
int Multi_passwd_background
Definition: multiui.cpp:9090
Definition: ui.h:428
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
#define MAX_PLAYERS
Definition: pstypes.h:32
short player_id
Definition: multi.h:460
net_addr server_addr
Definition: multi.h:562
void chatbox_clear()
Definition: chatbox.cpp:664
#define MSG_HELP
Definition: multiui.cpp:2167
void send_player_settings_packet(net_player *p)
Definition: multimsgs.cpp:5606
#define MPWD_W_COORD
Definition: multiui.cpp:9069
#define NETINFO_FLAG_HAXOR
Definition: multi.h:624
void fs2netd_store_stats()
void multi_sync_do()
Definition: multiui.cpp:7453
void send_jump_into_mission_packet(net_player *pl)
Definition: multimsgs.cpp:4747
char mission_name[NAME_LENGTH+1]
Definition: multi.h:488
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
#define MC_SCROLL_INFO_DOWN
Definition: multiui.cpp:3043
int multi_netplayer_state_check3(int state, int state2, int state3, int ignore_standalone)
Definition: multiutil.cpp:1467
bool multi_create_sort_func(const multi_create_info &m1, const multi_create_info &m2)
Definition: multiui.cpp:3367
bool dc_optional_string_either(const char *str1, const char *str2)
Searches for an optional string and it's alias.
#define MJ_CHAR_STANDALONE
Definition: multiui.cpp:701
#define MC_X_COORD
Definition: multiui.cpp:3057
void multi_ho_button_pressed(int n)
Definition: multiui.cpp:6039
UI_BUTTON button
Definition: ui.h:660
#define MULTI_HO_MSG_GROUP
Definition: multiui.cpp:5624
void send_mission_sync_packet(int mode, int start_campaign)
Definition: multimsgs.cpp:5154
char passwd[MAX_PASSWD_LEN+1]
Definition: multi.h:491
ubyte debug_flags
Definition: multi.h:516
int Multi_sync_button_count
Definition: multiui.cpp:7259
#define MICON_DOGFIGHT
Definition: multiui.h:62
#define NG_MODE_PASSWORD
Definition: multi.h:632
#define NETPLAYER_STATE_DEBRIEF_REPLAY
Definition: multi.h:704
int Game_ships_tbl_valid
Definition: fredstubs.cpp:181
void multi_create_game_close()
Definition: multiui.cpp:3911
UI_WINDOW Multi_sync_window
Definition: multiui.cpp:7258
#define AG_FLAG_COOP
Definition: multi.h:521
int save_flags
Definition: player.h:105
char * filename
Definition: multiui.cpp:5650
bool save_player(player *_p=NULL)
Definition: plr.cpp:935
#define NETINFO_FLAG_ACCEPT_HOST
Definition: multi.h:615
ubyte player_rank
Definition: multi.h:574
#define MULTI_HO_END_LEADER
Definition: multiui.cpp:5535
int idx
Definition: multiui.cpp:761
int Multi_common_msg_y[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:246
short multi_create_get_mouse_id()
Definition: multiui.cpp:5065
void multi_sync_check_buttons()
Definition: multiui.cpp:7819
#define MULTI_NUM_COMMON_ICONS
Definition: multiui.h:53
#define KEY_P
Definition: key.h:97
void multi_debrief_init()
Definition: multiui.cpp:8622
void multi_sync_common_do()
Definition: multiui.cpp:7610
char campaign_name[NAME_LENGTH+1]
Definition: multi.h:490
#define PROMPT_HOST
Definition: multi_endgame.h:27
int Multi_launch_button_created
Definition: multiui.cpp:7354
#define KEY_T
Definition: key.h:101
void multi_host_options_do()
Definition: multiui.cpp:5944
color Color_bright_yellow
Definition: alphacolors.cpp:34
void multi_create_init_as_server()
Definition: multiui.cpp:4158
void multi_join_notify_new_game()
Definition: multiui.cpp:792
int Cmdline_restricted_game
Definition: cmdline.cpp:278
int create_wings()
void multi_free_server_list()
Definition: multiutil.cpp:1781
void multi_game_client_setup_init()
Definition: multiui.cpp:6655
void multi_join_clear_game_list()
Definition: multiui.cpp:978
UI_INPUTBOX Multi_ho_voice_wait
Definition: multiui.cpp:5516
int mission_parse_get_multi_mission_info(const char *filename)
char * Cmdline_rank_below
Definition: cmdline.cpp:267
void multi_sync_start_countdown()
Definition: multiui.cpp:8463
#define MULTI_HO_MAX_OBS
Definition: multiui.cpp:5802
int Multi_create_plist_select_flag
Definition: multiui.cpp:3303
int chatbox_has_focus()
Definition: chatbox.cpp:1093
void multi_common_notify_init()
Definition: multiui.cpp:254
void multi_maybe_set_mission_loop()
Definition: multiui.cpp:8688
ui_button_info Multi_jw_buttons[GR_NUM_RESOLUTIONS][MULTI_JW_NUM_BUTTONS]
Definition: multiui.cpp:6548
#define MULTI_COMMON_TEXT_MAX_LINES
Definition: multiui.cpp:95
int multi_join_warn_update_low(int code)
Definition: multiui.cpp:2013
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
#define MULTI_SYNC_NUM_BUTTONS
Definition: multiui.cpp:7263
#define MICON_VALID
Definition: multiui.h:64
void chatbox_lose_focus()
Definition: chatbox.cpp:1082
long fix
Definition: pstypes.h:54
int Multi_create_bitmap
Definition: multiui.cpp:3053
GLclampd n
Definition: Glext.h:7286
void multi_xfer_release_handle(int handle)
Definition: multi_xfer.cpp:339
#define MS_FLAG_CAMP_DONE
Definition: multiui.cpp:7390
unsigned char ubyte
Definition: pstypes.h:62
#define MST_KICK
Definition: multiui.cpp:7288
void multi_ho_update_sliders()
Definition: multiui.cpp:5918
char title[NAME_LENGTH+1]
Definition: multi.h:489
ui_button_info Multi_pwd_buttons[GR_NUM_RESOLUTIONS][MULTI_PWD_NUM_BUTTONS]
Definition: multiui.cpp:9095
#define MSG_X_COORD
Definition: multiui.cpp:2106
char pxo_squad_name[LOGIN_LEN]
Definition: multi.h:581
int Multi_sync_plist_count
Definition: multiui.cpp:7343
#define MULTI_MSG_ALL
Definition: multi_pmsg.h:27
net_addr addr
Definition: multi.h:453
int Mj_game_icon_coords[GR_NUM_RESOLUTIONS][3]
Definition: multiui.cpp:612
void send_wss_slots_data_packet(int team_num, int final, net_player *p, int std_request)
Definition: multimsgs.cpp:6154
#define AG_FLAG_TEAMS
Definition: multi.h:522
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
netgame_info * Multi_sg_netgame
Definition: multiui.cpp:2248
UI_SLIDER2 Multi_join_slider
Definition: multiui.cpp:516
#define IP_CONFIG_FNAME
Definition: multiui.cpp:679
int rank_base
Definition: multi.h:496
#define MS_SCROLL_INFO_UP
Definition: multiui.cpp:7264
#define MULTI_JW_NUM_BUTTONS
Definition: multiui.cpp:6511
#define NETINFO_FLAG_LIMBO
Definition: multi.h:607
UI_INPUTBOX Multi_ho_respawns
Definition: multiui.cpp:5514
user_click (mouse selects a control)
Definition: gamesnd.h:305
void force_currentItem(int _currentItem)
Definition: slider2.cpp:279
int Multi_sync_player_select
Definition: multiui.cpp:7338
void multi_df_level_pre_enter()
void multi_create_set_selected_team(int team)
Definition: multiui.cpp:5040
color Color_bright_red
Definition: alphacolors.cpp:34
int Multi_tracker_id
Definition: multi.cpp:146
void multi_sg_rank_scroll_down()
Definition: multiui.cpp:2824
void multi_sync_launch()
Definition: multiui.cpp:8488
#define MJ_PING_RED
Definition: multiui.cpp:685
#define NETINFO_FLAG_ACCEPT_CLIENT
Definition: multi.h:617
#define MSG_OPTIONS
Definition: multiui.cpp:2168
ubyte num_players
Definition: multi.h:551
int cfeof(CFILE *cfile)
active_game * multi_join_get_game(int n)
Definition: multiui.cpp:1651
#define NOX(s)
Definition: pstypes.h:473
#define NG_TYPE_TVT
Definition: multi.h:648
void std_debug_set_standalone_state_string(char *str)
UI_WINDOW Multi_sg_window
Definition: multiui.cpp:2171
#define MS_FLAG_SENT_FILESIG
Definition: multiui.cpp:7380
#define MS_LAUNCH
Definition: multiui.cpp:7268
void multi_create_plist_blit_team()
Definition: multiui.cpp:4274
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
int Multi_common_top_text_line
Definition: multiui.cpp:101
void multi_ho_display_skill_level()
Definition: multiui.cpp:6492
void multi_ho_get_options()
Definition: multiui.cpp:6252
void broadcast_game_query()
Definition: multimsgs.cpp:2234
#define MULTI_END_NOTIFY_NONE
Definition: multi_endgame.h:32
void multi_create_list_sort(int mode)
Definition: multiui.cpp:3394
GLbitfield flags
Definition: Glext.h:6722
int Mc_icon_volition_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3214
float Multi_debrief_time
Definition: multiui.cpp:8619
#define vm_malloc(size)
Definition: pstypes.h:547
void set_hotkey(int keycode)
Definition: gadget.cpp:280
#define MVALID_STATUS_VALID
Definition: multi.h:113
#define CW_CODE_OK
Definition: multiui.cpp:2004
#define NETGAME_STATE_IN_MISSION
Definition: multi.h:666
color Color_text_active
Definition: alphacolors.cpp:27
void multi_sg_draw_radio_buttons()
Definition: multiui.cpp:2778
void multi_host_options_init()
Definition: multiui.cpp:5817
void dc_stuff_int(int *i)
Stuffs an int to the given variable. Supports binary (0b), hexadecimal (0x), and octal (0o) formats...
int Multi_did_autojoin
Definition: multiui.cpp:727
GLuint const GLchar * name
Definition: Glext.h:5608
void multi_jw_check_buttons()
Definition: multiui.cpp:6871
char valid_status
Definition: multiui.h:42
#define NETINFO_FLAG_CONNECTED
Definition: multi.h:598
#define PROMPT_NONE
Definition: multi_endgame.h:26
void multi_debrief_esc_hit()
Definition: multiui.cpp:8793
UI_BUTTON Multi_join_select_button
Definition: multiui.cpp:515
void multi_options_local_load(multi_local_options *options, net_player *pxo_pl)
void multi_server_update_player_weapons(net_player *pl, ship *shipp)
Definition: multiutil.cpp:2737
int Multi_sync_plist_start
Definition: multiui.cpp:7342
net_addr server_addr
Definition: multi.h:503
int Multi_sg_rank_select
Definition: multiui.cpp:2245
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _state)
Definition: checkbox.cpp:16
#define NETPLAYER_STATE_MISSION_XFER
Definition: multi.h:701
int Mc_column1_w[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3242
void multi_jw_scroll_players_down()
Definition: multiui.cpp:6938
char * cf_add_ext(const char *filename, const char *ext)
Definition: cfile.cpp:458
#define MST_LAUNCH
Definition: multiui.cpp:7289
void multi_sync_common_init()
Definition: multiui.cpp:7521
#define LOW_INFO_TEXT
Definition: multiui.cpp:2008
int current_mission
void multi_join_process_select()
Definition: multiui.cpp:1600
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
#define CF_TYPE_DATA
Definition: cfile.h:46
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
#define MC_SCROLL_PLAYERS_DOWN
Definition: multiui.cpp:3034
ui_button_info Multi_sg_buttons[GR_NUM_RESOLUTIONS][MULTI_SG_NUM_BUTTONS]
Definition: multiui.cpp:2177
void multi_sync_pre_init()
Definition: multiui.cpp:7870
struct generic_anim::@239::@241 ani
#define NETPLAYER_STATE_WAITING
Definition: multi.h:684
UI_XSTR Multi_ho_titles[GR_NUM_RESOLUTIONS][MULTI_HO_NUM_TITLES]
Definition: multiui.cpp:5683
int multi_join_warn_pxo()
Definition: multiui.cpp:2066
void send_netplayer_slot_packet()
Definition: multimsgs.cpp:4017
#define FS_CDROM_VOLUME_2
Definition: freespace.h:30
#define MULTI_PERM_OBSERVER(np)
Definition: multi.h:142
char * Multi_sync_bitmap_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:7240
void multi_common_move_to_bottom()
Definition: multiui.cpp:138
color Color_text_selected
Definition: alphacolors.cpp:26
active_game * Multi_join_selected_item
Definition: multiui.cpp:709
SCP_vector< multi_create_info > Multi_create_campaign_list
Definition: multiui.cpp:3327
void multi_sync_post_close()
Definition: multiui.cpp:8308
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
void chatbox_close()
Definition: chatbox.cpp:634
color Color_bright_white
Definition: alphacolors.cpp:32
#define MAX_PASSWD_LEN
Definition: multi.h:90
void multi_create_setup_list_data(int mode)
Definition: multiui.cpp:3448
SCP_vector< multi_create_info > Multi_create_mission_list
Definition: multiui.cpp:3326
void multi_free_active_games()
Definition: multiutil.cpp:1739
void send_netgame_descript_packet(net_addr *addr, int code)
Definition: multimsgs.cpp:2161
#define MJW_SCROLL_PLAYERS_UP
Definition: multiui.cpp:6530
int Mj_players_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:639
#define MULTI_JOIN_NUM_TEXT
Definition: multiui.cpp:548
#define MJ_PING_ONE_SECOND
Definition: multiui.cpp:686
void multi_create_list_select_item(int n)
Definition: multiui.cpp:4705
int game_start_mission()
Definition: fredstubs.cpp:179
#define MJ_SCROLL_INFO_DOWN
Definition: multiui.cpp:501
#define FONT1
Definition: font.h:65
#define MSO_FLAG_NO_VOICE
int Multi_jw_sw_checkbox_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:6618
void multi_options_update_netgame()
scroll pressed (and scroll)
Definition: gamesnd.h:296
color Color_white
Definition: alphacolors.cpp:32
#define CALLSIGN_LEN
Definition: globals.h:31
#define MC_ACCEPT
Definition: multiui.cpp:3047
int campaign_mode
Definition: multi.h:509
void multi_passwd_do(char *passwd)
Definition: multiui.cpp:9206
#define MULTI_HO_Y_COORD
Definition: multiui.cpp:5523
#define MSO_SQUAD_LEADER
#define MP_SINGLE_MISSION
Definition: multi.h:97
void link_hotspot(int num)
Definition: gadget.cpp:50
#define MC_MISSION_FILTER
Definition: multiui.cpp:3035
#define MULTI_COMMON_MAX_TEXT
Definition: multiui.cpp:96
campaign Campaign
int Mc_icon_type_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3205
void multi_debrief_accept_hit()
Definition: multiui.cpp:8711
#define CHATBOX_FLAG_DRAW_BOX
Definition: chatbox.h:24
#define strcat_s(...)
Definition: safe_strings.h:68
#define MAX_IP_STRING
Definition: multiui.cpp:110
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define NG_FLAG_TEMP_CLOSED
Definition: multi.h:638
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
void multi_jw_scroll_players_up()
Definition: multiui.cpp:6932
int Mc_slider_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:3287
void multi_endgame_init()
char * Multi_create_bitmap_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3006
#define NG_MODE_RESTRICTED
Definition: multi.h:633
int multi_join_autojoin_do()
Definition: multiui.cpp:799
#define MS_FLAG_PUSHED_BRIEFING
Definition: multiui.cpp:7382
void multi_sync_display_name(const char *name, int index, int np_index)
Definition: multiui.cpp:8335
int Msg_rank_sel_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:2134
#define UI_XSTR_COLOR_PINK
Definition: ui.h:161
void multi_join_eval_pong(net_addr *addr, fix pong_time)
Definition: multiui.cpp:1562
#define FONT2
Definition: font.h:66
void multi_create_do_netstuff()
Definition: multiui.cpp:4152
#define MULTI_SG_NUM_BUTTONS
Definition: multiui.cpp:2155
void multi_sync_init()
Definition: multiui.cpp:7426
int Multi_pwd_bitmap
Definition: multiui.cpp:9089
void palette_use_bm_palette(int n)
Definition: palman.cpp:578
#define MULTI_CONNECTED(np)
Definition: multi.h:136
#define OBJ_UPDATE_MEDIUM
Definition: multi_options.h:18
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
player * Player
#define NETPLAYER_STATE_DEBRIEF_ACCEPT
Definition: multi.h:703
int gr_force_fit_string(char *str, int max_str, int max_width)
Definition: font.cpp:48
#define MC_TEAM0
Definition: multiui.cpp:3038
#define MED_INFO_TEXT
Definition: multiui.cpp:2011
char passwd[MAX_PASSWD_LEN+1]
Definition: multi.h:570
#define MULTI_JOIN_REFRESH_TIME
Definition: multiui.h:27
#define MS_W_COORD
Definition: multiui.cpp:7255
int Please_wait_coords[GR_NUM_RESOLUTIONS][4]
#define MULTI_SG_NUM_TEXT
Definition: multiui.cpp:2209
int Mc_column2_w[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3247
#define MULTI_SYNC_INGAME
Definition: multiui.h:140
int Msg_title_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:2124
#define MS_Y_COORD
Definition: multiui.cpp:7254
Definition: ui.h:584
void chatbox_set_focus()
Definition: chatbox.cpp:1099
uint type
Definition: psnet2.h:39
screen gr_screen
Definition: 2d.cpp:46
#define MULTI_SYNC_POST_BRIEFING
Definition: multiui.h:139
#define MULTI_HO_ACCEPT
Definition: multiui.cpp:5541
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
#define MC_SCROLL_PLAYERS_UP
Definition: multiui.cpp:3033
void generic_anim_init(generic_anim *ga)
Definition: generic.cpp:80
int Mc_players_text[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3277
int Multi_common_num_text_lines
Definition: multiui.cpp:102
#define MS_CANCEL
Definition: multiui.cpp:7266
void multi_debrief_close()
Definition: multiui.cpp:8680
short Multi_create_plist_select_id
Definition: multiui.cpp:3304
#define MULTI_JOIN_OVERLAY
Definition: contexthelp.h:30
color * Multi_join_speed_colors[MJ_NUM_SPEED_LABELS]
Definition: multiui.cpp:666
#define MULTI_HO_NUM_BUTTONS
Definition: multiui.cpp:5495
GLint first
Definition: Gl.h:1491
Definition: ui.h:162
#define MS_FLAG_WSS_SLOTS
Definition: multiui.cpp:7384
short multi_get_new_id()
Definition: multiutil.cpp:3167
#define NETINFO_FLAG_RESPAWNING
Definition: multi.h:609
void multi_join_game_close()
Definition: multiui.cpp:1147
#define MULTI_JOIN_PING_TIME
Definition: multiui.cpp:512
void multi_sync_blit_screen_all()
Definition: multiui.cpp:7642
#define MAX_GAMENAME_LEN
Definition: multi.h:88
#define FSB_FROM_VOLITION
Definition: freespace.h:76
void enable(int n=1)
Definition: gadget.cpp:440
#define MULTI_COMMON_PALETTE_FNAME
Definition: multiui.cpp:400
#define MULTI_SYNC_NUM_TEXT
Definition: multiui.cpp:7287
int Ho_time_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:5719
#define MJ_HELP
Definition: multiui.cpp:505
void multi_create_plist_scroll_up()
Definition: multiui.cpp:4171
#define MULTI_HO_MSG_LEADER
Definition: multiui.cpp:5531
int Multi_debrief_stats_accept_code
Definition: multiui.cpp:8615
int Multi_create_list_select
Definition: multiui.cpp:3323
int gr_get_font_height()
Definition: font.cpp:187
#define MJ_NUM_SPEED_LABELS
Definition: multiui.cpp:658
#define CF_TYPE_MISSIONS
Definition: cfile.h:74
#define NETGAME_STATE_HOST_SETUP
Definition: multi.h:673
#define MS_X_COORD
Definition: multiui.cpp:7253
#define MJW_H_COORD
Definition: multiui.cpp:6546
#define NETPLAYER_STATE_WSS_ACK
Definition: multi.h:698
#define MULTI_HO_W_COORD
Definition: multiui.cpp:5524
UI_XSTR Multi_sg_text[GR_NUM_RESOLUTIONS][MULTI_SG_NUM_TEXT]
Definition: multiui.cpp:2210
#define MSG_RANK_ABOVE
Definition: multiui.cpp:2165
void debrief_assemble_optional_mission_popup_text(char *buffer, char *mission_loop_desc)
GLfloat GLfloat p
Definition: Glext.h:8373
int HEADER_LENGTH
Definition: multi.cpp:106
#define MC_Y_COORD
Definition: multiui.cpp:3058
#define MULTIPLAYER_MASTER
Definition: multi.h:130
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
int Multi_create_files_loaded
Definition: multiui.cpp:3324
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
#define NETPLAYER_STATE_POST_DATA_ACK
Definition: multi.h:697
int Mpwd_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:9078
#define MULTI_VOICE_STATUS_DENIED
Definition: multi_voice.h:23
#define NETPLAYER_STATE_INGAME_SHIP_SELECT
Definition: multi.h:690
#define MICON_TEAM0_SELECT
Definition: multiui.h:57
void create(UI_WINDOW *wnd, int _x, int _y, int _w, int _textlen, char *_text, int _flags=0, int pixel_lim=-1, color *clr=NULL)
Definition: inputbox.cpp:101
#define MC_SHOW_DOGFIGHT
Definition: multiui.cpp:3028
void main_hall_start_music()
#define MED_WARN_TEXT
Definition: multiui.cpp:2010
const char * Skill_level_names(int skill_level, int translate=1)
Definition: aicode.cpp:208
#define MS_FLAG_TS_SLOTS
Definition: multiui.cpp:7388
#define MC_CAMPAIGN_FILTER
Definition: multiui.cpp:3036
color Color_more_bright
Definition: alphacolors.cpp:28
int Active_game_count
Definition: multi.cpp:110
#define MICON_CD
Definition: multiui.h:65
#define MLO_FLAG_LOCAL_BROADCAST
#define timestamp_elapsed(stamp)
Definition: timer.h:102
int has_focus()
Definition: gadget.cpp:334
void multi_common_voice_display_status()
Definition: multiui.cpp:369
void get_mouse_pos(int *xx, int *yy)
Definition: gadget.cpp:341
int Multi_ho_bitmap
Definition: multiui.cpp:5519
#define UI_INPUTBOX_FLAG_INVIS
Definition: ui.h:35
#define PROMPT_CLIENT
Definition: multi_endgame.h:28
UI_INPUTBOX Multi_pwd_passwd
Definition: multiui.cpp:9088
void multi_join_display_games()
Definition: multiui.cpp:1293
void draw_tooltip()
Definition: window.cpp:304
#define MSO_FLAG_ACCEPT_PIX
#define FS_CDROM_VOLUME_3
Definition: freespace.h:31
BM_TYPE bm_get_type(int handle)
Returns the image type of the given bitmap handle.
Definition: bmpman.cpp:894
void multi_sync_close()
Definition: multiui.cpp:7491
char mission_desc[MISSION_DESC_LENGTH]
Definition: missionparse.h:137
#define NUM_RANKS
Definition: scoring.h:28
int Multi_debrief_server_framecount
Definition: multiui.cpp:8617
int chatbox_process(int key_in)
Definition: chatbox.cpp:575
int Ms_status2_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:7318
#define PROMPT_ALL
Definition: multi_endgame.h:29
void multi_campaign_start(char *filename)
int Game_skill_level
Definition: fredstubs.cpp:170
#define MULTI_HO_END_ANY
Definition: multiui.cpp:5536
#define MC_HELP
Definition: multiui.cpp:3045
mouse click
Definition: gamesnd.h:287
void multi_join_send_join_request(int as_observer)
Definition: multiui.cpp:1877
int Multi_debrief_replay_hit
Definition: multiui.cpp:8601
char callsign[CALLSIGN_LEN+1]
Definition: multi.h:571
#define NETPLAYER_STATE_SHIP_SELECT
Definition: multi.h:681
#define gr_free_screen
Definition: 2d.h:827
int multi_join_maybe_warn()
Definition: multiui.cpp:2039
#define KEY_CTRLED
Definition: key.h:64
color Color_normal
Definition: alphacolors.cpp:28
void drop_leading_white_space(char *str)
Definition: parselo.cpp:115
#define IP_ADDRESS_LENGTH
Definition: multi.h:93
UI_XSTR Multi_pwd_text[GR_NUM_RESOLUTIONS][MULTI_PWD_NUM_TEXT]
Definition: multiui.cpp:9108
int Multi_create_should_show_popup
Definition: multiui.cpp:3361
#define CAMPAIGN_TYPE_MULTI_TEAMS
char * filename
Definition: ui.h:657
void multi_create_check_buttons()
Definition: multiui.cpp:3925
int Multi_create_list_start
Definition: multiui.cpp:3322
void multi_ingame_sync_do()
int Mc_team_text[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3282
#define MICON_TEAM1_SELECT
Definition: multiui.h:59
#define OBJ_UPDATE_LOW
Definition: multi_options.h:17
void std_create_gen_dialog(char *title)
active_game * multi_update_active_games(active_game *ag)
Definition: multiutil.cpp:1649
int multi_team_ok_to_commit()
Definition: multi_team.cpp:323
void multi_get_mission_checksum(const char *filename)
Definition: multiutil.cpp:2921
bool Multi_create_sort_mode
Definition: multiui.cpp:3363
#define MPWD_X_COORD
Definition: multiui.cpp:9067
rank_stuff Ranks[NUM_RANKS]
Definition: scoring.cpp:45
#define MSG_H_COORD
Definition: multiui.cpp:2109
UI_SLIDER2 Multi_create_slider
Definition: multiui.cpp:3054
#define CAMPAIGN_TYPE_MULTI_COOP
void get_text(char *out)
Definition: inputbox.cpp:484
GLint GLsizei count
Definition: Gl.h:1491
void multi_create_list_blit_icons(int list_index, int y_start)
Definition: multiui.cpp:4862
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
#define CAMPAIGN_LOOP_MISSION_UNINITIALIZED
#define KEY_UP
Definition: key.h:179
#define UI_XSTR_COLOR_GREEN
Definition: ui.h:160
#define i2f(a)
Definition: fix.h:23
int Multi_join_mt_tried_verify
Definition: multiui.cpp:721
int Mc_create_game_text[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3272
int Multi_create_list_count
Definition: multiui.cpp:3320
#define NETPLAYER_STATE_BRIEFING
Definition: multi.h:680
#define NETPLAYER_STATE_WEAPON_SELECT
Definition: multi.h:682
#define NETPLAYER_STATE_INGAME_SHIPS
Definition: multi.h:687
color Color_text_normal
Definition: alphacolors.cpp:26
#define MJW_W_COORD
Definition: multiui.cpp:6545
void set_valid_chars(char *vchars)
Definition: inputbox.cpp:152
#define MULTI_HO_MSG_RANK
Definition: multiui.cpp:5530
#define IP_PORT_LENGTH
Definition: multi.h:94
#define MJ_X_COORD
Definition: multiui.cpp:584
int Multi_passwd_running
Definition: multiui.cpp:9092
void fs2netd_gameserver_update(bool force)
char Multi_common_text[MULTI_COMMON_TEXT_MAX_LINES][MULTI_COMMON_TEXT_MAX_LINE_LENGTH]
Definition: multiui.cpp:99
void multi_jw_handle_join(net_player *pl)
Definition: multiui.cpp:7167
void multi_sg_check_passwd()
Definition: multiui.cpp:2946
#define MSO_SQUAD_HOST
#define MS_FLAG_PSETTINGS
Definition: multiui.cpp:7385
#define MSO_END_LEADER
int Ms_cd_icon_offset[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:7327
void dc_printf(const char *format,...)
Prints the given char string to the debug console.
Definition: console.cpp:358
UI_XSTR Multi_create_text[GR_NUM_RESOLUTIONS][MULTI_CREATE_NUM_BUTTONS]
Definition: multiui.cpp:3116
int Ho_vd_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:5739
void multi_jw_plist_blit_team()
Definition: multiui.cpp:7034
net_addr Psnet_my_addr
Definition: psnet2.cpp:52
#define MC_KICK
Definition: multiui.cpp:3040
void multi_ho_display_record_time()
Definition: multiui.cpp:6357
#define MJ_H_COORD
Definition: multiui.cpp:587
#define MC_SCROLL_LIST_DOWN
Definition: multiui.cpp:3032
void multi_sync_pre_do()
Definition: multiui.cpp:7951
active_game * Active_game_head
Definition: multi.cpp:109
int multi_ho_check_values()
Definition: multiui.cpp:6377
UI_XSTR Multi_ho_text[GR_NUM_RESOLUTIONS][MULTI_HO_NUM_BUTTONS]
Definition: multiui.cpp:5591
void multi_oo_rate_init_all()
Definition: multi_obj.cpp:1668
int Multi_create_sw_checkbox_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3159
void multi_sg_check_name()
Definition: multiui.cpp:2954
char squad_filename[MAX_FILENAME_LEN+1]
Definition: multi.h:573
int Multi_common_interface_palette
Definition: multiui.cpp:403
#define MULTI_HO_HOST_MODIFIES
Definition: multiui.cpp:5540
void psnet_string_to_addr(net_addr *address, char *text)
Definition: psnet2.cpp:732
#define AG_FLAG_CONNECTION_BIT
Definition: multi.h:539
int bm_unload(int handle, int clear_render_targets, bool nodebug)
Unloads a bitmap's data, but not the bitmap info.
Definition: bmpman.cpp:2890
char m_squad_filename[MAX_FILENAME_LEN+1]
Definition: player.h:98
int multi_debrief_stats_accept_code()
Definition: multiui.cpp:8942
int Mc_icon_valid_coords[GR_NUM_RESOLUTIONS][2]
Definition: multiui.cpp:3232
#define MJW_X_COORD
Definition: multiui.cpp:6543
int Multi_join_bitmap
Definition: multiui.cpp:517
void multi_sync_create_launch_button()
Definition: multiui.cpp:8514
void multi_create_list_scroll_down()
Definition: multiui.cpp:4426
void multi_common_unload_palette()
Definition: multiui.cpp:438
#define NG_TYPE_SW
Definition: multi.h:649
void multi_join_ping_all()
Definition: multiui.cpp:1580
void multi_load_common_icons()
Definition: multiui.cpp:337
int Multi_common_jw_y[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:241
UI_CHECKBOX Multi_jw_sw_checkbox
Definition: multiui.cpp:6613
#define MS_SCROLL_INFO_DOWN
Definition: multiui.cpp:7265
#define MS_H_COORD
Definition: multiui.cpp:7256
#define MULTI_HO_END_RANK
Definition: multiui.cpp:5534
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
void multi_sg_rank_process_select()
Definition: multiui.cpp:2880
mission The_mission
#define NETINFO_FLAG_ACCEPT_OBSERVER
Definition: multi.h:616
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
#define MJW_TEAM1
Definition: multiui.cpp:6533
void disable()
Definition: gadget.cpp:432
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
void multi_debrief_server_process()
Definition: multiui.cpp:8947
char * Multi_common_icon_names[MULTI_NUM_COMMON_ICONS]
Definition: multiui.cpp:306
#define MULTI_HO_END_GROUP
Definition: multiui.cpp:5625
#define AG_FLAG_PASSWD
Definition: multi.h:529
void gr_set_font(int fontnum)
Definition: font.cpp:566
char * Cmdline_game_password
Definition: cmdline.cpp:265
void multi_ping_eval_pong(ping_struct *ps)
Definition: multi_ping.cpp:57
ping_struct ping
Definition: multi.h:555
join_request Multi_join_request
Definition: multiui.cpp:733
#define MJW_SCROLL_INFO_UP
Definition: multiui.cpp:6535
int Mj_cd_coords[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:674
GLenum const GLvoid * addr
Definition: Glext.h:9092
#define NETPLAYER_STATE_SLOTS_ACK
Definition: multi.h:696
void pilot_format_callsign_personal(char *in_callsign, char *out_callsign)
#define MULTI_VOICE_STATUS_PLAYING
Definition: multi_voice.h:25
UI_WINDOW Multi_ho_window
Definition: multiui.cpp:5513
#define MC_CANCEL
Definition: multiui.cpp:3037
#define MJ_REFRESH
Definition: multiui.cpp:499
void multi_game_client_setup_close()
Definition: multiui.cpp:6851
#define KEY_S
Definition: key.h:100
#define NETGAME_STATE_FORMING
Definition: multi.h:664
void multi_create_list_load_campaigns()
Definition: multiui.cpp:4522
#define MULTI_CREATE_SHOW_CAMPAIGNS
Definition: multiui.h:123
void multi_common_add_text(const char *str, int auto_scroll)
Definition: multiui.cpp:167
#define MAX_FREESPACE2_RANK
Definition: scoring.h:42
#define FS_CDROM_VOLUME_1
Definition: freespace.h:29
void multi_create_game_do()
Definition: multiui.cpp:3652
int cf_get_file_list(SCP_vector< SCP_string > &list, int pathtype, const char *filter, int sort=CF_SORT_NONE, SCP_vector< file_list_info > *info=NULL)
char * Multi_join_speed_labels[MJ_NUM_SPEED_LABELS]
Definition: multiui.cpp:659
int Multi_common_icon_dims[MULTI_NUM_COMMON_ICONS][2]
Definition: multiui.cpp:322
void multi_team_set_team(net_player *pl, int team)
Definition: multi_team.cpp:166
#define MULTI_IS_TRACKER_GAME
Definition: multi.h:146
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
int help_overlay_get_index(const char *overlay_name)
int generic_anim_stream(generic_anim *ga)
Definition: generic.cpp:159
int Multi_common_icons[MULTI_NUM_COMMON_ICONS]
Definition: multiui.cpp:304
void multi_create_list_do()
Definition: multiui.cpp:4613
void multi_team_mark_all_ships()
Definition: multi_team.cpp:497
#define MICON_TEAM0
Definition: multiui.h:56
int Mc_list_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:3177
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void multi_common_set_text(const char *str, int auto_scroll)
Definition: multiui.cpp:148
short port
Definition: psnet2.h:42
int max_players
Definition: multi.h:497
void multi_create_button_pressed(int n)
Definition: multiui.cpp:3943
void gameseq_post_event(int event)
#define MLO_FLAG_FLUSH_CACHE
#define CMISSION_FLAG_HAS_LOOP
void multi_join_cull_timeouts()
Definition: multiui.cpp:1741
#define AG_FLAG_CAMPAIGN
Definition: multi.h:531
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
UI_BUTTON Multi_jw_plist_select_button
Definition: multiui.cpp:6640
#define stricmp(s1, s2)
Definition: config.h:271
int Multi_passwd_done
Definition: multiui.cpp:9091
void multi_sync_handle_plist()
Definition: multiui.cpp:8542
int Ho_rsp_coords[GR_NUM_RESOLUTIONS][6]
Definition: multiui.cpp:5779
#define MULTI_JW_NUM_TEXT
Definition: multiui.cpp:6571
net_player * server
Definition: multi.h:505
#define MULTI_HO_SLIDER_VOICE_DUR
Definition: multiui.cpp:5647
void multi_ho_check_focus()
Definition: multiui.cpp:6438
void multi_sync_force_start_post()
Definition: multiui.cpp:8437
void send_firing_info_packet()
Definition: multimsgs.cpp:5520
int Multi_jw_should_show_popup
Definition: multiui.cpp:6642
multi_global_options Multi_options_g
#define MULTI_CREATE_NUM_TEXT
Definition: multiui.cpp:3115
void help_overlay_maybe_blit(int overlay_id, int resolution_index)
int help_overlay_active(int overlay_id)
int flags
Definition: multi.h:495
#define MULTI_XFER_SUCCESS
Definition: multi_xfer.h:24
#define MULTI_COMMON_TEXT_META_CHAR
Definition: multiui.cpp:93
ho_sliders(char *name, int x1, int y1, int xt1, int yt1, int h, int _dot_w, int _dots)
Definition: multiui.cpp:5657
#define MJ_LIST_START_SET(vl)
Definition: multiui.cpp:714
int Mj_speed_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:621
int Mj_status_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:603
void multi_create_init_as_client()
Definition: multiui.cpp:4165
void multi_sync_display_status(const char *status, int index)
Definition: multiui.cpp:8413
void multi_sync_scroll_info_up()
void send_post_sync_data_packet(net_player *p, int std_request)
Definition: multimsgs.cpp:5770
int Multi_common_notify_stamp
Definition: multiui.cpp:252
#define MULTI_HO_SLIDER_VOICE_QOS
Definition: multiui.cpp:5646
#define MSG_Y_COORD
Definition: multiui.cpp:2107
#define UI_INPUTBOX_FLAG_ESC_CLR
Definition: ui.h:37
#define MJ_SCROLL_INFO_UP
Definition: multiui.cpp:500
int Ho_kill_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:5729
#define NETPLAYER_STATE_STD_HOST_SETUP
Definition: multi.h:693
void send_mission_list_request(int what)
Definition: multimsgs.cpp:3550
void multi_join_blit_protocol()
Definition: multiui.cpp:2072
void multi_join_list_page_down()
Definition: multiui.cpp:1726
cmission missions[MAX_CAMPAIGN_MISSIONS]
UI_CHECKBOX Multi_create_sw_checkbox
Definition: multiui.cpp:3154
#define MULTI_XFER_FAIL
Definition: multi_xfer.h:25
#define fl2f(fl)
Definition: floating.h:38
#define MJ_W_COORD
Definition: multiui.cpp:586
UI_DOT_SLIDER_NEW slider
Definition: multiui.cpp:5655
#define MJ_SCROLL_UP
Definition: multiui.cpp:497
char * Multi_create_loading_fname[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3016
int changed()
Definition: checkbox.cpp:181
multi_local_options options
Definition: multi.h:452
int Mj_ping_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:648
GLint y
Definition: Gl.h:1505
void multi_debrief_server_left()
Definition: multiui.cpp:8888
GLuint res
Definition: Glext.h:9084
void send_endgame_packet(net_player *pl)
Definition: multimsgs.cpp:3855
#define NG_TYPE_DOGFIGHT
Definition: multi.h:651
#define NETPLAYER_STATE_FLAG_ACK
Definition: multi.h:699
void multi_start_game_close()
Definition: multiui.cpp:2476
int Ms_status_coords[GR_NUM_RESOLUTIONS][4]
Definition: multiui.cpp:7308
scoring_struct stats
Definition: player.h:127
void multi_jw_do_netstuff()
Definition: multiui.cpp:6928
UI_INPUTBOX Multi_sg_game_passwd
Definition: multiui.cpp:2174
#define MULTI_CREATE_OVERLAY
Definition: contexthelp.h:28
#define MULTI_PWD_NUM_BUTTONS
Definition: multiui.cpp:9073
ubyte comp_version
Definition: multi.h:554
void multi_create_draw_filter_buttons()
Definition: multiui.cpp:5024
#define MC_TEAM1
Definition: multiui.cpp:3039
#define strcpy_s(...)
Definition: safe_strings.h:67
void init_multiplayer_stats()
Definition: stats.cpp:308
int Is_standalone
Definition: systemvars.cpp:59
#define MS_KICK
Definition: multiui.cpp:7267
#define MC_H_COORD
Definition: multiui.cpp:3060
void multi_join_button_pressed(int n)
Definition: multiui.cpp:1174
struct fs_builtin_mission * game_find_builtin_mission(char *)
Definition: fredstubs.cpp:203
char name[NAME_LENGTH]
Definition: scoring.h:66
void fs2netd_update_ban_list()
int Multi_debrief_reported_tvt
Definition: multiui.cpp:8607
int psnet_rel_check()
Definition: psnet2.cpp:1067
void ship_level_init()
Definition: ship.cpp:5226
void multi_host_options_close()
Definition: multiui.cpp:6015
#define MISSION_TYPE_MULTI_TEAMS
Definition: missionparse.h:65
int Mc_column3_w[GR_NUM_RESOLUTIONS]
Definition: multiui.cpp:3252
int Game_weapons_tbl_valid
Definition: fredstubs.cpp:180
#define MULTI_END_ERROR_XFER_FAIL
Definition: multi_endgame.h:52
void multi_xfer_abort(int handle)
Definition: multi_xfer.cpp:308
int Multi_autojoin_join_stamp
Definition: multiui.cpp:729
UI_XSTR Multi_sync_text[GR_NUM_RESOLUTIONS][MULTI_SYNC_NUM_TEXT]
Definition: multiui.cpp:7290
#define MISSION_TYPE_MULTI_DOGFIGHT
Definition: missionparse.h:66
int Multi_join_glr_stamp
Definition: multiui.cpp:510