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