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