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