2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Network/multi_endgame.cpp $
16 * Revision 1.3 2002/06/09 04:41:23 relnev
17 * added copyright header
19 * Revision 1.2 2002/05/07 03:16:47 theoddone33
20 * The Great Newline Fix
22 * Revision 1.1.1.1 2002/05/03 03:28:10 root
26 * 10 8/22/99 1:55p Dave
27 * Cleaned up host/team-captain leaving code.
29 * 9 8/22/99 1:19p Dave
30 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
31 * which d3d cards are detected.
33 * 8 4/08/99 1:05p Dave
34 * Fixed some leave game packet problems. Updated builtin mission list for
37 * 7 3/24/99 4:05p Dave
38 * Put in support for assigning the player to a specific squadron with a
39 * specific logo. Preliminary work for doing pos/orient checksumming in
40 * multiplayer to reduce bandwidth.
42 * 6 11/19/98 4:57p Dave
43 * Ignore PXO option if IPX is selected.
45 * 5 11/19/98 4:19p Dave
46 * Put IPX sockets back in psnet. Consolidated all multiplayer config
49 * 4 11/19/98 8:03a Dave
50 * Full support for D3-style reliable sockets. Revamped packet lag/loss
51 * system, made it receiver side and at the lowest possible level.
53 * 3 11/05/98 5:55p Dave
54 * Big pass at reducing #includes
56 * 2 10/07/98 10:53a Dave
59 * 1 10/07/98 10:50a Dave
61 * 36 9/17/98 3:08p Dave
62 * PXO to non-pxo game warning popup. Player icon stuff in create and join
63 * game screens. Upped server count refresh time in PXO to 35 secs (from
66 * 35 9/15/98 7:24p Dave
67 * Minor UI changes. Localized bunch of new text.
69 * 34 9/14/98 3:40p Allender
70 * better error checking for invalid number of waves for player wings in a
71 * multiplayer game. Better popup message in FreeSpace side.
73 * 33 9/11/98 5:53p Dave
74 * Final revisions to kick system changes.
76 * 32 9/11/98 5:08p Dave
77 * More tweaks to kick notification system.
79 * 31 9/11/98 4:14p Dave
80 * Fixed file checksumming of < file_size. Put in more verbose kicking and
81 * PXO stats store reporting.
83 * 30 8/07/98 10:15a Allender
84 * changed the way the endgame sequencing timer works so that timer wrap
85 * doesn't hurt. Also use the obj_set_flags for the COULD_BE_PLAYER flag
87 * 29 7/24/98 9:27a Dave
88 * Tidied up endgame sequencing by removing several old flags and
89 * standardizing _all_ endgame stuff with a single function call.
91 * 28 7/13/98 5:34p Lawrance
92 * index a localized string in multi_endgame.cpp
94 * 27 7/13/98 5:19p Dave
96 * 26 6/30/98 4:53p Allender
97 * fixed endgame problems where standalone wasn't properly dropping
98 * everyone out of a game. Be sure that timestamp for endgame processing
101 * 25 6/13/98 9:32p Mike
102 * Kill last character in file which caused "Find in Files" to report the
103 * file as "not a text file."
105 * 24 6/13/98 6:01p Hoffoss
106 * Externalized all new (or forgot to be added) strings to all the code.
108 * 23 6/13/98 3:18p Hoffoss
109 * NOX()ed out a bunch of strings that shouldn't be translated.
111 * 22 5/24/98 8:15p Dave
112 * Tweaked pxo some more.
114 * 21 5/21/98 10:09a Dave
115 * Enable DNS checking for PXO and both trackers.
116 * Fixed problem with leaving the mission from the pause state. Fixed
117 * build errors in multimsgs.cpp
119 * 20 5/20/98 9:01p Allender
120 * change RELEASE to NDEBUG. Fix reentryancy problem in process_endgame
123 * 19 5/17/98 11:54p Allender
124 * only clear flying controls when in mission
126 * 18 5/17/98 11:34p Allender
127 * deal with resetting player controls better
129 * 17 5/17/98 6:32p Dave
130 * Make sure clients/servers aren't kicked out of the debriefing when team
131 * captains leave a game. Fixed chatbox off-by-one error. Fixed image
132 * xfer/pilot info popup stuff.
134 * 16 5/15/98 5:15p Dave
135 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
136 * status for team vs. team. Put in asserts to check for invalid team vs.
139 * 15 5/15/98 12:09a Dave
140 * New tracker api code. New game tracker code. Finished up first run of
141 * the PXO screen. Fixed a few game server list exceptions.
143 * 14 5/14/98 12:40a Dave
144 * Still more additions to the PXO screen. Updated tracker code.
146 * 13 5/09/98 7:16p Dave
147 * Put in CD checking. Put in standalone host password. Made pilot into
150 * 12 5/08/98 5:05p Dave
151 * Go to the join game screen when quitting multiplayer. Fixed mission
152 * text chat bugs. Put mission type symbols on the create game list.
153 * Started updating standalone gui controls.
155 * 11 5/07/98 6:26p Dave
156 * Fix strange boundary conditions which arise when players die/respawn
157 * while the game is being ended. Spiff up the chatbox doskey thing a bit.
159 * 10 5/07/98 3:29p Jim
160 * Make sure standalone doesn't display a popup when ending a game.
162 * 9 5/05/98 5:02p Dave
163 * Fix end-of-campaign sequencing to work right. Make all individual
164 * missions of a campaign replayable.
166 * 8 5/04/98 10:39p Dave
167 * Put in endgame sequencing. Need to check campaign situations.
168 * Realigned ship info on team select screen.
170 * 7 5/04/98 1:43p Dave
171 * Fixed up a standalone resetting problem. Fixed multiplayer stats
172 * collection for clients. Make sure all multiplayer ui screens have the
173 * correct palette at all times.
175 * 6 5/03/98 7:04p Dave
176 * Make team vs. team work mores smoothly with standalone. Change how host
177 * interacts with standalone for picking missions. Put in a time limit for
178 * ingame join ship select. Fix ingame join ship select screen for Vasudan
181 * 5 4/30/98 5:12p Dave
182 * Fixed game polling code for joining clients. Reworked some file xfer
185 * 4 4/30/98 12:13a Allender
186 * reset control info and afterburner when entering the quit game code.
187 * Prevents odd things from happening while the popup is up.
189 * 3 4/28/98 5:10p Dave
190 * Fixed multi_quit_game() client side sequencing problem. Turn off
191 * afterburners when ending multiplayer mission. Begin integration of mt
192 * API from Kevin Bentley.
194 * 2 4/23/98 1:28a Dave
195 * Seemingly nailed the current_primary_bank and current_secondary_bank -1
196 * problem. Made sure non-critical button presses are _never_ sent to the
199 * 1 4/22/98 5:50p Dave
205 // #include <windows.h>
209 #include "freespace.h"
210 #include "gamesequence.h"
212 #include "popupdead.h"
213 #include "multi_endgame.h"
214 #include "multimsgs.h"
216 #include "multiutil.h"
217 #include "multi_pmsg.h"
218 #include "multi_fstracker.h"
221 // ----------------------------------------------------------------------------------------------------------
222 // Put all functions/data related to leaving a netgame, handling players leaving, handling the server leaving,
223 // and notifying the user of all of these actions, here.
227 // ----------------------------------------------------------------------------------------------------------
228 // MULTI ENDGAME DEFINES/VARS
232 // set when the server/client has ended the game on some notification or error and is waiting for clients to leave
233 #define MULTI_ENDGAME_SERVER_WAIT 5.0f
234 int Multi_endgame_server_waiting = 0;
235 float Multi_endgame_server_wait_stamp = -1.0f;
236 int Multi_endgame_client_waiting = 0;
238 // error/notification codes (taken from parameters to multi_quit_game(...)
239 int Multi_endgame_notify_code;
240 int Multi_endgame_error_code;
241 int Multi_endgame_wsa_error;
243 // for reentrancy problems on standalone
244 int Multi_endgame_processing;
246 // ----------------------------------------------------------------------------------------------------------
247 // MULTI ENDGAME FORWARD DECLARATIONS
250 // called when a given netgame is about to end completely
251 void multi_endgame_cleanup();
253 // throw up a popup with the given notification code and optional winsock code
254 void multi_endgame_popup(int notify_code,int error_code,int wsa_error = -1);
256 // called when server is waiting for clients to disconnect
257 int multi_endgame_server_ok_to_leave();
259 // check to see if we need to be warping out (strange transition possibilities)
260 void multi_endgame_check_for_warpout();
263 // ----------------------------------------------------------------------------------------------------------
264 // MULTI ENDGAME FUNCTIONS
267 // initialize the endgame processor (call when joining/starting a new netgame)
268 void multi_endgame_init()
270 // set this so that the server/client knows he hasn't tried to end the game
271 Multi_endgame_server_waiting = 0;
272 Multi_endgame_client_waiting = 0;
274 // reset the timestamp used when server is waiting for all other clients to leave.
275 Multi_endgame_server_wait_stamp = -1.0f;
277 // initialiaze all endgame notify and error codes
278 Multi_endgame_notify_code = -1;
279 Multi_endgame_error_code = -1;
280 Multi_endgame_wsa_error = -1;
282 // for reentrancy problems in to endgame_process
283 Multi_endgame_processing = 0;
286 // process all endgame related events
287 void multi_endgame_process()
289 if ( Multi_endgame_processing )
292 Multi_endgame_processing = 1;
294 // check to see if we need to be warping out (strange transition possibilities)
295 multi_endgame_check_for_warpout();
297 // if we're the server of the game
298 if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
299 // if we're not waiting for clients to leave, do nothing
300 if(!Multi_endgame_server_waiting){
301 Multi_endgame_processing = 0;
305 // if a popup is already active, do nothing
307 Multi_endgame_processing = 0;
311 // otherwise popup until things are hunky-dory
312 if(!multi_endgame_server_ok_to_leave()){
313 if(Game_mode & GM_STANDALONE_SERVER){
314 while(!multi_endgame_server_ok_to_leave()){
315 // run networking, etc.
316 game_set_frametime(-1);
317 game_do_state_common(gameseq_get_state());
320 popup_till_condition( multi_endgame_server_ok_to_leave , XSTR("&Cancel",645), XSTR("Waiting for clients to disconnect",646));
324 // mark myself as not waiting and get the hell out
325 multi_endgame_cleanup();
327 // if we're not waiting to leave the game, do nothing
328 if(!Multi_endgame_client_waiting){
329 Multi_endgame_processing = 0;
333 // otherwise, check to see if there is a popup active
335 Multi_endgame_processing = 0;
339 // if not, then we are good to leave
340 multi_endgame_cleanup();
343 Multi_endgame_processing = 0;
346 // if the game has been flagged as ended (ie, its going to be reset)
347 int multi_endgame_ending()
349 return (Multi_endgame_client_waiting || Multi_endgame_server_waiting);
353 int Multi_quit_game = 0;
354 // general quit function, with optional notification, error, and winsock error codes
355 int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
357 int ret_val,quit_already;
359 // check for reentrancy
364 // if we're not connected or have not net-player
365 if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){
374 // reset my control info so that I don't continually do whacky stuff. This is ugly
375 //player_control_reset_ci( &Player->ci );
376 if ( Game_mode & GM_IN_MISSION ) {
377 memset(&Player->ci, 0, sizeof(Player->ci) );
378 Player->ci.afterburner_stop = 1;
379 physics_read_flying_controls( &Player_obj->orient, &Player_obj->phys_info, &(Player->ci), flFrametime);
382 // CASE 1 - response to a user request
383 // if there is no associated notification or error code, don't override the prompt argument
384 if((err_code == -1) && (notify_code == -1)){
385 // if we're the server and we're already waiting for clients to leave, don't do anything
386 if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && Multi_endgame_server_waiting){
391 // if we're the client and we're already waiting to leave, don't do anythin
392 if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER) && Multi_endgame_client_waiting){
397 // see if we should be prompting the host for confirmation
398 if((prompt==PROMPT_HOST || prompt==PROMPT_ALL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){
401 p_flags = PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_BODY_BIG;
402 if ( Game_mode & GM_IN_MISSION )
403 p_flags |= PF_RUN_STATE;
405 ret_val = popup(p_flags,2,POPUP_CANCEL,POPUP_OK,XSTR("Warning - quitting will end the game for all players!",647));
407 // check for host cancel
408 if((ret_val == 0) || (ret_val == -1)){
413 // set this so that under certain circumstances, we don't call the popup below us as well
417 // see if we should be prompting the client for confirmation
418 if((prompt==PROMPT_CLIENT || prompt==PROMPT_ALL) && !quit_already){
419 ret_val = popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_BODY_BIG,2,POPUP_NO,POPUP_YES,XSTR("Are you sure you want to quit?",648));
421 // check for host cancel
422 if((ret_val == 0) || (ret_val == -1)){
428 // if i'm the server of the game, tell all clients that i'm leaving, then wait
429 if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
430 send_netgame_end_error_packet(MULTI_END_NOTIFY_SERVER_LEFT,MULTI_END_ERROR_NONE);
432 // set the waiting flag and the waiting timestamp
433 Multi_endgame_server_waiting = 1;
434 Multi_endgame_server_wait_stamp = MULTI_ENDGAME_SERVER_WAIT;
436 // if i'm the client, quit now
438 multi_endgame_cleanup();
441 // CASE 2 - response to an error code or packet from the server
442 // this is the case where we're being forced to quit the game because of some error or other notification
444 // if i'm the server, send a packet to the clients telling them that I'm leaving and why
445 if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && !Multi_endgame_server_waiting){
446 // if we're in the debrief state, mark down that the server has left the game
447 if(((gameseq_get_state() == GS_STATE_DEBRIEF) || (gameseq_get_state() == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) && !(Game_mode & GM_STANDALONE_SERVER)){
448 multi_debrief_server_left();
450 // add a message to the chatbox
451 multi_display_chat_msg(XSTR("<Team captains have left>",649),0,0);
453 // set ourselves to be "not quitting"
456 // tell the users, the game has ended
457 send_netgame_end_error_packet(notify_code,err_code);
461 send_netgame_end_error_packet(notify_code,err_code);
464 Multi_endgame_notify_code = notify_code;
465 Multi_endgame_error_code = err_code;
466 Multi_endgame_wsa_error = wsa_error;
468 // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave
469 Multi_endgame_server_waiting = 1;
470 Multi_endgame_server_wait_stamp = MULTI_ENDGAME_SERVER_WAIT;
472 // if i'm the client, set the error codes and leave the game now
473 else if(!Multi_endgame_client_waiting){
474 // if we're in the debrief state, mark down that the server has left the game
475 if((gameseq_get_state() == GS_STATE_DEBRIEF) || (gameseq_get_state() == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)){
476 multi_debrief_server_left();
478 // add a message to the chatbox
479 multi_display_chat_msg(XSTR("<The server has ended the game>",650),0,0);
481 // shut our reliable socket to the server down
482 psnet_rel_close_socket(&Net_player->reliable_socket);
483 Net_player->reliable_socket = INVALID_SOCKET;
485 // remove our do-notworking flag
486 Net_player->flags &= ~(NETINFO_FLAG_DO_NETWORKING);
492 Multi_endgame_notify_code = notify_code;
493 Multi_endgame_error_code = err_code;
494 Multi_endgame_wsa_error = wsa_error;
496 // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave
497 Multi_endgame_client_waiting = 1;
501 // unset the reentrancy flag
508 // ----------------------------------------------------------------------------------------------------------
509 // MULTI ENDGAME FORWARD DEFINITIONS
512 // called when a given netgame is about to end completely
513 void multi_endgame_cleanup()
517 send_leave_game_packet();
519 // flush all outgoing io, force all packets through
520 multi_io_send_buffered_packets();
522 // mark myself as disconnected
523 if(!(Game_mode & GM_STANDALONE_SERVER)){
524 Net_player->flags &= ~(NETINFO_FLAG_CONNECTED|NETINFO_FLAG_DO_NETWORKING);
527 // this is a semi-hack so that if we're the master and we're quitting, we don't get an assert
528 if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Player_obj != NULL)){
529 Player_obj->flags &= ~(OF_PLAYER_SHIP);
530 obj_set_flags( Player_obj, Player_obj->flags | OF_COULD_BE_PLAYER );
533 // shut my socket down (will also let the server know i've received any notifications/error from him)
534 // psnet_rel_close_socket( &(Net_player->reliable_socket) );
536 // 11/18/98 - DB, changed the above to kill all sockets. Its the safest thing to do
537 for(idx=0; idx<MAX_PLAYERS; idx++){
538 psnet_rel_close_socket(&Net_players[idx].reliable_socket);
539 Net_players[idx].reliable_socket = INVALID_SOCKET;
542 // set the game quitting flag in our local netgame info - this will _insure_ that even if we miss a packet or
543 // there is some sequencing error, the next time through the multi_do_frame() loop, the game will be ended
544 // Netgame.flags |= (NG_FLAG_QUITTING | NG_FLAG_ENDED);
546 // close all open SPX/TCP reliable sockets
547 if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
549 // do it for all players, since we're leaving anyway.
550 for(idx=0;idx<MAX_PLAYERS;idx++){
551 // 6/25/98 -- MWA delete all players from the game
553 if ( &Net_players[idx] != Net_player ) {
554 delete_player( idx );
559 // if we're currently in the pause state, pop back into gameplay first
560 if(gameseq_get_state() == GS_STATE_MULTI_PAUSED){
564 if(Game_mode & GM_STANDALONE_SERVER){
565 // multi_standalone_quit_game();
566 multi_standalone_reset_all();
568 Player->flags |= PLAYER_FLAGS_IS_MULTI;
570 // if we're in Parallax Online mode, log back in there
571 gameseq_post_event(GS_EVENT_MULTI_JOIN_GAME);
573 // if we have an error code, bring up the discon popup
574 if(((Multi_endgame_notify_code != -1) || (Multi_endgame_error_code != -1)) && !(Game_mode & GM_STANDALONE_SERVER)){
575 multi_endgame_popup(Multi_endgame_notify_code,Multi_endgame_error_code,Multi_endgame_wsa_error);
579 if (MULTI_IS_TRACKER_GAME) {
580 multi_fs_tracker_logout();
584 extern CFILE *obj_stream;
585 if(obj_stream != NULL){
591 // unload the multiplayer common interface palette
592 multi_common_unload_palette();
594 // reinitialize endgame stuff
595 // multi_endgame_init();
598 // throw up a popup with the given notification code and optional winsock code
599 void multi_endgame_popup(int notify_code,int error_code,int wsa_error)
602 int flags = PF_USE_AFFIRMATIVE_ICON;
604 // if there is a popup already active, just kill it
606 // if there is already a popup active, kill it
607 popup_kill_any_active();
611 // if there is a winsock error code, stick it on the end of the text
613 SDL_snprintf(err_msg, SDL_arraysize(err_msg), NOX("WSAERROR : %d\n\n"), wsa_error);
614 flags |= PF_TITLE_RED;
616 SDL_strlcpy(err_msg, "", SDL_arraysize(err_msg));
619 // setup the error message string
620 if(notify_code != MULTI_END_NOTIFY_NONE){
622 case MULTI_END_NOTIFY_KICKED :
623 SDL_strlcat(err_msg,XSTR("You have been kicked",651),SDL_arraysize(err_msg));
625 case MULTI_END_NOTIFY_SERVER_LEFT:
626 SDL_strlcat(err_msg,XSTR("The server has left the game",652),SDL_arraysize(err_msg));
628 case MULTI_END_NOTIFY_FILE_REJECTED:
629 SDL_strlcat(err_msg,XSTR("Your mission file has been rejected by the server",653),SDL_arraysize(err_msg));
631 case MULTI_END_NOTIFY_EARLY_END:
632 SDL_strlcat(err_msg,XSTR("The game has ended while you were ingame joining",654),SDL_arraysize(err_msg));
634 case MULTI_END_NOTIFY_INGAME_TIMEOUT:
635 SDL_strlcat(err_msg,XSTR("You have waited too long to select a ship",655),SDL_arraysize(err_msg));
637 case MULTI_END_NOTIFY_KICKED_BAD_XFER:
638 SDL_strlcat(err_msg,XSTR("You were kicked because mission file xfer failed",998),SDL_arraysize(err_msg));
640 case MULTI_END_NOTIFY_KICKED_CANT_XFER:
641 SDL_strlcat(err_msg,XSTR("You were kicked because you do not have the builtin mission",999),SDL_arraysize(err_msg));
642 SDL_strlcat(err_msg, NOX(" "), SDL_arraysize(err_msg));
643 SDL_strlcat(err_msg, Game_current_mission_filename, SDL_arraysize(err_msg));
645 case MULTI_END_NOTIFY_KICKED_INGAME_ENDED:
646 SDL_strlcat(err_msg,XSTR("You were kicked because you were ingame joining a game that has ended",1000),SDL_arraysize(err_msg));
653 case MULTI_END_ERROR_CONTACT_LOST :
654 SDL_strlcat(err_msg,XSTR("Contact with server has been lost",656),SDL_arraysize(err_msg));
656 case MULTI_END_ERROR_CONNECT_FAIL :
657 SDL_strlcat(err_msg,XSTR("Failed to connect to server on reliable socket",657),SDL_arraysize(err_msg));
659 case MULTI_END_ERROR_LOAD_FAIL :
660 SDL_strlcat(err_msg,XSTR("Failed to load mission file properly",658),SDL_arraysize(err_msg));
662 case MULTI_END_ERROR_INGAME_SHIP :
663 SDL_strlcat(err_msg,XSTR("Unable to create ingame join player ship",659),SDL_arraysize(err_msg));
665 case MULTI_END_ERROR_INGAME_BOGUS :
666 SDL_strlcat(err_msg,XSTR("Recevied bogus packet data while ingame joining",660),SDL_arraysize(err_msg));
668 case MULTI_END_ERROR_STRANS_FAIL :
669 SDL_strlcat(err_msg,XSTR("Server transfer failed (obsolete)",661),SDL_arraysize(err_msg));
671 case MULTI_END_ERROR_SHIP_ASSIGN:
672 SDL_strlcat(err_msg,XSTR("Server encountered errors trying to assign players to ships",662),SDL_arraysize(err_msg));
674 case MULTI_END_ERROR_HOST_LEFT:
675 SDL_strlcat(err_msg,XSTR("Host has left the game, aborting...",663),SDL_arraysize(err_msg));
677 case MULTI_END_ERROR_XFER_FAIL:
678 SDL_strlcat(err_msg,XSTR("There was an error receiving the mission file!",665),SDL_arraysize(err_msg));
680 case MULTI_END_ERROR_WAVE_COUNT:
681 SDL_strlcat(err_msg,XSTR("The player wings Alpha, Beta, Gamma, and Zeta must have only 1 wave. One of these wings currently has more than 1 wave.", 987),SDL_arraysize(err_msg));
683 case MULTI_END_ERROR_TEAM0_EMPTY:
684 SDL_strlcat(err_msg,XSTR("All players from team 1 have left the game", 1466),SDL_arraysize(err_msg));
686 case MULTI_END_ERROR_TEAM1_EMPTY:
687 SDL_strlcat(err_msg,XSTR("All players from team 2 have left the game", 1467),SDL_arraysize(err_msg));
689 case MULTI_END_ERROR_CAPTAIN_LEFT:
690 SDL_strlcat(err_msg,XSTR("Team captain(s) have left the game, aborting...",664),SDL_arraysize(err_msg));
698 popup(flags,1,POPUP_OK,err_msg);
702 // called when server is waiting for clients to disconnect
703 int multi_endgame_server_ok_to_leave()
707 // check to see if our client disconnect timestamp has elapsed
708 if ( Multi_endgame_server_wait_stamp > 0.0f ) {
709 Multi_endgame_server_wait_stamp -= flFrametime;
710 if ( Multi_endgame_server_wait_stamp <= 0.0f ) {
715 // check to see if all clients have disconnected
716 for(idx=0;idx<MAX_PLAYERS;idx++){
717 if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){
722 // all conditions passed
726 // check to see if we need to be warping out (strange transition possibilities)
727 void multi_endgame_check_for_warpout()
729 int need_to_warpout = 0;
731 // if we're not in the process of warping out - do nothing
732 if(!(Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
736 // determine if sufficient warping-out conditions exist
737 if((Game_mode & GM_IN_MISSION) && // if i'm still in the mission
738 ((Netgame.game_state == NETGAME_STATE_ENDGAME) || // if the netgame ended
739 (Netgame.game_state == NETGAME_STATE_DEBRIEF)) // if the netgame is now in the debriefing state
744 // if we need to be warping out but are stuck in a dead popup, cancel it
745 if(need_to_warpout && (popupdead_is_active() || (Net_player->flags & NETINFO_FLAG_RESPAWNING) || (Net_player->flags & NETINFO_FLAG_OBSERVER)) ){
746 // flush all active pushed state
747 multi_handle_state_special();
749 // begin the warpout process
750 gameseq_post_event(GS_EVENT_DEBRIEF);
752 // if text input mode is active, clear it
753 multi_msg_text_flush();