mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 17:48:46 -10:00
Several things going on here: 1) refactor `get_display_string()` to `get_display_name()` to be more precise 2) likewise, refactor `alt_name` to `display_name` 3) automatically generate display names when parsing the ship, ship class, and weapon class for the first time 4) remove the on-the-fly truncation of names with hash symbols Basically this subsumes the `end_string_at_first_hash_symbol` logic into the display name. Rather than truncate the name every time it's displayed, truncate it once when it's parsed. This takes advantage of the previous display name infrastructure, since display names are a superset of the case of truncating the hash symbol. This also has the benefit of now allowing hash symbols within display names. When updating Destiny of Peace, I noticed that "Lockheed Shuttle #4" would no longer display properly; and it was not previously possible to fix this even with display names. I could pull out the `get_display_string()` and `alt_name` renaming into a separate PR if desired.
1998 lines
55 KiB
C++
1998 lines
55 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "asteroid/asteroid.h"
|
|
#include "cmdline/cmdline.h"
|
|
#include "freespace.h"
|
|
#include "gamehelp/contexthelp.h"
|
|
#include "gamesequence/gamesequence.h"
|
|
#include "gamesnd/eventmusic.h"
|
|
#include "gamesnd/gamesnd.h"
|
|
#include "globalincs/alphacolors.h"
|
|
#include "globalincs/linklist.h"
|
|
#include "graphics/font.h"
|
|
#include "graphics/matrix.h"
|
|
#include "hud/hud.h"
|
|
#include "io/key.h"
|
|
#include "io/mouse.h"
|
|
#include "io/timer.h"
|
|
#include "lighting/lighting.h"
|
|
#include "menuui/snazzyui.h"
|
|
#include "mission/missionbriefcommon.h"
|
|
#include "mission/missioncampaign.h"
|
|
#include "mission/missiongoals.h"
|
|
#include "mission/missionmessage.h"
|
|
#include "missionui/chatbox.h"
|
|
#include "missionui/missionbrief.h"
|
|
#include "missionui/missionscreencommon.h"
|
|
#include "missionui/missionshipchoice.h"
|
|
#include "model/model.h"
|
|
#include "network/multi.h"
|
|
#include "network/multimsgs.h"
|
|
#include "network/multiteamselect.h"
|
|
#include "network/multiui.h"
|
|
#include "parse/parselo.h"
|
|
#include "parse/sexp.h"
|
|
#include "playerman/player.h"
|
|
#include "popup/popup.h"
|
|
#include "render/3d.h"
|
|
#include "ship/ship.h"
|
|
#include "sound/audiostr.h"
|
|
#include "sound/fsspeech.h"
|
|
|
|
|
|
static int Brief_goals_coords[GR_NUM_RESOLUTIONS][4] = {
|
|
{
|
|
65,152,508,211 // GR_640
|
|
},
|
|
{
|
|
104,243,813,332 // GR_1024
|
|
}
|
|
};
|
|
|
|
static int Current_brief_stage; // what stage of the briefing we're on
|
|
static int Last_brief_stage;
|
|
static int Num_brief_stages;
|
|
static int Brief_multiplayer = FALSE;
|
|
|
|
static int Brief_last_auto_advance = 0; // timestamp of last auto-advance
|
|
|
|
// for managing the scene cut transition
|
|
static int Quick_transition_stage;
|
|
static int Start_fade_up_anim, Start_fade_down_anim;
|
|
static int Brief_playing_fade_sound;
|
|
hud_anim Fade_anim;
|
|
|
|
int Briefing_music_handle = -1;
|
|
int Briefing_music_begin_timestamp = 0;
|
|
|
|
int Briefing_overlay_id = -1;
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// Module scope globals
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
static MENU_REGION Briefing_select_region[NUM_BRIEFING_REGIONS];
|
|
static int Num_briefing_regions;
|
|
|
|
// For closeup display
|
|
#define ONE_REV_TIME 6 // time (sec) for one revolution
|
|
#define MAX_ANG_CHG 0.15f
|
|
|
|
static int Closeup_coords[GR_NUM_RESOLUTIONS][4] = {
|
|
{
|
|
203, 151, 200, 213 // GR_640
|
|
},
|
|
{
|
|
325, 241, 200, 213 // GR_1024
|
|
}
|
|
};
|
|
|
|
/* no longer used - taylor
|
|
static int Closeup_img_h[GR_NUM_RESOLUTIONS] = {
|
|
150, // GR_640
|
|
150 // GR_1024
|
|
};
|
|
|
|
static int Closeup_text_h[GR_NUM_RESOLUTIONS][4] = {
|
|
63, // GR_640
|
|
63 // GR_1024
|
|
}; */
|
|
|
|
static int Brief_infobox_coords[GR_NUM_RESOLUTIONS][2] = {
|
|
{ // GR_640
|
|
0, 391
|
|
},
|
|
{ // GR_1024
|
|
0, 627
|
|
}
|
|
};
|
|
|
|
static const char *Brief_infobox_filename[GR_NUM_RESOLUTIONS] = {
|
|
"InfoBox",
|
|
"2_Infobox"
|
|
};
|
|
|
|
static const char *Brief_filename[GR_NUM_RESOLUTIONS] = {
|
|
"Brief",
|
|
"2_Brief"
|
|
};
|
|
|
|
static const char *Brief_multi_filename[GR_NUM_RESOLUTIONS] = {
|
|
"BriefMulti",
|
|
"2_BriefMulti"
|
|
};
|
|
|
|
static const char *Brief_mask_filename[GR_NUM_RESOLUTIONS] = {
|
|
"Brief-m",
|
|
"2_Brief-m"
|
|
};
|
|
|
|
static const char *Brief_multi_mask_filename[GR_NUM_RESOLUTIONS] = {
|
|
"BriefMulti-m",
|
|
"2_BriefMulti-m"
|
|
};
|
|
|
|
|
|
static const char *Brief_win_filename[GR_NUM_RESOLUTIONS] = {
|
|
"Briefwin",
|
|
"2_Briefwin"
|
|
};
|
|
|
|
// coordinate inidices
|
|
#define BRIEF_X_COORD 0
|
|
#define BRIEF_Y_COORD 1
|
|
#define BRIEF_W_COORD 2
|
|
#define BRIEF_H_COORD 3
|
|
|
|
//static int Closeup_region[4] = {220,132,420,269};
|
|
int Closeup_region[GR_NUM_RESOLUTIONS][4] = {
|
|
{ // GR_640
|
|
211, 158, 215, 157
|
|
},
|
|
{ // GR_1024
|
|
337, 253, 345, 252
|
|
},
|
|
};
|
|
|
|
const char *Closeup_background_filename[GR_NUM_RESOLUTIONS] = {
|
|
NOX("BriefPop"), // GR_640
|
|
NOX("2_BriefPop") // GR_1024
|
|
};
|
|
|
|
const char *Closeup_button_filename[GR_NUM_RESOLUTIONS] = {
|
|
NOX("BPB_00"), // GR_640
|
|
NOX("2_BPB_00"), // GR_1024
|
|
};
|
|
|
|
int Closeup_button_hotspot = 14;
|
|
|
|
//static int Closeup_button_coords[2] = {CLOSEUP_X+164,CLOSEUP_Y+227};
|
|
int Closeup_button_coords[GR_NUM_RESOLUTIONS][2] = {
|
|
{ 374, 316 }, // GR_640
|
|
{ 599, 506 } // GR_1024
|
|
};
|
|
|
|
UI_BUTTON Closeup_close_button;
|
|
int Closeup_bitmap=-1;
|
|
int Closeup_one_revolution_time=ONE_REV_TIME;
|
|
|
|
brief_icon *Closeup_icon;
|
|
angles Closeup_angles;
|
|
matrix Closeup_orient;
|
|
vec3d Closeup_pos;
|
|
int Closeup_font_height;
|
|
int Closeup_x1, Closeup_y1;
|
|
|
|
// used for the 3d view of a closeup ship
|
|
float Closeup_zoom;
|
|
vec3d Closeup_cam_pos;
|
|
|
|
// Mask bitmap pointer and Mask bitmap_id
|
|
ubyte* Brief_ui_mask_data; // pointer to actual bitmap data
|
|
static int Brief_ui_mask_w = -1;
|
|
static int Brief_ui_mask_h = -1;
|
|
int Brief_inited = FALSE;
|
|
|
|
int Briefing_paused = 0; // for stopping audio and stage progression
|
|
|
|
int Max_brief_Lines;
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// Briefing specific UI
|
|
// --------------------------------------------------------------------------------------
|
|
#define BRIEF_LAST_STAGE_MASK 7
|
|
#define BRIEF_NEXT_STAGE_MASK 8
|
|
#define BRIEF_PREV_STAGE_MASK 9
|
|
#define BRIEF_FIRST_STAGE_MASK 10
|
|
#define BRIEF_TEXT_SCROLL_UP_MASK 11
|
|
#define BRIEF_TEXT_SCROLL_DOWN_MASK 12
|
|
#define BRIEF_SKIP_TRAINING_MASK 15
|
|
#define BRIEF_PAUSE_MASK 16
|
|
|
|
struct brief_buttons {
|
|
const char *filename;
|
|
int x, y;
|
|
int xt, yt;
|
|
int hotspot;
|
|
int repeat;
|
|
UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
|
|
|
|
brief_buttons(const char *name, int x1, int y1, int xt1, int yt1, int h, int r = 0) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), repeat(r) {}
|
|
};
|
|
|
|
int Brief_grid_bitmap = -1;
|
|
int Brief_text_bitmap = -1;
|
|
|
|
int Brief_multitext_bitmap = -1;
|
|
int Brief_background_bitmap =-1;
|
|
|
|
UI_WINDOW Brief_ui_window;
|
|
|
|
// Briefing specific buttons
|
|
#define NUM_BRIEF_BUTTONS 10
|
|
|
|
brief_buttons Brief_buttons[GR_NUM_RESOLUTIONS][NUM_BRIEF_BUTTONS] = {
|
|
{ // GR_640
|
|
brief_buttons("BRB_08", 110, 116, 117, 157, 8),
|
|
brief_buttons("BRB_09", 84, 116, 117, 157, 9),
|
|
brief_buttons("BRB_10", 29, 116, 117, 157, 10),
|
|
brief_buttons("BRB_11", 4, 116, 117, 157, 11),
|
|
brief_buttons("BRB_12", 0, 405, 117, 157, 12),
|
|
brief_buttons("BRB_13", 0, 447, 117, 157, 13),
|
|
brief_buttons("BRB_15", 562, 0, 117, 157, 15), // skip training
|
|
brief_buttons("BRB_16", 56, 116, 117, 157, 16),
|
|
brief_buttons("TSB_34", 603, 374, 117, 157, 34),
|
|
brief_buttons("BRB_15", 562, 0, 117, 157, 15) // exit loop
|
|
},
|
|
{ // GR_1024
|
|
brief_buttons("2_BRB_08", 175, 187, 117, 157, 8),
|
|
brief_buttons("2_BRB_09", 135, 187, 117, 157, 9),
|
|
brief_buttons("2_BRB_10", 47, 187, 117, 157, 10),
|
|
brief_buttons("2_BRB_11", 8, 187, 117, 157, 11),
|
|
brief_buttons("2_BRB_12", 0, 649, 117, 157, 12),
|
|
brief_buttons("2_BRB_13", 0, 716, 117, 157, 13),
|
|
brief_buttons("2_BRB_15", 900, 0, 117, 157, 15), // skip training
|
|
brief_buttons("2_BRB_16", 91, 187, 117, 157, 16),
|
|
brief_buttons("2_TSB_34", 966, 599, 117, 157, 34),
|
|
brief_buttons("2_BRB_15", 900, 0, 117, 157, 15) // exit loop
|
|
},
|
|
};
|
|
|
|
// briefing UI
|
|
#define BRIEF_SELECT_NUM_TEXT 3
|
|
UI_XSTR Brief_select_text[GR_NUM_RESOLUTIONS][BRIEF_SELECT_NUM_TEXT] = {
|
|
{ // GR_640
|
|
{ "Lock", 1270, 602, 364, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_MULTI_LOCK].button },
|
|
{ "Skip Training", 1442, 467, 7, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_SKIP_TRAINING].button },
|
|
{ "Exit Loop", 1477, 490, 7, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_EXIT_LOOP].button }
|
|
},
|
|
{ // GR_1024
|
|
{ "Lock", 1270, 964, 584, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_MULTI_LOCK].button },
|
|
{ "Skip Training", 1442, 805, 12, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_SKIP_TRAINING].button },
|
|
{ "Exit Loop", 1477, 830, 12, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_EXIT_LOOP].button }
|
|
}
|
|
};
|
|
|
|
// coordinates for briefing title -- the x value is for the RIGHT side of the text
|
|
static int Title_coords[GR_NUM_RESOLUTIONS][2] = {
|
|
{575, 117}, // GR_640
|
|
{918, 194} // GR_1024
|
|
};
|
|
|
|
// coordinates for briefing title in multiplayer briefings -- the x value is for the LEFT side of the text
|
|
// third coord is max width of area for it to fit into (it is force fit there)
|
|
static int Title_coords_multi[GR_NUM_RESOLUTIONS][3] = {
|
|
{1, 105, 190}, // GR_640
|
|
{1, 174, 304} // GR_1024
|
|
};
|
|
|
|
// briefing line widths
|
|
int Brief_max_line_width[GR_NUM_RESOLUTIONS] = {
|
|
MAX_BRIEF_LINE_W_640, MAX_BRIEF_LINE_W_1024
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// Forward declarations
|
|
// --------------------------------------------------------------------------------------
|
|
int brief_setup_closeup(brief_icon *bi);
|
|
void brief_maybe_blit_scene_cut(float frametime);
|
|
void brief_transition_reset();
|
|
|
|
const char *brief_tooltip_handler(const char *str)
|
|
{
|
|
if (!stricmp(str, NOX("@close"))) {
|
|
if (Closeup_icon)
|
|
return XSTR( "Close", 428);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// brief_skip_training_pressed()
|
|
//
|
|
// called when the skip training button on the briefing screen is hit. When this happens,
|
|
// do a popup, then move to the next mission in the campaign.
|
|
void brief_skip_training_pressed()
|
|
{
|
|
int val;
|
|
|
|
val = popup(PF_USE_NEGATIVE_ICON | PF_USE_AFFIRMATIVE_ICON,2,POPUP_NO,POPUP_YES,XSTR( "Skip Training\n\n\n\nAre you sure you want to skip this training mission?", 429));
|
|
|
|
// val is 0 when we hit no (first on the list)
|
|
// AL: also, -1 is returned when ESC is hit
|
|
if ( val <= 0 ){
|
|
return;
|
|
}
|
|
|
|
// page out mission messages
|
|
message_mission_shutdown();
|
|
|
|
if ( !(Game_mode & GM_CAMPAIGN_MODE) ){
|
|
gameseq_post_event( GS_EVENT_MAIN_MENU );
|
|
}
|
|
|
|
// tricky part. Need to move to the next mission in the campaign.
|
|
mission_goal_mark_objectives_complete();
|
|
mission_goal_fail_incomplete();
|
|
mission_campaign_store_goals_and_events_and_variables();
|
|
|
|
mission_campaign_eval_next_mission();
|
|
mission_campaign_mission_over();
|
|
|
|
if ( The_mission.flags[Mission::Mission_Flags::End_to_mainhall] ) {
|
|
gameseq_post_event( GS_EVENT_MAIN_MENU );
|
|
} else {
|
|
gameseq_post_event( GS_EVENT_START_GAME );
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_do_next_pressed()
|
|
//
|
|
//
|
|
void brief_do_next_pressed(int play_sound)
|
|
{
|
|
int now = timer_get_milliseconds();
|
|
|
|
if ( (now - Brief_last_auto_advance) < 500 ) {
|
|
return;
|
|
}
|
|
|
|
Current_brief_stage++;
|
|
if ( Current_brief_stage >= Num_brief_stages ) {
|
|
Current_brief_stage = Num_brief_stages - 1;
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
if ( Quick_transition_stage != -1 )
|
|
brief_transition_reset();
|
|
} else {
|
|
if ( play_sound ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_STAGE_CHG);
|
|
}
|
|
}
|
|
Assert(Current_brief_stage >= 0);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_do_prev_pressed()
|
|
//
|
|
//
|
|
void brief_do_prev_pressed()
|
|
{
|
|
Current_brief_stage--;
|
|
if ( Current_brief_stage < 0 ) {
|
|
Current_brief_stage = 0;
|
|
if (common_num_cutscenes_valid(MOVIE_PRE_BRIEF)) {
|
|
common_maybe_play_cutscene(MOVIE_PRE_BRIEF, true, SCORE_BRIEFING);
|
|
}
|
|
else {
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
if ( Quick_transition_stage != -1 )
|
|
brief_transition_reset();
|
|
}
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_STAGE_CHG);
|
|
}
|
|
Assert(Current_brief_stage >= 0);
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_do_start_pressed()
|
|
//
|
|
//
|
|
void brief_do_start_pressed()
|
|
{
|
|
if (common_num_cutscenes_valid(MOVIE_PRE_BRIEF)) {
|
|
common_maybe_play_cutscene(MOVIE_PRE_BRIEF, true, SCORE_BRIEFING);
|
|
Current_brief_stage = 0;
|
|
}
|
|
else if ( Current_brief_stage != 0 ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_STAGE_CHG);
|
|
Current_brief_stage = 0;
|
|
if ( Quick_transition_stage != -1 )
|
|
brief_transition_reset();
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
}
|
|
Assert(Current_brief_stage >= 0);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_do_end_pressed()
|
|
//
|
|
//
|
|
void brief_do_end_pressed()
|
|
{
|
|
if ( Current_brief_stage != Num_brief_stages - 1 ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_STAGE_CHG);
|
|
Current_brief_stage = Num_brief_stages - 1;
|
|
if ( Quick_transition_stage != -1 )
|
|
brief_transition_reset();
|
|
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
}
|
|
Assert(Current_brief_stage >= 0);
|
|
}
|
|
|
|
|
|
void brief_scroll_up_text()
|
|
{
|
|
Top_brief_text_line--;
|
|
if ( Top_brief_text_line < 0 ) {
|
|
Top_brief_text_line = 0;
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
}
|
|
}
|
|
|
|
void brief_scroll_down_text()
|
|
{
|
|
Top_brief_text_line++;
|
|
if ( (Num_brief_text_lines[0] - Top_brief_text_line) < Max_brief_Lines) {
|
|
Top_brief_text_line--;
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
}
|
|
}
|
|
|
|
|
|
// handles the exit loop option
|
|
void brief_exit_loop_pressed()
|
|
{
|
|
int val = popup(PF_USE_NEGATIVE_ICON | PF_USE_AFFIRMATIVE_ICON, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Loop\n\n\n\nAre you sure you want to leave the mission loop?", 1489));
|
|
|
|
// bail if esc hit or no clicked
|
|
if (val <= 0) {
|
|
return;
|
|
}
|
|
|
|
// handle the details
|
|
// this also posts the start game event
|
|
mission_campaign_exit_loop();
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_select_button_do() do the button action for the specified pressed button
|
|
//
|
|
void brief_button_do(int i)
|
|
{
|
|
switch ( i ) {
|
|
case BRIEF_BUTTON_LAST_STAGE:
|
|
brief_do_end_pressed();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_NEXT_STAGE:
|
|
brief_do_next_pressed(1);
|
|
break;
|
|
|
|
case BRIEF_BUTTON_PREV_STAGE:
|
|
brief_do_prev_pressed();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_FIRST_STAGE:
|
|
brief_do_start_pressed();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_SCROLL_UP:
|
|
brief_scroll_up_text();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_SCROLL_DOWN:
|
|
brief_scroll_down_text();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_PAUSE:
|
|
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
|
fsspeech_pause(Player->auto_advance != 0);
|
|
Player->auto_advance ^= 1;
|
|
break;
|
|
|
|
case BRIEF_BUTTON_SKIP_TRAINING:
|
|
fsspeech_stop();
|
|
brief_skip_training_pressed();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_EXIT_LOOP:
|
|
fsspeech_stop();
|
|
brief_exit_loop_pressed();
|
|
break;
|
|
|
|
case BRIEF_BUTTON_MULTI_LOCK:
|
|
Assert(Game_mode & GM_MULTIPLAYER);
|
|
// the "lock" button has been pressed
|
|
multi_ts_lock_pressed();
|
|
|
|
// disable the button if it is now locked
|
|
if(multi_ts_is_locked()){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
|
|
}
|
|
break;
|
|
} // end switch
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
// brief_check_buttons()
|
|
//
|
|
// Iterate through the briefing buttons, checking if they are pressed
|
|
//
|
|
void brief_check_buttons()
|
|
{
|
|
int i;
|
|
UI_BUTTON *b;
|
|
|
|
for (i=0; i<NUM_BRIEF_BUTTONS; i++) {
|
|
b = &Brief_buttons[gr_screen.res][i].button;
|
|
if ( b->pressed() ) {
|
|
common_flash_button_init();
|
|
brief_button_do(i);
|
|
}
|
|
}
|
|
|
|
if (Closeup_close_button.pressed()) {
|
|
brief_turn_off_closeup_icon();
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
// brief_redraw_pressed_buttons()
|
|
//
|
|
// Redraw any briefing buttons that are pressed down. This function is needed
|
|
// since we sometimes need to draw pressed buttons last to ensure the entire
|
|
// button gets drawn (and not overlapped by other buttons)
|
|
//
|
|
void brief_redraw_pressed_buttons()
|
|
{
|
|
int i;
|
|
UI_BUTTON *b;
|
|
|
|
common_redraw_pressed_buttons();
|
|
|
|
for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
|
|
b = &Brief_buttons[gr_screen.res][i].button;
|
|
if ( b->button_down() ) {
|
|
b->draw_forced(2);
|
|
}
|
|
}
|
|
|
|
if ( !Player->auto_advance ) {
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.draw_forced(2);
|
|
}
|
|
}
|
|
|
|
void brief_buttons_init()
|
|
{
|
|
UI_BUTTON *b;
|
|
int i;
|
|
|
|
//if ( Briefing->num_stages <= 0 )
|
|
// return;
|
|
|
|
for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
|
|
b = &Brief_buttons[gr_screen.res][i].button;
|
|
b->create( &Brief_ui_window, "", Brief_buttons[gr_screen.res][i].x, Brief_buttons[gr_screen.res][i].y, 60, 30, 0, 1 );
|
|
// set up callback for when a mouse first goes over a button
|
|
b->set_highlight_action( common_play_highlight_sound );
|
|
|
|
if ((i == BRIEF_BUTTON_SKIP_TRAINING) || (i == BRIEF_BUTTON_EXIT_LOOP)) {
|
|
b->set_bmaps(Brief_buttons[gr_screen.res][i].filename, 3, 0);
|
|
} else {
|
|
b->set_bmaps(Brief_buttons[gr_screen.res][i].filename);
|
|
}
|
|
b->link_hotspot(Brief_buttons[gr_screen.res][i].hotspot);
|
|
}
|
|
|
|
// add all xstrs
|
|
for(i=0; i<BRIEF_SELECT_NUM_TEXT; i++) {
|
|
Brief_ui_window.add_XSTR(&Brief_select_text[gr_screen.res][i]);
|
|
}
|
|
|
|
// Hide the 'skip training' button by default. Only enable and unhide if we are playing a training
|
|
// mission
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.hide();
|
|
if ( (Game_mode & GM_NORMAL) && (The_mission.game_type & MISSION_TYPE_TRAINING) ) {
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.enable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.unhide();
|
|
}
|
|
|
|
// Hide the 'exit loop' button by default. Only enable and unhide if we are playing a loop
|
|
// mission
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.hide();
|
|
if ( (Game_mode & GM_NORMAL) && (Campaign.loop_enabled) && (Game_mode & GM_CAMPAIGN_MODE) ) {
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.enable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.unhide();
|
|
}
|
|
|
|
// maybe disable the multi-lock button
|
|
if(!(Game_mode & GM_MULTIPLAYER)){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
|
|
} else {
|
|
// if we're not the host of the game (or a tema captain in team vs. team mode), disable the lock button
|
|
if(Netgame.type_flags & NG_TYPE_TEAM){
|
|
if(!(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
|
|
}
|
|
} else {
|
|
if(!(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
|
|
}
|
|
}
|
|
}
|
|
|
|
// create close button for closeup popup
|
|
Closeup_close_button.create( &Brief_ui_window, "", Closeup_button_coords[gr_screen.res][BRIEF_X_COORD], Closeup_button_coords[gr_screen.res][BRIEF_Y_COORD], 60, 30, 0, 1 );
|
|
Closeup_close_button.set_highlight_action( common_play_highlight_sound );
|
|
Closeup_close_button.set_bmaps(Closeup_button_filename[gr_screen.res]);
|
|
Closeup_close_button.link_hotspot(Closeup_button_hotspot);
|
|
|
|
// set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_RIGHT);
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.set_hotkey(KEY_RIGHT);
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.set_hotkey(KEY_LEFT);
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_LEFT);
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.set_hotkey(KEY_UP);
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);
|
|
|
|
Closeup_close_button.disable();
|
|
Closeup_close_button.hide();
|
|
|
|
// if we have no briefing stages, hide and disable briefing buttons
|
|
if(Num_brief_stages <= 0){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.hide();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.disable();
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.hide();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_get_closeup_icon()
|
|
//
|
|
//
|
|
// changed from uint for 64-bit support - taylor
|
|
brief_icon *brief_get_closeup_icon()
|
|
{
|
|
return Closeup_icon;
|
|
}
|
|
|
|
// stop showing the closeup view of an icon
|
|
void brief_turn_off_closeup_icon()
|
|
{
|
|
// turn off closup
|
|
if ( Closeup_icon != NULL ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_ICON_SELECT);
|
|
Closeup_icon = NULL;
|
|
Closeup_close_button.disable();
|
|
Closeup_close_button.hide();
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_load_bitmaps()
|
|
//
|
|
//
|
|
void brief_load_bitmaps()
|
|
{
|
|
Brief_text_bitmap = bm_load(Brief_infobox_filename[gr_screen.res]);
|
|
Brief_grid_bitmap = bm_load(Brief_win_filename[gr_screen.res]);
|
|
|
|
if ( Closeup_bitmap == -1 ) {
|
|
Closeup_bitmap = bm_load(Closeup_background_filename[gr_screen.res]);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_ui_init()
|
|
//
|
|
//
|
|
void brief_ui_init()
|
|
{
|
|
Brief_background_bitmap = mission_ui_background_load(Briefing->background[gr_screen.res], Brief_filename[gr_screen.res], Brief_multi_filename[gr_screen.res]);
|
|
|
|
if ( Num_brief_stages <= 0 ){
|
|
return;
|
|
}
|
|
|
|
brief_load_bitmaps();
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_set_default_closeup()
|
|
//
|
|
//
|
|
void brief_set_default_closeup()
|
|
{
|
|
brief_stage *bs;
|
|
int i;
|
|
|
|
bs = &Briefing->stages[0];
|
|
|
|
if ( Briefing->num_stages <= 0 ) {
|
|
Closeup_icon = NULL;
|
|
return;
|
|
}
|
|
|
|
if ( bs->num_icons <= 0 ) {
|
|
Closeup_icon = NULL;
|
|
return;
|
|
}
|
|
|
|
// check for the first highlighted icons to have as the default closeup
|
|
for ( i = 0; i < bs->num_icons; i++ ) {
|
|
if ( bs->icons[i].flags & BI_HIGHLIGHT )
|
|
break;
|
|
}
|
|
|
|
if ( i == bs->num_icons ) {
|
|
brief_setup_closeup(&bs->icons[0]);
|
|
}
|
|
else {
|
|
brief_setup_closeup(&bs->icons[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Evaluate the sexpressions of the briefing stages eliminating those stages
|
|
* which shouldn't get shown
|
|
*/
|
|
void brief_compact_stages()
|
|
{
|
|
int num, before, result, i;
|
|
|
|
before = Briefing->num_stages;
|
|
|
|
num = 0;
|
|
while ( num < Briefing->num_stages ) {
|
|
result = eval_sexp( Briefing->stages[num].formula );
|
|
if ( !result ) {
|
|
Briefing->stages[num].text = "";
|
|
|
|
if ( Briefing->stages[num].icons != NULL ) {
|
|
vm_free( Briefing->stages[num].icons );
|
|
Briefing->stages[num].icons = NULL;
|
|
}
|
|
|
|
if ( Briefing->stages[num].lines != NULL ) {
|
|
vm_free( Briefing->stages[num].lines );
|
|
Briefing->stages[num].lines = NULL;
|
|
}
|
|
|
|
Briefing->stages[num].num_icons = 0;
|
|
for ( i = num+1; i < Briefing->num_stages; i++ ) {
|
|
Briefing->stages[i-1] = Briefing->stages[i];
|
|
}
|
|
Briefing->num_stages--;
|
|
continue;
|
|
}
|
|
num++;
|
|
}
|
|
|
|
// completely clear out the old entries (if any) so we don't access them by mistake - taylor
|
|
if ( before > Briefing->num_stages ) {
|
|
for ( i = Briefing->num_stages; i < before; i++ ) {
|
|
Briefing->stages[i] = brief_stage();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_init()
|
|
//
|
|
int red_alert_mission(void);
|
|
//
|
|
void brief_init()
|
|
{
|
|
int i;
|
|
|
|
// for multiplayer, change the state in my netplayer structure
|
|
// and initialize the briefing chat area thingy
|
|
if ( Game_mode & GM_MULTIPLAYER ){
|
|
Net_player->state = NETPLAYER_STATE_BRIEFING;
|
|
}
|
|
|
|
// Non standard briefing in red alert mission
|
|
if ( red_alert_mission() ) {
|
|
Int3(); // since we shouldn't be here
|
|
gameseq_post_event(GS_EVENT_RED_ALERT);
|
|
return;
|
|
}
|
|
|
|
// get a pointer to the appropriate briefing structure
|
|
if(MULTI_TEAM){
|
|
Briefing = &Briefings[Net_player->p_info.team];
|
|
} else {
|
|
Briefing = &Briefings[0];
|
|
}
|
|
|
|
// Goober5000 - replace any variables (probably persistent variables) with their values
|
|
for (i = 0; i < Briefing->num_stages; i++)
|
|
sexp_replace_variable_names_with_values(Briefing->stages[i].text);
|
|
|
|
Brief_last_auto_advance = 0;
|
|
|
|
brief_compact_stages(); // compact the briefing array to eliminate unused stages
|
|
|
|
common_set_interface_palette("BriefingPalette");
|
|
|
|
set_active_ui(&Brief_ui_window);
|
|
Current_screen = ON_BRIEFING_SELECT;
|
|
brief_restart_text_wipe();
|
|
common_flash_button_init();
|
|
common_music_init(SCORE_BRIEFING);
|
|
|
|
Briefing_overlay_id = help_overlay_get_index(BR_OVERLAY);
|
|
help_overlay_set_state(Briefing_overlay_id,gr_screen.res,0);
|
|
|
|
if ( Brief_inited == TRUE ) {
|
|
common_buttons_maybe_reload(&Brief_ui_window); // AL 11-21-97: this is necessary since we may returning from the hotkey
|
|
// screen, which can release common button bitmaps.
|
|
common_reset_buttons();
|
|
nprintf(("Alan","brief_init() returning without doing anything\n"));
|
|
return;
|
|
}
|
|
|
|
if (The_mission.flags[Mission::Mission_Flags::Always_show_goals] || !(The_mission.game_type & MISSION_TYPE_TRAINING))
|
|
Num_brief_stages = Briefing->num_stages + 1;
|
|
else
|
|
Num_brief_stages = Briefing->num_stages;
|
|
|
|
Current_brief_stage = 0;
|
|
Last_brief_stage = 0;
|
|
|
|
// init the scene-cut data
|
|
brief_transition_reset();
|
|
|
|
hud_anim_init(&Fade_anim, Brief_static_coords[gr_screen.res][0], Brief_static_coords[gr_screen.res][1], Brief_static_name[gr_screen.res]);
|
|
hud_anim_load(&Fade_anim);
|
|
|
|
nprintf(("Alan","Entering brief_init()\n"));
|
|
common_select_init();
|
|
|
|
// Set up the mask regions
|
|
// initialize the different regions of the menu that will react when the mouse moves over it
|
|
Num_briefing_regions = 0;
|
|
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_BRIEFING_REGION, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_SS_REGION, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_WEAPON_REGION, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_COMMIT_REGION, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_HELP_REGION, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_OPTIONS_REGION, 0);
|
|
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_LAST_STAGE_MASK, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_NEXT_STAGE_MASK, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_PREV_STAGE_MASK, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_FIRST_STAGE_MASK, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_TEXT_SCROLL_UP_MASK, 0);
|
|
snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_TEXT_SCROLL_DOWN_MASK, 0);
|
|
|
|
// init common UI
|
|
Brief_ui_window.create( 0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0 );
|
|
|
|
if(Game_mode & GM_MULTIPLAYER){
|
|
Brief_ui_window.set_mask_bmap(Brief_multi_mask_filename[gr_screen.res]);
|
|
} else {
|
|
Brief_ui_window.set_mask_bmap(Brief_mask_filename[gr_screen.res]);
|
|
}
|
|
|
|
// get a pointer to the mask data
|
|
Brief_ui_mask_data = Brief_ui_window.get_mask_data( &Brief_ui_mask_w, &Brief_ui_mask_h );
|
|
|
|
Brief_ui_window.tooltip_handler = brief_tooltip_handler;
|
|
common_buttons_init(&Brief_ui_window);
|
|
brief_buttons_init();
|
|
|
|
// if multiplayer, initialize a few other systems
|
|
if(Game_mode & GM_MULTIPLAYER){
|
|
// again, should not be necessary, but we'll leave it for now
|
|
chatbox_create();
|
|
|
|
// force the chatbox to be small
|
|
chatbox_force_small();
|
|
}
|
|
|
|
// set up the screen regions
|
|
brief_init_screen(Brief_multiplayer);
|
|
|
|
// init briefing specific UI
|
|
brief_ui_init();
|
|
|
|
// init the briefing map
|
|
brief_init_map();
|
|
|
|
// init the briefing voice playback
|
|
brief_voice_init();
|
|
brief_voice_load_all();
|
|
|
|
// init objectives display stuff
|
|
ML_objectives_init(Brief_goals_coords[gr_screen.res][BRIEF_X_COORD], Brief_goals_coords[gr_screen.res][BRIEF_Y_COORD], Brief_goals_coords[gr_screen.res][BRIEF_W_COORD], Brief_goals_coords[gr_screen.res][BRIEF_H_COORD]);
|
|
|
|
// set the camera target
|
|
if ( Briefing->num_stages > 0 ) {
|
|
brief_set_new_stage(&Briefing->stages[0].camera_pos, &Briefing->stages[0].camera_orient, 0, Current_brief_stage);
|
|
brief_reset_icons(Current_brief_stage);
|
|
}
|
|
|
|
// fire the script hook, since when we first start the briefing there isn't a "new stage" function like there is for cbriefs
|
|
common_fire_stage_script_hook(Last_brief_stage, Current_brief_stage);
|
|
|
|
Brief_playing_fade_sound = 0;
|
|
Brief_mouse_up_flag = 0;
|
|
Closeup_font_height = gr_get_font_height();
|
|
Closeup_icon = NULL;
|
|
Brief_inited = TRUE;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_render_closeup_text()
|
|
//
|
|
//
|
|
#define CLOSEUP_TEXT_OFFSET 10
|
|
void brief_render_closeup_text()
|
|
{
|
|
/*
|
|
brief_icon *bi;
|
|
char line[MAX_ICON_TEXT_LINE_LEN];
|
|
int n_lines, i, render_x, render_y;
|
|
int n_chars[MAX_ICON_TEXT_LINES];
|
|
char *p_str[MAX_ICON_TEXT_LINES];
|
|
|
|
if ( Closeup_icon == NULL ) {
|
|
Int3();
|
|
return;
|
|
}
|
|
|
|
bi = Closeup_icon;
|
|
|
|
render_x = Closeup_region[0];
|
|
render_y = Closeup_region[1] + CLOSEUP_IMG_H;
|
|
|
|
gr_set_clip(render_x+CLOSEUP_TEXT_OFFSET, render_y, CLOSEUP_W,CLOSEUP_TEXT_H, GR_RESIZE_MENU);
|
|
gr_set_color_fast(&Color_white);
|
|
|
|
// n_lines = split_str(bi->text, CLOSEUP_W - 2*CLOSEUP_TEXT_OFFSET, n_chars, p_str, MAX_ICON_TEXT_LINES);
|
|
Assert(n_lines != -1);
|
|
|
|
for ( i = 0; i < n_lines; i++ ) {
|
|
Assert(n_chars[i] < MAX_ICON_TEXT_LINE_LEN);
|
|
strncpy(line, p_str[i], n_chars[i]);
|
|
line[n_chars[i]] = 0;
|
|
gr_printf_menu(0,0+i*Closeup_font_height,line);
|
|
}
|
|
*/
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_render_closeup()
|
|
//
|
|
//
|
|
void brief_render_closeup(int ship_class, float frametime)
|
|
{
|
|
matrix view_orient = IDENTITY_MATRIX;
|
|
matrix temp_matrix;
|
|
float ang;
|
|
int w,h;
|
|
|
|
if (ship_class < 0)
|
|
return;
|
|
|
|
if (Closeup_bitmap < 0)
|
|
return;
|
|
|
|
ang = PI2 * frametime/Closeup_one_revolution_time;
|
|
if ( ang > MAX_ANG_CHG )
|
|
ang = MAX_ANG_CHG;
|
|
|
|
Closeup_angles.h += ang;
|
|
if ( Closeup_angles.h > PI2 )
|
|
Closeup_angles.h -= PI2;
|
|
vm_angles_2_matrix(&temp_matrix, &Closeup_angles );
|
|
Closeup_orient = temp_matrix;
|
|
|
|
w = Closeup_region[gr_screen.res][2];
|
|
h = Closeup_region[gr_screen.res][3];
|
|
gr_set_clip(Closeup_region[gr_screen.res][0], Closeup_region[gr_screen.res][1], w, h, GR_RESIZE_MENU);
|
|
|
|
g3_start_frame(1);
|
|
g3_set_view_matrix(&Closeup_cam_pos, &view_orient, Closeup_zoom);
|
|
|
|
|
|
gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
|
|
gr_set_view_matrix(&Eye_position, &Eye_matrix);
|
|
|
|
// the following is copied from menuui/techmenu.cpp ... it works heehee :D - delt.
|
|
// lighting for techroom
|
|
light_reset();
|
|
vec3d light_dir = vmd_zero_vector;
|
|
light_dir.xyz.y = 1.0f;
|
|
light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
|
|
light_rotate_all();
|
|
// lighting for techroom
|
|
Glowpoint_use_depth_buffer = false;
|
|
|
|
model_clear_instance( Closeup_icon->modelnum );
|
|
|
|
|
|
// maybe switch off nebula rendering
|
|
auto neb_restore = The_mission.flags[Mission::Mission_Flags::Fullneb];
|
|
The_mission.flags.remove(Mission::Mission_Flags::Fullneb);
|
|
|
|
model_render_params render_info;
|
|
render_info.set_detail_level_lock(0);
|
|
|
|
if ( Closeup_icon->type == ICON_JUMP_NODE) {
|
|
render_info.set_color(HUD_color_red, HUD_color_green, HUD_color_blue);
|
|
render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_POLYS | MR_SHOW_OUTLINE_HTL | MR_NO_TEXTURING);
|
|
} else {
|
|
render_info.set_flags(MR_AUTOCENTER);
|
|
}
|
|
|
|
model_render_immediate( &render_info, Closeup_icon->modelnum, &Closeup_orient, &Closeup_pos );
|
|
|
|
The_mission.flags.set(Mission::Mission_Flags::Fullneb, neb_restore);
|
|
|
|
gr_end_view_matrix();
|
|
gr_end_proj_matrix();
|
|
|
|
g3_end_frame();
|
|
|
|
gr_set_color_fast(&Color_bright_white);
|
|
|
|
gr_get_string_size(&w, NULL, Closeup_icon->closeup_label);
|
|
|
|
gr_string((gr_screen.clip_width_unscaled - w) / 2,2,Closeup_icon->closeup_label,GR_RESIZE_MENU);
|
|
// brief_render_closeup_text();
|
|
|
|
Closeup_close_button.enable();
|
|
Closeup_close_button.unhide();
|
|
|
|
gr_reset_clip();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_render()
|
|
//
|
|
// frametime is in seconds
|
|
void brief_render(float frametime)
|
|
{
|
|
int z, w, h;
|
|
|
|
if ( Num_brief_stages <= 0 ) {
|
|
gr_set_color_fast(&Color_white);
|
|
Assert( Game_current_mission_filename != NULL );
|
|
|
|
gr_get_string_size(&w, NULL, XSTR("No Briefing exists for mission: %s", 430));
|
|
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2,200,XSTR( "No Briefing exists for mission: %s", 430), Game_current_mission_filename);
|
|
|
|
#ifndef NDEBUG
|
|
gr_get_string_size(&w, &h, The_mission.name);
|
|
gr_set_color_fast(&Color_normal);
|
|
SCP_string debugText;
|
|
sprintf(debugText, NOX("[filename: %s, last mod: %s]"), Mission_filename, The_mission.modified);
|
|
|
|
gr_get_string_size(&w, NULL, debugText.c_str());
|
|
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2, 230, "%s", debugText.c_str());
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
gr_set_bitmap(Brief_grid_bitmap);
|
|
gr_bitmap(Brief_bmap_coords[gr_screen.res][0], Brief_bmap_coords[gr_screen.res][1], GR_RESIZE_MENU);
|
|
|
|
brief_render_map(Current_brief_stage, frametime);
|
|
|
|
// draw the frame bitmaps
|
|
gr_set_bitmap(Brief_text_bitmap);
|
|
gr_bitmap(Brief_infobox_coords[gr_screen.res][0], Brief_infobox_coords[gr_screen.res][1], GR_RESIZE_MENU);
|
|
brief_blit_stage_num(Current_brief_stage, Num_brief_stages);
|
|
|
|
// only try to render text and play audio if there is really something here - taylor
|
|
if (Briefing->num_stages > 0) {
|
|
z = brief_render_text(Top_brief_text_line, Brief_text_coords[gr_screen.res][0], Brief_text_coords[gr_screen.res][1], Brief_text_coords[gr_screen.res][3], frametime);
|
|
if (z) {
|
|
brief_voice_play(Current_brief_stage);
|
|
}
|
|
|
|
Max_brief_Lines = Brief_text_coords[gr_screen.res][3]/gr_get_font_height(); //Make the max number of lines dependent on the font height.
|
|
|
|
// maybe output the "more" indicator
|
|
if ( (Max_brief_Lines + Top_brief_text_line) < Num_brief_text_lines[0] ) {
|
|
// can be scrolled down
|
|
int more_txt_x = Brief_text_coords[gr_screen.res][0] + (Brief_max_line_width[gr_screen.res]/2) - 10;
|
|
int more_txt_y = Brief_text_coords[gr_screen.res][1] + Brief_text_coords[gr_screen.res][3] - 2; // located below brief text, centered
|
|
|
|
gr_get_string_size(&w, &h, XSTR("more", 1469), (int)strlen(XSTR("more", 1469)));
|
|
gr_set_color_fast(&Color_black);
|
|
gr_rect(more_txt_x-2, more_txt_y, w+3, h, GR_RESIZE_MENU);
|
|
gr_set_color_fast(&Color_more_indicator);
|
|
gr_string(more_txt_x, more_txt_y, XSTR("more", 1469), GR_RESIZE_MENU); // base location on the input x and y?
|
|
}
|
|
}
|
|
|
|
if (Fade_anim.first_frame != -1) {
|
|
brief_maybe_blit_scene_cut(frametime);
|
|
}
|
|
|
|
#if !defined(NDEBUG)
|
|
gr_set_color_fast(&Color_normal);
|
|
int title_y_offset = (Game_mode & GM_MULTIPLAYER) ? 20 : 10;
|
|
gr_printf_menu(Brief_bmap_coords[gr_screen.res][0], Brief_bmap_coords[gr_screen.res][1]-title_y_offset, NOX("[name: %s, mod: %s]"), Mission_filename, The_mission.modified);
|
|
#endif
|
|
|
|
// output mission title
|
|
gr_set_color_fast(&Color_bright_white);
|
|
|
|
if (Game_mode & GM_MULTIPLAYER) {
|
|
char buf[256];
|
|
strncpy(buf, The_mission.name, 256);
|
|
font::force_fit_string(buf, 255, Title_coords_multi[gr_screen.res][2]);
|
|
gr_string(Title_coords_multi[gr_screen.res][0], Title_coords_multi[gr_screen.res][1], buf, GR_RESIZE_MENU);
|
|
} else {
|
|
gr_get_string_size(&w, NULL, The_mission.name);
|
|
gr_string(Title_coords[gr_screen.res][0] - w, Title_coords[gr_screen.res][1], The_mission.name, GR_RESIZE_MENU);
|
|
}
|
|
|
|
// maybe do objectives
|
|
if (Current_brief_stage == Briefing->num_stages) {
|
|
ML_objectives_do_frame(0);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_set_closeup_pos()
|
|
//
|
|
//
|
|
#define CLOSEUP_OFFSET 20
|
|
void brief_set_closeup_pos(brief_icon * /*bi*/)
|
|
{
|
|
Closeup_y1 = 10;
|
|
Closeup_x1 = (int)std::lround(320 - Closeup_coords[gr_screen.res][BRIEF_W_COORD]/2.0f);
|
|
}
|
|
|
|
void brief_get_closeup_ship_modelnum(brief_icon *ci)
|
|
{
|
|
object *objp;
|
|
ship *sp;
|
|
|
|
// find the model number for the ship to display
|
|
for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
|
|
|
|
if ( objp == &obj_used_list || objp->type != OBJ_SHIP ) {
|
|
continue;
|
|
}
|
|
|
|
sp = &Ships[objp->instance];
|
|
if ( sp->ship_info_index == ci->ship_class ) {
|
|
ci->ship_class = sp->ship_info_index;
|
|
ci->modelnum = Ship_info[sp->ship_info_index].model_num;
|
|
ci->radius = objp->radius;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_setup_closeup()
|
|
//
|
|
// exit: 0 => set-up icon sucessfully
|
|
// -1 => could not setup closeup icon
|
|
int brief_setup_closeup(brief_icon *bi)
|
|
{
|
|
char pof_filename[NAME_LENGTH];
|
|
ship_info *sip=NULL;
|
|
vec3d tvec;
|
|
|
|
Closeup_icon = bi;
|
|
Closeup_icon->ship_class = bi->ship_class;
|
|
Closeup_icon->modelnum = -1;
|
|
|
|
Closeup_one_revolution_time = ONE_REV_TIME;
|
|
|
|
switch(Closeup_icon->type) {
|
|
case ICON_PLANET:
|
|
Closeup_icon = NULL;
|
|
return -1;
|
|
/*
|
|
strcpy_s(pof_filename, NOX("planet.pof"));
|
|
strcpy_s(Closeup_icon->closeup_label, XSTR("planet",-1));
|
|
vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -8300.0f);
|
|
Closeup_zoom = 0.5f;
|
|
Closeup_one_revolution_time = ONE_REV_TIME * 3;
|
|
*/
|
|
break;
|
|
case ICON_ASTEROID_FIELD:
|
|
strcpy_s(pof_filename, Asteroid_icon_closeup_model);
|
|
strcpy_s(Closeup_icon->closeup_label, XSTR( "asteroid", 431));
|
|
Closeup_cam_pos = Asteroid_icon_closeup_position;
|
|
Closeup_zoom = Asteroid_icon_closeup_zoom;
|
|
break;
|
|
case ICON_JUMP_NODE:
|
|
strcpy_s(pof_filename, NOX("subspacenode.pof"));
|
|
strcpy_s(Closeup_icon->closeup_label, XSTR( "jump node", 432));
|
|
vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -2700.0f);
|
|
Closeup_zoom = 0.5f;
|
|
Closeup_one_revolution_time = ONE_REV_TIME * 3;
|
|
break;
|
|
case ICON_UNKNOWN:
|
|
case ICON_UNKNOWN_WING:
|
|
strcpy_s(pof_filename, NOX("unknownship.pof"));
|
|
strcpy_s(Closeup_icon->closeup_label, XSTR( "unknown", 433));
|
|
vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -22.0f);
|
|
Closeup_zoom = 0.5f;
|
|
break;
|
|
default:
|
|
brief_get_closeup_ship_modelnum(Closeup_icon);
|
|
Assert( Closeup_icon->ship_class != -1 );
|
|
sip = &Ship_info[Closeup_icon->ship_class];
|
|
|
|
strcpy_s(Closeup_icon->closeup_label, sip->get_display_name());
|
|
|
|
// Goober5000 - wcsaga doesn't want this
|
|
if (Ship_types[sip->class_type].flags[Ship::Type_Info_Flags::No_class_display] ) {
|
|
strcat_s(Closeup_icon->closeup_label, XSTR( " class", 434));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if ( Closeup_icon->modelnum == -1 ) {
|
|
if ( sip == NULL ) {
|
|
Closeup_icon->modelnum = model_load(pof_filename, 0, NULL);
|
|
} else {
|
|
Closeup_icon->modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
|
|
}
|
|
Closeup_icon->radius = model_get_radius(Closeup_icon->modelnum);
|
|
}
|
|
|
|
vm_set_identity(&Closeup_orient);
|
|
vm_vec_make(&tvec, 0.0f, 0.0f, -1.0f);
|
|
Closeup_orient.vec.fvec = tvec;
|
|
vm_vec_zero(&Closeup_pos);
|
|
Closeup_angles.p = 0.0f;
|
|
Closeup_angles.b = 0.0f;
|
|
Closeup_angles.h = PI;
|
|
|
|
brief_set_closeup_pos(bi);
|
|
|
|
if ( sip ) {
|
|
Closeup_cam_pos = sip->closeup_pos;
|
|
Closeup_zoom = sip->closeup_zoom;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_update_closeup_icon()
|
|
//
|
|
// input: mode => how to update the closeup view
|
|
// 0 -> disable
|
|
//
|
|
void brief_update_closeup_icon(int mode)
|
|
{
|
|
brief_stage *bs;
|
|
brief_icon *bi;
|
|
int i, closeup_index;
|
|
|
|
|
|
if ( mode == 0 ) {
|
|
// mode 0 means disable the closeup icon
|
|
if ( Closeup_icon != NULL ) {
|
|
brief_turn_off_closeup_icon();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( Closeup_icon == NULL )
|
|
return;
|
|
|
|
bs = &Briefing->stages[Current_brief_stage];
|
|
|
|
closeup_index = -1;
|
|
// see if any icons are being highlighted this stage
|
|
for ( i = 0; i < bs->num_icons; i++ ) {
|
|
bi = &bs->icons[i];
|
|
if ( bi->flags & BI_HIGHLIGHT ) {
|
|
closeup_index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( closeup_index != -1 ) {
|
|
bi = &bs->icons[closeup_index];
|
|
brief_setup_closeup(bi);
|
|
}
|
|
else {
|
|
Closeup_icon = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_check_for_anim()
|
|
//
|
|
//
|
|
void brief_check_for_anim()
|
|
{
|
|
int mx, my, i, iw, ih, x, y;
|
|
brief_stage *bs;
|
|
brief_icon *bi = NULL;
|
|
|
|
bs = &Briefing->stages[Current_brief_stage];
|
|
mouse_get_pos_unscaled( &mx, &my );
|
|
|
|
// if mouse click is over the VCR controls, don't launch an icon
|
|
// FIXME - should prolly push these into defines instead of hardcoding this
|
|
// if ( mx >= 0 && mx <= 115 && my >= 136 && my <= 148 ) {
|
|
// return;
|
|
// }
|
|
|
|
// same as above but without the hardcoded values, which were wrong anyway. don't know
|
|
// how this will work longterm but will hopefully keep things working well - taylor
|
|
for (i = 0; i <= BRIEF_BUTTON_FIRST_STAGE; i++) {
|
|
Brief_buttons[gr_screen.res][i].button.get_dimensions(&x, &y, &iw, &ih);
|
|
|
|
if (mx >= x && mx <= (x+iw) && my >= y && my <= (y+ih)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if mouse coords are outside the briefing screen, then go away
|
|
my -= bscreen.map_y1;
|
|
mx -= bscreen.map_x1;
|
|
if ( my < 0 || mx < 0 || mx > (bscreen.map_x2-bscreen.map_x1+1) || my > (bscreen.map_y2-bscreen.map_y1+1) )
|
|
return;
|
|
|
|
for ( i = 0; i < bs->num_icons; i++ ) {
|
|
bi = &bs->icons[i];
|
|
brief_common_get_icon_dimensions(&iw, &ih, bi);
|
|
if ( mx < bi->x ) continue;
|
|
if ( mx > (bi->x + iw) ) continue;
|
|
if ( my < bi->y ) continue;
|
|
if ( my > (bi->y + ih) ) continue;
|
|
// if we've got here, must be a hit
|
|
break;
|
|
}
|
|
|
|
if ( i == bs->num_icons ) {
|
|
brief_turn_off_closeup_icon();
|
|
return;
|
|
}
|
|
|
|
if ( brief_setup_closeup(bi) == 0 ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEF_ICON_SELECT);
|
|
} else {
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
}
|
|
}
|
|
|
|
// maybe flash a button if player hasn't done anything for a while
|
|
void brief_maybe_flash_button()
|
|
{
|
|
UI_BUTTON *b;
|
|
|
|
if ( Num_brief_stages <= 0 )
|
|
return;
|
|
|
|
if ( Closeup_icon != NULL ) {
|
|
common_flash_button_init();
|
|
return;
|
|
}
|
|
|
|
if ( common_flash_bright() ) {
|
|
if ( Current_brief_stage == (Num_brief_stages-1) ) {
|
|
// AL 30-3-98: Don't flash ship selection button if in a training mission,
|
|
if ( brief_only_allow_briefing() ) {
|
|
return;
|
|
}
|
|
|
|
b = &Common_buttons[Current_screen-1][gr_screen.res][1].button; // ship select button
|
|
} else {
|
|
b = &Brief_buttons[gr_screen.res][1].button; // next stage button
|
|
}
|
|
|
|
if ( b->button_hilighted() ) {
|
|
common_flash_button_init();
|
|
} else {
|
|
b->draw_forced(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------------------
|
|
// brief_do_frame()
|
|
//
|
|
// frametime is in seconds
|
|
//
|
|
void brief_do_frame(float frametime)
|
|
{
|
|
int k, brief_choice;
|
|
|
|
if ( red_alert_mission() ) {
|
|
return;
|
|
}
|
|
|
|
if ( !Brief_inited ){
|
|
brief_init();
|
|
}
|
|
|
|
// commit if skipping briefing, but not in multi - Goober5000
|
|
if (!(Game_mode & GM_MULTIPLAYER))
|
|
{
|
|
if (The_mission.flags[Mission::Mission_Flags::No_briefing])
|
|
{
|
|
commit_pressed();
|
|
return;
|
|
}
|
|
}
|
|
|
|
int snazzy_action = -1;
|
|
brief_choice = snazzy_menu_do(Brief_ui_mask_data, Brief_ui_mask_w, Brief_ui_mask_h, Num_briefing_regions, Briefing_select_region, &snazzy_action, 0);
|
|
|
|
k = common_select_do(frametime);
|
|
|
|
if ( Closeup_icon ) {
|
|
Brief_mouse_up_flag = 0;
|
|
}
|
|
|
|
if ( help_overlay_active(Briefing_overlay_id) ) {
|
|
common_flash_button_init();
|
|
brief_turn_off_closeup_icon();
|
|
}
|
|
|
|
// Check common keypresses
|
|
common_check_keys(k);
|
|
|
|
#ifndef NDEBUG
|
|
int cam_change = 0;
|
|
#endif
|
|
|
|
if ( Briefing->num_stages > 0 ) {
|
|
|
|
// check for special keys
|
|
switch(k) {
|
|
|
|
#ifndef NDEBUG
|
|
case KEY_CTRLED | KEY_PAGEUP: {
|
|
if ( Closeup_icon && Closeup_icon->ship_class ) {
|
|
Closeup_icon->ship_class--;
|
|
|
|
ship_info *sip = &Ship_info[Closeup_icon->ship_class];
|
|
if (sip->model_num < 0)
|
|
sip->model_num = model_load(sip->pof_file, 0, NULL);
|
|
|
|
mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
|
|
mprintf(("Modelnum = %d (%s)\n", sip->model_num, sip->pof_file));
|
|
brief_setup_closeup(Closeup_icon);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case KEY_CTRLED | KEY_PAGEDOWN: {
|
|
if ( Closeup_icon && (Closeup_icon->ship_class < ship_info_size() - 1) ) {
|
|
Closeup_icon->ship_class++;
|
|
|
|
ship_info *sip = &Ship_info[Closeup_icon->ship_class];
|
|
if (sip->model_num < 0)
|
|
sip->model_num = model_load(sip->pof_file, 0, NULL);
|
|
|
|
mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
|
|
mprintf(("Modelnum = %d (%s)\n", sip->model_num, sip->pof_file));
|
|
brief_setup_closeup(Closeup_icon);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case KEY_A:
|
|
Closeup_cam_pos.xyz.z += 1;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_A + KEY_SHIFTED:
|
|
Closeup_cam_pos.xyz.z += 10;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_Z:
|
|
Closeup_cam_pos.xyz.z -= 1;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_Z + KEY_SHIFTED:
|
|
Closeup_cam_pos.xyz.z -= 10;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_Y:
|
|
Closeup_cam_pos.xyz.y += 1;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_Y + KEY_SHIFTED:
|
|
Closeup_cam_pos.xyz.y += 10;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_H:
|
|
Closeup_cam_pos.xyz.y -= 1;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_H + KEY_SHIFTED:
|
|
Closeup_cam_pos.xyz.y -= 10;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_COMMA:
|
|
Closeup_zoom -= 0.1f;
|
|
if ( Closeup_zoom < 0.1 )
|
|
Closeup_zoom = 0.1f;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_COMMA+KEY_SHIFTED:
|
|
Closeup_zoom -= 0.5f;
|
|
if ( Closeup_zoom < 0.1 )
|
|
Closeup_zoom = 0.1f;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_PERIOD:
|
|
Closeup_zoom += 0.1f;
|
|
cam_change = 1;
|
|
break;
|
|
|
|
case KEY_PERIOD+KEY_SHIFTED:
|
|
Closeup_zoom += 0.5f;
|
|
cam_change = 1;
|
|
break;
|
|
#endif
|
|
case 1000: // need this to avoid warning about no case
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
} // end switch
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
if ( cam_change ) {
|
|
nprintf(("General","Camera pos: %.2f, %.2f %.2f // ", Closeup_cam_pos.xyz.x, Closeup_cam_pos.xyz.y, Closeup_cam_pos.xyz.z));
|
|
nprintf(("General","Camera zoom: %.2f\n", Closeup_zoom));
|
|
}
|
|
#endif
|
|
|
|
if ( brief_choice > -1 && snazzy_action == SNAZZY_OVER ) {
|
|
Brief_mouse_up_flag = 0;
|
|
brief_choice = -1;
|
|
}
|
|
|
|
|
|
common_check_buttons();
|
|
// if ( Briefing->num_stages > 0 )
|
|
brief_check_buttons();
|
|
|
|
if ( brief_choice != -1 ) {
|
|
Brief_mouse_up_flag = 0;
|
|
}
|
|
|
|
gr_reset_clip();
|
|
|
|
common_render(frametime);
|
|
|
|
if ( Current_brief_stage < (Num_brief_stages-1) ) {
|
|
if ( !help_overlay_active(Briefing_overlay_id) && brief_time_to_advance(Current_brief_stage) ) {
|
|
brief_do_next_pressed(0);
|
|
common_flash_button_init();
|
|
Brief_last_auto_advance = timer_get_milliseconds();
|
|
}
|
|
}
|
|
|
|
if ( !Background_playing ) {
|
|
int time = -1;
|
|
int check_jump_flag = 1;
|
|
|
|
if ( Current_brief_stage != Last_brief_stage ) {
|
|
|
|
// Check if we have a quick transition pending
|
|
if ( Quick_transition_stage != -1 ) {
|
|
Quick_transition_stage = -1;
|
|
brief_reset_last_new_stage();
|
|
time = 0;
|
|
check_jump_flag = 0;
|
|
}
|
|
|
|
if ( check_jump_flag ) {
|
|
if ( abs(Current_brief_stage - Last_brief_stage) > 1 ) {
|
|
Quick_transition_stage = Current_brief_stage;
|
|
Current_brief_stage = Last_brief_stage;
|
|
Assert(Current_brief_stage >= 0);
|
|
Start_fade_up_anim = 1;
|
|
goto Transition_done;
|
|
}
|
|
}
|
|
|
|
if ( time != 0 ) {
|
|
if ( Current_brief_stage > Last_brief_stage ) {
|
|
if ( Briefing->stages[Last_brief_stage].flags & BS_FORWARD_CUT ) {
|
|
Quick_transition_stage = Current_brief_stage;
|
|
Current_brief_stage = Last_brief_stage;
|
|
Assert(Current_brief_stage >= 0);
|
|
Start_fade_up_anim = 1;
|
|
goto Transition_done;
|
|
} else {
|
|
time = Briefing->stages[Current_brief_stage].camera_time;
|
|
}
|
|
}
|
|
else {
|
|
if ( Briefing->stages[Last_brief_stage].flags & BS_BACKWARD_CUT ) {
|
|
Quick_transition_stage = Current_brief_stage;
|
|
Current_brief_stage = Last_brief_stage;
|
|
Assert(Current_brief_stage >= 0);
|
|
Start_fade_up_anim = 1;
|
|
goto Transition_done;
|
|
} else {
|
|
time = Briefing->stages[Last_brief_stage].camera_time;
|
|
}
|
|
}
|
|
}
|
|
|
|
brief_voice_stop(Last_brief_stage);
|
|
fsspeech_stop();
|
|
|
|
if ( Current_brief_stage < 0 ) {
|
|
Int3();
|
|
Current_brief_stage=0;
|
|
}
|
|
|
|
// fire the script hook
|
|
common_fire_stage_script_hook(Last_brief_stage, Current_brief_stage);
|
|
|
|
// set the camera target
|
|
brief_set_new_stage(&Briefing->stages[Current_brief_stage].camera_pos,
|
|
&Briefing->stages[Current_brief_stage].camera_orient,
|
|
time, Current_brief_stage);
|
|
|
|
Brief_playing_fade_sound = 0;
|
|
Last_brief_stage = Current_brief_stage;
|
|
brief_reset_icons(Current_brief_stage);
|
|
brief_update_closeup_icon(0);
|
|
}
|
|
|
|
Transition_done:
|
|
|
|
if ( Brief_mouse_up_flag && !Closeup_icon) {
|
|
brief_check_for_anim();
|
|
}
|
|
|
|
brief_render(frametime);
|
|
brief_camera_move(frametime, Current_brief_stage);
|
|
|
|
if (Closeup_icon && (Closeup_bitmap >= 0)) {
|
|
// blit closeup background
|
|
gr_set_bitmap(Closeup_bitmap);
|
|
gr_bitmap(Closeup_coords[gr_screen.res][BRIEF_X_COORD], Closeup_coords[gr_screen.res][BRIEF_Y_COORD], GR_RESIZE_MENU);
|
|
}
|
|
|
|
Brief_ui_window.draw();
|
|
brief_redraw_pressed_buttons();
|
|
common_render_selected_screen_button();
|
|
|
|
if (Closeup_icon) {
|
|
brief_render_closeup(Closeup_icon->ship_class, frametime);
|
|
}
|
|
|
|
// render some extra stuff in multiplayer
|
|
if (Game_mode & GM_MULTIPLAYER) {
|
|
// should render this last so that it overlaps all controls
|
|
chatbox_render();
|
|
|
|
// render the status indicator for the voice system
|
|
multi_common_voice_display_status();
|
|
|
|
// maybe blit the multiplayer "locked" button
|
|
// if its locked, everyone blits it as such
|
|
if(multi_ts_is_locked()){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(2);
|
|
}
|
|
// anyone who can't hit the button sees it off, otherwise
|
|
else {
|
|
if( ((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)) ||
|
|
((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_GAME_HOST)) ){
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(0);
|
|
} else {
|
|
Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// maybe flash a button if player hasn't done anything for a while
|
|
brief_maybe_flash_button();
|
|
|
|
// blit help overlay if active
|
|
help_overlay_maybe_blit(Briefing_overlay_id, gr_screen.res);
|
|
|
|
gr_flip();
|
|
|
|
// If the commit button was pressed, do the commit button actions. Done at the end of the
|
|
// loop so there isn't a skip in the animation (since ship_create() can take a long time if
|
|
// the ship model is not in memory
|
|
if (Commit_pressed) {
|
|
if (Game_mode & GM_MULTIPLAYER) {
|
|
multi_ts_commit_pressed();
|
|
} else {
|
|
commit_pressed();
|
|
}
|
|
|
|
Commit_pressed = 0;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// brief_unload_bitmaps()
|
|
//
|
|
//
|
|
void brief_unload_bitmaps()
|
|
{
|
|
if ( Brief_text_bitmap != -1 ) {
|
|
bm_release(Brief_text_bitmap);
|
|
Brief_text_bitmap = -1;
|
|
}
|
|
|
|
if(Brief_grid_bitmap != -1){
|
|
bm_release(Brief_grid_bitmap);
|
|
Brief_grid_bitmap = -1;
|
|
}
|
|
|
|
if ( Brief_multitext_bitmap != -1 ) {
|
|
bm_release(Brief_multitext_bitmap);
|
|
Brief_multitext_bitmap = -1;
|
|
}
|
|
|
|
if ( Brief_background_bitmap != -1 ) {
|
|
bm_release(Brief_background_bitmap);
|
|
Brief_background_bitmap = -1;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// brief_close()
|
|
//
|
|
//
|
|
void brief_close()
|
|
{
|
|
if ( Brief_inited == FALSE ) {
|
|
nprintf(("Warning","brief_close() returning without doing anything\n"));
|
|
return;
|
|
}
|
|
|
|
nprintf(("Alan", "Entering brief_close()\n"));
|
|
|
|
ML_objectives_close();
|
|
fsspeech_stop();
|
|
|
|
// unload the audio streams used for voice playback
|
|
brief_voice_unload_all();
|
|
|
|
if (Fade_anim.first_frame != -1) {
|
|
bm_unload(Fade_anim.first_frame);
|
|
}
|
|
|
|
Brief_ui_window.destroy();
|
|
|
|
// unload the bitmaps
|
|
brief_unload_bitmaps();
|
|
|
|
brief_common_close();
|
|
|
|
Briefing_paused = 0;
|
|
|
|
Brief_inited = FALSE;
|
|
}
|
|
|
|
void briefing_stop_music(bool fade)
|
|
{
|
|
if ( Briefing_music_handle != -1 ) {
|
|
audiostream_close_file(Briefing_music_handle, fade);
|
|
Briefing_music_handle = -1;
|
|
}
|
|
}
|
|
|
|
void briefing_load_music(const char* fname)
|
|
{
|
|
if ( Cmdline_freespace_no_music ) {
|
|
return;
|
|
}
|
|
|
|
if ( Briefing_music_handle != -1 )
|
|
return;
|
|
|
|
if ( fname )
|
|
Briefing_music_handle = audiostream_open( fname, ASF_MENUMUSIC );
|
|
}
|
|
|
|
void briefing_start_music()
|
|
{
|
|
if ( Briefing_music_handle != -1 ) {
|
|
if ( !audiostream_is_playing(Briefing_music_handle) )
|
|
audiostream_play(Briefing_music_handle, Master_event_music_volume, 1);
|
|
}
|
|
else {
|
|
nprintf(("Warning", "No music file exists to play music at this briefing!\n"));
|
|
}
|
|
}
|
|
|
|
void brief_stop_voices()
|
|
{
|
|
brief_voice_stop(Current_brief_stage);
|
|
}
|
|
|
|
void brief_pause()
|
|
{
|
|
if (Briefing_paused)
|
|
return;
|
|
|
|
Briefing_paused = 1;
|
|
|
|
if (Briefing_music_handle >= 0) {
|
|
audiostream_pause(Briefing_music_handle);
|
|
}
|
|
|
|
brief_voice_pause(Current_brief_stage);
|
|
}
|
|
|
|
void brief_unpause()
|
|
{
|
|
if (!Briefing_paused)
|
|
return;
|
|
|
|
Briefing_paused = 0;
|
|
|
|
if (Briefing_music_handle >= 0) {
|
|
audiostream_unpause(Briefing_music_handle);
|
|
}
|
|
|
|
brief_voice_unpause(Current_brief_stage);
|
|
}
|
|
|
|
void brief_maybe_blit_scene_cut(float frametime)
|
|
{
|
|
if ( Start_fade_up_anim ) {
|
|
int framenum;
|
|
|
|
Fade_anim.time_elapsed += frametime;
|
|
|
|
if ( !Brief_playing_fade_sound ) {
|
|
gamesnd_play_iface(InterfaceSounds::BRIEFING_STATIC);
|
|
Brief_playing_fade_sound = 1;
|
|
}
|
|
|
|
if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
|
|
Fade_anim.time_elapsed = 0.0f;
|
|
Start_fade_up_anim = 0;
|
|
Start_fade_down_anim = 1;
|
|
Current_brief_stage = Quick_transition_stage;
|
|
|
|
if ( Current_brief_stage < 0 ) {
|
|
brief_transition_reset();
|
|
Current_brief_stage = Last_brief_stage;
|
|
}
|
|
|
|
Assert(Current_brief_stage >= 0);
|
|
goto Fade_down_anim_start;
|
|
}
|
|
|
|
// draw the correct frame of animation
|
|
framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
|
|
if ( framenum < 0 )
|
|
framenum = 0;
|
|
if ( framenum >= Fade_anim.num_frames )
|
|
framenum = Fade_anim.num_frames-1;
|
|
|
|
// Blit the bitmap for this frame
|
|
gr_set_bitmap(Fade_anim.first_frame + framenum);
|
|
gr_bitmap(Fade_anim.sx, Fade_anim.sy, GR_RESIZE_MENU);
|
|
}
|
|
|
|
|
|
Fade_down_anim_start:
|
|
if ( Start_fade_down_anim ) {
|
|
int framenum;
|
|
|
|
Fade_anim.time_elapsed += frametime;
|
|
|
|
if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
|
|
Fade_anim.time_elapsed = 0.0f;
|
|
Start_fade_up_anim = 0;
|
|
Start_fade_down_anim = 0;
|
|
return;
|
|
}
|
|
|
|
// draw the correct frame of animation
|
|
framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
|
|
if ( framenum < 0 )
|
|
framenum = 0;
|
|
if ( framenum >= Fade_anim.num_frames )
|
|
framenum = Fade_anim.num_frames-1;
|
|
|
|
// Blit the bitmap for this frame
|
|
gr_set_bitmap(Fade_anim.first_frame + (Fade_anim.num_frames-1) - framenum);
|
|
gr_bitmap(Fade_anim.sx, Fade_anim.sy, GR_RESIZE_MENU);
|
|
}
|
|
}
|
|
|
|
void brief_transition_reset()
|
|
{
|
|
Quick_transition_stage = -1;
|
|
Start_fade_up_anim = 0;
|
|
Start_fade_down_anim = 0;
|
|
Fade_anim.time_elapsed = 0.0f;
|
|
}
|
|
|
|
// return 1 if this mission only allow players to use the briefing (and not ship or
|
|
// weapon loadout). Otherwise return 0.
|
|
int brief_only_allow_briefing()
|
|
{
|
|
if ( The_mission.game_type & MISSION_TYPE_TRAINING ) {
|
|
return 1;
|
|
}
|
|
|
|
if ( The_mission.flags[Mission::Mission_Flags::Scramble, Mission::Mission_Flags::Red_alert] ) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|