2 * $Logfile: /Freespace2/code/MissionUI/MissionBrief.cpp $
7 * C module that contains code to display the mission briefing to the player
10 * Revision 1.2 2002/05/07 03:16:46 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:10 root
17 * 48 10/14/99 2:51p Jefff
20 * 47 10/13/99 3:23p Jefff
21 * fixed unnumbered XSTRs
23 * 46 9/12/99 8:09p Dave
24 * Fixed problem where skip-training button would cause mission messages
25 * not to get paged out for the current mission.
27 * 45 9/09/99 3:40p Jefff
28 * no exit loop outisde of campaign mode
30 * 44 9/07/99 6:53p Jefff
31 * functionality to break out of a loop
33 * 43 9/06/99 6:38p Dave
34 * Improved CD detection code.
36 * 42 9/03/99 10:57a Jefff
39 * 41 8/30/99 5:30p Jefff
40 * fixed "more" being cut off in d3d
42 * 40 8/30/99 10:29a Jefff
43 * added autocenter flag to closup rendering
45 * 39 8/19/99 11:33a Dave
48 * 38 8/19/99 10:59a Dave
49 * Packet loss detection.
51 * 37 8/16/99 4:05p Dave
52 * Big honking checkin.
54 * 36 8/16/99 9:48a Jefff
55 * all clicks on briefing icons should now register
57 * 35 8/10/99 7:29p Jefff
58 * added mission title to briefing screen
60 * 34 8/03/99 1:34a Andsager
61 * fix skip training mission (again)
63 * 33 8/02/99 12:01p Jefff
64 * fixed "skip training" text pos
66 * 32 7/30/99 5:42p Jasenw
67 * Fixed coords for skip training button.
69 * 31 7/29/99 10:50p Dave
70 * Oops. Accidentally blew away some interface text changes.
72 * 30 7/29/99 10:48p Dave
74 * 29 7/29/99 3:05p Andsager
75 * Add skip training text. and properly skip.
77 * 28 7/24/99 6:07p Jefff
78 * Added "lock" text to multiplayer lock button
80 * 27 7/21/99 10:51a Jefff
81 * added "more" indicator to briefing text box
83 * 26 7/19/99 3:01p Dave
84 * Fixed icons. Added single transport icon.
86 * 25 7/18/99 5:20p Dave
87 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
89 * 24 7/16/99 1:49p Dave
90 * 8 bit aabitmaps. yay.
92 * 23 7/15/99 9:20a Andsager
93 * FS2_DEMO initial checkin
95 * 22 7/09/99 5:54p Dave
96 * Seperated cruiser types into individual types. Added tons of new
97 * briefing icons. Campaign screen.
99 * 21 6/29/99 7:39p Dave
100 * Lots of small bug fixes.
102 * 20 6/11/99 11:13a Dave
103 * last minute changes before press tour build.
105 * 19 6/04/99 1:18p Dave
106 * Fixed briefing model rendering problems. Made show background option in
107 * fred toggle nebula rendering.
109 * 18 5/07/99 10:34a Andsager
110 * Make red alert work in FS2
112 * 17 4/23/99 12:01p Johnson
113 * Added SIF_HUGE_SHIP
115 * 16 3/25/99 2:45p Neilk
118 * 15 2/11/99 3:08p Dave
119 * PXO refresh button. Very preliminary squad war support.
121 * 14 2/05/99 7:19p Neilk
122 * Removed black part from mission screen, fixed info text coords
124 * 13 2/02/99 4:35p Neilk
125 * fixed coordinate problem where primary goals was on top of interface in
128 * 12 2/01/99 5:55p Dave
129 * Removed the idea of explicit bitmaps for buttons. Fixed text
130 * highlighting for disabled gadgets.
132 * 11 1/30/99 7:32p Neilk
133 * Fixed coords problems for mission briefing screens
135 * 10 1/30/99 5:08p Dave
136 * More new hi-res stuff.Support for nice D3D textures.
138 * 9 1/30/99 1:29a Dave
139 * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
140 * screen. Fixed beam weapon death messages.
142 * 8 1/29/99 4:17p Dave
143 * New interface screens.
145 * 7 1/13/99 7:19p Neilk
146 * Converted Mission Brief, Barracks, Synch to high res support
148 * 6 12/18/98 1:13a Dave
149 * Rough 1024x768 support for Direct3D. Proper detection and usage through
152 * 5 11/30/98 1:07p Dave
153 * 16 bit conversion, first run.
155 * 4 11/20/98 4:08p Dave
156 * Fixed flak effect in multiplayer.
158 * 3 10/13/98 9:28a Dave
159 * Started neatening up freespace.h. Many variables renamed and
160 * reorganized. Added AlphaColors.[h,cpp]
162 * 2 10/07/98 10:53a Dave
165 * 1 10/07/98 10:49a Dave
167 * 114 9/17/98 3:08p Dave
168 * PXO to non-pxo game warning popup. Player icon stuff in create and join
169 * game screens. Upped server count refresh time in PXO to 35 secs (from
172 * 113 6/19/98 3:52p Lawrance
173 * Don't use large text in popup, since it is missing large foreign chars
175 * 112 6/09/98 5:17p Lawrance
176 * French/German localization
178 * 111 6/09/98 10:31a Hoffoss
179 * Created index numbers for all xstr() references. Any new xstr() stuff
180 * added from here on out should be added to the end if the list. The
181 * current list count can be found in FreeSpace.cpp (search for
184 * 110 6/01/98 11:43a John
185 * JAS & MK: Classified all strings for localization.
187 * 109 5/22/98 10:44a Lawrance
188 * put in case label to suppress warning
190 * 108 5/19/98 11:35p Lawrance
191 * Play sound for briefing control button presses
193 * 107 5/19/98 8:47p Lawrance
194 * Set proper distance for jump nodes
196 * 106 5/19/98 8:35p Dave
197 * Revamp PXO channel listing system. Send campaign goals/events to
198 * clients for evaluation. Made lock button pressable on all screens.
200 * 105 5/12/98 2:16p Hoffoss
201 * Added debug code to switch models of closeup icon to more easily check
202 * positions and zooms.
204 * 104 5/06/98 11:50p Lawrance
205 * Clean up help overlay code for loadout screens
207 * 103 5/06/98 8:03p Allender
208 * AL: only free pointers in brief_compact_stages if non-null
210 * 102 5/05/98 4:48p Lawrance
211 * Fix bug with launching closeup icon when pause button is pressed
213 * 101 4/29/98 1:45p Lawrance
214 * Print out mission filename if debug build, or if INTERPLAY QA defined
216 * 100 4/29/98 12:15a Lawrance
217 * reset demo trailer timer when briefing moves to a new stage
219 * 98 4/25/98 11:55p Lawrance
220 * fix bug with the auto-advance button
222 * 97 4/25/98 3:49p Lawrance
223 * Save briefing auto-advance pref
225 * 96 4/25/98 12:00p Lawrance
226 * disable advance keypress for 1/2 second after autoadvance
228 * 95 4/22/98 7:24p Dave
229 * Made sure the "player/ships" locked button for multiplayer appears on
230 * all briefing screens.
232 * 94 4/20/98 3:53p Lawrance
233 * Fix various bugs with auto-advancing through briefings.
235 * 93 4/19/98 12:11p Lawrance
236 * add new art for pause button in the briefing
238 * 92 4/17/98 10:39p Andsager
239 * AL: Fix bug with auto-advance of briefing stages.
241 * 91 4/16/98 8:05p Lawrance
242 * Don't show closeup icon for planets
244 * 90 4/15/98 5:17p Lawrance
245 * fix bug with skip training
251 #include "freespace.h"
252 #include "missionload.h"
253 #include "missionscreencommon.h"
254 #include "missionshipchoice.h"
255 #include "missionparse.h"
256 #include "missiongoals.h"
257 #include "gamesequence.h"
266 #include "linklist.h"
271 #include "audiostr.h"
273 #include "eventmusic.h"
274 #include "missioncampaign.h"
277 #include "snazzyui.h"
279 #include "missionbrief.h"
280 #include "missionbriefcommon.h"
281 #include "missiongrid.h"
283 #include "multimsgs.h"
285 #include "contexthelp.h"
287 #include "multiteamselect.h"
289 #include "asteroid.h"
292 #include "alphacolors.h"
294 #include "missionmessage.h"
297 #define OBJECTIVES_X 65
298 #define OBJECTIVES_Y 137
299 #define OBJECTIVES_W 508
300 #define OBJECTIVES_H 233
303 static int Brief_goals_coords[GR_NUM_RESOLUTIONS][4] = {
305 65,152,508,211 // GR_640
308 104,243,813,332 // GR_1024
312 static int Current_brief_stage; // what stage of the briefing we're on
313 static int Last_brief_stage;
314 static int Num_brief_stages;
315 static int Brief_multiplayer = FALSE;
317 static int Brief_last_auto_advance = 0; // timestamp of last auto-advance
319 // for managing the scene cut transition
320 static int Quick_transition_stage;
321 static int Start_fade_up_anim, Start_fade_down_anim;
322 static int Brief_playing_fade_sound;
325 int Briefing_music_handle = -1;
326 int Briefing_music_begin_timestamp = 0;
328 // --------------------------------------------------------------------------------------
329 // Module scope globals
330 // --------------------------------------------------------------------------------------
332 static MENU_REGION Briefing_select_region[NUM_BREIFING_REGIONS];
333 static int Num_briefing_regions;
335 // For closeup display
336 #define ONE_REV_TIME 6 // time (sec) for one revolution
337 #define MAX_ANG_CHG 0.15f
339 static int Closeup_coords[GR_NUM_RESOLUTIONS][4] = {
341 203, 151, 200, 213 // GR_640
344 325, 241, 200, 213 // GR_1024
348 static int Closeup_img_h[GR_NUM_RESOLUTIONS] = {
357 static int Closeup_text_h[GR_NUM_RESOLUTIONS][4] = {
366 static int Brief_infobox_coords[GR_NUM_RESOLUTIONS][2] = {
375 static char *Brief_infobox_filename[GR_NUM_RESOLUTIONS] = {
380 static char *Brief_filename[GR_NUM_RESOLUTIONS] = {
385 static char *Brief_multi_filename[GR_NUM_RESOLUTIONS] = {
390 static char *Brief_mask_filename[GR_NUM_RESOLUTIONS] = {
395 static char *Brief_multi_mask_filename[GR_NUM_RESOLUTIONS] = {
401 static char *Brief_win_filename[GR_NUM_RESOLUTIONS] = {
406 // coordinate inidices
407 #define BRIEF_X_COORD 0
408 #define BRIEF_Y_COORD 1
409 #define BRIEF_W_COORD 2
410 #define BRIEF_H_COORD 3
412 //static int Closeup_region[4] = {220,132,420,269};
413 int Closeup_region[GR_NUM_RESOLUTIONS][4] = {
422 char *Closeup_background_filename[GR_NUM_RESOLUTIONS] = {
423 NOX("BriefPop"), // GR_640
424 NOX("2_BriefPop") // GR_1024
427 char *Closeup_button_filename[GR_NUM_RESOLUTIONS] = {
428 NOX("BPB_00"), // GR_640
429 NOX("2_BPB_00"), // GR_1024
432 int Closeup_button_hotspot = 14;
434 //static int Closeup_button_coords[2] = {CLOSEUP_X+164,CLOSEUP_Y+227};
435 int Closeup_button_coords[GR_NUM_RESOLUTIONS][2] = {
436 { 374, 316 }, // GR_640
437 { 599, 506 } // GR_1024
440 UI_BUTTON Closeup_close_button;
441 int Closeup_bitmap=-1;
442 int Closeup_one_revolution_time=ONE_REV_TIME;
444 brief_icon *Closeup_icon;
445 angles Closeup_angles;
446 matrix Closeup_orient;
448 int Closeup_font_height;
449 int Closeup_x1, Closeup_y1;
451 // used for the 3d view of a closeup ship
453 vector Closeup_cam_pos;
455 // Mask bitmap pointer and Mask bitmap_id
456 bitmap* BriefingMaskPtr; // bitmap pointer to the briefing select mask bitmap
457 ubyte* BriefingMaskData; // pointer to actual bitmap data
458 int Briefing_mask_w, Briefing_mask_h;
459 int BriefingMaskBitmap; // bitmap id of the briefing mask bitmap
460 int Brief_inited = FALSE;
462 // --------------------------------------------------------------------------------------
463 // Briefing specific UI
464 // --------------------------------------------------------------------------------------
465 #define BRIEF_LAST_STAGE_MASK 7
466 #define BRIEF_NEXT_STAGE_MASK 8
467 #define BRIEF_PREV_STAGE_MASK 9
468 #define BRIEF_FIRST_STAGE_MASK 10
469 #define BRIEF_TEXT_SCROLL_UP_MASK 11
470 #define BRIEF_TEXT_SCROLL_DOWN_MASK 12
471 #define BRIEF_SKIP_TRAINING_MASK 15
472 #define BRIEF_PAUSE_MASK 16
475 static char *Brief_mask_single[GR_NUM_RESOLUTIONS] = {
477 "2_brief-m" // GR_1024
480 static char *Brief_mask_multi[GR_NUM_RESOLUTIONS] = {
481 "briefmulti-m", // GR_640
482 "2_briefmulti-m" // GR_1024
486 struct brief_buttons {
492 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
494 brief_buttons(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) {}
497 int Brief_grid_bitmap = -1;
498 int Brief_text_bitmap = -1;
500 int Brief_multitext_bitmap = -1;
501 int Brief_background_bitmap =-1;
503 UI_WINDOW Brief_ui_window;
505 // Briefing specific buttons
506 #define NUM_BRIEF_BUTTONS 10
508 brief_buttons Brief_buttons[GR_NUM_RESOLUTIONS][NUM_BRIEF_BUTTONS] = {
510 brief_buttons("BRB_08", 110, 116, 117, 157, 8),
511 brief_buttons("BRB_09", 84, 116, 117, 157, 9),
512 brief_buttons("BRB_10", 29, 116, 117, 157, 10),
513 brief_buttons("BRB_11", 4, 116, 117, 157, 11),
514 brief_buttons("BRB_12", 0, 405, 117, 157, 12),
515 brief_buttons("BRB_13", 0, 447, 117, 157, 13),
516 brief_buttons("BRB_15", 562, 0, 117, 157, 15), // skip training
517 brief_buttons("BRB_16", 56, 116, 117, 157, 16),
518 brief_buttons("TSB_34", 603, 374, 117, 157, 34),
519 brief_buttons("BRB_15", 562, 0, 117, 157, 15) // exit loop
522 brief_buttons("2_BRB_08", 175, 187, 117, 157, 8),
523 brief_buttons("2_BRB_09", 135, 187, 117, 157, 9),
524 brief_buttons("2_BRB_10", 47, 187, 117, 157, 10),
525 brief_buttons("2_BRB_11", 8, 187, 117, 157, 11),
526 brief_buttons("2_BRB_12", 0, 649, 117, 157, 12),
527 brief_buttons("2_BRB_13", 0, 716, 117, 157, 13),
528 brief_buttons("2_BRB_15", 900, 0, 117, 157, 15), // skip training
529 brief_buttons("2_BRB_16", 91, 187, 117, 157, 16),
530 brief_buttons("2_TSB_34", 966, 599, 117, 157, 34),
531 brief_buttons("2_BRB_15", 900, 0, 117, 157, 15) // exit loop
536 #define BRIEF_SELECT_NUM_TEXT 3
537 UI_XSTR Brief_select_text[GR_NUM_RESOLUTIONS][BRIEF_SELECT_NUM_TEXT] = {
539 { "Lock", 1270, 602, 364, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_MULTI_LOCK].button },
540 { "Skip Training", 1442, 467, 7, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_SKIP_TRAINING].button },
541 { "Exit Loop", 1477, 490, 7, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_EXIT_LOOP].button }
544 { "Lock", 1270, 964, 584, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_MULTI_LOCK].button },
545 { "Skip Training", 1442, 805, 12, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_SKIP_TRAINING].button },
546 { "Exit Loop", 1477, 830, 12, UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_EXIT_LOOP].button }
550 // coordinates for briefing title -- the x value is for the RIGHT side of the text
551 static int Title_coords[GR_NUM_RESOLUTIONS][2] = {
552 {575, 117}, // GR_640
553 {918, 194} // GR_1024
556 // coordinates for briefing title in multiplayer briefings -- the x value is for the LEFT side of the text
557 // third coord is max width of area for it to fit into (it is force fit there)
558 static int Title_coords_multi[GR_NUM_RESOLUTIONS][3] = {
559 {1, 105, 190}, // GR_640
560 {1, 174, 304} // GR_1024
563 // briefing line widths
564 int Brief_max_line_width[GR_NUM_RESOLUTIONS] = {
565 MAX_BRIEF_LINE_W_640, MAX_BRIEF_LINE_W_1024
568 // --------------------------------------------------------------------------------------
569 // Forward declarations
570 // --------------------------------------------------------------------------------------
571 int brief_setup_closeup(brief_icon *bi);
572 void brief_maybe_blit_scene_cut(float frametime);
573 void brief_transition_reset();
575 char *brief_tooltip_handler(char *str)
577 if (!stricmp(str, NOX("@close"))) {
579 return XSTR( "Close", 428);
585 // brief_skip_training_pressed()
587 // called when the skip training button on the briefing screen is hit. When this happens,
588 // do a popup, then move to the next mission in the campaign.
589 void brief_skip_training_pressed()
593 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));
595 // val is 0 when we hit no (first on the list)
596 // AL: also, -1 is returned when ESC is hit
601 // page out mission messages
602 message_mission_shutdown();
604 if ( !(Game_mode & GM_CAMPAIGN_MODE) ){
605 gameseq_post_event( GS_EVENT_MAIN_MENU );
608 // tricky part. Need to move to the next mission in the campaign.
609 mission_goal_mark_objectives_complete();
610 mission_goal_fail_incomplete();
611 mission_campaign_store_goals_and_events();
613 mission_campaign_eval_next_mission();
614 mission_campaign_mission_over();
617 if(game_do_cd_mission_check(Game_current_mission_filename)){
618 gameseq_post_event( GS_EVENT_START_GAME );
620 gameseq_post_event( GS_EVENT_MAIN_MENU );
625 extern void demo_reset_trailer_timer();
627 // --------------------------------------------------------------------------------------
628 // brief_do_next_pressed()
631 void brief_do_next_pressed(int play_sound)
634 now = timer_get_milliseconds();
636 if ( (now - Brief_last_auto_advance) < 500 ) {
641 demo_reset_trailer_timer();
644 Current_brief_stage++;
645 if ( Current_brief_stage >= Num_brief_stages ) {
646 Current_brief_stage = Num_brief_stages - 1;
647 gamesnd_play_iface(SND_GENERAL_FAIL);
648 if ( Quick_transition_stage != -1 )
649 brief_transition_reset();
652 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
656 Assert(Current_brief_stage >= 0);
659 // --------------------------------------------------------------------------------------
660 // brief_do_prev_pressed()
663 void brief_do_prev_pressed()
665 Current_brief_stage--;
666 if ( Current_brief_stage < 0 ) {
667 Current_brief_stage = 0;
668 gamesnd_play_iface(SND_GENERAL_FAIL);
669 if ( Quick_transition_stage != -1 )
670 brief_transition_reset();
672 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
674 Assert(Current_brief_stage >= 0);
678 // --------------------------------------------------------------------------------------
679 // brief_do_start_pressed()
682 void brief_do_start_pressed()
684 if ( Current_brief_stage != 0 ) {
685 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
686 Current_brief_stage = 0;
687 if ( Quick_transition_stage != -1 )
688 brief_transition_reset();
690 gamesnd_play_iface(SND_GENERAL_FAIL);
692 Assert(Current_brief_stage >= 0);
695 // --------------------------------------------------------------------------------------
696 // brief_do_end_pressed()
699 void brief_do_end_pressed()
701 if ( Current_brief_stage != Num_brief_stages - 1 ) {
702 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
703 Current_brief_stage = Num_brief_stages - 1;
704 if ( Quick_transition_stage != -1 )
705 brief_transition_reset();
708 gamesnd_play_iface(SND_GENERAL_FAIL);
710 Assert(Current_brief_stage >= 0);
714 void brief_scroll_up_text()
716 Top_brief_text_line--;
717 if ( Top_brief_text_line < 0 ) {
718 Top_brief_text_line = 0;
719 gamesnd_play_iface(SND_GENERAL_FAIL);
721 gamesnd_play_iface(SND_SCROLL);
725 void brief_scroll_down_text()
727 Top_brief_text_line++;
728 if ( (Num_brief_text_lines[0] - Top_brief_text_line) < Brief_text_max_lines[gr_screen.res]) {
729 Top_brief_text_line--;
730 gamesnd_play_iface(SND_GENERAL_FAIL);
732 gamesnd_play_iface(SND_SCROLL);
737 // handles the exit loop option
738 void brief_exit_loop_pressed()
740 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));
742 // bail if esc hit or no clicked
747 // handle the details
748 // this also posts the start game event
749 mission_campaign_exit_loop();
753 // -------------------------------------------------------------------------------------
754 // brief_select_button_do() do the button action for the specified pressed button
756 void brief_button_do(int i)
759 case BRIEF_BUTTON_LAST_STAGE:
760 brief_do_end_pressed();
763 case BRIEF_BUTTON_NEXT_STAGE:
764 brief_do_next_pressed(1);
767 case BRIEF_BUTTON_PREV_STAGE:
768 brief_do_prev_pressed();
771 case BRIEF_BUTTON_FIRST_STAGE:
772 brief_do_start_pressed();
775 case BRIEF_BUTTON_SCROLL_UP:
776 brief_scroll_up_text();
779 case BRIEF_BUTTON_SCROLL_DOWN:
780 brief_scroll_down_text();
783 case BRIEF_BUTTON_PAUSE:
784 gamesnd_play_iface(SND_USER_SELECT);
785 Player->auto_advance ^= 1;
788 case BRIEF_BUTTON_SKIP_TRAINING:
789 brief_skip_training_pressed();
792 case BRIEF_BUTTON_EXIT_LOOP:
793 brief_exit_loop_pressed();
796 case BRIEF_BUTTON_MULTI_LOCK:
797 Assert(Game_mode & GM_MULTIPLAYER);
798 // the "lock" button has been pressed
799 multi_ts_lock_pressed();
801 // disable the button if it is now locked
802 if(multi_ts_is_locked()){
803 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
809 // -------------------------------------------------------------------
810 // brief_check_buttons()
812 // Iterate through the briefing buttons, checking if they are pressed
814 void brief_check_buttons()
819 for (i=0; i<NUM_BRIEF_BUTTONS; i++) {
820 b = &Brief_buttons[gr_screen.res][i].button;
821 if ( b->pressed() ) {
822 common_flash_button_init();
827 if (Closeup_close_button.pressed()) {
828 brief_turn_off_closeup_icon();
832 // -------------------------------------------------------------------
833 // brief_redraw_pressed_buttons()
835 // Redraw any briefing buttons that are pressed down. This function is needed
836 // since we sometimes need to draw pressed buttons last to ensure the entire
837 // button gets drawn (and not overlapped by other buttons)
839 void brief_redraw_pressed_buttons()
844 common_redraw_pressed_buttons();
846 for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
847 b = &Brief_buttons[gr_screen.res][i].button;
848 if ( b->button_down() ) {
853 if ( !Player->auto_advance ) {
854 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.draw_forced(2);
858 void brief_buttons_init()
863 //if ( Briefing->num_stages <= 0 )
866 for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
867 b = &Brief_buttons[gr_screen.res][i].button;
868 b->create( &Brief_ui_window, "", Brief_buttons[gr_screen.res][i].x, Brief_buttons[gr_screen.res][i].y, 60, 30, 0, 1 );
869 // set up callback for when a mouse first goes over a button
870 b->set_highlight_action( common_play_highlight_sound );
872 if ((i == BRIEF_BUTTON_SKIP_TRAINING) || (i == BRIEF_BUTTON_EXIT_LOOP)) {
873 b->set_bmaps(Brief_buttons[gr_screen.res][i].filename, 3, 0);
875 b->set_bmaps(Brief_buttons[gr_screen.res][i].filename);
877 b->link_hotspot(Brief_buttons[gr_screen.res][i].hotspot);
881 for(i=0; i<BRIEF_SELECT_NUM_TEXT; i++) {
882 Brief_ui_window.add_XSTR(&Brief_select_text[gr_screen.res][i]);
885 // Hide the 'skip training' button by default. Only enable and unhide if we are playing a training
887 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.disable();
888 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.hide();
889 if ( (Game_mode & GM_NORMAL) && (The_mission.game_type & MISSION_TYPE_TRAINING) ) {
890 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.enable();
891 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.unhide();
894 // Hide the 'exit loop' button by default. Only enable and unhide if we are playing a loop
896 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.disable();
897 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.hide();
898 if ( (Game_mode & GM_NORMAL) && (Campaign.loop_enabled) && (Game_mode & GM_CAMPAIGN_MODE) ) {
899 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.enable();
900 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.unhide();
903 // maybe disable the multi-lock button
904 if(!(Game_mode & GM_MULTIPLAYER)){
905 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.hide();
906 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
908 // if we're not the host of the game (or a tema captain in team vs. team mode), disable the lock button
909 if(Netgame.type_flags & NG_TYPE_TEAM){
910 if(!(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
911 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
914 if(!(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
915 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
920 // create close button for closeup popup
921 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 );
922 Closeup_close_button.set_highlight_action( common_play_highlight_sound );
923 Closeup_close_button.set_bmaps(Closeup_button_filename[gr_screen.res]);
924 Closeup_close_button.link_hotspot(Closeup_button_hotspot);
926 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
927 Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_RIGHT);
928 Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.set_hotkey(KEY_RIGHT);
929 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.set_hotkey(KEY_LEFT);
930 Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_LEFT);
931 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.set_hotkey(KEY_UP);
932 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);
934 Closeup_close_button.disable();
935 Closeup_close_button.hide();
937 // if we have no briefing stages, hide and disable briefing buttons
938 if(Num_brief_stages <= 0){
939 Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.disable();
940 Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.hide();
941 Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.disable();
942 Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.hide();
943 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.disable();
944 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.hide();
945 Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.disable();
946 Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.hide();
947 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.disable();
948 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.hide();
949 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.disable();
950 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.hide();
951 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.disable();
952 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.hide();
956 // --------------------------------------------------------------------------------------
957 // brief_get_closeup_icon()
960 uint brief_get_closeup_icon()
962 return (uint)Closeup_icon;
965 // stop showing the closeup view of an icon
966 void brief_turn_off_closeup_icon()
969 if ( Closeup_icon != NULL ) {
970 gamesnd_play_iface(SND_BRIEF_ICON_SELECT);
972 Closeup_close_button.disable();
973 Closeup_close_button.hide();
977 // --------------------------------------------------------------------------------------
978 // brief_load_bitmaps()
981 void brief_load_bitmaps()
983 Brief_text_bitmap = bm_load(Brief_infobox_filename[gr_screen.res]);
984 Brief_grid_bitmap = bm_load(Brief_win_filename[gr_screen.res]);
986 if ( Closeup_bitmap == -1 ) {
987 Closeup_bitmap = bm_load(Closeup_background_filename[gr_screen.res]);
991 // --------------------------------------------------------------------------------------
997 if(Game_mode & GM_MULTIPLAYER) {
998 Brief_background_bitmap = bm_load(Brief_multi_filename[gr_screen.res]);
1000 Brief_background_bitmap = bm_load(Brief_filename[gr_screen.res]);
1003 if ( Num_brief_stages <= 0 ){
1007 brief_load_bitmaps();
1011 // --------------------------------------------------------------------------------------
1012 // brief_set_default_closeup()
1015 void brief_set_default_closeup()
1020 bs = &Briefing->stages[0];
1022 if ( Briefing->num_stages <= 0 ) {
1023 Closeup_icon = NULL;
1027 if ( bs->num_icons <= 0 ) {
1028 Closeup_icon = NULL;
1032 // check for the first highlighted icons to have as the default closeup
1033 for ( i = 0; i < bs->num_icons; i++ ) {
1034 if ( bs->icons[i].flags & BI_HIGHLIGHT )
1038 if ( i == bs->num_icons ) {
1039 brief_setup_closeup(&bs->icons[0]);
1042 brief_setup_closeup(&bs->icons[i]);
1046 // funciton to evaluate the sexpressions of the briefing stages eliminating those stages
1047 // which shouldn't get shown
1048 void brief_compact_stages()
1053 if((Game_mode & GM_MULTIPLAYER) && (Netgame.campaign_mode == MP_CAMPAIGN) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1054 Game_mode |= GM_CAMPAIGN_MODE;
1059 while ( num < Briefing->num_stages ) {
1060 result = eval_sexp( Briefing->stages[num].formula );
1062 if ( Briefing->stages[num].new_text ) {
1063 free( Briefing->stages[num].new_text );
1064 Briefing->stages[num].new_text = NULL;
1067 if ( Briefing->stages[num].icons ) {
1068 free( Briefing->stages[num].icons );
1069 Briefing->stages[num].icons = NULL;
1073 if ( Briefing->stages[num].lines ) {
1074 free( Briefing->stages[num].lines );
1075 Briefing->stages[num].lines = NULL;
1078 Briefing->stages[num].num_icons = 0;
1079 for ( i = num+1; i < Briefing->num_stages; i++ ) {
1080 Briefing->stages[i-1] = Briefing->stages[i];
1082 Briefing->num_stages--;
1089 if((Game_mode & GM_MULTIPLAYER) && (Netgame.campaign_mode == MP_CAMPAIGN) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1090 Game_mode &= ~(GM_CAMPAIGN_MODE);
1096 // --------------------------------------------------------------------------------------
1099 int red_alert_mission(void);
1103 // Since first stage of briefing can take some time to arrive and play,
1104 // reset the trailer timer on briefing init.
1106 demo_reset_trailer_timer();
1109 // for multiplayer, change the state in my netplayer structure
1110 // and initialize the briefing chat area thingy
1111 if ( Game_mode & GM_MULTIPLAYER ){
1112 Net_player->state = NETPLAYER_STATE_BRIEFING;
1115 // Non standard briefing in red alert mission
1116 if ( red_alert_mission() ) {
1117 gameseq_post_event(GS_EVENT_RED_ALERT);
1121 // get a pointer to the appropriate briefing structure
1122 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1123 Briefing = &Briefings[Net_player->p_info.team];
1125 Briefing = &Briefings[0];
1128 Brief_last_auto_advance = 0;
1130 brief_compact_stages(); // compact the briefing array to eliminate unused stages
1132 common_set_interface_palette("BriefingPalette");
1134 ship_stop_animation();
1135 set_active_ui(&Brief_ui_window);
1136 Current_screen = ON_BRIEFING_SELECT;
1137 brief_restart_text_wipe();
1138 common_flash_button_init();
1139 common_music_init(SCORE_BRIEFING);
1142 help_overlay_set_state(BR_OVERLAY,0);
1144 if ( Brief_inited == TRUE ) {
1145 common_buttons_maybe_reload(&Brief_ui_window); // AL 11-21-97: this is necessary since we may returning from the hotkey
1146 // screen, which can release common button bitmaps.
1147 common_reset_buttons();
1148 nprintf(("Alan","brief_init() returning without doing anything\n"));
1152 if (The_mission.game_type & MISSION_TYPE_TRAINING)
1153 Num_brief_stages = Briefing->num_stages;
1155 Num_brief_stages = Briefing->num_stages + 1;
1157 Current_brief_stage = 0;
1158 Last_brief_stage = 0;
1160 // init the scene-cut data
1161 brief_transition_reset();
1164 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]);
1165 hud_anim_load(&Fade_anim);
1168 nprintf(("Alan","Entering brief_init()\n"));
1169 common_select_init();
1171 if(Game_mode & GM_MULTIPLAYER) {
1172 BriefingMaskBitmap = bm_load(Brief_multi_mask_filename[gr_screen.res]);
1174 BriefingMaskBitmap = bm_load(Brief_mask_filename[gr_screen.res]);
1177 if (BriefingMaskBitmap < 0) {
1178 Error(LOCATION,"Could not load in 'brief-m'!");
1181 Briefing_mask_w = -1;
1182 Briefing_mask_h = -1;
1184 // get a pointer to bitmap by using bm_lock()
1185 BriefingMaskPtr = bm_lock(BriefingMaskBitmap, 8, BMP_AABITMAP);
1186 BriefingMaskData = (ubyte*)BriefingMaskPtr->data;
1187 bm_get_info(BriefingMaskBitmap, &Briefing_mask_w, &Briefing_mask_h);
1189 help_overlay_load(BR_OVERLAY);
1191 // Set up the mask regions
1192 // initialize the different regions of the menu that will react when the mouse moves over it
1193 Num_briefing_regions = 0;
1195 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_BRIEFING_REGION, 0);
1196 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_SS_REGION, 0);
1197 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_WEAPON_REGION, 0);
1198 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_COMMIT_REGION, 0);
1199 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_HELP_REGION, 0);
1200 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", COMMON_OPTIONS_REGION, 0);
1202 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_LAST_STAGE_MASK, 0);
1203 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_NEXT_STAGE_MASK, 0);
1204 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_PREV_STAGE_MASK, 0);
1205 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_FIRST_STAGE_MASK, 0);
1206 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_TEXT_SCROLL_UP_MASK, 0);
1207 snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "", BRIEF_TEXT_SCROLL_DOWN_MASK, 0);
1210 Brief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1212 if(Game_mode & GM_MULTIPLAYER){
1213 Brief_ui_window.set_mask_bmap(Brief_mask_multi[gr_screen.res]);
1215 Brief_ui_window.set_mask_bmap(Brief_mask_single[gr_screen.res]);
1218 Brief_ui_window.tooltip_handler = brief_tooltip_handler;
1219 common_buttons_init(&Brief_ui_window);
1220 brief_buttons_init();
1222 // if multiplayer, initialize a few other systems
1223 if(Game_mode & GM_MULTIPLAYER){
1224 // again, should not be necessary, but we'll leave it for now
1227 // force the chatbox to be small
1228 chatbox_force_small();
1231 // set up the screen regions
1232 brief_init_screen(Brief_multiplayer);
1234 // init briefing specific UI
1237 // init the briefing map
1240 // init the briefing voice playback
1242 brief_voice_load_all();
1244 // init objectives display stuff
1245 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]);
1247 // set the camera target
1248 if ( Briefing->num_stages > 0 ) {
1249 brief_set_new_stage(&Briefing->stages[0].camera_pos, &Briefing->stages[0].camera_orient, 0, Current_brief_stage);
1250 brief_reset_icons(Current_brief_stage);
1253 Brief_playing_fade_sound = 0;
1254 Brief_mouse_up_flag = 0;
1255 Closeup_font_height = gr_get_font_height();
1256 Closeup_icon = NULL;
1257 Brief_inited = TRUE;
1260 // -------------------------------------------------------------------------------------
1261 // brief_render_closeup_text()
1264 #define CLOSEUP_TEXT_OFFSET 10
1265 void brief_render_closeup_text()
1269 char line[MAX_ICON_TEXT_LINE_LEN];
1270 int n_lines, i, render_x, render_y;
1271 int n_chars[MAX_ICON_TEXT_LINES];
1272 char *p_str[MAX_ICON_TEXT_LINES];
1274 if ( Closeup_icon == NULL ) {
1281 render_x = Closeup_region[0];
1282 render_y = Closeup_region[1] + CLOSEUP_IMG_H;
1284 gr_set_clip(render_x+CLOSEUP_TEXT_OFFSET, render_y, CLOSEUP_W,CLOSEUP_TEXT_H);
1285 gr_set_color_fast(&Color_white);
1287 // n_lines = split_str(bi->text, CLOSEUP_W - 2*CLOSEUP_TEXT_OFFSET, n_chars, p_str, MAX_ICON_TEXT_LINES);
1288 Assert(n_lines != -1);
1290 for ( i = 0; i < n_lines; i++ ) {
1291 Assert(n_chars[i] < MAX_ICON_TEXT_LINE_LEN);
1292 strncpy(line, p_str[i], n_chars[i]);
1293 line[n_chars[i]] = 0;
1294 gr_printf(0,0+i*Closeup_font_height,line);
1299 // -------------------------------------------------------------------------------------
1300 // brief_render_closeup()
1303 void brief_render_closeup(int ship_class, float frametime)
1305 matrix view_orient = IDENTITY_MATRIX;
1313 if (Closeup_bitmap < 0)
1316 ang = PI2 * frametime/Closeup_one_revolution_time;
1317 if ( ang > MAX_ANG_CHG )
1320 Closeup_angles.h += ang;
1321 if ( Closeup_angles.h > PI2 )
1322 Closeup_angles.h -= PI2;
1323 vm_angles_2_matrix(&temp_matrix, &Closeup_angles );
1324 Closeup_orient = temp_matrix;
1326 w = Closeup_region[gr_screen.res][2];
1327 h = Closeup_region[gr_screen.res][3];
1328 gr_set_clip(Closeup_region[gr_screen.res][0], Closeup_region[gr_screen.res][1], w, h);
1332 g3_set_view_matrix(&Closeup_cam_pos, &view_orient, Closeup_zoom);
1333 model_clear_instance( Closeup_icon->modelnum );
1334 model_set_detail_level(0);
1336 int is_neb = The_mission.flags & MISSION_FLAG_FULLNEB;
1338 // maybe switch off nebula rendering
1340 The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1343 int model_render_flags;
1344 if ( Closeup_icon->type == ICON_JUMP_NODE ) {
1345 model_set_outline_color(HUD_color_red, HUD_color_green, HUD_color_blue);
1346 model_render_flags = MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_POLYS | MR_SHOW_OUTLINE;
1348 model_render_flags = MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER;
1351 model_render( Closeup_icon->modelnum, &Closeup_orient, &Closeup_pos, model_render_flags );
1354 The_mission.flags |= MISSION_FLAG_FULLNEB;
1359 gr_set_color_fast(&Color_bright_white);
1361 gr_printf(0x8000,2,Closeup_icon->closeup_label);
1362 // brief_render_closeup_text();
1364 Closeup_close_button.enable();
1365 Closeup_close_button.unhide();
1370 // -------------------------------------------------------------------------------------
1373 // frametime is in seconds
1374 void brief_render(float frametime)
1383 if ( Num_brief_stages <= 0 ) {
1384 gr_set_color_fast(&Color_white);
1385 Assert( Game_current_mission_filename != NULL );
1386 gr_printf(0x8000,200,XSTR( "No Briefing exists for mission: %s", 430), Game_current_mission_filename);
1389 gr_get_string_size(&w, &h, The_mission.name);
1390 gr_set_color_fast(&Color_normal);
1391 gr_printf(0x8000, 230, NOX("[filename: %s, last mod: %s]"), Mission_filename, The_mission.modified);
1397 gr_set_bitmap(Brief_grid_bitmap);
1398 gr_bitmap(Brief_bmap_coords[gr_screen.res][0], Brief_bmap_coords[gr_screen.res][1]);
1400 brief_render_map(Current_brief_stage, frametime);
1402 // draw the frame bitmaps
1403 gr_set_bitmap(Brief_text_bitmap);
1404 gr_bitmap(Brief_infobox_coords[gr_screen.res][0], Brief_infobox_coords[gr_screen.res][1]);
1405 brief_blit_stage_num(Current_brief_stage, Num_brief_stages);
1407 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);
1409 brief_voice_play(Current_brief_stage);
1412 // maybe output the "more" indicator
1413 if ( (Brief_text_max_lines[gr_screen.res] + Top_brief_text_line + 2) < Num_brief_text_lines[0] ) {
1414 // can be scrolled down
1415 int more_txt_x = Brief_text_coords[gr_screen.res][0] + (Brief_max_line_width[gr_screen.res]/2) - 10;
1416 int more_txt_y = Brief_text_coords[gr_screen.res][1] + Brief_text_coords[gr_screen.res][3] - 2; // located below brief text, centered
1418 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
1419 gr_set_color_fast(&Color_black);
1420 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
1421 gr_set_color_fast(&Color_red);
1422 gr_string(more_txt_x, more_txt_y, XSTR("more", 1469)); // base location on the input x and y?
1425 brief_maybe_blit_scene_cut(frametime);
1427 #if !defined(NDEBUG) || defined(INTERPLAYQA)
1428 gr_set_color_fast(&Color_normal);
1429 int title_y_offset = (Game_mode & GM_MULTIPLAYER) ? 20 : 10;
1430 gr_printf(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);
1433 // output mission title
1434 gr_set_color_fast(&Color_bright_white);
1435 if (Game_mode & GM_MULTIPLAYER) {
1437 strncpy(buf, The_mission.name, 256);
1438 gr_force_fit_string(buf, 255, Title_coords_multi[gr_screen.res][2]);
1439 gr_string(Title_coords_multi[gr_screen.res][0], Title_coords_multi[gr_screen.res][1], buf);
1441 gr_get_string_size(&w, NULL, The_mission.name);
1442 gr_string(Title_coords[gr_screen.res][0] - w, Title_coords[gr_screen.res][1], The_mission.name);
1445 // maybe do objectives
1446 if (Current_brief_stage == Briefing->num_stages) {
1447 ML_objectives_do_frame(0);
1451 // -------------------------------------------------------------------------------------
1452 // brief_set_closeup_pos()
1455 #define CLOSEUP_OFFSET 20
1456 void brief_set_closeup_pos(brief_icon *bi)
1459 Closeup_x1 = fl2i(320 - Closeup_coords[gr_screen.res][BRIEF_W_COORD]/2.0f + 0.5f);
1462 void brief_get_closeup_ship_modelnum(brief_icon *ci)
1467 // find the model number for the ship to display
1468 for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1470 if ( objp == &obj_used_list || objp->type != OBJ_SHIP ) {
1474 sp = &Ships[objp->instance];
1475 if ( sp->ship_info_index == ci->ship_class ) {
1476 ci->ship_class = sp->ship_info_index;
1477 ci->modelnum = sp->modelnum;
1478 ci->radius = objp->radius;
1484 // cut any text off after (and including) '#' char
1485 void brief_truncate_label(char *src)
1487 char *pointer_to_last_char;
1489 pointer_to_last_char = strstr(src, NOX("#"));
1491 if ( pointer_to_last_char ) {
1492 *pointer_to_last_char = 0;
1496 // -------------------------------------------------------------------------------------
1497 // brief_setup_closeup()
1499 // exit: 0 => set-up icon sucessfully
1500 // -1 => could not setup closeup icon
1501 int brief_setup_closeup(brief_icon *bi)
1503 char pof_filename[NAME_LENGTH];
1504 ship_info *sip=NULL;
1508 Closeup_icon->ship_class = bi->ship_class;
1509 Closeup_icon->modelnum = -1;
1511 Closeup_one_revolution_time = ONE_REV_TIME;
1513 switch(Closeup_icon->type) {
1515 Closeup_icon = NULL;
1518 strcpy(pof_filename, NOX("planet.pof"));
1519 strcpy(Closeup_icon->closeup_label, XSTR("planet",-1));
1520 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -8300.0f);
1521 Closeup_zoom = 0.5f;
1522 Closeup_one_revolution_time = ONE_REV_TIME * 3;
1525 case ICON_ASTEROID_FIELD:
1527 strcpy(pof_filename, Asteroid_info[ASTEROID_TYPE_BIG].pof_files[0]);
1528 strcpy(Closeup_icon->closeup_label, XSTR( "asteroid", 431));
1529 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -334.0f);
1530 Closeup_zoom = 0.5f;
1533 case ICON_JUMP_NODE:
1534 strcpy(pof_filename, NOX("subspacenode.pof"));
1535 strcpy(Closeup_icon->closeup_label, XSTR( "jump node", 432));
1536 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -2700.0f);
1537 Closeup_zoom = 0.5f;
1538 Closeup_one_revolution_time = ONE_REV_TIME * 3;
1541 case ICON_UNKNOWN_WING:
1542 strcpy(pof_filename, NOX("unknownship.pof"));
1543 strcpy(Closeup_icon->closeup_label, XSTR( "unknown", 433));
1544 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -22.0f);
1545 Closeup_zoom = 0.5f;
1548 brief_get_closeup_ship_modelnum(Closeup_icon);
1549 Assert( Closeup_icon->ship_class != -1 );
1550 sip = &Ship_info[Closeup_icon->ship_class];
1552 strcpy(Closeup_icon->closeup_label,sip->name);
1554 // cut any text off after (and including) '#' char
1555 brief_truncate_label(Closeup_icon->closeup_label);
1557 if ( sip->flags & (SIF_SMALL_SHIP|SIF_BIG_SHIP|SIF_HUGE_SHIP|SIF_SENTRYGUN) ) {
1558 strcat(Closeup_icon->closeup_label, XSTR( " class", 434));
1563 if ( Closeup_icon->modelnum == -1 ) {
1564 if ( sip == NULL ) {
1565 Closeup_icon->modelnum = model_load(pof_filename, NULL, NULL);
1567 Closeup_icon->modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
1569 Closeup_icon->radius = model_get_radius(Closeup_icon->modelnum);
1572 vm_set_identity(&Closeup_orient);
1573 vm_vec_make(&tvec, 0.0f, 0.0f, -1.0f);
1574 Closeup_orient.fvec = tvec;
1575 vm_vec_zero(&Closeup_pos);
1576 Closeup_angles.p = 0.0f;
1577 Closeup_angles.b = 0.0f;
1578 Closeup_angles.h = PI;
1580 brief_set_closeup_pos(bi);
1583 Closeup_cam_pos = sip->closeup_pos;
1584 Closeup_zoom = sip->closeup_zoom;
1590 // -------------------------------------------------------------------------------------
1591 // brief_update_closeup_icon()
1593 // input: mode => how to update the closeup view
1596 void brief_update_closeup_icon(int mode)
1600 int i, closeup_index;
1604 // mode 0 means disable the closeup icon
1605 if ( Closeup_icon != NULL ) {
1606 brief_turn_off_closeup_icon();
1611 if ( Closeup_icon == NULL )
1614 bs = &Briefing->stages[Current_brief_stage];
1617 // see if any icons are being highlighted this stage
1618 for ( i = 0; i < bs->num_icons; i++ ) {
1620 if ( bi->flags & BI_HIGHLIGHT ) {
1626 if ( closeup_index != -1 ) {
1627 bi = &bs->icons[closeup_index];
1628 brief_setup_closeup(bi);
1631 Closeup_icon = NULL;
1636 // -------------------------------------------------------------------------------------
1637 // brief_check_for_anim()
1640 void brief_check_for_anim()
1642 int mx, my, i, iw, ih;
1644 brief_icon *bi = NULL;
1646 bs = &Briefing->stages[Current_brief_stage];
1647 mouse_get_pos( &mx, &my );
1649 // if mouse click is over the VCR controls, don't launch an icon
1650 // FIXME - should prolly push these into defines instead of hardcoding this
1651 if ( mx >= 0 && mx <= 115 && my >= 136 && my <= 148 ) {
1655 // if mouse coords are outside the briefing screen, then go away
1656 my -= bscreen.map_y1;
1657 mx -= bscreen.map_x1;
1658 if ( my < 0 || mx < 0 || mx > (bscreen.map_x2-bscreen.map_x1+1) || my > (bscreen.map_y2-bscreen.map_y1+1) )
1661 for ( i = 0; i < bs->num_icons; i++ ) {
1663 brief_common_get_icon_dimensions(&iw, &ih, bi->type, bi->ship_class);
1664 if ( mx < bi->x ) continue;
1665 if ( mx > (bi->x + iw) ) continue;
1666 if ( my < bi->y ) continue;
1667 if ( my > (bi->y + ih) ) continue;
1668 // if we've got here, must be a hit
1672 if ( i == bs->num_icons ) {
1673 brief_turn_off_closeup_icon();
1677 if ( brief_setup_closeup(bi) == 0 ) {
1678 gamesnd_play_iface(SND_BRIEF_ICON_SELECT);
1680 gamesnd_play_iface(SND_GENERAL_FAIL);
1684 // maybe flash a button if player hasn't done anything for a while
1685 void brief_maybe_flash_button()
1689 if ( Num_brief_stages <= 0 )
1692 if ( Closeup_icon != NULL ) {
1693 common_flash_button_init();
1697 if ( common_flash_bright() ) {
1698 if ( Current_brief_stage == (Num_brief_stages-1) ) {
1700 // AL 4-4-98: Don't flash ship selection button on briefing in demo build
1704 // AL 30-3-98: Don't flash ship selection button if in a training mission,
1705 if ( brief_only_allow_briefing() ) {
1709 b = &Common_buttons[Current_screen-1][gr_screen.res][1].button; // ship select button
1712 b = &Brief_buttons[gr_screen.res][1].button; // next stage button
1715 if ( b->button_hilighted() ) {
1716 common_flash_button_init();
1723 // -------------------------------------------------------------------------------------
1726 // frametime is in seconds
1728 void brief_do_frame(float frametime)
1730 int k, brief_choice;
1732 if ( red_alert_mission() ) {
1737 if ( !Brief_inited ){
1741 int snazzy_action = -1;
1742 brief_choice = snazzy_menu_do(BriefingMaskData, Briefing_mask_w, Briefing_mask_h, Num_briefing_regions, Briefing_select_region, &snazzy_action, 0);
1744 k = common_select_do(frametime);
1746 if ( Closeup_icon ) {
1747 Brief_mouse_up_flag = 0;
1750 if ( help_overlay_active(BR_OVERLAY) ) {
1751 common_flash_button_init();
1752 brief_turn_off_closeup_icon();
1755 // Check common keypresses
1756 common_check_keys(k);
1762 if ( Briefing->num_stages > 0 ) {
1764 // check for special keys
1768 case KEY_CTRLED | KEY_PAGEUP: {
1769 if (Closeup_icon->ship_class) {
1770 Closeup_icon->ship_class--;
1772 ship_info *sip = &Ship_info[Closeup_icon->ship_class];
1773 if (sip->modelnum < 0)
1774 sip->modelnum = model_load(sip->pof_file, NULL, NULL);
1776 mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
1777 mprintf(("Modelnum = %d (%s)\n", sip->modelnum, sip->pof_file));
1778 brief_setup_closeup(Closeup_icon);
1784 case KEY_CTRLED | KEY_PAGEDOWN: {
1785 if (Closeup_icon->ship_class < Num_ship_types - 1) {
1786 Closeup_icon->ship_class++;
1788 ship_info *sip = &Ship_info[Closeup_icon->ship_class];
1789 if (sip->modelnum < 0)
1790 sip->modelnum = model_load(sip->pof_file, NULL, NULL);
1792 mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
1793 mprintf(("Modelnum = %d (%s)\n", sip->modelnum, sip->pof_file));
1794 brief_setup_closeup(Closeup_icon);
1801 Closeup_cam_pos.z += 1;
1805 case KEY_A + KEY_SHIFTED:
1806 Closeup_cam_pos.z += 10;
1811 Closeup_cam_pos.z -= 1;
1815 case KEY_Z + KEY_SHIFTED:
1816 Closeup_cam_pos.z -= 10;
1821 Closeup_cam_pos.y += 1;
1825 case KEY_Y + KEY_SHIFTED:
1826 Closeup_cam_pos.y += 10;
1831 Closeup_cam_pos.y -= 1;
1835 case KEY_H + KEY_SHIFTED:
1836 Closeup_cam_pos.y -= 10;
1841 Closeup_zoom -= 0.1f;
1842 if ( Closeup_zoom < 0.1 )
1843 Closeup_zoom = 0.1f;
1847 case KEY_COMMA+KEY_SHIFTED:
1848 Closeup_zoom -= 0.5f;
1849 if ( Closeup_zoom < 0.1 )
1850 Closeup_zoom = 0.1f;
1855 Closeup_zoom += 0.1f;
1859 case KEY_PERIOD+KEY_SHIFTED:
1860 Closeup_zoom += 0.5f;
1864 case 1000: // need this to avoid warning about no case
1874 nprintf(("General","Camera pos: %.2f, %.2f %.2f // ", Closeup_cam_pos.x, Closeup_cam_pos.y, Closeup_cam_pos.z));
1875 nprintf(("General","Camera zoom: %.2f\n", Closeup_zoom));
1879 if ( brief_choice > -1 && snazzy_action == SNAZZY_OVER ) {
1880 Brief_mouse_up_flag = 0;
1885 common_check_buttons();
1886 // if ( Briefing->num_stages > 0 )
1887 brief_check_buttons();
1889 if ( brief_choice != -1 ) {
1890 Brief_mouse_up_flag = 0;
1895 common_render(frametime);
1897 if ( Current_brief_stage < (Num_brief_stages-1) ) {
1898 if ( !help_overlay_active(BR_OVERLAY) && brief_time_to_advance(Current_brief_stage, frametime) ) {
1899 brief_do_next_pressed(0);
1900 common_flash_button_init();
1901 Brief_last_auto_advance = timer_get_milliseconds();
1905 if ( !Background_playing ) {
1907 int check_jump_flag = 1;
1908 if ( Current_brief_stage != Last_brief_stage ) {
1910 // Check if we have a quick transition pending
1911 if ( Quick_transition_stage != -1 ) {
1912 Quick_transition_stage = -1;
1913 brief_reset_last_new_stage();
1915 check_jump_flag = 0;
1918 if ( check_jump_flag ) {
1919 if ( abs(Current_brief_stage - Last_brief_stage) > 1 ) {
1920 Quick_transition_stage = Current_brief_stage;
1921 Current_brief_stage = Last_brief_stage;
1922 Assert(Current_brief_stage >= 0);
1923 Start_fade_up_anim = 1;
1924 goto Transition_done;
1929 if ( Current_brief_stage > Last_brief_stage ) {
1930 if ( Briefing->stages[Last_brief_stage].flags & BS_FORWARD_CUT ) {
1931 Quick_transition_stage = Current_brief_stage;
1932 Current_brief_stage = Last_brief_stage;
1933 Assert(Current_brief_stage >= 0);
1934 Start_fade_up_anim = 1;
1935 goto Transition_done;
1937 time = Briefing->stages[Current_brief_stage].camera_time;
1941 if ( Briefing->stages[Last_brief_stage].flags & BS_BACKWARD_CUT ) {
1942 Quick_transition_stage = Current_brief_stage;
1943 Current_brief_stage = Last_brief_stage;
1944 Assert(Current_brief_stage >= 0);
1945 Start_fade_up_anim = 1;
1946 goto Transition_done;
1948 time = Briefing->stages[Last_brief_stage].camera_time;
1953 brief_voice_stop(Last_brief_stage);
1955 if ( Current_brief_stage < 0 ) {
1957 Current_brief_stage=0;
1960 // set the camera target
1961 brief_set_new_stage(&Briefing->stages[Current_brief_stage].camera_pos,
1962 &Briefing->stages[Current_brief_stage].camera_orient,
1963 time, Current_brief_stage);
1965 Brief_playing_fade_sound = 0;
1966 Last_brief_stage = Current_brief_stage;
1967 brief_reset_icons(Current_brief_stage);
1968 brief_update_closeup_icon(0);
1973 if ( Brief_mouse_up_flag && !Closeup_icon) {
1974 brief_check_for_anim();
1977 brief_render(frametime);
1978 brief_camera_move(frametime, Current_brief_stage);
1980 if (Closeup_icon && (Closeup_bitmap >= 0)) {
1981 // blit closeup background
1982 gr_set_bitmap(Closeup_bitmap);
1983 gr_bitmap(Closeup_coords[gr_screen.res][BRIEF_X_COORD], Closeup_coords[gr_screen.res][BRIEF_Y_COORD]);
1986 Brief_ui_window.draw();
1987 brief_redraw_pressed_buttons();
1988 common_render_selected_screen_button();
1991 brief_render_closeup(Closeup_icon->ship_class, frametime);
1994 // render some extra stuff in multiplayer
1995 if (Game_mode & GM_MULTIPLAYER) {
1996 // should render this last so that it overlaps all controls
1999 // render the status indicator for the voice system
2000 multi_common_voice_display_status();
2002 // blit the "ships/players" locked button
2003 // multi_ts_blit_locked_button();
2005 // maybe blit the multiplayer "locked" button
2006 // if its locked, everyone blits it as such
2007 if(multi_ts_is_locked()){
2008 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(2);
2010 // anyone who can't hit the button sees it off, otherwise
2012 if( ((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)) ||
2013 ((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_GAME_HOST)) ){
2014 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(0);
2016 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw();
2022 // maybe flash a button if player hasn't done anything for a while
2023 brief_maybe_flash_button();
2025 // blit help overlay if active
2026 help_overlay_maybe_blit(BR_OVERLAY);
2030 // If the commit button was pressed, do the commit button actions. Done at the end of the
2031 // loop so there isn't a skip in the animation (since ship_create() can take a long time if
2032 // the ship model is not in memory
2033 if (Commit_pressed) {
2034 if (Game_mode & GM_MULTIPLAYER) {
2035 multi_ts_commit_pressed();
2044 // --------------------------------------------------------------------------------------
2045 // brief_unload_bitmaps()
2048 void brief_unload_bitmaps()
2050 if ( BriefingMaskBitmap != -1 ) {
2051 bm_unload(BriefingMaskBitmap);
2052 BriefingMaskBitmap = -1;
2055 if ( Brief_text_bitmap != -1 ) {
2056 bm_unload(Brief_text_bitmap);
2057 Brief_text_bitmap = -1;
2060 if(Brief_grid_bitmap != -1){
2061 bm_unload(Brief_grid_bitmap);
2062 Brief_grid_bitmap = -1;
2065 if ( Brief_multitext_bitmap != -1 ) {
2066 bm_unload(Brief_multitext_bitmap);
2067 Brief_multitext_bitmap = -1;
2070 if ( Brief_background_bitmap != -1 ) {
2071 bm_unload(Brief_background_bitmap);
2072 Brief_background_bitmap = -1;
2075 help_overlay_unload(BR_OVERLAY);
2078 // ------------------------------------------------------------------------------------
2084 if ( Brief_inited == FALSE ) {
2085 nprintf(("Warning","brief_close() returning without doing anything\n"));
2089 nprintf(("Alan", "Entering brief_close()\n"));
2091 ML_objectives_close();
2093 // unload the audio streams used for voice playback
2094 brief_voice_unload_all();
2097 hud_anim_release(&Fade_anim);
2100 // done mask bitmap, so unlock it
2101 bm_unlock(BriefingMaskBitmap);
2103 Brief_ui_window.destroy();
2105 // unload the bitmaps
2106 brief_unload_bitmaps();
2108 brief_common_close();
2110 Brief_inited = FALSE;
2113 void briefing_stop_music()
2115 if ( Briefing_music_handle != -1 ) {
2116 audiostream_close_file(Briefing_music_handle);
2117 Briefing_music_handle = -1;
2121 void briefing_load_music(char* fname)
2123 if ( Cmdline_freespace_no_music ) {
2127 if ( Briefing_music_handle != -1 )
2131 Briefing_music_handle = audiostream_open( fname, ASF_EVENTMUSIC );
2134 void briefing_start_music()
2136 if ( Briefing_music_handle != -1 ) {
2137 if ( !audiostream_is_playing(Briefing_music_handle) )
2138 audiostream_play(Briefing_music_handle, Master_event_music_volume);
2141 nprintf(("Warning", "No music file exists to play music at this briefing!\n"));
2145 void brief_stop_voices()
2147 brief_voice_stop(Current_brief_stage);
2150 void brief_maybe_blit_scene_cut(float frametime)
2152 if ( Start_fade_up_anim ) {
2155 Fade_anim.time_elapsed = 0.0f;
2156 Start_fade_up_anim = 0;
2157 Start_fade_down_anim = 1;
2158 Current_brief_stage = Quick_transition_stage;
2160 if ( Current_brief_stage < 0 ) {
2161 brief_transition_reset();
2162 Current_brief_stage = Last_brief_stage;
2164 goto Fade_down_anim_start;
2168 Fade_anim.time_elapsed += frametime;
2170 if ( !Brief_playing_fade_sound ) {
2171 gamesnd_play_iface(SND_BRIEFING_STATIC);
2172 Brief_playing_fade_sound = 1;
2175 if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
2176 Fade_anim.time_elapsed = 0.0f;
2177 Start_fade_up_anim = 0;
2178 Start_fade_down_anim = 1;
2179 Current_brief_stage = Quick_transition_stage;
2181 if ( Current_brief_stage < 0 ) {
2182 brief_transition_reset();
2183 Current_brief_stage = Last_brief_stage;
2186 Assert(Current_brief_stage >= 0);
2187 goto Fade_down_anim_start;
2190 // draw the correct frame of animation
2191 framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
2194 if ( framenum >= Fade_anim.num_frames )
2195 framenum = Fade_anim.num_frames-1;
2197 // Blit the bitmap for this frame
2198 gr_set_bitmap(Fade_anim.first_frame + framenum);
2199 gr_bitmap(Fade_anim.sx, Fade_anim.sy);
2204 Fade_down_anim_start:
2205 if ( Start_fade_down_anim ) {
2208 Fade_anim.time_elapsed = 0.0f;
2209 Start_fade_up_anim = 0;
2210 Start_fade_down_anim = 0;
2216 Fade_anim.time_elapsed += frametime;
2218 if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
2219 Fade_anim.time_elapsed = 0.0f;
2220 Start_fade_up_anim = 0;
2221 Start_fade_down_anim = 0;
2225 // draw the correct frame of animation
2226 framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
2229 if ( framenum >= Fade_anim.num_frames )
2230 framenum = Fade_anim.num_frames-1;
2232 // Blit the bitmap for this frame
2233 gr_set_bitmap(Fade_anim.first_frame + (Fade_anim.num_frames-1) - framenum);
2234 gr_bitmap(Fade_anim.sx, Fade_anim.sy);
2240 void brief_transition_reset()
2242 Quick_transition_stage = -1;
2243 Start_fade_up_anim = 0;
2244 Start_fade_down_anim = 0;
2245 Fade_anim.time_elapsed = 0.0f;
2248 // return 1 if this mission only allow players to use the briefing (and not ship or
2249 // weapon loadout). Otherwise return 0.
2250 int brief_only_allow_briefing()
2252 if ( The_mission.game_type & MISSION_TYPE_TRAINING ) {
2256 if ( The_mission.scramble || The_mission.red_alert) {