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