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