]> icculus.org git repositories - taylor/freespace2.git/blob - src/missionui/missionbrief.cpp
warning cleanup
[taylor/freespace2.git] / src / missionui / missionbrief.cpp
1 /*
2  * $Logfile: /Freespace2/code/MissionUI/MissionBrief.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module that contains code to display the mission briefing to the player
8  *
9  * $Log$
10  * Revision 1.3  2002/06/02 04:26:34  relnev
11  * warning cleanup
12  *
13  * Revision 1.2  2002/05/07 03:16:46  theoddone33
14  * The Great Newline Fix
15  *
16  * Revision 1.1.1.1  2002/05/03 03:28:10  root
17  * Initial import.
18  *
19  * 
20  * 48    10/14/99 2:51p Jefff
21  * localiztion fixes
22  * 
23  * 47    10/13/99 3:23p Jefff
24  * fixed unnumbered XSTRs
25  * 
26  * 46    9/12/99 8:09p Dave
27  * Fixed problem where skip-training button would cause mission messages
28  * not to get paged out for the current mission.
29  * 
30  * 45    9/09/99 3:40p Jefff
31  * no exit loop outisde of campaign mode
32  * 
33  * 44    9/07/99 6:53p Jefff
34  * functionality to break out of a loop
35  * 
36  * 43    9/06/99 6:38p Dave
37  * Improved CD detection code.
38  * 
39  * 42    9/03/99 10:57a Jefff
40  * numbered an xstr
41  * 
42  * 41    8/30/99 5:30p Jefff
43  * fixed "more" being cut off in d3d
44  * 
45  * 40    8/30/99 10:29a Jefff
46  * added autocenter flag to closup rendering
47  * 
48  * 39    8/19/99 11:33a Dave
49  * Fixed debug build.
50  * 
51  * 38    8/19/99 10:59a Dave
52  * Packet loss detection.
53  * 
54  * 37    8/16/99 4:05p Dave
55  * Big honking checkin.
56  * 
57  * 36    8/16/99 9:48a Jefff
58  * all clicks on briefing icons should now register
59  * 
60  * 35    8/10/99 7:29p Jefff
61  * added mission title to briefing screen
62  * 
63  * 34    8/03/99 1:34a Andsager
64  * fix skip training mission (again)
65  * 
66  * 33    8/02/99 12:01p Jefff
67  * fixed "skip training" text pos
68  * 
69  * 32    7/30/99 5:42p Jasenw
70  * Fixed coords for skip training button.
71  * 
72  * 31    7/29/99 10:50p Dave
73  * Oops. Accidentally blew away some interface text changes.
74  * 
75  * 30    7/29/99 10:48p Dave
76  * 
77  * 29    7/29/99 3:05p Andsager
78  * Add skip training text. and properly skip.
79  * 
80  * 28    7/24/99 6:07p Jefff
81  * Added "lock" text to multiplayer lock button
82  * 
83  * 27    7/21/99 10:51a Jefff
84  * added "more" indicator to briefing text box
85  * 
86  * 26    7/19/99 3:01p Dave
87  * Fixed icons. Added single transport icon.
88  * 
89  * 25    7/18/99 5:20p Dave
90  * Jump node icon. Fixed debris fogging. Framerate warning stuff.
91  * 
92  * 24    7/16/99 1:49p Dave
93  * 8 bit aabitmaps. yay.
94  * 
95  * 23    7/15/99 9:20a Andsager
96  * FS2_DEMO initial checkin
97  * 
98  * 22    7/09/99 5:54p Dave
99  * Seperated cruiser types into individual types. Added tons of new
100  * briefing icons. Campaign screen.
101  * 
102  * 21    6/29/99 7:39p Dave
103  * Lots of small bug fixes.
104  * 
105  * 20    6/11/99 11:13a Dave
106  * last minute changes before press tour build.
107  * 
108  * 19    6/04/99 1:18p Dave
109  * Fixed briefing model rendering problems. Made show background option in
110  * fred toggle nebula rendering.
111  * 
112  * 18    5/07/99 10:34a Andsager
113  * Make red alert work in FS2
114  * 
115  * 17    4/23/99 12:01p Johnson
116  * Added SIF_HUGE_SHIP
117  * 
118  * 16    3/25/99 2:45p Neilk
119  * Fixed lock button
120  * 
121  * 15    2/11/99 3:08p Dave
122  * PXO refresh button. Very preliminary squad war support.
123  * 
124  * 14    2/05/99 7:19p Neilk
125  * Removed black part from mission screen, fixed info text coords
126  * 
127  * 13    2/02/99 4:35p Neilk
128  * fixed coordinate problem where primary goals was on top of interface in
129  * mission briefing
130  * 
131  * 12    2/01/99 5:55p Dave
132  * Removed the idea of explicit bitmaps for buttons. Fixed text
133  * highlighting for disabled gadgets.
134  * 
135  * 11    1/30/99 7:32p Neilk
136  * Fixed coords problems for mission briefing screens
137  * 
138  * 10    1/30/99 5:08p Dave
139  * More new hi-res stuff.Support for nice D3D textures.
140  * 
141  * 9     1/30/99 1:29a Dave
142  * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
143  * screen.  Fixed beam weapon death messages.
144  * 
145  * 8     1/29/99 4:17p Dave
146  * New interface screens.
147  * 
148  * 7     1/13/99 7:19p Neilk
149  * Converted Mission Brief, Barracks, Synch to high res support
150  * 
151  * 6     12/18/98 1:13a Dave
152  * Rough 1024x768 support for Direct3D. Proper detection and usage through
153  * the launcher.
154  * 
155  * 5     11/30/98 1:07p Dave
156  * 16 bit conversion, first run.
157  * 
158  * 4     11/20/98 4:08p Dave
159  * Fixed flak effect in multiplayer.
160  * 
161  * 3     10/13/98 9:28a Dave
162  * Started neatening up freespace.h. Many variables renamed and
163  * reorganized. Added AlphaColors.[h,cpp]
164  * 
165  * 2     10/07/98 10:53a Dave
166  * Initial checkin.
167  * 
168  * 1     10/07/98 10:49a Dave
169  * 
170  * 114   9/17/98 3:08p Dave
171  * PXO to non-pxo game warning popup. Player icon stuff in create and join
172  * game screens. Upped server count refresh time in PXO to 35 secs (from
173  * 20).
174  * 
175  * 113   6/19/98 3:52p Lawrance
176  * Don't use large text in popup, since it is missing large foreign chars
177  * 
178  * 112   6/09/98 5:17p Lawrance
179  * French/German localization
180  * 
181  * 111   6/09/98 10:31a Hoffoss
182  * Created index numbers for all xstr() references.  Any new xstr() stuff
183  * added from here on out should be added to the end if the list.  The
184  * current list count can be found in FreeSpace.cpp (search for
185  * XSTR_SIZE).
186  * 
187  * 110   6/01/98 11:43a John
188  * JAS & MK:  Classified all strings for localization.
189  * 
190  * 109   5/22/98 10:44a Lawrance
191  * put in case label to suppress warning
192  * 
193  * 108   5/19/98 11:35p Lawrance
194  * Play sound for briefing control button presses
195  * 
196  * 107   5/19/98 8:47p Lawrance
197  * Set proper distance for jump nodes
198  * 
199  * 106   5/19/98 8:35p Dave
200  * Revamp PXO channel listing system. Send campaign goals/events to
201  * clients for evaluation. Made lock button pressable on all screens. 
202  * 
203  * 105   5/12/98 2:16p Hoffoss
204  * Added debug code to switch models of closeup icon to more easily check
205  * positions and zooms.
206  * 
207  * 104   5/06/98 11:50p Lawrance
208  * Clean up help overlay code for loadout screens
209  * 
210  * 103   5/06/98 8:03p Allender
211  * AL: only free pointers in brief_compact_stages if non-null
212  * 
213  * 102   5/05/98 4:48p Lawrance
214  * Fix bug with launching closeup icon when pause button is pressed
215  * 
216  * 101   4/29/98 1:45p Lawrance
217  * Print out mission filename if debug build, or if INTERPLAY QA defined
218  * 
219  * 100   4/29/98 12:15a Lawrance
220  * reset demo trailer timer when briefing moves to a new stage
221  * 
222  * 98    4/25/98 11:55p Lawrance
223  * fix bug with the auto-advance button
224  * 
225  * 97    4/25/98 3:49p Lawrance
226  * Save briefing auto-advance pref
227  * 
228  * 96    4/25/98 12:00p Lawrance
229  * disable advance keypress for 1/2 second after autoadvance
230  * 
231  * 95    4/22/98 7:24p Dave
232  * Made sure the "player/ships" locked button for multiplayer appears on
233  * all briefing screens.
234  * 
235  * 94    4/20/98 3:53p Lawrance
236  * Fix various bugs with auto-advancing through briefings.
237  * 
238  * 93    4/19/98 12:11p Lawrance
239  * add new art for pause button in the briefing
240  * 
241  * 92    4/17/98 10:39p Andsager
242  * AL: Fix bug with auto-advance of briefing stages.
243  * 
244  * 91    4/16/98 8:05p Lawrance
245  * Don't show closeup icon for planets
246  * 
247  * 90    4/15/98 5:17p Lawrance
248  * fix bug with skip training 
249  *
250  * $NoKeywords: $
251  *
252 */
253
254 #include "freespace.h"
255 #include "missionload.h"
256 #include "missionscreencommon.h"
257 #include "missionshipchoice.h"
258 #include "missionparse.h"
259 #include "missiongoals.h"
260 #include "gamesequence.h"
261 #include "ship.h"
262 #include "key.h"
263 #include "2d.h"
264 #include "line.h"
265 #include "3d.h"
266 #include "model.h"
267 #include "timer.h"
268 #include "math.h"
269 #include "linklist.h"
270 #include "mouse.h"
271 #include "hud.h"
272 #include "ui.h"
273 #include "osapi.h"
274 #include "audiostr.h"
275 #include "gamesnd.h"
276 #include "eventmusic.h"
277 #include "missioncampaign.h"
278 #include "object.h"
279 #include "multi.h"
280 #include "snazzyui.h"
281 #include "bmpman.h"
282 #include "missionbrief.h"
283 #include "missionbriefcommon.h"
284 #include "missiongrid.h"
285 #include "bmpman.h"
286 #include "multimsgs.h"
287 #include "cmdline.h"
288 #include "contexthelp.h"
289 #include "chatbox.h"
290 #include "multiteamselect.h"
291 #include "multiui.h"
292 #include "asteroid.h"
293 #include "popup.h"
294 #include "sexp.h"
295 #include "alphacolors.h"
296 #include "font.h"
297 #include "missionmessage.h"
298
299 /*
300 #define OBJECTIVES_X    65
301 #define OBJECTIVES_Y    137
302 #define OBJECTIVES_W    508
303 #define OBJECTIVES_H    233
304 */
305
306 static int Brief_goals_coords[GR_NUM_RESOLUTIONS][4] = {
307         {
308                 65,152,508,211          // GR_640
309         },
310         {
311                 104,243,813,332         // GR_1024
312         }
313 };
314
315 static int      Current_brief_stage;    // what stage of the briefing we're on
316 static int      Last_brief_stage;
317 static int      Num_brief_stages;
318 static int      Brief_multiplayer = FALSE;
319
320 static int      Brief_last_auto_advance = 0;    // timestamp of last auto-advance
321
322 // for managing the scene cut transition
323 static int      Quick_transition_stage;
324 static int      Start_fade_up_anim, Start_fade_down_anim;
325 static int      Brief_playing_fade_sound;
326 hud_anim                Fade_anim;
327
328 int     Briefing_music_handle = -1;
329 int     Briefing_music_begin_timestamp = 0;
330
331 // --------------------------------------------------------------------------------------
332 // Module scope globals
333 // --------------------------------------------------------------------------------------
334
335 static MENU_REGION      Briefing_select_region[NUM_BREIFING_REGIONS];
336 static int                              Num_briefing_regions;
337
338 // For closeup display 
339 #define                                 ONE_REV_TIME            6               // time (sec) for one revolution
340 #define                                 MAX_ANG_CHG                     0.15f
341
342 static int Closeup_coords[GR_NUM_RESOLUTIONS][4] = {
343         {
344                 203, 151, 200, 213      // GR_640
345         },
346         {
347                 325, 241, 200, 213      // GR_1024
348         }
349 };
350
351 static int Brief_infobox_coords[GR_NUM_RESOLUTIONS][2] = {
352         { // GR_640
353                 0, 391
354         },
355         { // GR_1024
356                 0, 627
357         }
358 };
359
360 static char *Brief_infobox_filename[GR_NUM_RESOLUTIONS] = {
361         "InfoBox",
362         "2_Infobox"
363 };
364
365 static char *Brief_filename[GR_NUM_RESOLUTIONS] = {
366         "Brief",
367         "2_Brief"
368 };
369
370 static char *Brief_multi_filename[GR_NUM_RESOLUTIONS] = {
371         "BriefMulti",
372         "2_BriefMulti"
373 };
374
375 static char *Brief_mask_filename[GR_NUM_RESOLUTIONS] = {
376         "Brief-m",
377         "2_Brief-m"
378 };
379
380 static char *Brief_multi_mask_filename[GR_NUM_RESOLUTIONS] = {
381         "BriefMulti-m",
382         "2_BriefMulti-m"
383 };
384
385
386 static char *Brief_win_filename[GR_NUM_RESOLUTIONS] = {
387         "Briefwin",
388         "2_Briefwin"
389 };
390
391 // coordinate inidices
392 #define BRIEF_X_COORD 0
393 #define BRIEF_Y_COORD 1
394 #define BRIEF_W_COORD 2
395 #define BRIEF_H_COORD 3
396
397 //static int Closeup_region[4] = {220,132,420,269};
398 int Closeup_region[GR_NUM_RESOLUTIONS][4] = {
399         { // GR_640
400                 211, 158, 215, 157
401         }, 
402         { // GR_1024
403                 337, 253, 345, 252
404         }, 
405 };
406
407 char *Closeup_background_filename[GR_NUM_RESOLUTIONS] = {
408         NOX("BriefPop"),        // GR_640
409         NOX("2_BriefPop")       // GR_1024
410 };
411
412 char *Closeup_button_filename[GR_NUM_RESOLUTIONS] = {
413         NOX("BPB_00"),          // GR_640
414         NOX("2_BPB_00"),                // GR_1024
415 };
416
417 int Closeup_button_hotspot = 14;
418
419 //static int                    Closeup_button_coords[2] = {CLOSEUP_X+164,CLOSEUP_Y+227};
420 int Closeup_button_coords[GR_NUM_RESOLUTIONS][2] = {    
421         { 374, 316 },           // GR_640       
422         { 599, 506 }            // GR_1024      
423 };
424
425 UI_BUTTON       Closeup_close_button;
426 int Closeup_bitmap=-1;
427 int Closeup_one_revolution_time=ONE_REV_TIME;
428
429 brief_icon *Closeup_icon;
430 angles Closeup_angles;
431 matrix Closeup_orient;
432 vector Closeup_pos;
433 int Closeup_font_height;
434 int Closeup_x1, Closeup_y1;
435
436 // used for the 3d view of a closeup ship
437 float Closeup_zoom;
438 vector Closeup_cam_pos;
439
440 // Mask bitmap pointer and Mask bitmap_id
441 bitmap* BriefingMaskPtr;                // bitmap pointer to the briefing select mask bitmap
442 ubyte* BriefingMaskData;                // pointer to actual bitmap data
443 int Briefing_mask_w, Briefing_mask_h;
444 int BriefingMaskBitmap; // bitmap id of the briefing mask bitmap
445 int Brief_inited = FALSE;
446
447 // --------------------------------------------------------------------------------------
448 // Briefing specific UI
449 // --------------------------------------------------------------------------------------
450 #define BRIEF_LAST_STAGE_MASK                   7
451 #define BRIEF_NEXT_STAGE_MASK                   8
452 #define BRIEF_PREV_STAGE_MASK                   9
453 #define BRIEF_FIRST_STAGE_MASK                  10
454 #define BRIEF_TEXT_SCROLL_UP_MASK               11
455 #define BRIEF_TEXT_SCROLL_DOWN_MASK     12
456 #define BRIEF_SKIP_TRAINING_MASK                15
457 #define BRIEF_PAUSE_MASK                                        16
458
459 //XSTR:OFF
460 static char *Brief_mask_single[GR_NUM_RESOLUTIONS] = {
461         "brief-m",              // GR_640
462         "2_brief-m"             // GR_1024
463 };
464
465 static char *Brief_mask_multi[GR_NUM_RESOLUTIONS] = {
466         "briefmulti-m",         // GR_640
467         "2_briefmulti-m"                        // GR_1024
468 };
469 //XSTR:ON
470
471 struct brief_buttons {  
472         char *filename;
473         int x, y;
474         int xt, yt;
475         int hotspot;
476         int repeat;
477         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
478
479         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) {}
480 };
481
482 int     Brief_grid_bitmap = -1;
483 int     Brief_text_bitmap = -1;
484
485 int     Brief_multitext_bitmap = -1;
486 int     Brief_background_bitmap =-1;
487
488 UI_WINDOW Brief_ui_window;
489
490 // Briefing specific buttons
491 #define NUM_BRIEF_BUTTONS 10
492
493 brief_buttons   Brief_buttons[GR_NUM_RESOLUTIONS][NUM_BRIEF_BUTTONS] = {
494         { // GR_640
495                 brief_buttons("BRB_08",         110,    116,    117,    157,    8),
496                 brief_buttons("BRB_09",         84,     116,    117,    157,    9),
497                 brief_buttons("BRB_10",         29,     116,    117,    157,    10),
498                 brief_buttons("BRB_11",         4,              116,    117,    157,    11),
499                 brief_buttons("BRB_12",         0,              405,    117,    157,    12),
500                 brief_buttons("BRB_13",         0,              447,    117,    157,    13),                    
501                 brief_buttons("BRB_15",         562,    0,              117,    157,    15),                    // skip training
502                 brief_buttons("BRB_16",         56,     116,    117,    157,    16),
503                 brief_buttons("TSB_34",         603,    374,    117,    157,    34),    
504                 brief_buttons("BRB_15",         562,    0,              117,    157,    15)                     // exit loop    
505         }, 
506         { // GR_1024
507                 brief_buttons("2_BRB_08",               175,    187,    117,    157,    8),
508                 brief_buttons("2_BRB_09",               135,    187,    117,    157,    9),
509                 brief_buttons("2_BRB_10",               47,     187,    117,    157,    10),
510                 brief_buttons("2_BRB_11",               8,              187,    117,    157,    11),
511                 brief_buttons("2_BRB_12",               0,              649,    117,    157,    12),
512                 brief_buttons("2_BRB_13",               0,              716,    117,    157,    13),                    
513                 brief_buttons("2_BRB_15",               900,    0,              117,    157,    15),            // skip training
514                 brief_buttons("2_BRB_16",               91,     187,    117,    157,    16),
515                 brief_buttons("2_TSB_34",               966,    599,    117,    157,    34),                    
516                 brief_buttons("2_BRB_15",               900,    0,              117,    157,    15)                     // exit loop    
517         },      
518 };
519
520 // briefing UI
521 #define BRIEF_SELECT_NUM_TEXT                   3
522 UI_XSTR Brief_select_text[GR_NUM_RESOLUTIONS][BRIEF_SELECT_NUM_TEXT] = {
523         { // GR_640
524                 { "Lock",                               1270,   602,    364,    UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_MULTI_LOCK].button },
525                 { "Skip Training",      1442,   467,    7,              UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_SKIP_TRAINING].button },
526                 { "Exit Loop",                  1477,   490,    7,              UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[0][BRIEF_BUTTON_EXIT_LOOP].button }
527         }, 
528         { // GR_1024
529                 { "Lock",                               1270,   964,    584,    UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_MULTI_LOCK].button },
530                 { "Skip Training",      1442,   805,    12,     UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_SKIP_TRAINING].button },
531                 { "Exit Loop",                  1477,   830,    12,     UI_XSTR_COLOR_GREEN, -1, &Brief_buttons[1][BRIEF_BUTTON_EXIT_LOOP].button }
532         }
533 };
534
535 // coordinates for briefing title -- the x value is for the RIGHT side of the text
536 static int Title_coords[GR_NUM_RESOLUTIONS][2] = {
537         {575, 117},             // GR_640
538         {918, 194}              // GR_1024
539 };
540
541 // coordinates for briefing title in multiplayer briefings -- the x value is for the LEFT side of the text
542 // third coord is max width of area for it to fit into (it is force fit there)
543 static int Title_coords_multi[GR_NUM_RESOLUTIONS][3] = {
544         {1, 105, 190},          // GR_640
545         {1, 174, 304}           // GR_1024
546 };
547
548 // briefing line widths
549 int Brief_max_line_width[GR_NUM_RESOLUTIONS] = {
550         MAX_BRIEF_LINE_W_640, MAX_BRIEF_LINE_W_1024
551 };
552
553 // --------------------------------------------------------------------------------------
554 // Forward declarations
555 // --------------------------------------------------------------------------------------
556 int brief_setup_closeup(brief_icon *bi);
557 void brief_maybe_blit_scene_cut(float frametime);
558 void brief_transition_reset();
559
560 char *brief_tooltip_handler(char *str)
561 {
562         if (!stricmp(str, NOX("@close"))) {
563                 if (Closeup_icon)
564                         return XSTR( "Close", 428);
565         }
566
567         return NULL;
568 }
569
570 // brief_skip_training_pressed()
571 //
572 // called when the skip training button on the briefing screen is hit.  When this happens,
573 // do a popup, then move to the next mission in the campaign.
574 void brief_skip_training_pressed()
575 {
576         int val;
577
578         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));
579
580         // val is 0 when we hit no (first on the list)
581         // AL: also, -1 is returned when ESC is hit
582         if ( val <= 0 ){
583                 return;
584         }
585
586         // page out mission messages
587         message_mission_shutdown();
588
589         if ( !(Game_mode & GM_CAMPAIGN_MODE) ){
590                 gameseq_post_event( GS_EVENT_MAIN_MENU );
591         }
592
593         // tricky part.  Need to move to the next mission in the campaign.
594         mission_goal_mark_objectives_complete();
595         mission_goal_fail_incomplete();
596         mission_campaign_store_goals_and_events();
597
598         mission_campaign_eval_next_mission();
599         mission_campaign_mission_over();        
600
601         // CD CHECK
602         if(game_do_cd_mission_check(Game_current_mission_filename)){
603                 gameseq_post_event( GS_EVENT_START_GAME );
604         } else {
605                 gameseq_post_event( GS_EVENT_MAIN_MENU );
606         }
607 }
608
609 #ifdef FS2_DEMO
610         extern void demo_reset_trailer_timer();
611 #endif
612 // --------------------------------------------------------------------------------------
613 //      brief_do_next_pressed()
614 //
615 //
616 void brief_do_next_pressed(int play_sound)
617 {
618         int now;
619         now = timer_get_milliseconds();
620
621         if ( (now - Brief_last_auto_advance) < 500 ) {
622                 return;
623         }
624
625 #ifdef FS2_DEMO
626         demo_reset_trailer_timer();
627 #endif
628
629         Current_brief_stage++;
630         if ( Current_brief_stage >= Num_brief_stages ) {
631                 Current_brief_stage = Num_brief_stages - 1;
632                 gamesnd_play_iface(SND_GENERAL_FAIL);
633                 if ( Quick_transition_stage != -1 )
634                         brief_transition_reset();
635         } else {
636                 if ( play_sound ) {
637                         gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
638                 }
639         }
640
641         Assert(Current_brief_stage >= 0);
642 }
643
644 // --------------------------------------------------------------------------------------
645 //      brief_do_prev_pressed()
646 //
647 //
648 void brief_do_prev_pressed()
649 {
650         Current_brief_stage--;
651         if ( Current_brief_stage < 0 ) {
652                 Current_brief_stage = 0;
653                 gamesnd_play_iface(SND_GENERAL_FAIL);
654                 if ( Quick_transition_stage != -1 )
655                         brief_transition_reset();
656         } else {
657                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
658         }
659         Assert(Current_brief_stage >= 0);
660 }
661
662
663 // --------------------------------------------------------------------------------------
664 //      brief_do_start_pressed()
665 //
666 //
667 void brief_do_start_pressed()
668 {
669         if ( Current_brief_stage != 0 ) {
670                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
671                 Current_brief_stage = 0;
672                 if ( Quick_transition_stage != -1 )
673                         brief_transition_reset();
674         } else {
675                 gamesnd_play_iface(SND_GENERAL_FAIL);
676         }
677         Assert(Current_brief_stage >= 0);
678 }
679
680 // --------------------------------------------------------------------------------------
681 //      brief_do_end_pressed()
682 //
683 //
684 void brief_do_end_pressed()
685 {
686         if ( Current_brief_stage != Num_brief_stages - 1 ) {
687                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
688                 Current_brief_stage = Num_brief_stages - 1;
689                 if ( Quick_transition_stage != -1 )
690                         brief_transition_reset();
691
692         } else {
693                 gamesnd_play_iface(SND_GENERAL_FAIL);
694         }
695         Assert(Current_brief_stage >= 0);
696 }
697
698
699 void brief_scroll_up_text()
700 {
701         Top_brief_text_line--;
702         if ( Top_brief_text_line < 0 ) {
703                 Top_brief_text_line = 0;
704                 gamesnd_play_iface(SND_GENERAL_FAIL);
705         } else {
706                 gamesnd_play_iface(SND_SCROLL);
707         }
708 }
709
710 void brief_scroll_down_text()
711 {
712         Top_brief_text_line++;
713         if ( (Num_brief_text_lines[0] - Top_brief_text_line) < Brief_text_max_lines[gr_screen.res]) {
714                 Top_brief_text_line--;
715                 gamesnd_play_iface(SND_GENERAL_FAIL);
716         } else {
717                 gamesnd_play_iface(SND_SCROLL);
718         }
719 }
720
721
722 // handles the exit loop option
723 void brief_exit_loop_pressed()
724 {
725         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));
726
727         // bail if esc hit or no clicked
728         if (val <= 0) {
729                 return;
730         }
731
732         // handle the details
733         // this also posts the start game event
734         mission_campaign_exit_loop();
735 }
736
737
738 // -------------------------------------------------------------------------------------
739 // brief_select_button_do() do the button action for the specified pressed button
740 //
741 void brief_button_do(int i)
742 {
743         switch ( i ) {
744                 case BRIEF_BUTTON_LAST_STAGE:
745                         brief_do_end_pressed();
746                         break;
747
748                 case BRIEF_BUTTON_NEXT_STAGE:
749                         brief_do_next_pressed(1);
750                         break;
751
752                 case BRIEF_BUTTON_PREV_STAGE:
753                         brief_do_prev_pressed();
754                         break;
755
756                 case BRIEF_BUTTON_FIRST_STAGE:
757                         brief_do_start_pressed();
758                         break;
759
760                 case BRIEF_BUTTON_SCROLL_UP:
761                         brief_scroll_up_text();
762                         break;
763
764                 case BRIEF_BUTTON_SCROLL_DOWN:
765                         brief_scroll_down_text();
766                         break;
767
768                 case BRIEF_BUTTON_PAUSE:
769                         gamesnd_play_iface(SND_USER_SELECT);
770                         Player->auto_advance ^= 1;
771                         break;
772
773                 case BRIEF_BUTTON_SKIP_TRAINING:
774                         brief_skip_training_pressed();
775                         break;
776
777                 case BRIEF_BUTTON_EXIT_LOOP:
778                         brief_exit_loop_pressed();
779                         break;
780
781                 case BRIEF_BUTTON_MULTI_LOCK:
782                         Assert(Game_mode & GM_MULTIPLAYER);                     
783                         // the "lock" button has been pressed
784                         multi_ts_lock_pressed();
785
786                         // disable the button if it is now locked
787                         if(multi_ts_is_locked()){
788                                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
789                         }
790                         break;
791         } // end switch
792 }
793
794 // -------------------------------------------------------------------
795 // brief_check_buttons()
796 //
797 // Iterate through the briefing buttons, checking if they are pressed
798 //
799 void brief_check_buttons()
800 {
801         int                     i;
802         UI_BUTTON       *b;
803
804         for (i=0; i<NUM_BRIEF_BUTTONS; i++) {
805                 b = &Brief_buttons[gr_screen.res][i].button;
806                 if ( b->pressed() ) {
807                         common_flash_button_init();
808                         brief_button_do(i);
809                 }
810         }
811
812         if (Closeup_close_button.pressed()) {
813                 brief_turn_off_closeup_icon();
814         }
815 }
816
817 // -------------------------------------------------------------------
818 // brief_redraw_pressed_buttons()
819 //
820 // Redraw any briefing buttons that are pressed down.  This function is needed
821 // since we sometimes need to draw pressed buttons last to ensure the entire
822 // button gets drawn (and not overlapped by other buttons)
823 //
824 void brief_redraw_pressed_buttons()
825 {
826         int                     i;
827         UI_BUTTON       *b;
828         
829         common_redraw_pressed_buttons();
830
831         for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
832                 b = &Brief_buttons[gr_screen.res][i].button;
833                 if ( b->button_down() ) {
834                         b->draw_forced(2);
835                 }
836         }
837
838         if ( !Player->auto_advance ) {
839                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.draw_forced(2);
840         }
841 }
842
843 void brief_buttons_init()
844 {
845         UI_BUTTON       *b;
846         int                     i;
847
848         //if ( Briefing->num_stages <= 0 )
849         //      return;
850
851         for ( i = 0; i < NUM_BRIEF_BUTTONS; i++ ) {
852                 b = &Brief_buttons[gr_screen.res][i].button;
853                 b->create( &Brief_ui_window, "", Brief_buttons[gr_screen.res][i].x, Brief_buttons[gr_screen.res][i].y, 60, 30, 0, 1 );
854                 // set up callback for when a mouse first goes over a button
855                 b->set_highlight_action( common_play_highlight_sound );
856
857                 if ((i == BRIEF_BUTTON_SKIP_TRAINING) || (i == BRIEF_BUTTON_EXIT_LOOP)) {
858                         b->set_bmaps(Brief_buttons[gr_screen.res][i].filename, 3, 0);
859                 } else {
860                         b->set_bmaps(Brief_buttons[gr_screen.res][i].filename);
861                 }
862                 b->link_hotspot(Brief_buttons[gr_screen.res][i].hotspot);
863         }
864
865         // add all xstrs
866         for(i=0; i<BRIEF_SELECT_NUM_TEXT; i++) {
867                 Brief_ui_window.add_XSTR(&Brief_select_text[gr_screen.res][i]);
868         }
869
870         // Hide the 'skip training' button by default.  Only enable and unhide if we are playing a training
871         // mission
872         Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.disable();
873         Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.hide();
874         if ( (Game_mode & GM_NORMAL) && (The_mission.game_type & MISSION_TYPE_TRAINING) ) {
875                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.enable();
876                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SKIP_TRAINING].button.unhide();
877         }
878
879         // Hide the 'exit loop' button by default.  Only enable and unhide if we are playing a loop
880         // mission
881         Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.disable();
882         Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.hide();
883         if ( (Game_mode & GM_NORMAL) && (Campaign.loop_enabled) && (Game_mode & GM_CAMPAIGN_MODE) ) {
884                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.enable();
885                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_EXIT_LOOP].button.unhide();
886         }
887
888         // maybe disable the multi-lock button
889         if(!(Game_mode & GM_MULTIPLAYER)){
890                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.hide();
891                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
892         } else {
893                 // if we're not the host of the game (or a tema captain in team vs. team mode), disable the lock button
894                 if(Netgame.type_flags & NG_TYPE_TEAM){
895                         if(!(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
896                                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
897                         }
898                 } else {
899                         if(!(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
900                                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.disable();
901                         }
902                 }
903         }
904
905         // create close button for closeup popup
906         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 );
907         Closeup_close_button.set_highlight_action( common_play_highlight_sound );
908         Closeup_close_button.set_bmaps(Closeup_button_filename[gr_screen.res]);
909         Closeup_close_button.link_hotspot(Closeup_button_hotspot);
910
911         // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
912         Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_RIGHT);
913         Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.set_hotkey(KEY_RIGHT);
914         Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.set_hotkey(KEY_LEFT);
915         Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.set_hotkey(KEY_SHIFTED|KEY_LEFT);
916         Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.set_hotkey(KEY_UP);
917         Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);
918
919         Closeup_close_button.disable();
920         Closeup_close_button.hide();
921
922         // if we have no briefing stages, hide and disable briefing buttons
923         if(Num_brief_stages <= 0){
924                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.disable();
925                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_LAST_STAGE].button.hide();
926                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.disable();
927                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_NEXT_STAGE].button.hide();
928                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.disable();
929                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PREV_STAGE].button.hide();
930                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.disable();
931                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_FIRST_STAGE].button.hide();
932                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.disable();
933                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_UP].button.hide();
934                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.disable();
935                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_SCROLL_DOWN].button.hide();
936                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.disable();
937                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_PAUSE].button.hide();         
938         }
939 }
940
941 // --------------------------------------------------------------------------------------
942 //      brief_get_closeup_icon()
943 //
944 //
945 uint brief_get_closeup_icon()
946 {
947         return (uint)Closeup_icon;
948 }
949
950 // stop showing the closeup view of an icon
951 void brief_turn_off_closeup_icon()
952 {
953         // turn off closup
954         if ( Closeup_icon != NULL ) {
955                 gamesnd_play_iface(SND_BRIEF_ICON_SELECT);
956                 Closeup_icon = NULL;
957                 Closeup_close_button.disable();
958                 Closeup_close_button.hide();
959         }
960 }
961
962 // --------------------------------------------------------------------------------------
963 //      brief_load_bitmaps()
964 //
965 //
966 void brief_load_bitmaps()
967 {
968         Brief_text_bitmap = bm_load(Brief_infobox_filename[gr_screen.res]);
969         Brief_grid_bitmap = bm_load(Brief_win_filename[gr_screen.res]);
970         
971         if ( Closeup_bitmap == -1 ) {
972                 Closeup_bitmap = bm_load(Closeup_background_filename[gr_screen.res]);
973         }
974 }
975
976 // --------------------------------------------------------------------------------------
977 //      brief_ui_init()
978 //
979 //
980 void brief_ui_init()
981 {
982         if(Game_mode & GM_MULTIPLAYER) {
983                 Brief_background_bitmap = bm_load(Brief_multi_filename[gr_screen.res]);
984         } else {
985                 Brief_background_bitmap = bm_load(Brief_filename[gr_screen.res]);       
986         }
987
988         if ( Num_brief_stages <= 0 ){
989                 return;
990         }
991
992         brief_load_bitmaps();
993 }
994
995
996 // --------------------------------------------------------------------------------------
997 //      brief_set_default_closeup()
998 //
999 //
1000 void brief_set_default_closeup()
1001 {
1002         brief_stage             *bs;
1003         int                             i;
1004
1005         bs = &Briefing->stages[0];
1006
1007         if ( Briefing->num_stages <= 0 ) {
1008                 Closeup_icon = NULL;
1009                 return;
1010         }
1011
1012         if ( bs->num_icons <= 0 ) {
1013                 Closeup_icon = NULL;
1014                 return;
1015         }
1016
1017         // check for the first highlighted icons to have as the default closeup
1018         for ( i = 0; i < bs->num_icons; i++ ) {
1019                 if ( bs->icons[i].flags & BI_HIGHLIGHT )
1020                         break;
1021         }
1022         
1023         if ( i == bs->num_icons ) {
1024                 brief_setup_closeup(&bs->icons[0]);
1025         }
1026         else {
1027                 brief_setup_closeup(&bs->icons[i]);
1028         }
1029 }
1030
1031 //  funciton to evaluate the sexpressions of the briefing stages eliminating those stages
1032 // which shouldn't get shown
1033 void brief_compact_stages()
1034 {
1035         int num, result, i;
1036
1037         /*
1038         if((Game_mode & GM_MULTIPLAYER) && (Netgame.campaign_mode == MP_CAMPAIGN) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1039                 Game_mode |= GM_CAMPAIGN_MODE;
1040         }
1041         */
1042
1043         num = 0;
1044         while ( num < Briefing->num_stages ) {
1045                 result = eval_sexp( Briefing->stages[num].formula );
1046                 if ( !result ) {
1047                         if ( Briefing->stages[num].new_text ) {
1048                                 free( Briefing->stages[num].new_text );
1049                                 Briefing->stages[num].new_text = NULL;
1050                         }
1051
1052                         if ( Briefing->stages[num].icons ) {
1053                                 free( Briefing->stages[num].icons );
1054                                 Briefing->stages[num].icons = NULL;
1055                         }
1056
1057
1058                         if ( Briefing->stages[num].lines ) {
1059                                 free( Briefing->stages[num].lines );
1060                                 Briefing->stages[num].lines = NULL;
1061                         }
1062
1063                         Briefing->stages[num].num_icons = 0;
1064                         for ( i = num+1; i < Briefing->num_stages; i++ ) {
1065                                 Briefing->stages[i-1] = Briefing->stages[i];
1066                         }
1067                         Briefing->num_stages--;
1068                         continue;
1069                 }
1070                 num++;
1071         }
1072
1073         /*
1074         if((Game_mode & GM_MULTIPLAYER) && (Netgame.campaign_mode == MP_CAMPAIGN) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1075                 Game_mode &= ~(GM_CAMPAIGN_MODE);
1076         }
1077         */
1078 }
1079
1080
1081 // --------------------------------------------------------------------------------------
1082 // brief_init() 
1083 //
1084         int red_alert_mission(void);
1085 //
1086 void brief_init()
1087 {
1088         // Since first stage of briefing can take some time to arrive and play, 
1089         // reset the trailer timer on briefing init.
1090 #ifdef FS2_DEMO
1091         demo_reset_trailer_timer();
1092 #endif
1093
1094         // for multiplayer, change the state in my netplayer structure
1095         // and initialize the briefing chat area thingy
1096         if ( Game_mode & GM_MULTIPLAYER ){
1097                 Net_player->state = NETPLAYER_STATE_BRIEFING;
1098         }
1099
1100         // Non standard briefing in red alert mission
1101         if ( red_alert_mission() ) {
1102                 gameseq_post_event(GS_EVENT_RED_ALERT);
1103                 return;
1104         }
1105
1106         // get a pointer to the appropriate briefing structure
1107         if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
1108                 Briefing = &Briefings[Net_player->p_info.team];
1109         } else {
1110                 Briefing = &Briefings[0];                       
1111         }
1112
1113         Brief_last_auto_advance = 0;
1114
1115         brief_compact_stages();                 // compact the briefing array to eliminate unused stages
1116
1117         common_set_interface_palette("BriefingPalette");
1118
1119         ship_stop_animation();
1120         set_active_ui(&Brief_ui_window);
1121         Current_screen = ON_BRIEFING_SELECT;
1122         brief_restart_text_wipe();
1123         common_flash_button_init();
1124         common_music_init(SCORE_BRIEFING);
1125
1126
1127         help_overlay_set_state(BR_OVERLAY,0);
1128
1129         if ( Brief_inited == TRUE ) {
1130                 common_buttons_maybe_reload(&Brief_ui_window);  // AL 11-21-97: this is necessary since we may returning from the hotkey
1131                                                                                                                                                 // screen, which can release common button bitmaps.
1132                 common_reset_buttons();
1133                 nprintf(("Alan","brief_init() returning without doing anything\n"));
1134                 return;
1135         }
1136
1137         if (The_mission.game_type & MISSION_TYPE_TRAINING)
1138                 Num_brief_stages = Briefing->num_stages;
1139         else
1140                 Num_brief_stages = Briefing->num_stages + 1;
1141
1142         Current_brief_stage = 0;
1143         Last_brief_stage = 0;
1144
1145         // init the scene-cut data
1146         brief_transition_reset();
1147
1148 #ifndef FS2_DEMO        
1149         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]);
1150         hud_anim_load(&Fade_anim);
1151 #endif
1152
1153         nprintf(("Alan","Entering brief_init()\n"));
1154         common_select_init();
1155
1156         if(Game_mode & GM_MULTIPLAYER) {
1157                 BriefingMaskBitmap = bm_load(Brief_multi_mask_filename[gr_screen.res]);
1158         } else {
1159                 BriefingMaskBitmap = bm_load(Brief_mask_filename[gr_screen.res]);
1160         }
1161
1162         if (BriefingMaskBitmap < 0) {
1163                 Error(LOCATION,"Could not load in 'brief-m'!");
1164         }
1165
1166         Briefing_mask_w = -1;
1167         Briefing_mask_h = -1;
1168
1169         // get a pointer to bitmap by using bm_lock()
1170         BriefingMaskPtr = bm_lock(BriefingMaskBitmap, 8, BMP_AABITMAP);
1171         BriefingMaskData = (ubyte*)BriefingMaskPtr->data;
1172         bm_get_info(BriefingMaskBitmap, &Briefing_mask_w, &Briefing_mask_h);
1173
1174         help_overlay_load(BR_OVERLAY);
1175
1176         // Set up the mask regions
1177    // initialize the different regions of the menu that will react when the mouse moves over it
1178         Num_briefing_regions = 0;
1179
1180         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_BRIEFING_REGION,                         0);
1181         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_SS_REGION,                                               0);
1182         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_WEAPON_REGION,                           0);
1183         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_COMMIT_REGION,                           0);
1184         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_HELP_REGION,                                     0);
1185         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     COMMON_OPTIONS_REGION,                          0);
1186
1187         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_LAST_STAGE_MASK,                  0);
1188         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_NEXT_STAGE_MASK,                  0);
1189         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_PREV_STAGE_MASK,                  0);
1190         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_FIRST_STAGE_MASK,                 0);
1191         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_TEXT_SCROLL_UP_MASK,              0);
1192         snazzy_menu_add_region(&Briefing_select_region[Num_briefing_regions++], "",     BRIEF_TEXT_SCROLL_DOWN_MASK,    0);
1193
1194         // init common UI
1195         Brief_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
1196
1197         if(Game_mode & GM_MULTIPLAYER){
1198                 Brief_ui_window.set_mask_bmap(Brief_mask_multi[gr_screen.res]);
1199         } else {
1200                 Brief_ui_window.set_mask_bmap(Brief_mask_single[gr_screen.res]);
1201         }
1202
1203         Brief_ui_window.tooltip_handler = brief_tooltip_handler;
1204         common_buttons_init(&Brief_ui_window);
1205         brief_buttons_init();
1206
1207         // if multiplayer, initialize a few other systems
1208         if(Game_mode & GM_MULTIPLAYER){         
1209                 // again, should not be necessary, but we'll leave it for now
1210                 chatbox_create();
1211
1212                 // force the chatbox to be small
1213                 chatbox_force_small();
1214         }
1215
1216         // set up the screen regions
1217         brief_init_screen(Brief_multiplayer);
1218
1219         // init briefing specific UI
1220         brief_ui_init();
1221
1222         // init the briefing map
1223         brief_init_map();
1224
1225         // init the briefing voice playback
1226         brief_voice_init();
1227         brief_voice_load_all();
1228
1229         // init objectives display stuff
1230         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]);
1231
1232         // set the camera target
1233         if ( Briefing->num_stages > 0 ) {
1234                 brief_set_new_stage(&Briefing->stages[0].camera_pos, &Briefing->stages[0].camera_orient, 0, Current_brief_stage);
1235                 brief_reset_icons(Current_brief_stage);
1236         }
1237
1238         Brief_playing_fade_sound = 0;
1239         Brief_mouse_up_flag     = 0;
1240         Closeup_font_height = gr_get_font_height();
1241         Closeup_icon = NULL;
1242    Brief_inited = TRUE;
1243 }
1244
1245 // -------------------------------------------------------------------------------------
1246 // brief_render_closeup_text()
1247 //
1248 //
1249 #define CLOSEUP_TEXT_OFFSET     10
1250 void brief_render_closeup_text()
1251 {
1252 /*
1253         brief_icon      *bi;
1254         char                    line[MAX_ICON_TEXT_LINE_LEN];
1255         int                     n_lines, i, render_x, render_y;
1256         int                     n_chars[MAX_ICON_TEXT_LINES];
1257         char                    *p_str[MAX_ICON_TEXT_LINES];
1258
1259         if ( Closeup_icon == NULL ) {
1260                 Int3();
1261                 return;
1262         }
1263
1264         bi = Closeup_icon;
1265
1266         render_x = Closeup_region[0];
1267         render_y = Closeup_region[1] + CLOSEUP_IMG_H;
1268         
1269         gr_set_clip(render_x+CLOSEUP_TEXT_OFFSET, render_y, CLOSEUP_W,CLOSEUP_TEXT_H);
1270         gr_set_color_fast(&Color_white);
1271
1272 //      n_lines = split_str(bi->text, CLOSEUP_W - 2*CLOSEUP_TEXT_OFFSET, n_chars, p_str, MAX_ICON_TEXT_LINES);
1273         Assert(n_lines != -1);
1274
1275         for ( i = 0; i < n_lines; i++ ) {
1276                 Assert(n_chars[i] < MAX_ICON_TEXT_LINE_LEN);
1277                 strncpy(line, p_str[i], n_chars[i]);
1278                 line[n_chars[i]] = 0;
1279                 gr_printf(0,0+i*Closeup_font_height,line);
1280         }
1281 */
1282 }
1283
1284 // -------------------------------------------------------------------------------------
1285 // brief_render_closeup()
1286 //
1287 //
1288 void brief_render_closeup(int ship_class, float frametime)
1289 {
1290         matrix  view_orient = IDENTITY_MATRIX;
1291         matrix  temp_matrix;
1292         float           ang;
1293         int             w,h;
1294
1295         if (ship_class < 0)
1296                 return;
1297
1298         if (Closeup_bitmap < 0)
1299                 return;
1300
1301         ang = PI2 * frametime/Closeup_one_revolution_time;
1302         if ( ang > MAX_ANG_CHG )
1303                 ang = MAX_ANG_CHG;
1304
1305         Closeup_angles.h += ang;
1306         if ( Closeup_angles.h > PI2 )
1307                 Closeup_angles.h -= PI2;
1308         vm_angles_2_matrix(&temp_matrix, &Closeup_angles );
1309         Closeup_orient = temp_matrix;
1310
1311         w = Closeup_region[gr_screen.res][2];
1312         h = Closeup_region[gr_screen.res][3];
1313         gr_set_clip(Closeup_region[gr_screen.res][0], Closeup_region[gr_screen.res][1], w, h);
1314
1315         g3_start_frame(1);
1316
1317         g3_set_view_matrix(&Closeup_cam_pos, &view_orient, Closeup_zoom);
1318         model_clear_instance( Closeup_icon->modelnum );
1319         model_set_detail_level(0);
1320
1321         int is_neb = The_mission.flags & MISSION_FLAG_FULLNEB;
1322
1323         // maybe switch off nebula rendering
1324         if(is_neb){
1325                 The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1326         }
1327
1328         int model_render_flags;
1329         if ( Closeup_icon->type == ICON_JUMP_NODE ) {
1330                 model_set_outline_color(HUD_color_red, HUD_color_green, HUD_color_blue);                
1331                 model_render_flags = MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_POLYS | MR_SHOW_OUTLINE;
1332         } else {
1333                 model_render_flags = MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER;
1334         }
1335
1336         model_render( Closeup_icon->modelnum, &Closeup_orient, &Closeup_pos, model_render_flags );
1337
1338         if (is_neb) {
1339                 The_mission.flags |= MISSION_FLAG_FULLNEB;
1340         }
1341
1342         g3_end_frame();
1343
1344         gr_set_color_fast(&Color_bright_white);
1345
1346         gr_printf(0x8000,2,Closeup_icon->closeup_label);
1347 //      brief_render_closeup_text();
1348
1349         Closeup_close_button.enable();
1350         Closeup_close_button.unhide();
1351
1352         gr_reset_clip();
1353 }
1354
1355 // -------------------------------------------------------------------------------------
1356 // brief_render()
1357 //
1358 //      frametime is in seconds
1359 void brief_render(float frametime)
1360 {
1361         int z;
1362         int w;
1363
1364 #ifndef NDEBUG
1365         int h;
1366 #endif
1367
1368         if ( Num_brief_stages <= 0 ) {
1369                 gr_set_color_fast(&Color_white);
1370                 Assert( Game_current_mission_filename != NULL );
1371                 gr_printf(0x8000,200,XSTR( "No Briefing exists for mission: %s", 430), Game_current_mission_filename);
1372
1373                 #ifndef NDEBUG
1374                 gr_get_string_size(&w, &h, The_mission.name);
1375                 gr_set_color_fast(&Color_normal);
1376                 gr_printf(0x8000, 230, NOX("[filename: %s, last mod: %s]"), Mission_filename, The_mission.modified);
1377                 #endif
1378
1379                 return;
1380         }
1381
1382         gr_set_bitmap(Brief_grid_bitmap);
1383         gr_bitmap(Brief_bmap_coords[gr_screen.res][0], Brief_bmap_coords[gr_screen.res][1]);
1384
1385         brief_render_map(Current_brief_stage, frametime);
1386
1387         // draw the frame bitmaps
1388         gr_set_bitmap(Brief_text_bitmap);
1389         gr_bitmap(Brief_infobox_coords[gr_screen.res][0], Brief_infobox_coords[gr_screen.res][1]);
1390         brief_blit_stage_num(Current_brief_stage, Num_brief_stages);
1391
1392         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);
1393         if (z) {
1394                 brief_voice_play(Current_brief_stage);
1395         }
1396
1397         // maybe output the "more" indicator
1398         if ( (Brief_text_max_lines[gr_screen.res] + Top_brief_text_line + 2) < Num_brief_text_lines[0] ) {
1399                 // can be scrolled down
1400                 int more_txt_x = Brief_text_coords[gr_screen.res][0] + (Brief_max_line_width[gr_screen.res]/2) - 10;
1401                 int more_txt_y = Brief_text_coords[gr_screen.res][1] + Brief_text_coords[gr_screen.res][3] - 2;                         // located below brief text, centered
1402                 int w, h;
1403                 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
1404                 gr_set_color_fast(&Color_black);
1405                 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
1406                 gr_set_color_fast(&Color_red);
1407                 gr_string(more_txt_x, more_txt_y, XSTR("more", 1469));  // base location on the input x and y?
1408         }
1409
1410         brief_maybe_blit_scene_cut(frametime);  
1411
1412 #if !defined(NDEBUG) || defined(INTERPLAYQA)
1413         gr_set_color_fast(&Color_normal);
1414         int title_y_offset = (Game_mode & GM_MULTIPLAYER) ? 20 : 10;
1415         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);
1416 #endif
1417
1418         // output mission title
1419         gr_set_color_fast(&Color_bright_white);
1420         if (Game_mode & GM_MULTIPLAYER) {
1421                 char buf[256];
1422                 strncpy(buf, The_mission.name, 256);
1423                 gr_force_fit_string(buf, 255, Title_coords_multi[gr_screen.res][2]);
1424                 gr_string(Title_coords_multi[gr_screen.res][0], Title_coords_multi[gr_screen.res][1], buf);
1425         } else {
1426                 gr_get_string_size(&w, NULL, The_mission.name);
1427                 gr_string(Title_coords[gr_screen.res][0] - w, Title_coords[gr_screen.res][1], The_mission.name);
1428         }
1429
1430         // maybe do objectives
1431         if (Current_brief_stage == Briefing->num_stages) {
1432                 ML_objectives_do_frame(0);
1433         }       
1434 }
1435
1436 // -------------------------------------------------------------------------------------
1437 // brief_set_closeup_pos()
1438 //
1439 //
1440 #define CLOSEUP_OFFSET 20
1441 void brief_set_closeup_pos(brief_icon *bi)
1442 {
1443         Closeup_y1 = 10;
1444         Closeup_x1 = fl2i(320 - Closeup_coords[gr_screen.res][BRIEF_W_COORD]/2.0f + 0.5f);
1445 }
1446
1447 void brief_get_closeup_ship_modelnum(brief_icon *ci)
1448 {
1449         object  *objp;
1450         ship            *sp;
1451
1452         // find the model number for the ship to display
1453         for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
1454
1455                 if ( objp == &obj_used_list || objp->type != OBJ_SHIP ) {
1456                         continue;
1457                 }
1458                 
1459                 sp = &Ships[objp->instance];
1460                 if ( sp->ship_info_index == ci->ship_class ) {
1461                         ci->ship_class = sp->ship_info_index;
1462                         ci->modelnum = sp->modelnum;
1463                         ci->radius = objp->radius;
1464                         break;
1465                 }
1466         }
1467 }
1468
1469 // cut any text off after (and including) '#' char
1470 void brief_truncate_label(char *src)
1471 {
1472         char *pointer_to_last_char;
1473
1474         pointer_to_last_char = strstr(src, NOX("#"));
1475
1476         if ( pointer_to_last_char ) {
1477                 *pointer_to_last_char = 0;
1478         }
1479 }
1480
1481 // -------------------------------------------------------------------------------------
1482 // brief_setup_closeup()
1483 //
1484 // exit: 0      =>              set-up icon sucessfully
1485 //                      -1      =>              could not setup closeup icon
1486 int brief_setup_closeup(brief_icon *bi)
1487 {
1488         char                            pof_filename[NAME_LENGTH];
1489         ship_info               *sip=NULL;
1490         vector                  tvec;
1491
1492         Closeup_icon = bi;
1493         Closeup_icon->ship_class = bi->ship_class;
1494         Closeup_icon->modelnum = -1;
1495
1496         Closeup_one_revolution_time = ONE_REV_TIME;
1497
1498         switch(Closeup_icon->type) {
1499         case ICON_PLANET:
1500                 Closeup_icon = NULL;
1501                 return -1;
1502                 /*
1503                 strcpy(pof_filename, NOX("planet.pof"));
1504                 strcpy(Closeup_icon->closeup_label, XSTR("planet",-1));
1505                 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -8300.0f);
1506                 Closeup_zoom = 0.5f;
1507                 Closeup_one_revolution_time = ONE_REV_TIME * 3;
1508                 */
1509                 break;
1510         case ICON_ASTEROID_FIELD:
1511 #ifndef FS2_DEMO
1512                 strcpy(pof_filename, Asteroid_info[ASTEROID_TYPE_BIG].pof_files[0]);
1513                 strcpy(Closeup_icon->closeup_label, XSTR( "asteroid", 431));
1514                 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -334.0f);
1515                 Closeup_zoom = 0.5f;
1516 #endif
1517                 break;
1518         case ICON_JUMP_NODE:
1519                 strcpy(pof_filename, NOX("subspacenode.pof"));
1520                 strcpy(Closeup_icon->closeup_label, XSTR( "jump node", 432));
1521                 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -2700.0f);
1522                 Closeup_zoom = 0.5f;
1523                 Closeup_one_revolution_time = ONE_REV_TIME * 3;
1524                 break;
1525         case ICON_UNKNOWN:
1526         case ICON_UNKNOWN_WING:
1527                 strcpy(pof_filename, NOX("unknownship.pof"));
1528                 strcpy(Closeup_icon->closeup_label, XSTR( "unknown", 433));
1529                 vm_vec_make(&Closeup_cam_pos, 0.0f, 0.0f, -22.0f);
1530                 Closeup_zoom = 0.5f;
1531                 break;
1532         default:
1533                 brief_get_closeup_ship_modelnum(Closeup_icon);
1534                 Assert( Closeup_icon->ship_class != -1 );
1535                 sip = &Ship_info[Closeup_icon->ship_class];
1536
1537                 strcpy(Closeup_icon->closeup_label,sip->name);
1538
1539                 // cut any text off after (and including) '#' char
1540                 brief_truncate_label(Closeup_icon->closeup_label);
1541
1542                 if ( sip->flags & (SIF_SMALL_SHIP|SIF_BIG_SHIP|SIF_HUGE_SHIP|SIF_SENTRYGUN) ) {
1543                         strcat(Closeup_icon->closeup_label, XSTR( " class", 434));
1544                 }
1545                 break;
1546         }
1547         
1548         if ( Closeup_icon->modelnum == -1 ) {
1549                 if ( sip == NULL ) {
1550                         Closeup_icon->modelnum = model_load(pof_filename, 0, NULL);
1551                 } else {
1552                         Closeup_icon->modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
1553                 }
1554                 Closeup_icon->radius = model_get_radius(Closeup_icon->modelnum);
1555         }
1556
1557         vm_set_identity(&Closeup_orient);
1558         vm_vec_make(&tvec, 0.0f, 0.0f, -1.0f);
1559         Closeup_orient.fvec = tvec;
1560         vm_vec_zero(&Closeup_pos);
1561         Closeup_angles.p  = 0.0f;
1562         Closeup_angles.b  = 0.0f;
1563         Closeup_angles.h  = PI;
1564
1565         brief_set_closeup_pos(bi);
1566
1567         if ( sip ) {
1568                 Closeup_cam_pos = sip->closeup_pos;
1569                 Closeup_zoom = sip->closeup_zoom;
1570         }
1571
1572         return 0;
1573 }
1574
1575 // -------------------------------------------------------------------------------------
1576 // brief_update_closeup_icon()
1577 //
1578 //      input:  mode    =>              how to update the closeup view
1579 //                                                              0 -> disable
1580 //
1581 void brief_update_closeup_icon(int mode)
1582 {
1583         brief_stage             *bs;
1584         brief_icon              *bi;
1585         int                             i, closeup_index;
1586         
1587
1588         if ( mode == 0 ) {
1589                 // mode 0 means disable the closeup icon
1590                 if ( Closeup_icon != NULL ) {
1591                         brief_turn_off_closeup_icon();
1592                 }
1593                 return;
1594         }
1595
1596         if ( Closeup_icon == NULL )
1597                 return;
1598
1599         bs = &Briefing->stages[Current_brief_stage];
1600
1601         closeup_index = -1;
1602         // see if any icons are being highlighted this stage
1603         for ( i = 0; i < bs->num_icons; i++ ) {
1604                 bi = &bs->icons[i];
1605                 if ( bi->flags & BI_HIGHLIGHT ) {
1606                         closeup_index = i;
1607                         break;
1608                 }
1609         }
1610
1611         if ( closeup_index != -1 ) {
1612                 bi = &bs->icons[closeup_index];
1613                 brief_setup_closeup(bi);
1614         }
1615         else {
1616                 Closeup_icon = NULL;
1617         }
1618 }
1619
1620
1621 // -------------------------------------------------------------------------------------
1622 // brief_check_for_anim()
1623 //
1624 //
1625 void brief_check_for_anim()
1626 {
1627         int                             mx, my, i, iw, ih;
1628         brief_stage             *bs;
1629         brief_icon              *bi = NULL;
1630
1631         bs = &Briefing->stages[Current_brief_stage];
1632         mouse_get_pos( &mx, &my );
1633
1634         // if mouse click is over the VCR controls, don't launch an icon
1635         // FIXME - should prolly push these into defines instead of hardcoding this
1636         if ( mx >= 0 && mx <= 115 && my >= 136 && my <= 148 ) {
1637                 return;
1638         }
1639
1640         // if mouse coords are outside the briefing screen, then go away
1641         my -= bscreen.map_y1;
1642         mx -= bscreen.map_x1;
1643         if ( my < 0 || mx < 0 || mx > (bscreen.map_x2-bscreen.map_x1+1) || my > (bscreen.map_y2-bscreen.map_y1+1) )
1644                 return;
1645
1646         for ( i = 0; i < bs->num_icons; i++ ) {
1647                 bi = &bs->icons[i];
1648                 brief_common_get_icon_dimensions(&iw, &ih, bi->type, bi->ship_class);
1649                 if ( mx < bi->x ) continue;
1650                 if ( mx > (bi->x + iw) ) continue;
1651                 if ( my < bi->y ) continue;
1652                 if ( my > (bi->y + ih) ) continue;
1653                 // if we've got here, must be a hit
1654                 break;
1655         }
1656
1657         if ( i == bs->num_icons ) {
1658                 brief_turn_off_closeup_icon();
1659                 return;
1660         }
1661
1662         if ( brief_setup_closeup(bi) == 0 ) {
1663                 gamesnd_play_iface(SND_BRIEF_ICON_SELECT);
1664         } else {
1665                 gamesnd_play_iface(SND_GENERAL_FAIL);
1666         }
1667 }
1668
1669 // maybe flash a button if player hasn't done anything for a while
1670 void brief_maybe_flash_button()
1671 {
1672         UI_BUTTON *b;
1673
1674         if ( Num_brief_stages <= 0 ) 
1675                 return;
1676
1677         if ( Closeup_icon != NULL ) {
1678                 common_flash_button_init();
1679                 return;
1680         }
1681
1682         if ( common_flash_bright() ) {
1683                 if ( Current_brief_stage == (Num_brief_stages-1) ) {
1684
1685                         // AL 4-4-98: Don't flash ship selection button on briefing in demo build
1686 #ifdef FS2_DEMO
1687                                 return;
1688 #else
1689                         // AL 30-3-98: Don't flash ship selection button if in a training mission, 
1690                         if ( brief_only_allow_briefing() ) {
1691                                 return;
1692                         }
1693
1694                         b = &Common_buttons[Current_screen-1][gr_screen.res][1].button;         // ship select button
1695 #endif
1696                 } else {
1697                         b = &Brief_buttons[gr_screen.res][1].button;            // next stage button
1698                 }
1699
1700                 if ( b->button_hilighted() ) {
1701                         common_flash_button_init();
1702                 } else {
1703                         b->draw_forced(1);
1704                 }
1705         }
1706 }
1707
1708 // -------------------------------------------------------------------------------------
1709 // brief_do_frame()
1710 //
1711 // frametime is in seconds
1712 //
1713 void brief_do_frame(float frametime)
1714 {
1715         int k, brief_choice;
1716
1717         if ( red_alert_mission() ) {
1718                 return;
1719         }
1720
1721
1722         if ( !Brief_inited ){
1723                 brief_init();
1724         }
1725
1726         int snazzy_action = -1;
1727         brief_choice = snazzy_menu_do(BriefingMaskData, Briefing_mask_w, Briefing_mask_h, Num_briefing_regions, Briefing_select_region, &snazzy_action, 0);
1728
1729         k = common_select_do(frametime);
1730
1731         if ( Closeup_icon ) {
1732                 Brief_mouse_up_flag = 0;
1733         }
1734
1735         if ( help_overlay_active(BR_OVERLAY) ) {
1736                 common_flash_button_init();
1737                 brief_turn_off_closeup_icon();
1738         }
1739
1740         // Check common keypresses
1741         common_check_keys(k);
1742
1743 #ifndef NDEBUG
1744         int cam_change = 0;
1745 #endif
1746
1747         if ( Briefing->num_stages > 0 ) {
1748
1749                 // check for special keys
1750                 switch(k) {
1751
1752 #ifndef NDEBUG                  
1753                         case KEY_CTRLED | KEY_PAGEUP: {
1754                                 if (Closeup_icon->ship_class) {
1755                                         Closeup_icon->ship_class--;
1756
1757                                         ship_info *sip = &Ship_info[Closeup_icon->ship_class];
1758                                         if (sip->modelnum < 0)
1759                                                 sip->modelnum = model_load(sip->pof_file, NULL, NULL);
1760
1761                                         mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
1762                                         mprintf(("Modelnum = %d (%s)\n", sip->modelnum, sip->pof_file));
1763                                         brief_setup_closeup(Closeup_icon);
1764                                 }
1765
1766                                 break;
1767                         }
1768
1769                         case KEY_CTRLED | KEY_PAGEDOWN: {
1770                                 if (Closeup_icon->ship_class < Num_ship_types - 1) {
1771                                         Closeup_icon->ship_class++;
1772
1773                                         ship_info *sip = &Ship_info[Closeup_icon->ship_class];
1774                                         if (sip->modelnum < 0)
1775                                                 sip->modelnum = model_load(sip->pof_file, NULL, NULL);
1776
1777                                         mprintf(("Shiptype = %d (%s)\n", Closeup_icon->ship_class, sip->name));
1778                                         mprintf(("Modelnum = %d (%s)\n", sip->modelnum, sip->pof_file));
1779                                         brief_setup_closeup(Closeup_icon);
1780                                 }
1781
1782                                 break;
1783                         }
1784
1785                         case KEY_A:
1786                                 Closeup_cam_pos.z += 1;
1787                                 cam_change = 1;
1788                                 break;
1789
1790                         case KEY_A + KEY_SHIFTED:
1791                                 Closeup_cam_pos.z += 10;
1792                                 cam_change = 1;
1793                                 break;
1794
1795                         case KEY_Z:
1796                                 Closeup_cam_pos.z -= 1;
1797                                 cam_change = 1;
1798                                 break;
1799
1800                         case KEY_Z + KEY_SHIFTED:
1801                                 Closeup_cam_pos.z -= 10;
1802                                 cam_change = 1;
1803                                 break;
1804                         
1805                         case KEY_Y:
1806                                 Closeup_cam_pos.y += 1;
1807                                 cam_change = 1;
1808                                 break;
1809
1810                         case KEY_Y + KEY_SHIFTED:
1811                                 Closeup_cam_pos.y += 10;
1812                                 cam_change = 1;
1813                                 break;
1814
1815                         case KEY_H:
1816                                 Closeup_cam_pos.y -= 1;
1817                                 cam_change = 1;
1818                                 break;
1819
1820                         case KEY_H + KEY_SHIFTED:
1821                                 Closeup_cam_pos.y -= 10;
1822                                 cam_change = 1;
1823                                 break;
1824
1825                         case KEY_COMMA:
1826                                 Closeup_zoom -= 0.1f;
1827                                 if ( Closeup_zoom < 0.1 ) 
1828                                         Closeup_zoom = 0.1f;
1829                                 cam_change = 1;
1830                                 break;
1831
1832                         case KEY_COMMA+KEY_SHIFTED:
1833                                 Closeup_zoom -= 0.5f;
1834                                 if ( Closeup_zoom < 0.1 ) 
1835                                         Closeup_zoom = 0.1f;
1836                                 cam_change = 1;
1837                                 break;
1838
1839                         case KEY_PERIOD:
1840                                 Closeup_zoom += 0.1f;
1841                                 cam_change = 1;
1842                                 break;
1843
1844                         case KEY_PERIOD+KEY_SHIFTED:
1845                                 Closeup_zoom += 0.5f;
1846                                 cam_change = 1;
1847                                 break;
1848 #endif
1849                         case 1000:              // need this to avoid warning about no case
1850                                 break;
1851
1852                         default:
1853                                 break;
1854                 } // end switch
1855         }
1856
1857 #ifndef NDEBUG
1858         if ( cam_change ) {
1859                 nprintf(("General","Camera pos: %.2f, %.2f %.2f // ", Closeup_cam_pos.x, Closeup_cam_pos.y, Closeup_cam_pos.z));
1860                 nprintf(("General","Camera zoom: %.2f\n", Closeup_zoom));
1861         }
1862 #endif
1863
1864         if ( brief_choice > -1 && snazzy_action == SNAZZY_OVER ) {
1865                 Brief_mouse_up_flag = 0;
1866                 brief_choice = -1;
1867         }
1868
1869
1870         common_check_buttons();
1871         // if ( Briefing->num_stages > 0 )
1872         brief_check_buttons();
1873
1874         if ( brief_choice != -1 ) {
1875                 Brief_mouse_up_flag = 0;
1876         }
1877
1878         gr_reset_clip();
1879
1880         common_render(frametime);
1881
1882         if ( Current_brief_stage < (Num_brief_stages-1) ) {
1883                 if ( !help_overlay_active(BR_OVERLAY) && brief_time_to_advance(Current_brief_stage, frametime) ) {
1884                         brief_do_next_pressed(0);
1885                         common_flash_button_init();
1886                         Brief_last_auto_advance = timer_get_milliseconds();
1887                 }
1888         }
1889
1890         if ( !Background_playing ) {
1891                 int time = -1;
1892                 int check_jump_flag = 1;
1893                 if ( Current_brief_stage != Last_brief_stage ) {
1894
1895                         // Check if we have a quick transition pending
1896                         if ( Quick_transition_stage != -1 ) {
1897                                         Quick_transition_stage = -1;
1898                                         brief_reset_last_new_stage();
1899                                         time = 0;
1900                                         check_jump_flag = 0;
1901                         }
1902
1903                         if ( check_jump_flag ) {
1904                                 if ( abs(Current_brief_stage - Last_brief_stage) > 1 ) {
1905                                         Quick_transition_stage = Current_brief_stage;
1906                                         Current_brief_stage = Last_brief_stage;
1907                                         Assert(Current_brief_stage >= 0);
1908                                         Start_fade_up_anim = 1;
1909                                         goto Transition_done;
1910                                 }
1911                         }
1912
1913                         if ( time != 0 ) {
1914                                 if ( Current_brief_stage > Last_brief_stage ) {
1915                                         if ( Briefing->stages[Last_brief_stage].flags & BS_FORWARD_CUT ) {
1916                                                 Quick_transition_stage = Current_brief_stage;
1917                                                 Current_brief_stage = Last_brief_stage;
1918                                                 Assert(Current_brief_stage >= 0);
1919                                                 Start_fade_up_anim = 1;
1920                                                 goto Transition_done;
1921                                         } else {
1922                                                 time = Briefing->stages[Current_brief_stage].camera_time;
1923                                         }
1924                                 }
1925                                 else {
1926                                         if ( Briefing->stages[Last_brief_stage].flags & BS_BACKWARD_CUT ) { 
1927                                                 Quick_transition_stage = Current_brief_stage;
1928                                                 Current_brief_stage = Last_brief_stage;
1929                                                 Assert(Current_brief_stage >= 0);
1930                                                 Start_fade_up_anim = 1;
1931                                                 goto Transition_done;
1932                                         } else {
1933                                                 time = Briefing->stages[Last_brief_stage].camera_time;
1934                                         }
1935                                 }
1936                         }
1937
1938                         brief_voice_stop(Last_brief_stage);
1939
1940                         if ( Current_brief_stage < 0 ) {
1941                                 Int3();
1942                                 Current_brief_stage=0;
1943                         }
1944
1945                         // set the camera target
1946                         brief_set_new_stage(&Briefing->stages[Current_brief_stage].camera_pos,
1947                                                                           &Briefing->stages[Current_brief_stage].camera_orient,
1948                                                                           time, Current_brief_stage);
1949
1950                         Brief_playing_fade_sound = 0;
1951                         Last_brief_stage = Current_brief_stage;
1952                         brief_reset_icons(Current_brief_stage);
1953                         brief_update_closeup_icon(0);
1954                 }
1955
1956                 Transition_done:
1957
1958                 if ( Brief_mouse_up_flag && !Closeup_icon) {
1959                         brief_check_for_anim();
1960                 }
1961
1962                 brief_render(frametime);
1963                 brief_camera_move(frametime, Current_brief_stage);
1964
1965                 if (Closeup_icon && (Closeup_bitmap >= 0)) {
1966                         // blit closeup background
1967                         gr_set_bitmap(Closeup_bitmap);
1968                         gr_bitmap(Closeup_coords[gr_screen.res][BRIEF_X_COORD], Closeup_coords[gr_screen.res][BRIEF_Y_COORD]);
1969                 }
1970
1971                 Brief_ui_window.draw();
1972                 brief_redraw_pressed_buttons();
1973                 common_render_selected_screen_button();
1974
1975                 if (Closeup_icon) {
1976                         brief_render_closeup(Closeup_icon->ship_class, frametime);
1977                 }
1978
1979                 // render some extra stuff in multiplayer
1980                 if (Game_mode & GM_MULTIPLAYER) {
1981                         // should render this last so that it overlaps all controls
1982                         chatbox_render();
1983
1984                         // render the status indicator for the voice system
1985                         multi_common_voice_display_status();
1986
1987                         // blit the "ships/players" locked button
1988                         // multi_ts_blit_locked_button();
1989
1990                         // maybe blit the multiplayer "locked" button   
1991                         // if its locked, everyone blits it as such
1992                         if(multi_ts_is_locked()){
1993                                 Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(2);
1994                         } 
1995                         // anyone who can't hit the button sees it off, otherwise
1996                         else {
1997                                 if( ((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)) ||
1998                                          ((Netgame.type_flags & NG_TYPE_TEAM) && !(Net_player->flags & NETINFO_FLAG_GAME_HOST)) ){
1999                                         Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw_forced(0);
2000                                 } else {
2001                                         Brief_buttons[gr_screen.res][BRIEF_BUTTON_MULTI_LOCK].button.draw();
2002                                 }
2003                         }
2004                 }
2005         }               
2006
2007         // maybe flash a button if player hasn't done anything for a while
2008         brief_maybe_flash_button();
2009
2010         // blit help overlay if active
2011         help_overlay_maybe_blit(BR_OVERLAY);    
2012
2013         gr_flip();      
2014
2015         // If the commit button was pressed, do the commit button actions.  Done at the end of the
2016         // loop so there isn't a skip in the animation (since ship_create() can take a long time if
2017         // the ship model is not in memory
2018         if (Commit_pressed) {
2019                 if (Game_mode & GM_MULTIPLAYER) {
2020                         multi_ts_commit_pressed();
2021                 } else {
2022                         commit_pressed();
2023                 }
2024
2025                 Commit_pressed = 0;
2026         }
2027 }
2028
2029 // --------------------------------------------------------------------------------------
2030 //      brief_unload_bitmaps()
2031 //
2032 //
2033 void brief_unload_bitmaps()
2034 {       
2035         if ( BriefingMaskBitmap != -1 ) {
2036                 bm_unload(BriefingMaskBitmap);
2037                 BriefingMaskBitmap = -1;
2038         }
2039
2040         if ( Brief_text_bitmap != -1 ) {
2041                 bm_unload(Brief_text_bitmap);
2042                 Brief_text_bitmap = -1;
2043         }
2044
2045         if(Brief_grid_bitmap != -1){
2046                 bm_unload(Brief_grid_bitmap);
2047                 Brief_grid_bitmap = -1;
2048         }
2049
2050         if ( Brief_multitext_bitmap != -1 ) {
2051                 bm_unload(Brief_multitext_bitmap);
2052                 Brief_multitext_bitmap = -1;
2053         }
2054
2055         if ( Brief_background_bitmap != -1 ) {
2056                 bm_unload(Brief_background_bitmap);
2057                 Brief_background_bitmap = -1;
2058         }
2059
2060         help_overlay_unload(BR_OVERLAY);
2061 }
2062
2063 // ------------------------------------------------------------------------------------
2064 // brief_close()
2065 //
2066 //
2067 void brief_close()
2068 {
2069         if ( Brief_inited == FALSE ) {
2070                 nprintf(("Warning","brief_close() returning without doing anything\n"));
2071                 return;
2072         }
2073
2074         nprintf(("Alan", "Entering brief_close()\n"));
2075
2076         ML_objectives_close();
2077
2078         // unload the audio streams used for voice playback
2079         brief_voice_unload_all();
2080
2081 #ifndef FS2_DEMO
2082         hud_anim_release(&Fade_anim);
2083 #endif
2084
2085         // done mask bitmap, so unlock it
2086         bm_unlock(BriefingMaskBitmap);
2087
2088         Brief_ui_window.destroy();
2089
2090         // unload the bitmaps
2091         brief_unload_bitmaps();
2092
2093         brief_common_close();
2094
2095         Brief_inited = FALSE;
2096 }
2097
2098 void briefing_stop_music()
2099 {
2100         if ( Briefing_music_handle != -1 ) {
2101                 audiostream_close_file(Briefing_music_handle);
2102                 Briefing_music_handle = -1;
2103         }
2104 }
2105
2106 void briefing_load_music(char* fname)
2107 {
2108         if ( Cmdline_freespace_no_music ) {
2109                 return;
2110         }
2111
2112         if ( Briefing_music_handle != -1 )
2113                 return;
2114
2115         if ( fname )
2116                 Briefing_music_handle = audiostream_open( fname, ASF_EVENTMUSIC );
2117 }
2118
2119 void briefing_start_music()
2120 {
2121         if ( Briefing_music_handle != -1 ) {
2122                 if ( !audiostream_is_playing(Briefing_music_handle) )
2123                         audiostream_play(Briefing_music_handle, Master_event_music_volume);
2124         }
2125         else {
2126                 nprintf(("Warning", "No music file exists to play music at this briefing!\n"));
2127         }
2128 }
2129
2130 void brief_stop_voices()
2131 {
2132         brief_voice_stop(Current_brief_stage);
2133 }
2134
2135 void brief_maybe_blit_scene_cut(float frametime)
2136 {
2137         if ( Start_fade_up_anim ) {
2138
2139 #ifdef FS2_DEMO
2140                 Fade_anim.time_elapsed = 0.0f;
2141                 Start_fade_up_anim = 0;
2142                 Start_fade_down_anim = 1;
2143                 Current_brief_stage = Quick_transition_stage;
2144
2145                 if ( Current_brief_stage < 0 ) {
2146                         brief_transition_reset();
2147                         Current_brief_stage = Last_brief_stage;
2148                 }
2149                 goto Fade_down_anim_start;
2150 #else
2151                 int framenum;
2152
2153                 Fade_anim.time_elapsed += frametime;
2154
2155                 if ( !Brief_playing_fade_sound ) {
2156                         gamesnd_play_iface(SND_BRIEFING_STATIC);                                        
2157                         Brief_playing_fade_sound = 1;
2158                 }
2159
2160                 if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
2161                         Fade_anim.time_elapsed = 0.0f;
2162                         Start_fade_up_anim = 0;
2163                         Start_fade_down_anim = 1;
2164                         Current_brief_stage = Quick_transition_stage;
2165                 
2166                         if ( Current_brief_stage < 0 ) {
2167                                 brief_transition_reset();
2168                                 Current_brief_stage = Last_brief_stage;
2169                         }
2170
2171                         Assert(Current_brief_stage >= 0);                       
2172                         goto Fade_down_anim_start;
2173                 }
2174
2175                 // draw the correct frame of animation
2176                 framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
2177                 if ( framenum < 0 )
2178                         framenum = 0;
2179                 if ( framenum >= Fade_anim.num_frames )
2180                         framenum = Fade_anim.num_frames-1;
2181
2182                 // Blit the bitmap for this frame
2183                 gr_set_bitmap(Fade_anim.first_frame + framenum);
2184                 gr_bitmap(Fade_anim.sx, Fade_anim.sy);
2185 #endif
2186         }
2187
2188
2189         Fade_down_anim_start:
2190         if ( Start_fade_down_anim ) {
2191
2192 #ifdef FS2_DEMO
2193                 Fade_anim.time_elapsed = 0.0f;
2194                 Start_fade_up_anim = 0;
2195                 Start_fade_down_anim = 0;
2196                 return;
2197 #else
2198
2199                 int framenum;
2200
2201                 Fade_anim.time_elapsed += frametime;
2202
2203                 if ( Fade_anim.time_elapsed > Fade_anim.total_time ) {
2204                         Fade_anim.time_elapsed = 0.0f;
2205                         Start_fade_up_anim = 0;
2206                         Start_fade_down_anim = 0;
2207                         return;
2208                 }
2209
2210                 // draw the correct frame of animation
2211                 framenum = fl2i( (Fade_anim.time_elapsed * Fade_anim.num_frames) / Fade_anim.total_time );
2212                 if ( framenum < 0 )
2213                         framenum = 0;
2214                 if ( framenum >= Fade_anim.num_frames )
2215                         framenum = Fade_anim.num_frames-1;
2216
2217                 // Blit the bitmap for this frame
2218                 gr_set_bitmap(Fade_anim.first_frame + (Fade_anim.num_frames-1) - framenum);
2219                 gr_bitmap(Fade_anim.sx, Fade_anim.sy);
2220
2221 #endif
2222         }
2223 }
2224
2225 void brief_transition_reset()
2226 {
2227         Quick_transition_stage = -1;
2228         Start_fade_up_anim = 0;
2229         Start_fade_down_anim = 0;
2230         Fade_anim.time_elapsed = 0.0f;
2231 }
2232
2233 // return 1 if this mission only allow players to use the briefing (and not ship or 
2234 // weapon loadout).  Otherwise return 0.
2235 int brief_only_allow_briefing()
2236 {
2237         if ( The_mission.game_type & MISSION_TYPE_TRAINING ) {
2238                 return 1;
2239         }
2240
2241         if ( The_mission.scramble || The_mission.red_alert) {
2242                 return 1;
2243         }
2244
2245         return 0;
2246 }