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