// a button was pressed, deal with it
void red_alert_button_pressed(int n)
{
	switch (n) {
	case RA_CONTINUE:		
		// warp the mouse cursor the the middle of the screen for those who control with a mouse
		mouse_set_pos( gr_screen.max_w/2, gr_screen.max_h/2 );

		if(Game_mode & GM_MULTIPLAYER){	
			// process the initial orders now (moved from post_process_mission()in missionparse) 
			mission_parse_fixup_players();
			ai_post_process_mission();
		}

		gameseq_post_event(GS_EVENT_ENTER_GAME);
		break;

	case RA_REPLAY_MISSION:
		if ( Game_mode & GM_CAMPAIGN_MODE ) {
			// TODO: make call to campaign code to set correct mission for loading
			// mission_campaign_play_previous_mission(Red_alert_precursor_mission);
			if ( !mission_campaign_previous_mission() ) {
				gamesnd_play_iface(SND_GENERAL_FAIL);
				break;
			}

			gameseq_post_event(GS_EVENT_START_GAME);
		} else {
			gamesnd_play_iface(SND_GENERAL_FAIL);
		}
		break;
	}
}
// called from the game loop to check if we should actually do the red-alert
void red_alert_maybe_move_to_next_mission()
{
	// if the timestamp is invalid, do nothing.
	if ( !timestamp_valid(Red_alert_new_mission_timestamp) )
		return;

	// return if the timestamp hasn't elapsed yet
	if ( !timestamp_elapsed(Red_alert_new_mission_timestamp) )
		return;

	// basic premise here is to stop the current mission, and then set the next mission in the campaign
	// which better be a red alert mission
	if ( Game_mode & GM_CAMPAIGN_MODE ) {
		red_alert_store_wingman_status();
		mission_goal_fail_incomplete();
		mission_campaign_store_goals_and_events_and_variables();
		scoring_level_close();
		mission_campaign_eval_next_mission();
		mission_campaign_mission_over();

		// CD CHECK
		gameseq_post_event(GS_EVENT_START_GAME);
	} else {
		gameseq_post_event(GS_EVENT_END_GAME);
	}
}
int credits_screen_button_pressed(int n)
{
	switch (n) {
	case TECH_DATABASE_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_TECH_MENU);
		return 1;

	case SIMULATOR_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
		return 1;

	case CUTSCENES_BUTTON:
		gamesnd_play_iface(SND_SWITCH_SCREENS);
		gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
		return 1;

	case EXIT_BUTTON:
		gamesnd_play_iface(SND_COMMIT_PRESSED);
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		game_flush();
		break;
	}

	return 0;
}
void fiction_viewer_exit()
{
	if (mission_has_cmd_brief())
		gameseq_post_event(GS_EVENT_CMD_BRIEF);
	else if (red_alert_mission())
		gameseq_post_event(GS_EVENT_RED_ALERT);
	else
		gameseq_post_event(GS_EVENT_START_BRIEFING);
}
/**
 * called to leave the command briefing screen
 */
void cmd_brief_exit()
{
	// I know, going to red alert from cmd brief is stupid, but we have stupid fredders
	if (red_alert_mission()) {
		gameseq_post_event(GS_EVENT_RED_ALERT);
	} else {
		gameseq_post_event(GS_EVENT_START_BRIEFING);
	}
}
// (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]);
			}
		}
	}
}
// called once per frame when game state is GS_STATE_RED_ALERT
void red_alert_do_frame(float frametime)
{
	int i, k;	

	// ensure that the red alert interface has been initialized
	if (!Red_alert_inited) {
		Int3();
		return;
	}

	// commit if skipping briefing, but not in multi - Goober5000
	if (!(Game_mode & GM_MULTIPLAYER)) {
		if (The_mission.flags[Mission::Mission_Flags::No_briefing])
		{
			red_alert_button_pressed(RA_CONTINUE);
			return;
		}
	}

	k = Ui_window.process() & ~KEY_DEBUGGED;
	switch (k) {
		case KEY_ESC:
//			gameseq_post_event(GS_EVENT_ENTER_GAME);
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			break;
	}	// end switch

	for (i=0; i<NUM_BUTTONS; i++){
		if (Buttons[gr_screen.res][i].button.pressed()){
			red_alert_button_pressed(i);
		}
	}

	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap);
		gr_bitmap(0, 0, GR_RESIZE_MENU);
	} 

	Ui_window.draw();
	// hud_anim_render(&Flash_anim, frametime);

	font::set_font(font::FONT1);

	if ( timestamp_elapsed(Text_delay) ) {
		int finished_wipe = 0;
		if ( Briefing->num_stages > 0 ) {
			finished_wipe = brief_render_text(0, Ra_brief_text_wnd_coords[gr_screen.res][RA_X_COORD], Ra_brief_text_wnd_coords[gr_screen.res][RA_Y_COORD], Ra_brief_text_wnd_coords[gr_screen.res][RA_H_COORD], frametime, 0);
		}

		if (finished_wipe) {
			red_alert_voice_play();
		}
	}

	// blit incoming transmission
	red_alert_blit_title();

	gr_flip();
}
void mht_exit_game()
{
	// stop music first
	main_hall_stop_music(true);
	main_hall_stop_ambient();
	gameseq_post_event(GS_EVENT_QUIT_GAME);
}
// called when the screen is exited
void gameplay_help_leave()
{
	// unpause all game sounds
	weapon_unpause_sounds();
	audiostream_unpause_all();

	gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
	game_flush();
}
Exemple #10
0
// debug pause do frame
void pause_debug_do()
{
	int key;

	key = Pause_win.process();
	if (Pause_single_step.changed())
	{
		game_single_step = Pause_single_step.checked();
	}

	if (Pause_physics.changed())
	{
		physics_paused = Pause_physics.checked();
	}

	if (Pause_ai.changed())
	{
		ai_paused = Pause_ai.checked();
		if (ai_paused)
		{
			obj_init_all_ships_physics();
		}
	}

	if (Pause_ai_render.changed())
	{
		Ai_render_debug_flag = Pause_ai_render.checked();
	}

	if (Pause_firing.changed())
	{
		Ai_firing_enabled = Pause_firing.checked();
	}

	if (Pause_external_view_mode_check.changed())
	{
		Pause_external_view_mode = Pause_external_view_mode_check.checked();
		if (Pause_external_view_mode)
		{
			HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("External view of player ship.", 182));
		}
		else
		{
			HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("View from inside player ship.", 183));
		}
	}

	if (Pause_continue.pressed() || (key == KEY_PAUSE))
	{	//	Changed, MK, 11/9/97, only Pause break pause.
		gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
	}

	gr_clear();
	Pause_win.draw();

	gr_flip();
}
Exemple #11
0
// respawn the server immediately
void multi_respawn_server()
{	
	Assert(Net_player->flags & NETINFO_FLAG_AM_MASTER);

	// respawn me
	multi_respawn_player(Net_player, Net_player->s_info.cur_primary_bank, Net_player->s_info.cur_secondary_bank, Net_player->s_info.cur_link_status, Net_player->s_info.ship_ets, 0, Net_player->p_info.p_objp->name);

	// jump back into the game
	gameseq_post_event(GS_EVENT_ENTER_GAME);	
}
// button press
void loop_brief_button_pressed(int i)
{	
	switch(i){
	case LOOP_BRIEF_DECLINE:		
		gameseq_post_event(GS_EVENT_START_GAME);
		gamesnd_play_iface(SND_USER_SELECT);
		break;

	case LOOP_BRIEF_ACCEPT:
		// select the loop mission		
		Campaign.loop_enabled = 1;
		Campaign.loop_reentry = Campaign.next_mission;			// save reentry pt, so we can break out of loop
		Campaign.next_mission = Campaign.loop_mission;		

		gameseq_post_event(GS_EVENT_START_GAME);
		gamesnd_play_iface(SND_USER_SELECT);
		break;
	}
}
void supernova_process()
{
	int sn_stage;

	// if the supernova is running
	sn_stage = supernova_active();
	if(sn_stage) {
		Supernova_time -= flFrametime;

		// sound stuff
		if((Supernova_time <= SUPERNOVA_SOUND_1_TIME) && !Supernova_sound_1_played) {
			Supernova_sound_1_played = 1;
			snd_play(&Snds[SND_SUPERNOVA_1], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY);
		}
		if((Supernova_time <= SUPERNOVA_SOUND_2_TIME) && !Supernova_sound_2_played) {
			Supernova_sound_2_played = 1;
			snd_play(&Snds[SND_SUPERNOVA_2], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY);
		}

		// if we've crossed from stage 1 to stage 2 kill all particles and stick a bunch on the player ship
		if((sn_stage == 1) && (supernova_active() == 2)) {
			// first kill all active particles so we have a bunch of free ones
			particle_kill_all();
		}

		// if we're in stage 2, emit particles
		if((sn_stage >= 2) && (sn_stage != 5)) {
			supernova_do_particles();
		}

		// if we've got negative. the supernova is done
		if(Supernova_time < 0.0f) {
			Supernova_finished = 1;
			Supernova_fade_to_white += flFrametime;

			// start the dead popup
			if(Supernova_fade_to_white >= SUPERNOVA_FADE_TO_WHITE_TIME) {
				if(!Supernova_popup) {
					// main freespace 2 campaign? if so - end it now
					//
					// don't actually check for a specific campaign here since others may want to end this way but we
					// should test positive here if in campaign mode and sexp_end_campaign() got called - taylor
					if (Campaign_ending_via_supernova && (Game_mode & GM_CAMPAIGN_MODE) /*&& !stricmp(Campaign.filename, "freespace2")*/) {
						gameseq_post_event(GS_EVENT_END_CAMPAIGN);
					} else {
						popupdead_start();
					}
					Supernova_popup = 1;
				}
				Supernova_finished = 2;
			}
		}
	}
}
void player_select_commit()
{
	// if we've gotten to this point, we should have ensured this was the case
	Assert(Player_select_num_pilots > 0);

	gameseq_post_event(GS_EVENT_MAIN_MENU);
	gamesnd_play_iface(SND_COMMIT_PRESSED);

	// evaluate if this is the _very_ first pilot
	player_select_eval_very_first_pilot();
} 
void player_select_process_noninput(int k)
{
	int idx;

	// check for pressed buttons
	for (idx=0; idx<NUM_PLAYER_SELECT_BUTTONS; idx++) {
		if (Player_select_buttons[gr_screen.res][idx].button.pressed()) {
			player_select_button_pressed(idx);
		}
	}

	// check for keypresses
	switch (k) {
	// quit the game entirely
	case KEY_ESC:
		gameseq_post_event(GS_EVENT_QUIT_GAME);
		break;

	case KEY_ENTER | KEY_CTRLED:
		player_select_button_pressed(ACCEPT_BUTTON);
		break;

	// delete the currently highlighted pilot
	case KEY_DELETE:
		player_select_button_pressed(DELETE_BUTTON);
		break;
	}

	// check to see if the user has clicked on the "list region" button
	// and change the selected pilot appropriately
	if (Player_select_list_region.pressed()) {
		int click_y;
		// get the mouse position
		Player_select_list_region.get_mouse_pos(NULL, &click_y);
		
		// determine what index to select
		//idx = (click_y+5) / 10;
		idx = click_y / gr_get_font_height();


		// if he selected a valid item
		if ( ((idx + Player_select_list_start) < Player_select_num_pilots) && (idx >= 0) ) {
			Player_select_pilot = idx + Player_select_list_start;
		}
	}

	// if the player has double clicked on a valid pilot, choose it and hit the accept button
	if (Player_select_list_region.double_clicked()) {
		if ((Player_select_pilot >= 0) && (Player_select_pilot < Player_select_num_pilots)) {
			player_select_button_pressed(ACCEPT_BUTTON);
		}
	}
}
void mht_button_pressed(int n)
{
	switch(n){		
	case MHT_READY_ROOM:
		if (Player->flags & PLAYER_FLAGS_IS_MULTI){
			main_hall_do_multi_ready();
		} else {			
			gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);			

			gamesnd_play_iface(SND_USER_SELECT);
		}
		break;

	case MHT_CAMPAIGN_ROOM:
		gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);			
		gamesnd_play_iface(SND_USER_SELECT);
		break;
		
	case MHT_OPTIONS:
		gameseq_post_event(GS_EVENT_OPTIONS_MENU);
		gamesnd_play_iface(SND_USER_SELECT);
		break;

	case MHT_TECH_ROOM:
		gameseq_post_event( GS_EVENT_TECH_MENU );
		gamesnd_play_iface(SND_USER_SELECT);
		break;
	
	case MHT_BARRACKS:
		gameseq_post_event( GS_EVENT_BARRACKS_MENU );
		gamesnd_play_iface(SND_USER_SELECT);
		break;

	case MHT_EXIT:
		mht_exit_game();
		gamesnd_play_iface(SND_USER_SELECT);
		break;
	}							
}
int cutscenes_screen_button_pressed(int n)
{
	switch (n) {
		case TECH_DATABASE_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_TECH_MENU);
			return 1;

		case SIMULATOR_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
			return 1;

		case CREDITS_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_CREDITS);
			return 1;

		case SCROLL_UP_BUTTON:
			cutscenes_screen_scroll_screen_up();
			break;

		case SCROLL_DOWN_BUTTON:
			cutscenes_screen_scroll_screen_down();
			break;

		case PLAY_BUTTON:
			cutscenes_screen_play();
			break;

		case EXIT_BUTTON:
			gamesnd_play_iface(SND_COMMIT_PRESSED);
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			game_flush();
			break;
	}

	return 0;
}
void hotkey_button_pressed(int n)
{
	switch (n) {
		case SCROLL_UP_BUTTON:
			hotkey_scroll_screen_up();
			break;

		case SCROLL_DOWN_BUTTON:
			hotkey_scroll_screen_down();
			break;

		case ADD_HOTKEY_BUTTON:
			add_hotkey(Cur_hotkey);
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case REMOVE_HOTKEY_BUTTON:
			remove_hotkey();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case ACCEPT_BUTTON:
			save_hotkeys();
			// fall through to CANCEL_BUTTON

		case CANCEL_BUTTON:			
			mission_hotkey_exit();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case HELP_BUTTON:
			launch_context_help();
			gamesnd_play_iface(SND_HELP_PRESSED);
			break;

		case OPTIONS_BUTTON:			
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case CLEAR_BUTTON:
			clear_hotkeys();
			gamesnd_play_iface(SND_USER_SELECT);
			break;

		case RESET_BUTTON:
			reset_hotkeys();
			gamesnd_play_iface(SND_USER_SELECT);
			break;
	}
}
Exemple #19
0
void training_menu_do_frame(float frametime)
{
	int training_menu_choice;

	if (!training_menu_inited)
	{
		training_menu_init();
		training_menu_inited = 1;
	}

	gr_reset_clip();
	gr_set_color(0, 0, 0);
	GR_MAYBE_CLEAR_RES(trainingMenuBitmap);
	// set the background
	if (trainingMenuBitmap != -1)
	{
		gr_set_bitmap(trainingMenuBitmap);
		gr_bitmap(0, 0);
	}

	int snazzy_action = -1;
	training_menu_choice = snazzy_menu_do(mask_data, Training_mask_w, Training_mask_h, num_training,
		region, &snazzy_action);
	if (snazzy_action != SNAZZY_CLICKED)
	{
		training_menu_choice = -1;
	}

	switch (training_menu_choice)
	{

	case TRAINING_MENU_TRAINING_MISSIONS_MASK:
		break;
	case TRAINING_MENU_REPLAY_MISSIONS_MASK:
		// TODO: load the mission and start the briefing
		break;
	case TRAINING_MENU_RETURN_MASK:
	case ESC_PRESSED:
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		break;
	case -1:
		// nothing selected
		break;
	default:
		Error(LOCATION, "Unknown option %d in training menu screen", training_menu_choice);
		break;

	} // end switch

	gr_flip();
}
Exemple #20
0
// respawn as an observer
void multi_respawn_observer()
{
	// make sure we should be respawning as an observer 
	Assert(!(Net_player->flags & NETINFO_FLAG_RESPAWNING) && (Net_player->flags & NETINFO_FLAG_LIMBO));

	// respawn as an observer
	multi_respawn_as_observer();

	// clients should notify the server that they are doing so
	if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
		multi_respawn_send_request(1);
	}	

	// jump back into the game right away
	gameseq_post_event(GS_EVENT_ENTER_GAME);				
}	
Exemple #21
0
// 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
}
void cutscenes_screen_do_frame()
{
	int i, k, y, z;
	int font_height = gr_get_font_height();
	int select_tease_line = -1;

	k = Ui_window.process();
	switch (k) {
		case KEY_DOWN:  // select next line
			cutscenes_screen_scroll_line_down();
			break;

		case KEY_UP:  // select previous line
			cutscenes_screen_scroll_line_up();
			break;

		case KEY_TAB:
		case KEY_CTRLED | KEY_DOWN:
			cutscenes_screen_button_pressed(CREDITS_BUTTON);
			break;

		case KEY_SHIFTED | KEY_TAB:
		case KEY_CTRLED | KEY_UP:
			cutscenes_screen_button_pressed(SIMULATOR_BUTTON);
			break;

		case KEY_ENTER:
			cutscenes_screen_play();
			break;

		case KEY_ESC:  // cancel
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			game_flush();
			break;

		case KEY_F1:  // show help overlay
			break;

		case KEY_F2:  // goto options screen
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			break;

		// the "show-all" hotkey
		case KEY_CTRLED | KEY_SHIFTED | KEY_S:
		{
            Cutscene_list.clear();
			size_t size = Cutscenes.size();
			for (size_t t = 0; t < size; t++) {
                Cutscene_list.push_back((int)t);
			}

			break;
		}
	}	// end switch

	for (i=0; i<NUM_BUTTONS; i++){
		if (Buttons[gr_screen.res][i].button.pressed()){
			if (cutscenes_screen_button_pressed(i)){
				return;
			}
		}
	}

	if (List_region.button_down()) {
		List_region.get_mouse_pos(NULL, &y);
		z = Scroll_offset + y / font_height;
		if ((z >= 0) && (z < (int)Cutscene_list.size()))
			select_tease_line = z;
	}
	
	if (List_region.pressed()) {
		List_region.get_mouse_pos(NULL, &y);
		z = Scroll_offset + y / font_height;
		if ((z >= 0) && (z < (int)Cutscene_list.size()))
			Selected_line = z;
	}

	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap);
		gr_bitmap(0, 0);
	} 

	Ui_window.draw();

	for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
		if (Buttons[gr_screen.res][i].button.button_down()){
			break;
		}
	}

	if (i > CREDITS_BUTTON){
		Buttons[gr_screen.res][CUTSCENES_BUTTON].button.draw_forced(2);
	}

	y = 0;
	z = Scroll_offset;
	while (y + font_height <= Cutscene_list_coords[gr_screen.res][3]) {
		if (z >= (int)Cutscene_list.size()){
			break;
		}

		if (z == Selected_line){
			gr_set_color_fast(&Color_text_selected);
		} else if (z == select_tease_line) {
			gr_set_color_fast(&Color_text_subselected);
		} else {
			gr_set_color_fast(&Color_text_normal);
		}

		gr_printf(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y, Cutscenes[Cutscene_list[z]].name);

		y += font_height;
		z++;
	}

	if (Description_index != Selected_line) {
		char *src = NULL;

		Description_index = Selected_line;
		Text_size = 0;
		if ( Description_index < (int)Cutscene_list.size( ) &&
			 (int)Cutscene_list[ Description_index ] < (int)Cutscenes.size( ) ) {
			src = Cutscenes[Cutscene_list[Description_index]].description;
			if (src) {
				Text_size = split_str(src, Cutscene_desc_coords[gr_screen.res][2], Text_line_size, Text_lines, Cutscene_max_text_lines[gr_screen.res]);
				Assert(Text_size >= 0 && Text_size < Cutscene_max_text_lines[gr_screen.res]);
			}
		}
	}

	if (Description_index >= 0) {
		int len;
		char line[MAX_TEXT_LINE_LEN + 1];

		gr_set_color_fast(&Color_text_normal);

		y = 0;
		z = Text_offset;
		while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3]) {
			if (z >= Text_size || z >= MAX_TEXT_LINES-1)
				break;

			len = Text_line_size[z];
			if (len > MAX_TEXT_LINE_LEN)
				len = MAX_TEXT_LINE_LEN;

			strncpy(line, Text_lines[z], len);
			line[len] = 0;
			gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line);

			y += font_height;
			z++;
		}
	}

	gr_flip();
}
void barracks_button_pressed(int n)
{
	switch (n) {
		case B_PILOT_SCROLL_UP_BUTTON:
			barracks_scroll_callsign_up();
			break;

		case B_PILOT_SCROLL_DOWN_BUTTON:
			barracks_scroll_callsign_down();
			break;

		case B_STATS_SCROLL_UP_BUTTON:
			barracks_scroll_stats_up();
			break;

		case B_STATS_SCROLL_DOWN_BUTTON:
			barracks_scroll_stats_down();
			break;

		case B_PIC_PREV_PILOT_BUTTON:
			barracks_prev_pic();
			break;

		case B_PIC_NEXT_PILOT_BUTTON:
			barracks_next_pic();
			break;

		case B_SQUAD_PREV_BUTTON:
			barracks_prev_squad_pic();
			break;

		case B_SQUAD_NEXT_BUTTON:
			barracks_next_squad_pic();
			break;

		case B_PILOT_SET_ACTIVE_BUTTON:
			if (barracks_new_pilot_selected()){
				gamesnd_play_iface(SND_GENERAL_FAIL);

				// if it's just the missing campaign file that failed for us then don't give the second popup
				if (Campaign_file_missing) {
					break;
				}
			} else {
				gamesnd_play_iface(SND_SCROLL);

				if (Campaign_file_missing) {
					popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "The currently active campaign cannot be found.  Please select another...", 1600));
					gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
				}
			}
			break;

		case B_ACCEPT_BUTTON:
			if (Num_pilots && !barracks_pilot_accepted()) {
				gamesnd_play_iface(SND_COMMIT_PRESSED);

				if (Campaign_file_missing) {
					popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "The currently active campaign cannot be found.  Please select another...", 1600));
					gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
				} else {
					gameseq_post_event(GS_EVENT_MAIN_MENU);
				}
			} else {
				gamesnd_play_iface(SND_GENERAL_FAIL);

				// if it's just the missing campaign file that failed for us then don't give the second popup
				if (Campaign_file_missing) {
					break;
				}
			}
			break;

		case B_PILOT_CLONE_BUTTON:
			if (Num_pilots < 1) {
				gamesnd_play_error_beep();
				break;
			}

			Clone_flag = 1;
			barracks_create_new_pilot();
			break;

		case B_PILOT_CONVERT_BUTTON: {
	/*	New Pilot code no longer needs a conversion function. */
			popup(PF_TITLE_BIG | PF_TITLE_BLUE | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK,
				XSTR("Disabled!\n\n\nMulti and Single Player Pilot files are now identical.\n\n"
				"Conversion between the two is no longer necessary.", 1601));
		/*	// no actual conversion with new pilot code
			if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
				barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
			} else {
				// make sure we don't carry over the multi flag
				if (Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI) {
					Cur_pilot->flags &= ~PLAYER_FLAGS_IS_MULTI;
				}
				barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
			}

			gamesnd_play_iface(SND_USER_SELECT);	*/
			break;
		}

		case B_PILOT_CREATE_BUTTON:
			Clone_flag = 0;
			barracks_create_new_pilot();
			break;

		case B_HELP_BUTTON:
			launch_context_help();
			gamesnd_play_iface(SND_HELP_PRESSED);
			break;

		case B_OPTION_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			break;

		case B_STATS_MEDAL_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_VIEW_MEDALS);
			break;

		case B_PILOT_DELETE_BUTTON:
			barracks_delete_pilot();
			break;

		case B_PILOT_SINGLE_MODE_BUTTON:
			if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
				gamesnd_play_iface(SND_USER_SELECT);
				// make sure we don't carry over the multi flag
				if (Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI) {
					Cur_pilot->flags &= ~PLAYER_FLAGS_IS_MULTI;
				}
				Pilot.save_player(Cur_pilot);
				barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
			}
			break;

		case B_PILOT_MULTI_MODE_BUTTON:
			if ( Networking_disabled ) {
				game_feature_disabled_popup();
				break;
			}

			if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
				gamesnd_play_iface(SND_USER_SELECT);
				Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
				Pilot.save_player(Cur_pilot);
				barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
			}
			break;
	}
}
void credits_do_frame(float frametime)
{
	GR_DEBUG_SCOPE("Credits do frame");

	int i, k, next, percent, bm1, bm2;
	int bx1, by1, bw1, bh1;
	int bx2, by2, bw2, bh2;

	// Use this id to trigger the start of music playing on the credits screen
	if ( timestamp_elapsed(Credits_music_begin_timestamp) ) {
		Credits_music_begin_timestamp = 0;
		credits_start_music();
	}

	k = Ui_window.process();
	switch (k) {
	case KEY_ESC:
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		key_flush();
		break;

	case KEY_CTRLED | KEY_UP:
	case KEY_SHIFTED | KEY_TAB:
		if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
			credits_screen_button_pressed(CUTSCENES_BUTTON);
			break;
		}
		// else, react like tab key.

	case KEY_CTRLED | KEY_DOWN:
	case KEY_TAB:
		credits_screen_button_pressed(TECH_DATABASE_BUTTON);
		break;

	default:
		break;
	} // end switch

	for (i=0; i<NUM_BUTTONS; i++){
		if (Buttons[i][gr_screen.res].button.pressed()){
			if (credits_screen_button_pressed(i)){
				return;
			}
		}
	}

	gr_reset_clip();	
	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap);
		gr_bitmap(0, 0, GR_RESIZE_MENU);
	} 

	percent = (int) (100.0f - (Credits_artwork_display_time - Credits_counter) * 100.0f / Credits_artwork_fade_time);
	if (percent < 0){
		percent = 0;
	}

	next = Credits_artwork_index + 1;
	if (next >= Credits_num_images){
		next = 0;
	}

	if (Credits_bmps[Credits_artwork_index] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), Credits_artwork_index);
		}
		Credits_bmps[Credits_artwork_index] = bm_load(buf);
	}

	if (Credits_bmps[next] < 0) {
		char buf[40];

		if (gr_screen.res == GR_1024) {
			sprintf(buf, NOX("2_CrIm%.2d"), next);
		} else {
			sprintf(buf, NOX("CrIm%.2d"), next);
		}
		Credits_bmps[next] = bm_load(buf);
	}

	bm1 = Credits_bmps[Credits_artwork_index];
	bm2 = Credits_bmps[next];

	if((bm1 != -1) && (bm2 != -1)){
		GR_DEBUG_SCOPE("Render credits bitmap");

		Assert(percent >= 0 && percent <= 100);

		// get width and height
		bm_get_info(bm1, &bw1, &bh1, NULL, NULL, NULL);	
		bm_get_info(bm2, &bw2, &bh2, NULL, NULL, NULL);	
	
		// determine where to draw the coords
		bx1 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw1)/2);
		by1 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh1)/2);
		bx2 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw2)/2);
		by2 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh2)/2);

		auto alpha = (float)percent / 100.0f;

		gr_set_bitmap(bm1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - alpha);
		gr_bitmap(bx1, by1, GR_RESIZE_MENU);

		gr_set_bitmap(bm2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha);
		gr_bitmap(bx2, by2, GR_RESIZE_MENU);
	}

	Ui_window.draw();

	for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
		if (Buttons[i][gr_screen.res].button.button_down()){
			break;
		}
	}

	if (i > CREDITS_BUTTON){
		Buttons[CREDITS_BUTTON][gr_screen.res].button.draw_forced(2);
	}

	gr_set_clip(Credits_text_coords[gr_screen.res][CREDITS_X_COORD], Credits_text_coords[gr_screen.res][CREDITS_Y_COORD], Credits_text_coords[gr_screen.res][CREDITS_W_COORD], Credits_text_coords[gr_screen.res][CREDITS_H_COORD], GR_RESIZE_MENU);
	font::set_font(font::FONT1);
	gr_set_color_fast(&Color_normal);
	
	int y_offset = 0;
	for (SCP_vector<SCP_string>::iterator iter = Credit_text_parts.begin(); iter != Credit_text_parts.end(); ++iter)
	{
		size_t currentPos = 0;
		size_t lineEnd;
		do
		{
			int height;
			int width;
			lineEnd = iter->find('\n', currentPos);

			auto length = lineEnd - currentPos;
			if (lineEnd == SCP_string::npos)
			{
				length = std::numeric_limits<size_t>::max();
			}

			gr_get_string_size(&width, &height, iter->c_str() + currentPos, static_cast<int>(length));
			// Check if the text part is actually visible
			if (Credit_position + y_offset + height > 0.0f)
			{
				float x = static_cast<float>((gr_screen.clip_width_unscaled - width) / 2);
				gr_string(x, Credit_position + y_offset, iter->c_str() + currentPos, GR_RESIZE_MENU, static_cast<int>(length));
			}

			y_offset += height;
			currentPos = lineEnd + 1;
		} while (lineEnd < iter->length() && lineEnd != SCP_string::npos);
	}

	int temp_time;
	temp_time = timer_get_milliseconds();

	Credits_frametime = temp_time - Credits_last_time;
	Credits_last_time = temp_time;
	timestamp_inc(i2f(Credits_frametime) / TIMESTAMP_FREQUENCY);

	float fl_frametime = i2fl(Credits_frametime) / 1000.f;
	if (keyd_pressed[KEY_LSHIFT]) {
		Credit_position -= fl_frametime * Credits_scroll_rate * 4.0f;
	} else {
		Credit_position -= fl_frametime * Credits_scroll_rate;
	}

	if (Credit_position < Credit_stop_pos){
		Credit_position = Credit_start_pos;
	}

	Credits_counter += fl_frametime;
	while (Credits_counter >= Credits_artwork_display_time) {
		Credits_counter -= Credits_artwork_display_time;
		Credits_artwork_index = next;
	}

	gr_flip();
}
// -----------------------------------------------------------------------------
void barracks_do_frame(float frametime)
{
	int k = Ui_window.process();

	if ( k > 0 ) {
		if ( help_overlay_active(Barracks_overlay_id) ) {
			help_overlay_set_state(Barracks_overlay_id,gr_screen.res,0);
			k = 0;
		}
	}

	// pilot that mouse is over
	int prospective_pilot = -1;
	int i;

	// Entering pilot callsign
	if (Barracks_callsign_enter_mode) {
		// set focus to inputbox
		Inputbox.set_focus();

		switch (k) {
			case KEY_ESC:
				// cancel create pilot
				Num_pilots--;
				for (i=0; i<Num_pilots; i++) {
					strcpy(Pilots[i], Pilots[i + 1]);
					Pilot_ranks[i] = Pilot_ranks[i + 1];
				}

				barracks_set_callsign_enter_mode(false);
				break;

			case KEY_ENTER: 
				barracks_accept_new_pilot_callsign();
				break;
		} 
	} else {
		// not entering pilot callsign
		switch (k) {
			case KEY_ENTER:
				if (barracks_new_pilot_selected()) {
					gamesnd_play_iface(SND_GENERAL_FAIL);
				} else {
					gamesnd_play_iface(SND_USER_SELECT);
				}
				break;

			case KEY_ESC:  // cancel
				if (!help_overlay_active(Barracks_overlay_id)) {
					if (Num_pilots && !barracks_pilot_accepted()) {
						gameseq_post_event(GS_EVENT_MAIN_MENU);
					} else {
						gamesnd_play_iface(SND_GENERAL_FAIL);
					}
				} else {
					// kill the overlay
					help_overlay_set_state(Barracks_overlay_id,gr_screen.res,0);
				}
				break;

			case KEY_TAB:  // switch mode (simgle/multi)
				if ( Networking_disabled ) {
					game_feature_disabled_popup();
					break;
				}

				if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
					Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
					Pilot.save_player(Cur_pilot);
					barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
				} else {
					// make sure we don't carry over the multi flag
					Cur_pilot->flags &= ~PLAYER_FLAGS_IS_MULTI;
					Pilot.save_player(Cur_pilot);
					barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
				}

				gamesnd_play_iface(SND_USER_SELECT);
				break;

			case KEY_F1:  // show help overlay
				gamesnd_play_iface(SND_HELP_PRESSED);
				break;

			case KEY_F2:  // goto options screen
				gamesnd_play_iface(SND_SWITCH_SCREENS);
				gameseq_post_event(GS_EVENT_OPTIONS_MENU);
				break;
		}	// end switch

		// process buttons
		for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
			if (Buttons[gr_screen.res][i].button.pressed()) {
				barracks_button_pressed(i);
			}
		}

		// if mouse is over a pilot, find index into Pilots array
		if (List_region.is_mouse_on()) {
			int y;
			List_region.get_mouse_pos(NULL, &y);
			int pilot_index = List_scroll_offset + (y / gr_get_font_height());
			if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
				prospective_pilot = pilot_index;
			}
		}
		
		// if mouse clicked in list region, find index into Pilots array 
		if (List_region.pressed()) {
			if (prospective_pilot != -1) {
				Selected_line = prospective_pilot;
				gamesnd_play_iface(SND_USER_SELECT);
			}
		}
	}

	// check mouse over help
	if (mouse_down(MOUSE_LEFT_BUTTON)) {
		help_overlay_set_state(Barracks_overlay_id, gr_screen.res, 0);
	}

	// do pilot pic stuff
	if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
		if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
			Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
			if (Pilot_images[Pic_number] >= 0) {
				int w, h;

				bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
				// check for invalid pilot pic file
				if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
					bm_release(Pilot_images[Pic_number]);
					Pilot_images[Pic_number] = -1;
				}
			}
		}		
	} else {
		Pic_number = -1;
	}

	// do squad pic stuff
	if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
		if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
			Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
			if (Pilot_squad_images[Pic_squad_number] >= 0) {
				int w, h;

				bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
				// check for invalid pilot pic file
				if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
					bm_release(Pilot_squad_images[Pic_squad_number]);
					Pilot_squad_images[Pic_squad_number] = -1;
				}
			}
		}
	} else {
		Pic_squad_number = -1;
	}

	// draw the background, etc
	gr_reset_clip();	
	GR_MAYBE_CLEAR_RES(Background_bitmap);
	if (Background_bitmap >= 0) {
		gr_set_bitmap(Background_bitmap);
		gr_bitmap(0, 0, GR_RESIZE_MENU);	
	}		

	// draw pilot image and clean up afterwards
	barracks_draw_pilot_pic();
	barracks_draw_squad_pic();

	// draw the window	
	Ui_window.draw();	

	// light up the correct mode button (single or multi)	
	if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
		Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
	} else {
		Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
	}	

	// write out pilot call signs
	barracks_display_pilot_callsigns(prospective_pilot);

	// write out current pilot stats
	barracks_display_pilot_stats();

	// blit help overlay if active
	help_overlay_maybe_blit(Barracks_overlay_id, gr_screen.res);
	
	// flip the page
	gr_flip();
}
// translates all special tokens in a message, producing the new finalized message to be displayed
void message_translate_tokens(char *buf, char *text)
{
	char temp[40], *toke1, *toke2, *ptr, *orig_buf;
	int r;

	orig_buf = buf;
	*buf = 0;
	toke1 = strchr(text, '$');
	toke2 = strchr(text, '#');
	while (toke1 || toke2) {  // is either token types present?
		if (!toke2 || (toke1 && (toke1 < toke2))) {  // found $ before #
			strncpy(buf, text, toke1 - text + 1);  // copy text up to token
			buf += toke1 - text + 1;
			text = toke1 + 1;  // advance pointers past processed data

			toke2 = strchr(text, '$');
			if (!toke2)  // No second one?
				break;

			strncpy(temp, text, toke2 - text);  // isolate token into seperate buffer
			temp[toke2 - text] = 0;  // null terminate string
			ptr = translate_key(temp);  // try and translate key
			if (ptr) {  // was key translated properly?
				if (!stricmp(ptr, NOX("none")) && (Training_bind_warning != Missiontime)) {
					if ( The_mission.game_type & MISSION_TYPE_TRAINING ) {
						r = popup(PF_TITLE_BIG | PF_TITLE_RED, 2, XSTR( "&Bind Control", 424), XSTR( "&Abort mission", 425),
							XSTR( "Warning\nYou have no control bound to the action \"%s\".  You must do so before you can continue with your training.", 426),
							XSTR(Control_config[Failed_key_index].text, CONTROL_CONFIG_XSTR + Failed_key_index));

						if (r) {  // do they want to abort the mission?
							gameseq_post_event(GS_EVENT_END_GAME);
							return;
						}

						gameseq_post_event(GS_EVENT_CONTROL_CONFIG);  // goto control config screen to bind the control
					}
				}

				buf--;  // erase the $
				strcpy(buf, ptr);  // put translated key in place of token
				buf += strlen(buf);
				text = toke2 + 1;
			}

		} else {
			strncpy(buf, text, toke2 - text + 1);  // copy text up to token
			buf += toke2 - text + 1;
			text = toke2 + 1;  // advance pointers past processed data

			toke1 = strchr(text, '#');
			if (toke1)  // No second one?
				break;

			strncpy(temp, text, toke1 - text);  // isolate token into seperate buffer
			temp[toke1 - text] = 0;  // null terminate string
			ptr = translate_msg_token(temp);  // try and translate key
			if (ptr) {  // was key translated properly?
				buf--;  // erase the #
				strcpy(buf, ptr);  // put translated key in place of token
				buf += strlen(buf);
				text = toke1 + 1;
			}
		}

		toke1 = strchr(text, '$');
		toke2 = strchr(text, '#');
	}

	strcpy(buf, text);
	return;
}
// 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);
		}
	}
}
int techroom_button_pressed(int num)
{
	switch (num) {
		case SHIPS_DATA_TAB:
		case WEAPONS_DATA_TAB:
		case INTEL_DATA_TAB:
			fsspeech_stop();
			techroom_change_tab(num);
			break;

		case SIMULATOR_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
			return 1;

		case CUTSCENES_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
			return 1;

		case CREDITS_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_CREDITS);
			return 1;

		case PREV_ENTRY_BUTTON:
			tech_prev_entry();
			break;

		case NEXT_ENTRY_BUTTON:
			tech_next_entry();
			break;

		case SCROLL_LIST_UP:
			tech_scroll_list_up();
			Tech_slider.forceUp();
			break;

		case SCROLL_LIST_DOWN:
			tech_scroll_list_down();
			Tech_slider.forceDown();
			break;

		case SCROLL_INFO_UP:
			tech_scroll_info_up();
			break;

		case SCROLL_INFO_DOWN:
			tech_scroll_info_down();
			break;

		case HELP_BUTTON:
			launch_context_help();
			gamesnd_play_iface(SND_HELP_PRESSED);
			break;

		case OPTIONS_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			break;

		case EXIT_BUTTON:
			fsspeech_stop();
			gamesnd_play_iface(SND_COMMIT_PRESSED);
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			break;
	}

	return 0;
}
void techroom_do_frame(float frametime)
{
	
	int i, k;	

	// turn off controls when overlay is on
	if ( help_overlay_active(Techroom_overlay_id) ) {
		Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
		Ui_window.set_ignore_gadgets(1);
	}

	// turn off controls in trackball mode
	if (Trackball_active) {
		Ui_window.set_ignore_gadgets(1);
	} else {
		Ui_window.set_ignore_gadgets(0);
	}

	k = Ui_window.process() & ~KEY_DEBUGGED;

	if ( (k > 0) || B1_JUST_RELEASED ) {
		if ( help_overlay_active(Techroom_overlay_id) ) {
			help_overlay_set_state(Techroom_overlay_id, gr_screen.res, 0);
			Ui_window.set_ignore_gadgets(0);
			k = 0;
		}
	}

	if ( !help_overlay_active(Techroom_overlay_id) ) {
		Ui_window.set_ignore_gadgets(0);
	}

	switch (k) {
		case KEY_SHIFTED | KEY_TAB:  // activate previous tab
			i = Tab - 1;
			if (i < 0) {
				i = NUM_TABS - 1;
			}

			techroom_change_tab(i);
			break;

		case KEY_TAB:  // activate next tab
			i = Tab + 1;
			if (i >= NUM_TABS) {
				i = 0;
			}

			techroom_change_tab(i);
			break;

		case KEY_CTRLED | KEY_DOWN:
			if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
				techroom_button_pressed(SIMULATOR_TAB);
				break;
			}
			// fall through

		case KEY_CTRLED | KEY_UP:
			techroom_button_pressed(CREDITS_TAB);
			break;

		case KEY_CTRLED | KEY_ENTER:
		case KEY_ESC:
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			break;

		case KEY_CTRLED | KEY_SHIFTED | KEY_S:
			Techroom_show_all = 1;
			techroom_lists_reset();
			techroom_change_tab(Tab);
			break;

	}	

	// check ship model window for activity
	if (View_window.pressed()) {
		Trackball_active = 1;
		Trackball_mode = 1;
	}
	if (B1_RELEASED) {
		Trackball_active = 0;
	}

	// check all da buttons
	for (i=0; i<NUM_BUTTONS; i++) {
		if (Buttons[gr_screen.res][i].button.pressed()) {
			if (techroom_button_pressed(i)) {
				return;
			}
		}
	}

	// check for mouseovers/clicks on the selection list
	Select_tease_line = -1;
	for (i=0; i<LIST_BUTTONS_MAX; i++) {
		if (List_buttons[i].is_mouse_on()) {
			Select_tease_line = i + List_offset;
		}
	
		if (List_buttons[i].pressed()) {
			Cur_entry = i + List_offset;
			gamesnd_play_iface(SND_USER_SELECT);
			techroom_select_new_entry();
		}
	}

	// clear & draw bg bitmap
	GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
	if (Tech_background_bitmap >= 0) {
		gr_set_bitmap(Tech_background_bitmap);
		gr_bitmap(0, 0, GR_RESIZE_MENU);
	}

	// render
	switch (Tab) {
		case SHIPS_DATA_TAB:
			techroom_ships_render(frametime);
			break;

		case WEAPONS_DATA_TAB:
		case INTEL_DATA_TAB:
			techroom_anim_render(frametime);
			break;
	}

	Ui_window.draw();

	for (i=TECH_DATABASE_TAB; i<=CREDITS_TAB; i++) {
		if (Buttons[gr_screen.res][i].button.button_down()) {
			break;
		}
	}
	if (i > CREDITS_TAB) {
		Buttons[gr_screen.res][TECH_DATABASE_TAB].button.draw_forced(2);
	}

	for (i=0; i<NUM_TABS; i++){
		if (Buttons[gr_screen.res][i].button.button_down()){
			break;
		}
	}
	if (i == NUM_TABS){
		Buttons[gr_screen.res][Tab].button.draw_forced(2);
	}

	// blit help overlay if active
	help_overlay_maybe_blit(Techroom_overlay_id, gr_screen.res);

	gr_flip();
}
void player_select_process_noninput(int k)
{
	int idx;

	// check for pressed buttons
	for (idx=0; idx<NUM_PLAYER_SELECT_BUTTONS; idx++) {
		if (Player_select_buttons[gr_screen.res][idx].button.pressed()) {
			player_select_button_pressed(idx);
		}
	}

	// check for keypresses
	switch (k) {
	// quit the game entirely
	case KEY_ESC:
		gameseq_post_event(GS_EVENT_QUIT_GAME);
		break;

	case KEY_ENTER | KEY_CTRLED:
		player_select_button_pressed(ACCEPT_BUTTON);
		break;

	// delete the currently highlighted pilot
	case KEY_DELETE:
		if (Player_select_pilot >= 0) {
			int ret;

			if (Player_select_mode == PLAYER_SELECT_MODE_MULTI) {
				popup(PF_TITLE_BIG | PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("Pilots can only be deleted from the single player menu!", 1611));
			} else {
				// display a popup requesting confirmation
				ret = popup(PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON,2,POPUP_NO,POPUP_YES,XSTR( "Are you sure you want to delete this pilot?", 383));										

				// delete the pilot
				if (ret == 1) {
					player_select_delete_pilot();
				}
			}
		}
		break;
	}

	// check to see if the user has clicked on the "list region" button
	// and change the selected pilot appropriately
	if (Player_select_list_region.pressed()) {
		int click_y;
		// get the mouse position
		Player_select_list_region.get_mouse_pos(NULL, &click_y);
		
		// determine what index to select
		//idx = (click_y+5) / 10;
		idx = click_y / gr_get_font_height();


		// if he selected a valid item
		if ( ((idx + Player_select_list_start) < Player_select_num_pilots) && (idx >= 0) ) {
			Player_select_pilot = idx + Player_select_list_start;
		}
	}

	// if the player has double clicked on a valid pilot, choose it and hit the accept button
	if (Player_select_list_region.double_clicked()) {
		if ((Player_select_pilot >= 0) && (Player_select_pilot < Player_select_num_pilots)) {
			player_select_button_pressed(ACCEPT_BUTTON);
		}
	}
}