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