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