// display the medals screen for this player void multi_pinfo_do_medals() { #ifdef FS2DEMO game_feature_not_in_demo_popup(); #elif defined(SAGA_NO_MULTIPLAYER_YET) game_feature_not_supported_by_saga_yet(); #else int ret_code; // initialize the medals screen medal_main_init(Multi_pinfo_popup_player->m_player, MM_POPUP); // run the medals screen until it says that it should be closed do { // set frametime and run common functions game_set_frametime(-1); game_do_state_common(gameseq_get_state()); // run the medals screen ret_code = medal_main_do(); } while (ret_code && !Multi_pinfo_popup_done); // close the medals screen down medal_main_close(); // restore the proper palette multi_pinfo_set_palette(); #endif }
// (client) call when receiving a packet indicating we should pause void multi_pause_pause() { int idx; // if we're already paused, don't do anything if(Multi_pause_status){ return; } // sanity check Assert(!Multi_pause_status); // mark the game as being paused Multi_pause_status = 1; // if we're not already in the pause state if(gameseq_get_state() != GS_STATE_MULTI_PAUSED){ // jump into the paused state gameseq_post_event(GS_EVENT_MULTI_PAUSE); // mark the netgame state Netgame.game_state = NETGAME_STATE_PAUSED; } // if we're the server of the game, send a packet which will pause the clients in the game now if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){ send_client_update_packet(&Net_players[idx]); } } } }
// run the popup in a tight loop (no states) void multi_pinfo_popup_do() { int k; // if there was an error in initialization, return immediately if (Multi_pinfo_popup_error) { return; } // tight loop while (!Multi_pinfo_popup_done) { multi_pinfo_maybe_reload_pic(&Mp_pilot); multi_pinfo_maybe_reload_pic(&Mp_squad); // process the window k = Multi_pinfo_window.process(); switch (k) { case KEY_ESC : Multi_pinfo_popup_done = 1; break; } // check button presses multi_pinfo_popup_check_buttons(); // set frametime and run background stuff game_set_frametime(-1); game_do_state_common(gameseq_get_state()); // draw the background bitmap and the ui window over it Assert(Multi_pinfo_screen_save != -1); gr_reset_clip(); gr_restore_screen(Multi_pinfo_screen_save); // grey the screen gr_set_shader(&Grey_shader); gr_shade(0, 0, gr_screen.clip_width, gr_screen.clip_height, false); // draw the background bitmap gr_set_bitmap(Multi_pinfo_bitmap); gr_bitmap(0, 0); // blit the selected pilot image multi_pinfo_blit_pilot_image(); // blit the squadron logo multi_pinfo_blit_squadron_logo(); // blit the player statistics multi_pinfo_blit_player_stats(); // draw the ui window and flip Multi_pinfo_window.draw(); gr_flip(); } }
// process all endgame related events void multi_endgame_process() { if ( Multi_endgame_processing ) return; Multi_endgame_processing = 1; // check to see if we need to be warping out (strange transition possibilities) multi_endgame_check_for_warpout(); // if we're the server of the game if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ // if we're not waiting for clients to leave, do nothing if(!Multi_endgame_server_waiting){ Multi_endgame_processing = 0; return; } // if a popup is already active, do nothing if(popup_active()){ Multi_endgame_processing = 0; return; } // otherwise popup until things are hunky-dory if(!multi_endgame_server_ok_to_leave()){ if(Game_mode & GM_STANDALONE_SERVER){ while(!multi_endgame_server_ok_to_leave()){ // run networking, etc. game_set_frametime(-1); game_do_state_common(gameseq_get_state()); } } else { popup_till_condition( multi_endgame_server_ok_to_leave , XSTR("&Cancel",645), XSTR("Waiting for clients to disconnect",646)); } } // mark myself as not waiting and get out multi_endgame_cleanup(); } else { // if we're not waiting to leave the game, do nothing if(!Multi_endgame_client_waiting){ Multi_endgame_processing = 0; return; } // otherwise, check to see if there is a popup active if(popup_active()){ Multi_endgame_processing = 0; return; } // if not, then we are good to leave multi_endgame_cleanup(); } Multi_endgame_processing = 0; }
int popup_do_with_condition(popup_info *pi, int flags, int(*condition)()) { int screen_id, choice = -1, done = 0; int test; screen_id = gr_save_screen(); if ( popup_init(pi, flags) == -1 ) return -1; int old_max_w_unscaled = gr_screen.max_w_unscaled; int old_max_h_unscaled = gr_screen.max_h_unscaled; int old_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed; int old_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed; gr_reset_screen_scale(); while(!done) { int k; os_poll(); game_set_frametime(-1); game_do_state_common(gameseq_get_state()); // do stuff common to all states gr_restore_screen(screen_id); // draw one frame first Popup_window.draw(); popup_force_draw_buttons(pi); popup_draw_msg_text(pi, flags); popup_draw_button_text(pi, flags); gr_flip(); // test the condition function or process for the window if ((test = condition()) > 0) { done = 1; choice = test; } else { k = Popup_window.process(); // poll for input, handle mouse choice = popup_process_keys(pi, k, flags); if ( choice != POPUP_NOCHANGE ) { done=1; } if ( !done ) { choice = popup_check_buttons(pi); if ( choice != POPUP_NOCHANGE ) { done=1; } } } } gr_set_screen_scale(old_max_w_unscaled, old_max_h_unscaled, old_max_w_unscaled_zoomed, old_max_h_unscaled_zoomed); popup_close(pi,screen_id); return choice; }
// (server) evaluate a pause request from the given player (should call for himself as well) void multi_pause_server_eval_request(net_player *pl, int pause) { int cur_state; // if this is a pause request and we're already in the pause state, do nothing if(pause && Multi_pause_status){ return; } // if this is an unpause request and we're already unpaused, do nothing if(!pause && !Multi_pause_status){ return; } // get the current state (don't allow pausing from certain states cur_state = gameseq_get_state(); if((cur_state == GS_STATE_DEBRIEF) || (cur_state == GS_STATE_MULTI_MISSION_SYNC) || (cur_state == GS_STATE_BRIEFING) || (cur_state == GS_STATE_STANDALONE_POSTGAME) || (cur_state == GS_STATE_MULTI_STD_WAIT) || (cur_state == GS_STATE_WEAPON_SELECT) || (cur_state == GS_STATE_TEAM_SELECT) || (cur_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)){ return; } // if this is a pause request if(pause){ // record who the pauser is Multi_pause_pauser = pl; // pause the game multi_pause_pause(); } // if this is an unpause request else { // if this guy is allowed to unpause the game, do so if(multi_pause_can_unpause(pl)){ // unmark the "pauser" Multi_pause_pauser = NULL; // unpause the game multi_pause_unpause(); } } }
// display the medals screen for this player void multi_pinfo_do_medals() { int ret_code; // initialize the medals screen medal_main_init(Multi_pinfo_popup_player->m_player,MM_POPUP); // run the medals screen until it says that it should be closed do { // set frametime and run common functions game_set_frametime(-1); game_do_state_common(gameseq_get_state()); // run the medals screen ret_code = medal_main_do(); } while(ret_code && !Multi_pinfo_popup_done); // close the medals screen down medal_main_close(); }
// launch_context_help() will switch to a context sensitive help state void launch_context_help() { // look at the state the game was in when F1 was pressed Source_game_state = gameseq_get_state(); switch (Source_game_state) { case GS_STATE_MAIN_MENU: #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD) int main_hall_num; main_hall_num = (main_hall_id() == 0) ? MH_OVERLAY : MH2_OVERLAY; if (!help_overlay_active(main_hall_num)) { help_overlay_set_state(main_hall_num, 1); } else { help_overlay_set_state(main_hall_num, 0); } #endif break; case GS_STATE_GAME_PLAY: case GS_STATE_GAME_PAUSED: case GS_STATE_TRAINING_PAUSED: gameseq_post_event(GS_EVENT_GAMEPLAY_HELP); break; case GS_STATE_BRIEFING: if (!help_overlay_active(BR_OVERLAY)) { help_overlay_set_state(BR_OVERLAY, 1); } else { help_overlay_set_state(BR_OVERLAY, 0); } break; case GS_STATE_SHIP_SELECT: if (!help_overlay_active(SS_OVERLAY)) { help_overlay_set_state(SS_OVERLAY, 1); } else { help_overlay_set_state(SS_OVERLAY, 0); } break; case GS_STATE_WEAPON_SELECT: if (!help_overlay_active(WL_OVERLAY)) { help_overlay_set_state(WL_OVERLAY, 1); } else { help_overlay_set_state(WL_OVERLAY, 0); } break; case GS_STATE_BARRACKS_MENU: if (!help_overlay_active(BARRACKS_OVERLAY)) { help_overlay_set_state(BARRACKS_OVERLAY, 1); } else { help_overlay_set_state(BARRACKS_OVERLAY, 0); } break; case GS_STATE_CONTROL_CONFIG: if (!help_overlay_active(CONTROL_CONFIG_OVERLAY)) { help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 1); } else { help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0); } break; case GS_STATE_DEBRIEF: if (!help_overlay_active(DEBRIEFING_OVERLAY)) { help_overlay_set_state(DEBRIEFING_OVERLAY, 1); } else { help_overlay_set_state(DEBRIEFING_OVERLAY, 0); } break; case GS_STATE_MULTI_HOST_SETUP: if (!help_overlay_active(MULTI_CREATE_OVERLAY)) { help_overlay_set_state(MULTI_CREATE_OVERLAY, 1); } else { help_overlay_set_state(MULTI_CREATE_OVERLAY, 0); } break; case GS_STATE_MULTI_START_GAME: if (!help_overlay_active(MULTI_START_OVERLAY)) { help_overlay_set_state(MULTI_START_OVERLAY, 1); } else { help_overlay_set_state(MULTI_START_OVERLAY, 0); } break; /* case GS_STATE_NET_CHAT: if (!help_overlay_active(FS2OX_OVERLAY) ) { help_overlay_set_state(FS2OX_OVERLAY, 1); } else { help_overlay_set_state(FS2OX_OVERLAY, 1); } break; */ case GS_STATE_MULTI_JOIN_GAME: if (!help_overlay_active(MULTI_JOIN_OVERLAY)) { help_overlay_set_state(MULTI_JOIN_OVERLAY, 1); } else { help_overlay_set_state(MULTI_JOIN_OVERLAY, 0); } break; case GS_STATE_HOTKEY_SCREEN: if (!help_overlay_active(HOTKEY_OVERLAY)) { help_overlay_set_state(HOTKEY_OVERLAY, 1); } else { help_overlay_set_state(HOTKEY_OVERLAY, 0); } break; case GS_STATE_CAMPAIGN_ROOM: if (!help_overlay_active(CAMPAIGN_ROOM_OVERLAY)) { help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 1); } else { help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 0); } break; case GS_STATE_SIMULATOR_ROOM: if (!help_overlay_active(SIM_ROOM_OVERLAY)) { help_overlay_set_state(SIM_ROOM_OVERLAY, 1); } else { help_overlay_set_state(SIM_ROOM_OVERLAY, 0); } break; case GS_STATE_TECH_MENU: { if (!help_overlay_active(TECH_ROOM_OVERLAY)) { help_overlay_set_state(TECH_ROOM_OVERLAY, 1); } else { help_overlay_set_state(TECH_ROOM_OVERLAY, 0); } break; } case GS_STATE_CMD_BRIEF: if (!help_overlay_active(CMD_BRIEF_OVERLAY)) { help_overlay_set_state(CMD_BRIEF_OVERLAY, 1); } else { help_overlay_set_state(CMD_BRIEF_OVERLAY, 0); } break; default: nprintf(("Warning", "WARNING ==> There is no context help available for state %s\n", GS_state_text[Source_game_state - 1])); break; } // end switch }
// launch_context_help() will switch to a context sensitive help state void launch_context_help() { int overlay_id = -1; int resolution_index = gr_screen.res; // look at the state the game was in when F1 was pressed Source_game_state = gameseq_get_state(); switch (Source_game_state) { case GS_STATE_MAIN_MENU: overlay_id = main_hall_get_overlay_id(); resolution_index = main_hall_get_overlay_resolution_index(); break; case GS_STATE_GAME_PLAY: case GS_STATE_GAME_PAUSED: case GS_STATE_TRAINING_PAUSED: gameseq_post_event(GS_EVENT_GAMEPLAY_HELP); break; case GS_STATE_BRIEFING: overlay_id = Briefing_overlay_id; break; case GS_STATE_SHIP_SELECT: overlay_id = Ship_select_overlay_id; break; case GS_STATE_WEAPON_SELECT: overlay_id = Weapon_select_overlay_id; break; case GS_STATE_BARRACKS_MENU: overlay_id = Barracks_overlay_id; break; case GS_STATE_CONTROL_CONFIG: overlay_id = Control_config_overlay_id; break; case GS_STATE_DEBRIEF: overlay_id = Debrief_overlay_id; break; case GS_STATE_MULTI_HOST_SETUP: overlay_id = Multi_create_overlay_id; break; case GS_STATE_MULTI_START_GAME: overlay_id = Multi_sg_overlay_id; break; case GS_STATE_MULTI_JOIN_GAME: overlay_id = Multi_join_overlay_id; break; case GS_STATE_HOTKEY_SCREEN: overlay_id = Hotkey_overlay_id; break; case GS_STATE_CAMPAIGN_ROOM: overlay_id = Campaign_room_overlay_id; break; case GS_STATE_SIMULATOR_ROOM: overlay_id = Sim_room_overlay_id; break; case GS_STATE_TECH_MENU: overlay_id = Techroom_overlay_id; break; case GS_STATE_CMD_BRIEF: overlay_id = Cmd_brief_overlay_id; break; default: nprintf(("Warning","WARNING ==> There is no context help available for state %s\n", GS_state_text[Source_game_state-1])); break; } // end switch if (overlay_id >= 0) { if ( !help_overlay_active(overlay_id) ) { help_overlay_set_state(overlay_id, resolution_index, 1); } else { help_overlay_set_state(overlay_id, resolution_index, 0); } } }
// called when a given netgame is about to end completely void multi_endgame_cleanup() { int idx; hud_config_as_player(); send_leave_game_packet(); // flush all outgoing io, force all packets through multi_io_send_buffered_packets(); // mark myself as disconnected if(!(Game_mode & GM_STANDALONE_SERVER)){ Net_player->flags &= ~(NETINFO_FLAG_CONNECTED|NETINFO_FLAG_DO_NETWORKING); } /*this is a semi-hack so that if we're the master and we're quitting, we don't get an assert Karajorma - From the looks of things this code actually CAUSES an Int3 and doesn't cause an assert anymore besides if the game is over why are we setting flags on a Player_obj anyway? if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Player_obj != NULL)){ Player_obj->flags &= ~(OF_PLAYER_SHIP); obj_set_flags( Player_obj, Player_obj->flags | OF_COULD_BE_PLAYER ); } */ // shut my socket down (will also let the server know i've received any notifications/error from him) // psnet_rel_close_socket( &(Net_player->reliable_socket) ); // 11/18/98 - DB, changed the above to kill all sockets. Its the safest thing to do for(idx=0; idx<MAX_PLAYERS; idx++){ psnet_rel_close_socket(&Net_players[idx].reliable_socket); Net_players[idx].reliable_socket = INVALID_SOCKET; } // set the game quitting flag in our local netgame info - this will _insure_ that even if we miss a packet or // there is some sequencing error, the next time through the multi_do_frame() loop, the game will be ended // Netgame.flags |= (NG_FLAG_QUITTING | NG_FLAG_ENDED); // close all open SPX/TCP reliable sockets if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ // do it for all players, since we're leaving anyway. for(idx=0;idx<MAX_PLAYERS;idx++){ // 6/25/98 -- MWA delete all players from the game if ( &Net_players[idx] != Net_player ) { delete_player( idx ); } } } // if we're currently in the pause state, pop back into gameplay first if(gameseq_get_state() == GS_STATE_MULTI_PAUSED){ gameseq_pop_state(); } // handle game disconnect from FS2NetD (NOTE: must be done *before* standalone is reset!!) if ( MULTI_IS_TRACKER_GAME && (Net_player->flags & NETINFO_FLAG_AM_MASTER) ) { fs2netd_gameserver_disconnect(); } if (Game_mode & GM_STANDALONE_SERVER) { // multi_standalone_quit_game(); multi_standalone_reset_all(); } else { Player->flags |= PLAYER_FLAGS_IS_MULTI; // if we're in Parallax Online mode, log back in there gameseq_post_event(GS_EVENT_MULTI_JOIN_GAME); // if we have an error code, bring up the discon popup if ( ((Multi_endgame_notify_code != -1) || (Multi_endgame_error_code != -1)) && !(Game_mode & GM_STANDALONE_SERVER) ) { multi_endgame_popup(Multi_endgame_notify_code,Multi_endgame_error_code,Multi_endgame_wsa_error); } } /* extern CFILE *obj_stream; if(obj_stream != NULL){ cfclose(obj_stream); obj_stream = NULL; } */ // unload the multiplayer common interface palette multi_common_unload_palette(); // reinitialize endgame stuff // multi_endgame_init(); }
// general quit function, with optional notification, error, and winsock error codes int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error) { int ret_val,quit_already; // check for reentrancy if(Multi_quit_game){ return 0; } // if we're not connected or have not net-player if((Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_CONNECTED)){ return 1; } // reentrancy Multi_quit_game = 1; quit_already = 0; // reset my control info so that I don't continually do whacky stuff. This is ugly //player_control_reset_ci( &Player->ci ); if ( Game_mode & GM_IN_MISSION ) { memset(&Player->ci, 0, sizeof(Player->ci) ); Player->ci.afterburner_stop = 1; physics_read_flying_controls( &Player_obj->orient, &Player_obj->phys_info, &(Player->ci), flFrametime); } // CASE 1 - response to a user request // if there is no associated notification or error code, don't override the prompt argument if((err_code == -1) && (notify_code == -1)){ // if we're the server and we're already waiting for clients to leave, don't do anything if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && Multi_endgame_server_waiting){ Multi_quit_game = 0; return 0; } // if we're the client and we're already waiting to leave, don't do anythin if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER) && Multi_endgame_client_waiting){ Multi_quit_game = 0; return 0; } // see if we should be prompting the host for confirmation if((prompt==PROMPT_HOST || prompt==PROMPT_ALL) && (Net_player->flags & NETINFO_FLAG_GAME_HOST)){ int p_flags; p_flags = PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON | PF_BODY_BIG; if ( Game_mode & GM_IN_MISSION ) p_flags |= PF_RUN_STATE; ret_val = popup(p_flags,2,POPUP_CANCEL,POPUP_OK,XSTR("Warning - quitting will end the game for all players!",647)); // check for host cancel if((ret_val == 0) || (ret_val == -1)){ Multi_quit_game = 0; return 0; } // set this so that under certain circumstances, we don't call the popup below us as well quit_already = 1; } // see if we should be prompting the client for confirmation if((prompt==PROMPT_CLIENT || prompt==PROMPT_ALL) && !quit_already){ 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)); // check for host cancel if((ret_val == 0) || (ret_val == -1)){ Multi_quit_game = 0; return 0; } quit_already = 1; } // if i'm the server of the game, tell all clients that i'm leaving, then wait if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ send_netgame_end_error_packet(MULTI_END_NOTIFY_SERVER_LEFT,MULTI_END_ERROR_NONE); // set the waiting flag and the waiting timestamp Multi_endgame_server_waiting = 1; Multi_endgame_server_wait_stamp = MULTI_ENDGAME_SERVER_WAIT; } // if i'm the client, quit now else { multi_endgame_cleanup(); } } // CASE 2 - response to an error code or packet from the server // this is the case where we're being forced to quit the game because of some error or other notification else { // if i'm the server, send a packet to the clients telling them that I'm leaving and why if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && !Multi_endgame_server_waiting){ // if we're in the debrief state, mark down that the server has left the game if(((gameseq_get_state() == GS_STATE_DEBRIEF) || (gameseq_get_state() == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) && !(Game_mode & GM_STANDALONE_SERVER)){ multi_debrief_server_left(); // add a message to the chatbox multi_display_chat_msg(XSTR("<Team captains have left>",649),0,0); // set ourselves to be "not quitting" Multi_quit_game = 0; // tell the users, the game has ended send_netgame_end_error_packet(notify_code,err_code); return 0; } send_netgame_end_error_packet(notify_code,err_code); // store the globals Multi_endgame_notify_code = notify_code; Multi_endgame_error_code = err_code; Multi_endgame_wsa_error = wsa_error; // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave Multi_endgame_server_waiting = 1; Multi_endgame_server_wait_stamp = MULTI_ENDGAME_SERVER_WAIT; } // if i'm the client, set the error codes and leave the game now else if(!Multi_endgame_client_waiting){ // if we're in the debrief state, mark down that the server has left the game if((gameseq_get_state() == GS_STATE_DEBRIEF) || (gameseq_get_state() == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)){ multi_debrief_server_left(); // add a message to the chatbox multi_display_chat_msg(XSTR("<The server has ended the game>",650),0,0); // shut our reliable socket to the server down psnet_rel_close_socket(&Net_player->reliable_socket); Net_player->reliable_socket = INVALID_SOCKET; // remove our do-notworking flag Net_player->flags &= ~(NETINFO_FLAG_DO_NETWORKING); Multi_quit_game = 0; return 0; } Multi_endgame_notify_code = notify_code; Multi_endgame_error_code = err_code; Multi_endgame_wsa_error = wsa_error; // by setting this, multi_endgame_process() will know to check and see if it is ok for us to leave Multi_endgame_client_waiting = 1; } } // unset the reentrancy flag Multi_quit_game = 0; return 1; }
// exit: -1 => error // 0..nchoices-1 => choice int popup_do(popup_info *pi, int flags) { int screen_id, choice = -1, done = 0; if ( popup_init(pi, flags) == -1 ){ return -1; } screen_id = gr_save_screen(); int old_max_w_unscaled = gr_screen.max_w_unscaled; int old_max_h_unscaled = gr_screen.max_h_unscaled; int old_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed; int old_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed; gr_reset_screen_scale(); while(!done) { int k; os_poll(); // if we were killed by a call to popup_kill_any_active(), kill the popup if(Popup_should_die){ choice = -1; break; } // if we're flagged as should be running the state underneath, then do so if(flags & PF_RUN_STATE){ game_do_state(gameseq_get_state()); } // otherwise just run the common functions (for networking,etc) else { game_set_frametime(-1); game_do_state_common(gameseq_get_state(),flags & PF_NO_NETWORKING); // do stuff common to all states } k = Popup_window.process(); // poll for input, handle mouse choice = popup_process_keys(pi, k, flags); if ( choice != POPUP_NOCHANGE ) { done=1; } if ( !done ) { choice = popup_check_buttons(pi); if ( choice != POPUP_NOCHANGE ) { done=1; } } // don't draw anything if(!(flags & PF_RUN_STATE)){ gr_restore_screen(screen_id); } // if this is an input popup, store the input text if(flags & PF_INPUT){ Popup_input.get_text(pi->input_text); } Popup_window.draw(); popup_force_draw_buttons(pi); popup_draw_msg_text(pi, flags); popup_draw_button_text(pi, flags); gr_flip(); } gr_set_screen_scale(old_max_w_unscaled, old_max_h_unscaled, old_max_w_unscaled_zoomed, old_max_h_unscaled_zoomed); popup_close(pi,screen_id); return choice; }
bool ConditionedHook::ConditionsValid(int action, object* objp) { uint i; //Return false if any conditions are not met script_condition* scp; ship_info* sip; for (i = 0; i < MAX_HOOK_CONDITIONS; i++) { scp = &Conditions[i]; switch (scp->condition_type) { case CHC_STATE: if (gameseq_get_depth() < 0) return false; if (stricmp(GS_state_text[gameseq_get_state(0)], scp->data.name)) return false; break; case CHC_SHIPTYPE: if (objp == NULL || objp->type != OBJ_SHIP) return false; sip = &Ship_info[Ships[objp->instance].ship_info_index]; if (sip->class_type < 0) return false; if (stricmp(Ship_types[sip->class_type].name, scp->data.name)) return false; case CHC_SHIPCLASS: if (objp == NULL || objp->type != OBJ_SHIP) return false; if (stricmp(Ship_info[Ships[objp->instance].ship_info_index].name, scp->data.name)) return false; break; case CHC_SHIP: if (objp == NULL || objp->type != OBJ_SHIP) return false; if (stricmp(Ships[objp->instance].ship_name, scp->data.name)) return false; break; case CHC_MISSION: { //WMC - Get mission filename with Mission_filename //I don't use Game_current_mission_filename, because //Mission_filename is valid in both fs2_open and FRED size_t len = strlen(Mission_filename); if (!len) return false; if (len > 4 && !stricmp(&Mission_filename[len - 4], ".fs2")) len -= 4; if (strnicmp(scp->data.name, Mission_filename, len)) return false; break; } case CHC_CAMPAIGN: { size_t len = strlen(Campaign.filename); if (!len) return false; if (len > 4 && !stricmp(&Mission_filename[len - 4], ".fc2")) len -= 4; if (strnicmp(scp->data.name, Mission_filename, len)) return false; break; } case CHC_WEAPONCLASS: if (objp == NULL || objp->type != OBJ_WEAPON) return false; if (stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, scp->data.name)) return false; break; case CHC_OBJECTTYPE: if (objp == NULL) return false; if (stricmp(Object_type_names[objp->type], scp->data.name)) return false; break; case CHC_KEYPRESS: { extern int Current_key_down; if (gameseq_get_depth() < 0) return false; if (Current_key_down == 0) return false; //WMC - could be more efficient, but whatever. if (stricmp(textify_scancode(Current_key_down), scp->data.name)) return false; break; } case CHC_VERSION: { // Goober5000: I'm going to assume scripting doesn't care about SVN revision char buf[32]; sprintf(buf, "%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD); if (stricmp(buf, scp->data.name)) { //In case some people are lazy and say "3.7" instead of "3.7.0" or something if (FS_VERSION_BUILD == 0) { sprintf(buf, "%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR); if (stricmp(buf, scp->data.name)) return false; } else { return false; } } break; } case CHC_APPLICATION: { if (Fred_running) { if (stricmp("FRED2_Open", scp->data.name) && stricmp("FRED2_Open", scp->data.name) && stricmp("FRED 2", scp->data.name) && stricmp("FRED", scp->data.name)) return false; } else { if (stricmp("FS2_Open", scp->data.name) && stricmp("FS2Open", scp->data.name) && stricmp("Freespace 2", scp->data.name) && stricmp("Freespace", scp->data.name)) return false; } } default: break; } } return true; }
// init the Popup window int popup_init(popup_info *pi, int flags) { int i; UI_BUTTON *b; popup_background *pbg; char *fname; int state, choice; // to have those cool holo projection popups we need to find what // state the game is then load the appropiate popup graphic for // display state = gameseq_get_state(); choice = pi->nchoices - 2; if (choice < 0) choice = 0; //pbg = &Popup_background[gr_screen.res][0][POPUP_DEFAULT]; switch (state) { case GS_STATE_INITIAL_PLAYER_SELECT: pbg = &Popup_background[gr_screen.res][choice][POPUP_REGDESK]; break; case GS_STATE_MAIN_MENU: pbg = &Popup_background[gr_screen.res][choice][POPUP_CONCOURSE]; break; case GS_STATE_SIMULATOR_ROOM: pbg = &Popup_background[gr_screen.res][choice][POPUP_LOADMISSION]; break; case GS_STATE_PILOT_MANAGE: pbg = &Popup_background[gr_screen.res][choice][POPUP_PILOTMANAGE]; break; case GS_STATE_VIEW_CUTSCENES: pbg = &Popup_background[gr_screen.res][choice][POPUP_FILMROOM]; break; case GS_STATE_GAME_PLAY: pbg = &Popup_background[gr_screen.res][choice][POPUP_FLY]; break; /*case GS_STATE_MULTI_DOGFIGHT_DEBRIEF: case GS_STATE_MULTI_JOIN_GAME: case GS_STATE_DEBRIEF: pbg = &Popup_background[gr_screen.res][choice][POPUP_DEFAULT]; break;*/ default: pbg = &Popup_background[gr_screen.res][choice][POPUP_DEFAULT]; } // anytime in single player, and multiplayer, not in mission, go ahead and stop time if ( (Game_mode & GM_NORMAL) || ((Game_mode && GM_MULTIPLAYER) && !(Game_mode & GM_IN_MISSION)) ){ game_stop_time(); } // create base window Popup_window.create(pbg->coords[0], pbg->coords[1], Popup_text_coords[gr_screen.res][2]+100, Popup_text_coords[gr_screen.res][3]+50, 0); Popup_window.set_foreground_bmap(pbg->filename); // create buttons for (i=0; i<pi->nchoices; i++) { b = &Popup_buttons[i]; // accommodate single-choice positive icon being positioned differently if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) { b->create(&Popup_window, "", Button_coords[gr_screen.res][i+1][0], Button_coords[gr_screen.res][i+1][1], 30, 25, 0, 1); } else { b->create(&Popup_window, "", Button_coords[gr_screen.res][i][0], Button_coords[gr_screen.res][i][1], 30, 25, 0, 1); } fname = popup_get_button_filename(pi, i, flags); b->set_bmaps(fname, 3, 0); b->set_highlight_action(common_play_highlight_sound); if ( pi->keypress[i] >= 0 ) { b->set_hotkey(pi->keypress[i]); } // create invisible buttons to detect mouse presses... can't use mask since button region is dynamically sized int lx, w, h; gr_get_string_size(&w, &h, pi->button_text[i]); lx = Button_regions[gr_screen.res][i][0] - w; b = &Popup_button_regions[i]; // accommodate single-choice positive icon being positioned differently if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) { b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i+1][1], Button_regions[gr_screen.res][i+1][2]-lx, Button_regions[gr_screen.res][i+1][3]-Button_regions[gr_screen.res][i+1][1], 0, 1); } else { b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i][1], Button_regions[gr_screen.res][i][2]-lx, Button_regions[gr_screen.res][i][3]-Button_regions[gr_screen.res][i][1], 0, 1); } b->hide(); } // webcursor setup if (Web_cursor_bitmap >= 0) { if (flags & PF_WEB_CURSOR_1) { Popup_buttons[1].set_custom_cursor_bmap(Web_cursor_bitmap); } if (flags & PF_WEB_CURSOR_2) { Popup_buttons[2].set_custom_cursor_bmap(Web_cursor_bitmap); } } // if this is an input popup, create and center the popup if(flags & PF_INPUT){ Popup_input.create(&Popup_window, Popup_text_coords[gr_screen.res][0], pbg->coords[1] + Popup_input_y_offset[gr_screen.res], Popup_text_coords[gr_screen.res][2], pi->max_input_text_len, "", UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_TEXT_CEN); Popup_input.set_focus(); } Popup_default_choice=0; Popup_should_die = 0; if (flags & PF_RUN_STATE) { Popup_running_state = 1; } else { Popup_running_state = 0; } popup_split_lines(pi, flags); // create the popup slider (which we may not need to use Popup_slider.create(&Popup_window, Popup_slider_coords[gr_screen.res][0], Popup_slider_coords[gr_screen.res][1], Popup_slider_coords[gr_screen.res][2], Popup_slider_coords[gr_screen.res][3], pi->nlines > Popup_max_display[gr_screen.res] ? pi->nlines - Popup_max_display[gr_screen.res] : 0, Popup_slider_name[gr_screen.res], popup_slider_bogus, popup_slider_bogus, NULL); return 0; }
bool ConditionedHook::ConditionsValid(int action, object *objp, int more_data) { uint i; //Return false if any conditions are not met script_condition *scp; ship_info *sip; for(i = 0; i < MAX_HOOK_CONDITIONS; i++) { scp = &Conditions[i]; switch(scp->condition_type) { case CHC_STATE: if(gameseq_get_depth() < 0) return false; if(stricmp(GS_state_text[gameseq_get_state(0)], scp->data.name)) return false; break; case CHC_SHIPTYPE: if(objp == NULL || objp->type != OBJ_SHIP) return false; sip = &Ship_info[Ships[objp->instance].ship_info_index]; if(sip->class_type < 0) return false; if(stricmp(Ship_types[sip->class_type].name, scp->data.name)) return false; case CHC_SHIPCLASS: if(objp == NULL || objp->type != OBJ_SHIP) return false; if(stricmp(Ship_info[Ships[objp->instance].ship_info_index].name, scp->data.name)) return false; break; case CHC_SHIP: if(objp == NULL || objp->type != OBJ_SHIP) return false; if(stricmp(Ships[objp->instance].ship_name, scp->data.name)) return false; break; case CHC_MISSION: { //WMC - Get mission filename with Mission_filename //I don't use Game_current_mission_filename, because //Mission_filename is valid in both fs2_open and FRED size_t len = strlen(Mission_filename); if(!len) return false; if(len > 4 && !stricmp(&Mission_filename[len-4], ".fs2")) len -= 4; if(strnicmp(scp->data.name, Mission_filename, len)) return false; break; } case CHC_CAMPAIGN: { size_t len = strlen(Campaign.filename); if(!len) return false; if(len > 4 && !stricmp(&Mission_filename[len-4], ".fc2")) len -= 4; if(strnicmp(scp->data.name, Mission_filename, len)) return false; break; } case CHC_WEAPONCLASS: { if (action == CHA_COLLIDEWEAPON) { if (stricmp(Weapon_info[more_data].name, scp->data.name) != 0) return false; } else if (!(action == CHA_ONWPSELECTED || action == CHA_ONWPDESELECTED || action == CHA_ONWPEQUIPPED || action == CHA_ONWPFIRED || action == CHA_ONTURRETFIRED )) { if(objp == NULL || (objp->type != OBJ_WEAPON && objp->type != OBJ_BEAM)) return false; else if (( objp->type == OBJ_WEAPON) && (stricmp(Weapon_info[Weapons[objp->instance].weapon_info_index].name, scp->data.name) != 0 )) return false; else if (( objp->type == OBJ_BEAM) && (stricmp(Weapon_info[Beams[objp->instance].weapon_info_index].name, scp->data.name) != 0 )) return false; } else if(objp == NULL || objp->type != OBJ_SHIP) { return false; } else { // Okay, if we're still here, then objp is both valid and a ship ship* shipp = &Ships[objp->instance]; bool primary = false, secondary = false, prev_primary = false, prev_secondary = false; switch (action) { case CHA_ONWPSELECTED: primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0; secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0; if (!(primary || secondary)) return false; if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return false; break; case CHA_ONWPDESELECTED: primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0; prev_primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].name, scp->data.name) == 0; secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0; prev_secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.previous_secondary_bank]].name, scp->data.name) == 0; if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && prev_primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.previous_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return true; if ( !prev_secondary && ! secondary && !prev_primary && !primary ) return false; if ( (!prev_secondary && !secondary) && (prev_primary && primary) ) return false; if ( (!prev_secondary && !secondary) && (!prev_primary && primary) ) return false; if ( (!prev_primary && !primary) && (prev_secondary && secondary) ) return false; if ( (!prev_primary && !primary) && (!prev_secondary && secondary) ) return false; break; case CHA_ONWPEQUIPPED: { bool equipped = false; for(int j = 0; j < MAX_SHIP_PRIMARY_BANKS; j++) { if (!equipped && (shipp->weapons.primary_bank_weapons[j] >= 0) && (shipp->weapons.primary_bank_weapons[j] < MAX_WEAPON_TYPES) ) { if ( !stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[j]].name, scp->data.name) ) { equipped = true; break; } } } if (!equipped) { for(int j = 0; j < MAX_SHIP_SECONDARY_BANKS; j++) { if (!equipped && (shipp->weapons.secondary_bank_weapons[j] >= 0) && (shipp->weapons.secondary_bank_weapons[j] < MAX_WEAPON_TYPES) ) { if ( !stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[j]].name, scp->data.name) ) { equipped = true; break; } } } } if (!equipped) return false; break; } case CHA_ONWPFIRED: { if (more_data == 1) { primary = stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name) == 0; secondary = false; } else { primary = false; secondary = stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name) == 0; } if ((shipp->flags[Ship::Ship_Flags::Primary_linked]) && primary && (Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].wi_flags[Weapon::Info_Flags::Nolink])) return false; return more_data == 1 ? primary : secondary; break; } case CHA_ONTURRETFIRED: { if (! (stricmp(Weapon_info[shipp->last_fired_turret->last_fired_weapon_info_index].name, scp->data.name) == 0)) return false; break; } case CHA_PRIMARYFIRE: { if (stricmp(Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name, scp->data.name)) return false; break; } case CHA_SECONDARYFIRE: { if (stricmp(Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name, scp->data.name)) return false; break; } case CHA_BEAMFIRE: { if (!(stricmp(Weapon_info[more_data].name, scp->data.name) == 0)) return false; break; } } } // case CHC_WEAPONCLASS break; } case CHC_OBJECTTYPE: if(objp == NULL) return false; if(stricmp(Object_type_names[objp->type], scp->data.name)) return false; break; case CHC_KEYPRESS: { extern int Current_key_down; if(gameseq_get_depth() < 0) return false; if(Current_key_down == 0) return false; //WMC - could be more efficient, but whatever. if(stricmp(textify_scancode(Current_key_down), scp->data.name)) return false; break; } case CHC_ACTION: { if(gameseq_get_depth() < 0) return false; int action_index = more_data; if (action_index <= 0 || stricmp(scp->data.name, Control_config[action_index].text)) return false; break; } case CHC_VERSION: { // Goober5000: I'm going to assume scripting doesn't care about SVN revision char buf[32]; sprintf(buf, "%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD); if(stricmp(buf, scp->data.name)) { //In case some people are lazy and say "3.7" instead of "3.7.0" or something if(FS_VERSION_BUILD == 0) { sprintf(buf, "%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR); if(stricmp(buf, scp->data.name)) return false; } else { return false; } } break; } case CHC_APPLICATION: { if(Fred_running) { if(stricmp("FRED2_Open", scp->data.name) && stricmp("FRED2Open", scp->data.name) && stricmp("FRED 2", scp->data.name) && stricmp("FRED", scp->data.name)) return false; } else { if(stricmp("FS2_Open", scp->data.name) && stricmp("FS2Open", scp->data.name) && stricmp("Freespace 2", scp->data.name) && stricmp("Freespace", scp->data.name)) return false; } } default: break; } } return true; }