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