]> icculus.org git repositories - taylor/freespace2.git/blob - src/missionui/missioncmdbrief.cpp
Freespace 1 support
[taylor/freespace2.git] / src / missionui / missioncmdbrief.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/MissionCmdBrief.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Mission Command Briefing Screen
16  *
17  * $Log$
18  * Revision 1.4  2003/05/25 02:30:43  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.3  2002/06/09 04:41:23  relnev
22  * added copyright header
23  *
24  * Revision 1.2  2002/05/07 03:16:46  theoddone33
25  * The Great Newline Fix
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:10  root
28  * Initial import.
29  *
30  * 
31  * 14    10/06/99 10:28a Jefff
32  * for OEM: cmd brief anim defaults to the default anim if load failure
33  * 
34  * 13    9/03/99 1:32a Dave
35  * CD checking by act. Added support to play 2 cutscenes in a row
36  * seamlessly. Fixed super low level cfile bug related to files in the
37  * root directory of a CD. Added cheat code to set campaign mission # in
38  * main hall.
39  * 
40  * 12    8/27/99 12:04a Dave
41  * Campaign loop screen.
42  * 
43  * 11    8/19/99 6:28p Jefff
44  * move animation in 640 a bit
45  * 
46  * 10    7/15/99 4:11p Andsager
47  * Leave command briefs in DEMO
48  * 
49  * 9     7/15/99 9:20a Andsager
50  * FS2_DEMO initial checkin
51  * 
52  * 8     7/09/99 10:32p Dave
53  * Command brief and red alert screens.
54  * 
55  * 7     2/08/99 5:06p Johnson
56  * Removed reference to a now non-existent palette.
57  * 
58  * 6     1/30/99 5:08p Dave
59  * More new hi-res stuff.Support for nice D3D textures.
60  * 
61  * 5     1/14/99 5:15p Neilk
62  * changed credits, command debrief interfaces to high resolution support
63  * 
64  * 4     10/16/98 9:40a Andsager
65  * Remove ".h" files from model.h
66  * 
67  * 3     10/13/98 9:28a Dave
68  * Started neatening up freespace.h. Many variables renamed and
69  * reorganized. Added AlphaColors.[h,cpp]
70  * 
71  * 2     10/07/98 10:53a Dave
72  * Initial checkin.
73  * 
74  * 1     10/07/98 10:49a Dave
75  * 
76  * 42    6/09/98 10:31a Hoffoss
77  * Created index numbers for all xstr() references.  Any new xstr() stuff
78  * added from here on out should be added to the end if the list.  The
79  * current list count can be found in FreeSpace.cpp (search for
80  * XSTR_SIZE).
81  * 
82  * 41    6/05/98 9:54a Lawrance
83  * OEM changes
84  * 
85  * 40    6/01/98 11:43a John
86  * JAS & MK:  Classified all strings for localization.
87  * 
88  * 39    5/26/98 11:10a Lawrance
89  * Fix bug where window controls get disabled when F1 pressed twice
90  * 
91  * 38    5/23/98 10:38p Lawrance
92  * Avoid doing a cfile refresh when running debug
93  * 
94  * 37    5/23/98 6:49p Lawrance
95  * Fix problems with refreshing the file list when a CD is inserted
96  * 
97  * 36    5/22/98 11:15a Lawrance
98  * Tweak how CD gets asked for
99  * 
100  * 35    5/21/98 6:57p Lawrance
101  * Only ask for the CD once
102  * 
103  * 34    5/20/98 9:46p John
104  * added code so the places in code that change half the palette don't
105  * have to clear the screen.
106  * 
107  * 33    5/20/98 6:41p Lawrance
108  * Add hook for command brief stage changes
109  * 
110  * 32    5/18/98 5:59p Hoffoss
111  * Made command briefing advanced now once the speech stops and animation
112  * has fully played once, whichever is longer.
113  * 
114  * 31    5/14/98 3:34p Hoffoss
115  * Made command brief screen wait until animation finishes before
116  * auto-advancing to the next state (in addition to the wait that was
117  * already implemented).
118  * 
119  * 30    5/08/98 5:32p Lawrance
120  * prompt for CD if can't load animations or voice
121  * 
122  * 29    5/06/98 11:49p Lawrance
123  * Add help overlay for command brief
124  * 
125  * 28    5/05/98 2:44p Hoffoss
126  * Fixed bug where not having a valid command brief ani would crash the
127  * cmd brief screen.
128  * 
129  * 27    4/28/98 4:16p Hoffoss
130  * Implemented auto-advancing functionality to command briefings.
131  * 
132  * 26    4/27/98 11:01a Hoffoss
133  * Changed code to utilize proper palette.
134  * 
135  * 25    4/26/98 5:11p Hoffoss
136  * Fixed bug where going to options screen and then returning to the cmd
137  * brief screen didn't start ani back up.
138  * 
139  * 24    4/13/98 11:00a Hoffoss
140  * Made the ani in a cmd brief continue playing if it's the same as the
141  * new stage.
142  * 
143  * 23    4/06/98 8:37p Hoffoss
144  * Fixed a few bugs with command brief screen.  Now the voice starts after
145  * the text has printed, and options screen doesn't reset cmd brief.
146  * 
147  * 22    4/06/98 11:24a Lawrance
148  * stop command brief music if returning to main menu
149  * 
150  * 21    4/02/98 11:40a Lawrance
151  * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
152  * 
153  * 20    3/31/98 5:18p John
154  * Removed demo/save/restore.  Made NDEBUG defined compile.  Removed a
155  * bunch of debug stuff out of player file.  Made model code be able to
156  * unload models and malloc out only however many models are needed.
157  *  
158  * 
159  * 19    3/31/98 12:00p Hoffoss
160  * Fixed bug with setting palette using <default> as filename.
161  * 
162  * 18    3/30/98 3:22p Hoffoss
163  * Changed Command Brief screen to merge current ani's palette with
164  * interface palette for better overall color.
165  * 
166  * 17    3/30/98 12:18a Lawrance
167  * change some DEMO_RELEASE code to not compile code rather than return
168  * early
169  * 
170  * 16    3/29/98 12:55a Lawrance
171  * Get demo build working with limited set of data.
172  * 
173  * 15    3/27/98 9:49a Lawrance
174  * AL: Ensure anim stops playing when leaving the command brief
175  * 
176  * 14    3/26/98 5:24p Hoffoss
177  * Changed Command Brief to use memory mapped ani files instead, so we
178  * avoid the huge pauses for huge anis that play!
179  * 
180  * 13    3/24/98 8:52a Jasen
181  * Updated coords for new button.
182  * 
183  * 12    3/23/98 4:21p Hoffoss
184  * Fixed bug where command brief screen couldn't be re-entered unless
185  * mission was reloaded.
186  * 
187  * 11    3/19/98 5:59p Hoffoss
188  * Added reset to cmd brief shutdown.
189  * 
190  * 10    3/19/98 5:32p Lawrance
191  * Added music to the background of command brief screen.
192  * 
193  * 9     3/19/98 4:25p Hoffoss
194  * Added remaining support for command brief screen (ANI and WAVE file
195  * playing).
196  * 
197  * 8     3/18/98 12:03p John
198  * Marked all the new strings as externalized or not.
199  * 
200  * 7     3/17/98 6:24p Hoffoss
201  * Added ani playing to command brief screen, which defaults to
202  * CB_default.ani.
203  * 
204  * 6     3/13/98 6:12p Frank
205  * AL: Fix bug caused by conflict with command brief and red alert
206  * missions
207  * 
208  * 5     3/13/98 3:44p Hoffoss
209  * Added stage indication to Mission Command Briefing screen.
210  * 
211  * 4     3/12/98 4:02p Hoffoss
212  * Added commit sound
213  * 
214  * 3     3/05/98 9:38p Hoffoss
215  * Finished up command brief screen.
216  * 
217  * 2     3/05/98 3:59p Hoffoss
218  * Added a bunch of new command brief stuff, and asteroid initialization
219  * to Fred.
220  * 
221  * 1     3/02/98 6:13p Hoffoss
222  *
223  * $NoKeywords: $
224  */
225
226 #include "ui.h"
227 #include "uidefs.h"
228 #include "gamesnd.h"
229 #include "gamesequence.h"
230 #include "missionscreencommon.h"
231 #include "key.h"
232 #include "bmpman.h"
233 #include "font.h"
234 #include "missionbriefcommon.h"
235 #include "missioncmdbrief.h"
236 #include "redalert.h"
237 #include "audiostr.h"
238 #include "timer.h"
239 #include "eventmusic.h"
240 #include "player.h"
241 #include "contexthelp.h"
242 #include "alphacolors.h"
243 #include "animplay.h"
244
245 char *Cmd_brief_fname[GR_NUM_RESOLUTIONS] = {
246         "CommandBrief",
247         "2_CommandBrief"
248 };
249
250 char *Cmd_brief_mask[GR_NUM_RESOLUTIONS] = {
251         "CommandBrief-m",
252         "2_Commandbrief-m"
253 };
254
255 // lookups for coordinates
256 #define CMD_X_COORD 0
257 #define CMD_Y_COORD 1
258 #define CMD_W_COORD 2
259 #define CMD_H_COORD 3
260
261 int Cmd_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
262         {
263 #ifdef MAKE_FS1
264                 30, 165, 362, 271
265 #else
266                 17, 109, 606, 108                       // GR_640
267 #endif
268         },
269         {
270                 28, 174, 969, 174                       // GR_1024
271         }
272 };
273
274
275 int Cmd_stage_y[GR_NUM_RESOLUTIONS] = {
276 #ifdef MAKE_FS1
277         147,
278 #else
279         90,             // GR_640
280 #endif
281         145             // GR_1024
282 };
283
284 int Cmd_image_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
285         {
286 #ifdef MAKE_FS1
287                 424, 140, 197, 148
288 #else
289                 26, 258, 441, 204                               // GR_640
290 #endif
291         },
292         {
293                 155, 475, 706, 327              // GR_1024
294         }
295 };
296
297 #define NUM_BUTTONS     8
298
299 #ifdef MAKE_FS1
300 #define FIRST_STAGE_BUTTON  0
301 #define PREV_STAGE_BUTTON   1
302 #define NEXT_STAGE_BUTTON   2
303 #define LAST_STAGE_BUTTON   3
304 #define HELP_BUTTON         4
305 #define OPTIONS_BUTTON      5
306 #define ACCEPT_BUTTON       6
307 #define PAUSE_BUTTON        7
308 #else
309 #define FIRST_STAGE_BUTTON      0
310 #define PREV_STAGE_BUTTON       1
311 #define PAUSE_BUTTON                    2
312 #define NEXT_STAGE_BUTTON       3
313 #define LAST_STAGE_BUTTON       4
314 #define HELP_BUTTON                     5
315 #define OPTIONS_BUTTON          6
316 #define ACCEPT_BUTTON           7
317 #endif
318
319 // buttons
320 ui_button_info Cmd_brief_buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
321         { // GR_640
322 #ifdef MAKE_FS1
323                 ui_button_info("CBB_00",        144,    442,    -1,     -1,     0),     // vcr - beginning
324                 ui_button_info("CBB_01",        169,    442,    -1,     -1,     1),     // vcr - reverse
325                 ui_button_info("CBB_02",        221,    442,    -1,     -1,     2),     // vcr - play
326                 ui_button_info("CBB_03",        247,    442,    -1,     -1,     3),     // vcr - end
327                 ui_button_info("CBB_04",        469,    424,    -1,     -1,     4),     // help
328                 ui_button_info("CBB_05",        447,    452,    -1,     -1,     5),     // options
329                 ui_button_info("CBB_06",        552,    411,    -1,     -1,     6),     // continue
330                 ui_button_info("CBB_07",        195,    442,    -1,     -1,     7),     // vcr - pause
331 #else
332                 ui_button_info("CBB_00",        504,    221,    -1,     -1,     0),
333                 ui_button_info("CBB_01",        527,    221,    -1,     -1,     1),
334                 ui_button_info("CBB_02",        555,    221,    -1,     -1,     2),
335                 ui_button_info("CBB_03",        583,    221,    -1,     -1,     3),
336                 ui_button_info("CBB_04",        607,    221,    -1,     -1,     4),
337                 ui_button_info("CBB_05",        539,    431,    -1,     -1,     5),
338                 ui_button_info("CBB_06",        538,    455,    -1,     -1,     6),
339                 ui_button_info("CBB_07",        575,    432,    -1,     -1,     7),
340 #endif
341         },
342         { // GR_1024
343                 ui_button_info("2_CBB_00",      806,    354,    -1,     -1,     0),
344                 ui_button_info("2_CBB_01",      844,    354,    -1,     -1,     1),
345                 ui_button_info("2_CBB_02",      888,    354,    -1,     -1,     2),
346                 ui_button_info("2_CBB_03",      933,    354,    -1,     -1,     3),
347                 ui_button_info("2_CBB_04",      971,    354,    -1,     -1,     4),
348                 ui_button_info("2_CBB_05",      863,    690,    -1,     -1,     5),
349                 ui_button_info("2_CBB_06",      861,    728,    -1,     -1,     6),
350                 ui_button_info("2_CBB_07",      920,    692,    -1,     -1,     7),
351         }
352 };
353
354 // text
355 #ifdef MAKE_FS1
356         #define CMD_BRIEF_NUM_TEXT              0
357 #else
358         #define CMD_BRIEF_NUM_TEXT              3
359 #endif
360 UI_XSTR Cmd_brief_text[GR_NUM_RESOLUTIONS][CMD_BRIEF_NUM_TEXT] = {
361         { // GR_640
362                 // not needed for FS1
363 #ifndef MAKE_FS1
364                 { "Help",               928,    500,    440,    UI_XSTR_COLOR_GREEN,    -1,     &Cmd_brief_buttons[0][HELP_BUTTON].button },
365                 { "Options",    1036,   479,    464,    UI_XSTR_COLOR_GREEN,    -1,     &Cmd_brief_buttons[0][OPTIONS_BUTTON].button },
366                 { "Continue",   1069,   564,    413,    UI_XSTR_COLOR_PINK,     -1,     &Cmd_brief_buttons[0][ACCEPT_BUTTON].button },
367 #endif
368         },
369         { // GR_1024
370                 // not needed for FS1
371 #ifndef MAKE_FS1
372                 { "Help",               928,    800,    704,    UI_XSTR_COLOR_GREEN,    -1,     &Cmd_brief_buttons[1][HELP_BUTTON].button },
373                 { "Options",    1036,   797,    743,    UI_XSTR_COLOR_GREEN,    -1,     &Cmd_brief_buttons[1][OPTIONS_BUTTON].button },
374                 { "Continue",   1069,   917,    661,    UI_XSTR_COLOR_PINK,     -1,     &Cmd_brief_buttons[1][ACCEPT_BUTTON].button },
375 #endif
376         }
377 };
378
379 static UI_WINDOW Ui_window;
380 static int Background_bitmap;                                   // bitmap for the background of the cmd_briefing
381 static int Cur_stage;
382 static int Scroll_offset;
383 static int Cmd_brief_inited = 0;
384 // static int Cmd_brief_ask_for_cd;
385 static int Voice_good_to_go = 0;
386 static int Voice_started_time = 0;
387 static int Voice_ended_time;
388 static int Anim_playing_id = -1;
389 static anim_instance *Cur_anim_instance = NULL;
390 static int Last_anim_frame_num;
391
392 static int Cmd_brief_last_voice;
393 static int Palette_bmp = -1;
394 static ubyte Palette[768];
395 static char Palette_name[128];
396
397 void cmd_brief_init_voice()
398 {
399         int i;
400
401         Assert(Cur_cmd_brief);
402         for (i=0; i<Cur_cmd_brief->num_stages; i++) {
403                 Cur_cmd_brief->stage[i].wave = -1;
404                 if (stricmp(Cur_cmd_brief->stage[i].wave_filename, NOX("none")) && Cur_cmd_brief->stage[i].wave_filename[0]) {
405                         Cur_cmd_brief->stage[i].wave = audiostream_open(Cur_cmd_brief->stage[i].wave_filename, ASF_VOICE);
406                         if (Cur_cmd_brief->stage[i].wave < 0) {
407                                 nprintf(("General", "Failed to load \"%s\"", Cur_cmd_brief->stage[i].wave_filename));
408                         }
409                 }
410         }
411
412         Cmd_brief_last_voice = -1;
413 }
414
415 int cmd_brief_check_stage_done()
416 {
417         if (!Voice_good_to_go)
418                 return 0;
419
420         if (Voice_ended_time && (timer_get_milliseconds() - Voice_ended_time >= 1000))
421                 return 1;
422
423         if (Briefing_voice_enabled && (Cmd_brief_last_voice >= 0)) {
424                 if (audiostream_is_playing(Cmd_brief_last_voice)){
425                         return 0;
426                 }
427
428                 if (!Voice_ended_time){
429                         Voice_ended_time = timer_get_milliseconds();
430                 }
431
432                 return 0;
433         }
434
435         // if we get here, there is no voice, so we simulate the time it would take instead
436         if (!Voice_ended_time)
437                 Voice_ended_time = Voice_started_time + max(5000, Num_brief_text_lines[0] * 3500);
438
439         return 0;
440 }
441
442 // start playback of the voice for a particular briefing stage
443 void cmd_brief_voice_play(int stage_num)
444 {
445         int voice = -1;
446
447         if (!Voice_good_to_go) {
448                 Voice_started_time = 0;
449                 return;
450         }
451
452         if (!Voice_started_time) {
453                 Voice_started_time = timer_get_milliseconds();
454                 Voice_ended_time = 0;
455         }
456
457         if (!Briefing_voice_enabled){
458                 return;
459         }
460
461         if (Cur_stage >= 0 && Cur_stage < Cur_cmd_brief->num_stages){
462                 voice = Cur_cmd_brief->stage[stage_num].wave;
463         }
464
465         // are we still on same voice that is currently playing/played?
466         if (Cmd_brief_last_voice == voice){
467                 return;  // no changes, nothing to do.
468         }
469
470         // if previous wave is still playing, stop it first.
471         if (Cmd_brief_last_voice >= 0) {
472                 audiostream_stop(Cmd_brief_last_voice);  // stream is automatically rewound
473                 Cmd_brief_last_voice = -1;
474         }
475
476         // ok, new wave needs playing, so we can start playing it now (and it becomes the current wave)
477         Cmd_brief_last_voice = voice;
478         if (voice >= 0){
479                 audiostream_play(voice, Master_voice_volume, 0);
480         }
481 }
482
483 // called to leave the command briefing screen
484 void cmd_brief_exit()
485 {
486         gameseq_post_event(GS_EVENT_START_BRIEFING);
487 }
488
489 void cmd_brief_stop_anim(int id)
490 {
491         if (Cur_anim_instance && (id != Anim_playing_id)) {
492                 anim_stop_playing(Cur_anim_instance);
493                 Cur_anim_instance = NULL;
494         }
495
496         Voice_good_to_go = 0;
497         if (Cmd_brief_last_voice >= 0) {
498                 audiostream_stop(Cmd_brief_last_voice);  // stream is automatically rewound
499                 Cmd_brief_last_voice = -1;
500         }
501 }
502
503 void cmd_brief_new_stage(int stage)
504 {
505         int i;
506         anim_play_struct aps;
507
508         if (stage < 0) {
509                 cmd_brief_stop_anim(-1);
510                 Cur_stage = -1;
511                 Anim_playing_id = -1;
512         }
513
514         Cur_stage = stage;
515         brief_color_text_init(Cur_cmd_brief->stage[stage].text, Cmd_text_wnd_coords[gr_screen.res][CMD_W_COORD]);
516
517         i = Cur_cmd_brief->stage[Cur_stage].anim_ref;
518         if (i < 0)
519                 i = Cur_stage;
520
521         cmd_brief_stop_anim(i);
522
523         if (i != Anim_playing_id) {
524                 if (Cur_cmd_brief->stage[i].anim) {
525                         anim_play_init(&aps, Cur_cmd_brief->stage[i].anim,Cmd_image_wnd_coords[gr_screen.res][CMD_X_COORD], Cmd_image_wnd_coords[gr_screen.res][CMD_Y_COORD]);
526                         aps.looped = 1;
527                         Cur_anim_instance = anim_play(&aps);
528                         Last_anim_frame_num = 0;
529                 }
530
531                 Anim_playing_id = i;
532         }
533
534         if (Cur_cmd_brief->stage[i].anim) {
535                 memcpy(Palette, Cur_cmd_brief->stage[i].anim->palette, 384);
536                 gr_set_palette(Cur_cmd_brief->stage[i].ani_filename, Palette, 1);
537         }
538 }
539
540 void cmd_brief_hold()
541 {
542         cmd_brief_stop_anim(-1);
543         Anim_playing_id = -1;
544 }
545
546 void cmd_brief_unhold()
547 {
548         cmd_brief_new_stage(Cur_stage);
549 }
550
551 void cmd_brief_button_pressed(int n)
552 {
553         switch (n) {
554                 case HELP_BUTTON:
555                         launch_context_help();
556                         gamesnd_play_iface(SND_HELP_PRESSED);
557                         break;
558
559                 case OPTIONS_BUTTON:
560                         gamesnd_play_iface(SND_SWITCH_SCREENS);
561                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
562                         break;
563
564                 case FIRST_STAGE_BUTTON:
565                         if (Cur_stage) {
566                                 cmd_brief_new_stage(0);
567                                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
568                         } else {
569                                 gamesnd_play_iface(SND_GENERAL_FAIL);
570                         }
571
572                         break;
573
574                 case PREV_STAGE_BUTTON:
575                         if (Cur_stage) {
576                                 cmd_brief_new_stage(Cur_stage - 1);
577                                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
578                         } else {
579                                 gamesnd_play_iface(SND_GENERAL_FAIL);
580                         }
581
582                         break;
583
584                 case NEXT_STAGE_BUTTON:
585                         if (Cur_stage < Cur_cmd_brief->num_stages - 1) {
586                                 cmd_brief_new_stage(Cur_stage + 1);
587                                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
588                         } else {
589                                 gamesnd_play_iface(SND_GENERAL_FAIL);
590                         }
591
592                         break;
593
594                 case LAST_STAGE_BUTTON:
595                         if (Cur_stage < Cur_cmd_brief->num_stages - 1) {
596                                 cmd_brief_new_stage(Cur_cmd_brief->num_stages - 1);
597                                 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
598                         } else {
599                                 gamesnd_play_iface(SND_GENERAL_FAIL);
600                         }
601                         break;
602
603                 case ACCEPT_BUTTON:
604                         cmd_brief_exit();
605                         gamesnd_play_iface(SND_COMMIT_PRESSED);
606                         break;
607
608                 case PAUSE_BUTTON:
609                         gamesnd_play_iface(SND_USER_SELECT);
610                         Player->auto_advance ^= 1;
611                         break;
612         }
613 }
614
615 void cmd_brief_ani_wave_init(int index)
616 {
617         char *name;
618         int i;
619
620         // first, search and see if anim is already used in another stage
621         for (i=0; i<index; i++) {
622                 if (!stricmp(Cur_cmd_brief->stage[i].ani_filename, Cur_cmd_brief->stage[index].ani_filename)) {
623                         if (Cur_cmd_brief->stage[i].anim_ref >= 0)
624                                 Cur_cmd_brief->stage[index].anim_ref = Cur_cmd_brief->stage[i].anim_ref;
625                         else
626                                 Cur_cmd_brief->stage[index].anim_ref = i;
627
628                         return;
629                 }
630         }
631
632         // this is the first instance of the given anim filename
633         Cur_cmd_brief->stage[index].anim_ref = -1;
634         name = Cur_cmd_brief->stage[index].ani_filename;
635         if (!name[0] || !stricmp(name, NOX("<default>")) || !stricmp(name, NOX("none.ani"))) {
636                 name = NOX("CB_default");
637                 strcpy(Cur_cmd_brief->stage[index].ani_filename, name);
638         }
639
640         int load_attempts = 0;
641         while (1) {
642
643                 if ( load_attempts++ > 5 ) {
644                         break;
645                 }
646
647                 Cur_cmd_brief->stage[index].anim = anim_load(name, 1);
648                 if ( Cur_cmd_brief->stage[index].anim ) {
649                         break;
650                 }
651
652                 // couldn't load animation, ask user to insert CD (if necessary)
653                 // if ( Cmd_brief_ask_for_cd ) {
654                         // if ( game_do_cd_check() == 0 ) {
655                                 // Cmd_brief_ask_for_cd = 0;
656                                 // break;
657                         // }
658                 // }
659         }
660
661         // check to see if cb anim loaded, if not, try the default one
662         if ( !Cur_cmd_brief->stage[index].anim ) {
663                 Cur_cmd_brief->stage[index].anim = anim_load(NOX("CB_default"), 1);
664         }
665 }
666
667 void cmd_brief_init(int team)
668 {
669         common_music_init(SCORE_BRIEFING);
670
671 //#ifndef FS2_DEMO
672
673         int i;
674         ui_button_info *b;
675
676         Cmd_brief_inited = 0;
677         Cur_cmd_brief = &Cmd_briefs[team];
678
679         if ( red_alert_mission() ) {
680                 gameseq_post_event(GS_EVENT_RED_ALERT);
681                 return;
682         }
683
684         if (Cur_cmd_brief->num_stages <= 0)
685                 return;
686
687         gr_reset_clip();
688         gr_clear();
689         Mouse_hidden++;
690         gr_flip();
691         Mouse_hidden--;
692
693         /*
694         Palette_bmp = bm_load("BarracksPalette");       //CommandBriefPalette");
695         Assert(Palette_bmp);
696         bm_get_palette(Palette_bmp, Palette, Palette_name);  // get the palette for this bitmap
697         gr_set_palette(Palette_name, Palette, 1);
698         */
699
700 #ifdef MAKE_FS1
701         common_set_interface_palette("BarracksPalette");
702 #endif
703
704         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
705         Ui_window.set_mask_bmap(Cmd_brief_mask[gr_screen.res]);
706
707         // Cmd_brief_ask_for_cd = 1;
708
709         for (i=0; i<NUM_BUTTONS; i++) {
710                 b = &Cmd_brief_buttons[gr_screen.res][i];
711
712                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, 0, 1);
713                 // set up callback for when a mouse first goes over a button
714                 b->button.set_highlight_action(common_play_highlight_sound);
715                 b->button.set_bmaps(b->filename);
716                 b->button.link_hotspot(b->hotspot);
717         }
718
719         // add text
720         for(i=0; i<CMD_BRIEF_NUM_TEXT; i++){
721                 Ui_window.add_XSTR(&Cmd_brief_text[gr_screen.res][i]);
722         }
723
724         // set up readyrooms for buttons so we draw the correct animation frame when a key is pressed
725         Cmd_brief_buttons[gr_screen.res][FIRST_STAGE_BUTTON].button.set_hotkey(KEY_SHIFTED | KEY_LEFT);
726         Cmd_brief_buttons[gr_screen.res][LAST_STAGE_BUTTON].button.set_hotkey(KEY_SHIFTED | KEY_RIGHT);
727         Cmd_brief_buttons[gr_screen.res][PREV_STAGE_BUTTON].button.set_hotkey(KEY_LEFT);
728         Cmd_brief_buttons[gr_screen.res][NEXT_STAGE_BUTTON].button.set_hotkey(KEY_RIGHT);
729         Cmd_brief_buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
730         Cmd_brief_buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(KEY_F1);
731         Cmd_brief_buttons[gr_screen.res][OPTIONS_BUTTON].button.set_hotkey(KEY_F2);
732
733         // load in help overlay bitmap  
734         help_overlay_load(CMD_BRIEF_OVERLAY);
735         help_overlay_set_state(CMD_BRIEF_OVERLAY,0);
736
737         Background_bitmap = bm_load(Cmd_brief_fname[gr_screen.res]);
738
739         for (i=0; i<Cur_cmd_brief->num_stages; i++)
740                 cmd_brief_ani_wave_init(i);
741
742         cmd_brief_init_voice();
743         Scroll_offset = 0;
744         Cur_anim_instance = NULL;
745         cmd_brief_new_stage(0);
746         Cmd_brief_inited = 1;
747
748 //#endif
749 }
750
751 void cmd_brief_close()
752 {
753         int i;
754
755         if (Cmd_brief_inited) {
756                 cmd_brief_stop_anim(-1);
757                 Anim_playing_id = -1;
758                 for (i=0; i<Cur_cmd_brief->num_stages; i++) {
759                         if (Cur_cmd_brief->stage[i].wave >= 0)
760                                 audiostream_close_file(Cur_cmd_brief->stage[i].wave, 0);
761
762                         if (Cur_cmd_brief->stage[i].anim_ref < 0)
763                                 if (Cur_cmd_brief->stage[i].anim)
764                                         anim_free(Cur_cmd_brief->stage[i].anim);
765                 }
766
767                 if (Background_bitmap >= 0)
768                         bm_unload(Background_bitmap);
769
770                 // unload the overlay bitmap
771                 help_overlay_unload(CMD_BRIEF_OVERLAY);
772
773                 Ui_window.destroy();
774                 /*
775                 if (Palette_bmp){
776                         bm_unload(Palette_bmp);
777                 }
778                 */
779 #ifdef MAKE_FS1
780                 common_free_interface_palette();
781 #endif
782
783                 game_flush();
784                 Cmd_brief_inited = 0;
785         }
786 }
787
788 void cmd_brief_do_frame(float frametime)
789 {
790         char buf[40];
791         int i, k, w;            
792
793         // if no command briefing exists, skip this screen.
794         if (!Cmd_brief_inited) {
795                 cmd_brief_exit();
796                 return;
797         }
798
799         if ( help_overlay_active(CMD_BRIEF_OVERLAY) ) {
800                 Cmd_brief_buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
801                 Ui_window.set_ignore_gadgets(1);
802         }
803
804         k = Ui_window.process() & ~KEY_DEBUGGED;
805
806         if ( (k > 0) || B1_JUST_RELEASED ) {
807                 if ( help_overlay_active(CMD_BRIEF_OVERLAY) ) {
808                         help_overlay_set_state(CMD_BRIEF_OVERLAY, 0);
809                         Ui_window.set_ignore_gadgets(0);
810                         k = 0;
811                 }
812         }
813
814         if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
815                 Ui_window.set_ignore_gadgets(0);
816         }
817
818         switch (k) {
819         case KEY_ESC:
820                 common_music_close();
821                 gameseq_post_event(GS_EVENT_MAIN_MENU);
822                 break;
823         }       // end switch
824
825         for (i=0; i<NUM_BUTTONS; i++){
826                 if (Cmd_brief_buttons[gr_screen.res][i].button.pressed()){
827                         cmd_brief_button_pressed(i);
828                 }
829         }
830
831         cmd_brief_voice_play(Cur_stage);
832         common_music_do();
833
834         if (cmd_brief_check_stage_done() && Player->auto_advance && (Cur_stage < Cur_cmd_brief->num_stages - 1)){
835 //              if (!Cur_anim_instance || (Cur_anim_instance->frame_num < Last_anim_frame_num))
836                 if (!Cur_anim_instance || Cur_anim_instance->loop_count){
837                         cmd_brief_new_stage(Cur_stage + 1);
838                 }
839         }
840
841         if (Cur_anim_instance){
842                 Last_anim_frame_num = Cur_anim_instance->frame_num;
843         }
844
845         GR_MAYBE_CLEAR_RES(Background_bitmap);
846         if (Background_bitmap >= 0) {
847                 gr_set_bitmap(Background_bitmap);
848                 gr_bitmap(0, 0);
849         } 
850
851         {
852                 // JAS: This code is hacked to allow the animation to use all 256 colors
853                 extern int Palman_allow_any_color;
854                 Palman_allow_any_color = 1;
855                 anim_render_all(0, frametime);
856                 Palman_allow_any_color = 0;
857         }
858         Ui_window.draw();
859
860         if (!Player->auto_advance){
861                 Cmd_brief_buttons[gr_screen.res][PAUSE_BUTTON].button.draw_forced(2);
862         }
863
864         gr_set_font(FONT1);
865         gr_set_color_fast(&Color_text_heading);
866
867         sprintf(buf, XSTR( "Stage %d of %d", 464), Cur_stage + 1, Cur_cmd_brief->num_stages);
868         gr_get_string_size(&w, NULL, buf);
869         gr_string(Cmd_text_wnd_coords[gr_screen.res][CMD_X_COORD] + Cmd_text_wnd_coords[gr_screen.res][CMD_W_COORD] - w, Cmd_stage_y[gr_screen.res], buf);
870
871         if (brief_render_text(Scroll_offset, Cmd_text_wnd_coords[gr_screen.res][CMD_X_COORD], Cmd_text_wnd_coords[gr_screen.res][CMD_Y_COORD], Cmd_text_wnd_coords[gr_screen.res][CMD_H_COORD], frametime, 0, 1)){
872                 Voice_good_to_go = 1;
873         }
874
875         // blit help overlay if active
876         help_overlay_maybe_blit(CMD_BRIEF_OVERLAY);
877
878         gr_flip();
879 }
880