2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/MissionUI/MissionCmdBrief.cpp $
15 * Mission Command Briefing Screen
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
25 * Revision 1.6 2004/09/20 01:31:44 theoddone33
28 * Revision 1.5 2003/08/03 16:10:29 taylor
29 * cleanup; compile warning fixes
31 * Revision 1.4 2003/05/25 02:30:43 taylor
34 * Revision 1.3 2002/06/09 04:41:23 relnev
35 * added copyright header
37 * Revision 1.2 2002/05/07 03:16:46 theoddone33
38 * The Great Newline Fix
40 * Revision 1.1.1.1 2002/05/03 03:28:10 root
44 * 14 10/06/99 10:28a Jefff
45 * for OEM: cmd brief anim defaults to the default anim if load failure
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
53 * 12 8/27/99 12:04a Dave
54 * Campaign loop screen.
56 * 11 8/19/99 6:28p Jefff
57 * move animation in 640 a bit
59 * 10 7/15/99 4:11p Andsager
60 * Leave command briefs in DEMO
62 * 9 7/15/99 9:20a Andsager
63 * FS2_DEMO initial checkin
65 * 8 7/09/99 10:32p Dave
66 * Command brief and red alert screens.
68 * 7 2/08/99 5:06p Johnson
69 * Removed reference to a now non-existent palette.
71 * 6 1/30/99 5:08p Dave
72 * More new hi-res stuff.Support for nice D3D textures.
74 * 5 1/14/99 5:15p Neilk
75 * changed credits, command debrief interfaces to high resolution support
77 * 4 10/16/98 9:40a Andsager
78 * Remove ".h" files from model.h
80 * 3 10/13/98 9:28a Dave
81 * Started neatening up freespace.h. Many variables renamed and
82 * reorganized. Added AlphaColors.[h,cpp]
84 * 2 10/07/98 10:53a Dave
87 * 1 10/07/98 10:49a Dave
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
95 * 41 6/05/98 9:54a Lawrance
98 * 40 6/01/98 11:43a John
99 * JAS & MK: Classified all strings for localization.
101 * 39 5/26/98 11:10a Lawrance
102 * Fix bug where window controls get disabled when F1 pressed twice
104 * 38 5/23/98 10:38p Lawrance
105 * Avoid doing a cfile refresh when running debug
107 * 37 5/23/98 6:49p Lawrance
108 * Fix problems with refreshing the file list when a CD is inserted
110 * 36 5/22/98 11:15a Lawrance
111 * Tweak how CD gets asked for
113 * 35 5/21/98 6:57p Lawrance
114 * Only ask for the CD once
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.
120 * 33 5/20/98 6:41p Lawrance
121 * Add hook for command brief stage changes
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.
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).
132 * 30 5/08/98 5:32p Lawrance
133 * prompt for CD if can't load animations or voice
135 * 29 5/06/98 11:49p Lawrance
136 * Add help overlay for command brief
138 * 28 5/05/98 2:44p Hoffoss
139 * Fixed bug where not having a valid command brief ani would crash the
142 * 27 4/28/98 4:16p Hoffoss
143 * Implemented auto-advancing functionality to command briefings.
145 * 26 4/27/98 11:01a Hoffoss
146 * Changed code to utilize proper palette.
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.
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
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.
160 * 22 4/06/98 11:24a Lawrance
161 * stop command brief music if returning to main menu
163 * 21 4/02/98 11:40a Lawrance
164 * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
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.
172 * 19 3/31/98 12:00p Hoffoss
173 * Fixed bug with setting palette using <default> as filename.
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.
179 * 17 3/30/98 12:18a Lawrance
180 * change some DEMO_RELEASE code to not compile code rather than return
183 * 16 3/29/98 12:55a Lawrance
184 * Get demo build working with limited set of data.
186 * 15 3/27/98 9:49a Lawrance
187 * AL: Ensure anim stops playing when leaving the command brief
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!
193 * 13 3/24/98 8:52a Jasen
194 * Updated coords for new button.
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.
200 * 11 3/19/98 5:59p Hoffoss
201 * Added reset to cmd brief shutdown.
203 * 10 3/19/98 5:32p Lawrance
204 * Added music to the background of command brief screen.
206 * 9 3/19/98 4:25p Hoffoss
207 * Added remaining support for command brief screen (ANI and WAVE file
210 * 8 3/18/98 12:03p John
211 * Marked all the new strings as externalized or not.
213 * 7 3/17/98 6:24p Hoffoss
214 * Added ani playing to command brief screen, which defaults to
217 * 6 3/13/98 6:12p Frank
218 * AL: Fix bug caused by conflict with command brief and red alert
221 * 5 3/13/98 3:44p Hoffoss
222 * Added stage indication to Mission Command Briefing screen.
224 * 4 3/12/98 4:02p Hoffoss
227 * 3 3/05/98 9:38p Hoffoss
228 * Finished up command brief screen.
230 * 2 3/05/98 3:59p Hoffoss
231 * Added a bunch of new command brief stuff, and asteroid initialization
234 * 1 3/02/98 6:13p Hoffoss
242 #include "gamesequence.h"
243 #include "missionscreencommon.h"
247 #include "missionbriefcommon.h"
248 #include "missioncmdbrief.h"
249 #include "redalert.h"
250 #include "audiostr.h"
252 #include "eventmusic.h"
254 #include "contexthelp.h"
255 #include "alphacolors.h"
256 #include "animplay.h"
258 char *Cmd_brief_fname[GR_NUM_RESOLUTIONS] = {
263 char *Cmd_brief_mask[GR_NUM_RESOLUTIONS] = {
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
274 int Cmd_text_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
279 17, 109, 606, 108 // GR_640
283 28, 174, 969, 174 // GR_1024
288 int Cmd_stage_y[GR_NUM_RESOLUTIONS] = {
297 int Cmd_image_wnd_coords[GR_NUM_RESOLUTIONS][4] = {
302 26, 258, 441, 204 // GR_640
306 155, 475, 706, 327 // GR_1024
310 #define NUM_BUTTONS 8
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
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
333 ui_button_info Cmd_brief_buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
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
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),
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),
369 #define CMD_BRIEF_NUM_TEXT 3
371 UI_XSTR Cmd_brief_text[GR_NUM_RESOLUTIONS][CMD_BRIEF_NUM_TEXT] = {
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 },
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 },
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;
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
403 void cmd_brief_init_voice()
407 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 (stricmp(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));
418 Cmd_brief_last_voice = -1;
421 int cmd_brief_check_stage_done()
423 if (!Voice_good_to_go)
426 if (Voice_ended_time && (timer_get_milliseconds() - Voice_ended_time >= 1000))
429 if (Briefing_voice_enabled && (Cmd_brief_last_voice >= 0)) {
430 if (audiostream_is_playing(Cmd_brief_last_voice)){
434 if (!Voice_ended_time){
435 Voice_ended_time = timer_get_milliseconds();
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 + max(5000, Num_brief_text_lines[0] * 3500);
448 // start playback of the voice for a particular briefing stage
449 void cmd_brief_voice_play(int stage_num)
453 if (!Voice_good_to_go) {
454 Voice_started_time = 0;
458 if (!Voice_started_time) {
459 Voice_started_time = timer_get_milliseconds();
460 Voice_ended_time = 0;
463 if (!Briefing_voice_enabled){
467 if (Cur_stage >= 0 && Cur_stage < Cur_cmd_brief->num_stages){
468 voice = Cur_cmd_brief->stage[stage_num].wave;
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.
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;
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;
485 audiostream_play(voice, Master_voice_volume, 0);
489 // called to leave the command briefing screen
490 void cmd_brief_exit()
492 gameseq_post_event(GS_EVENT_START_BRIEFING);
495 void cmd_brief_stop_anim(int id)
497 if (Cur_anim_instance && (id != Anim_playing_id)) {
498 anim_stop_playing(Cur_anim_instance);
499 Cur_anim_instance = NULL;
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;
509 void cmd_brief_new_stage(int stage)
512 anim_play_struct aps;
515 cmd_brief_stop_anim(-1);
517 Anim_playing_id = -1;
521 brief_color_text_init(Cur_cmd_brief->stage[stage].text, Cmd_text_wnd_coords[gr_screen.res][CMD_W_COORD]);
523 i = Cur_cmd_brief->stage[Cur_stage].anim_ref;
527 cmd_brief_stop_anim(i);
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]);
533 Cur_anim_instance = anim_play(&aps);
534 Last_anim_frame_num = 0;
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);
546 void cmd_brief_hold()
548 cmd_brief_stop_anim(-1);
549 Anim_playing_id = -1;
552 void cmd_brief_unhold()
554 cmd_brief_new_stage(Cur_stage);
557 void cmd_brief_button_pressed(int n)
561 launch_context_help();
562 gamesnd_play_iface(SND_HELP_PRESSED);
566 gamesnd_play_iface(SND_SWITCH_SCREENS);
567 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
570 case FIRST_STAGE_BUTTON:
572 cmd_brief_new_stage(0);
573 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
575 gamesnd_play_iface(SND_GENERAL_FAIL);
580 case PREV_STAGE_BUTTON:
582 cmd_brief_new_stage(Cur_stage - 1);
583 gamesnd_play_iface(SND_BRIEF_STAGE_CHG);
585 gamesnd_play_iface(SND_GENERAL_FAIL);
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);
595 gamesnd_play_iface(SND_GENERAL_FAIL);
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);
605 gamesnd_play_iface(SND_GENERAL_FAIL);
611 gamesnd_play_iface(SND_COMMIT_PRESSED);
615 gamesnd_play_iface(SND_USER_SELECT);
616 Player->auto_advance ^= 1;
621 void cmd_brief_ani_wave_init(int index)
626 // first, search and see if anim is already used in another stage
627 for (i=0; i<index; i++) {
628 if (!stricmp(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;
632 Cur_cmd_brief->stage[index].anim_ref = i;
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] || !stricmp(name, NOX("<default>")) || !stricmp(name, NOX("none.ani"))) {
642 name = NOX("CB_default");
643 strcpy(Cur_cmd_brief->stage[index].ani_filename, name);
646 int load_attempts = 0;
649 if ( load_attempts++ > 5 ) {
653 Cur_cmd_brief->stage[index].anim = anim_load(name, 1);
654 if ( Cur_cmd_brief->stage[index].anim ) {
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;
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"), 1);
673 void cmd_brief_init(int team)
675 common_music_init(SCORE_BRIEFING);
682 Cmd_brief_inited = 0;
683 Cur_cmd_brief = &Cmd_briefs[team];
685 if ( red_alert_mission() ) {
686 gameseq_post_event(GS_EVENT_RED_ALERT);
690 if (Cur_cmd_brief->num_stages <= 0)
700 Palette_bmp = bm_load("BarracksPalette"); //CommandBriefPalette");
702 bm_get_palette(Palette_bmp, Palette, Palette_name); // get the palette for this bitmap
703 gr_set_palette(Palette_name, Palette, 1);
707 common_set_interface_palette("BarracksPalette");
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]);
713 // Cmd_brief_ask_for_cd = 1;
715 for (i=0; i<NUM_BUTTONS; i++) {
716 b = &Cmd_brief_buttons[gr_screen.res][i];
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);
727 for(i=0; i<CMD_BRIEF_NUM_TEXT; i++){
728 Ui_window.add_XSTR(&Cmd_brief_text[gr_screen.res][i]);
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 | KEY_LEFT);
734 Cmd_brief_buttons[gr_screen.res][LAST_STAGE_BUTTON].button.set_hotkey(KEY_SHIFTED | KEY_RIGHT);
735 Cmd_brief_buttons[gr_screen.res][PREV_STAGE_BUTTON].button.set_hotkey(KEY_LEFT);
736 Cmd_brief_buttons[gr_screen.res][NEXT_STAGE_BUTTON].button.set_hotkey(KEY_RIGHT);
737 Cmd_brief_buttons[gr_screen.res][ACCEPT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
738 Cmd_brief_buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(KEY_F1);
739 Cmd_brief_buttons[gr_screen.res][OPTIONS_BUTTON].button.set_hotkey(KEY_F2);
741 // load in help overlay bitmap
742 help_overlay_load(CMD_BRIEF_OVERLAY);
743 help_overlay_set_state(CMD_BRIEF_OVERLAY,0);
745 Background_bitmap = bm_load(Cmd_brief_fname[gr_screen.res]);
747 for (i=0; i<Cur_cmd_brief->num_stages; i++)
748 cmd_brief_ani_wave_init(i);
750 cmd_brief_init_voice();
752 Cur_anim_instance = NULL;
753 cmd_brief_new_stage(0);
754 Cmd_brief_inited = 1;
759 void cmd_brief_close()
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);
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);
775 if (Background_bitmap >= 0)
776 bm_unload(Background_bitmap);
778 // unload the overlay bitmap
779 help_overlay_unload(CMD_BRIEF_OVERLAY);
784 bm_unload(Palette_bmp);
788 common_free_interface_palette();
792 Cmd_brief_inited = 0;
796 void cmd_brief_do_frame(float frametime)
801 // if no command briefing exists, skip this screen.
802 if (!Cmd_brief_inited) {
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);
812 k = Ui_window.process() & ~KEY_DEBUGGED;
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);
822 if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
823 Ui_window.set_ignore_gadgets(0);
828 common_music_close();
829 gameseq_post_event(GS_EVENT_MAIN_MENU);
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);
839 cmd_brief_voice_play(Cur_stage);
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);
849 if (Cur_anim_instance){
850 Last_anim_frame_num = Cur_anim_instance->frame_num;
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);
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;
868 if (!Player->auto_advance){
869 Cmd_brief_buttons[gr_screen.res][PAUSE_BUTTON].button.draw_forced(2);
873 gr_set_color_fast(&Color_text_heading);
875 sprintf(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);
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;
883 // blit help overlay if active
884 help_overlay_maybe_blit(CMD_BRIEF_OVERLAY);