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