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