]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamesnd/eventmusic.cpp
Initial revision
[taylor/freespace2.git] / src / gamesnd / eventmusic.cpp
1 /*
2  * $Logfile: /Freespace2/code/Gamesnd/EventMusic.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module for high-level control of event driven music 
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 14    8/19/99 9:41a Alanl
15  * don't play victory 2 music if there are no goals in the mission
16  * 
17  * 13    8/11/99 5:33p Jefff
18  * added 3rd debrief music track
19  * 
20  * 12    8/01/99 2:11p Alanl
21  * make hull value to play more intense battle music a constant
22  * 
23  * 11    8/01/99 2:06p Alanl
24  * tweak battle music track switching
25  * 
26  * 10    7/25/99 9:57p Alanl
27  * change battle music track selection after enemy arrivals to make battle
28  * tracks less repetitive
29  * 
30  * 9     7/19/99 10:13p Andsager
31  * Tie in hud_targeting to  hostile_ships_present() used to determine next
32  * song.
33  * 
34  * 8     6/24/99 10:47p Alanl
35  * loop battle between tracks 2 and 3 if hull integrity < 70%
36  * 
37  * 7     6/21/99 1:34p Alanl
38  * event music tweaks
39  * 
40  * 6     6/20/99 12:06a Alanl
41  * new event music changes
42  * 
43  * 5     11/23/98 11:55a Johnson
44  * return -1 if a score isn't found
45  * 
46  * 4     11/20/98 4:08p Dave
47  * Fixed flak effect in multiplayer.
48  * 
49  * 3     10/23/98 3:51p Dave
50  * Full support for tstrings.tbl and foreign languages. All that remains
51  * is to make it active in Fred.
52  * 
53  * 2     10/07/98 10:52a Dave
54  * Initial checkin.
55  * 
56  * 1     10/07/98 10:48a Dave
57  * 
58  * 107   6/09/98 5:15p Lawrance
59  * French/German localization
60  * 
61  * 106   6/09/98 10:31a Hoffoss
62  * Created index numbers for all xstr() references.  Any new xstr() stuff
63  * added from here on out should be added to the end if the list.  The
64  * current list count can be found in FreeSpace.cpp (search for
65  * XSTR_SIZE).
66  * 
67  * 105   5/24/98 5:28p Dan
68  * let event_music_level_init() over-ride Event_music_enabled
69  * 
70  * 104   5/24/98 4:42p Dan
71  * AL: Fix several bugs related to pausing and enabling/disabling event
72  * music
73  * 
74  * 103   5/23/98 3:17a Lawrance
75  * Tweak how battle music gets restarted
76  * 
77  * 102   5/22/98 10:43a Lawrance
78  * If mission doesn't have event music, don't choose random track
79  * 
80  * 101   5/21/98 6:56p Lawrance
81  * Tweak how victory music plays
82  * 
83  * 100   5/21/98 2:47a Lawrance
84  * Fix some problems with event music
85  * 
86  * 99    5/18/98 3:21p Mike
87  * Don't play arrival and goals tracks in a training mission.
88  * 
89  * 98    5/04/98 3:15p Duncan
90  * AL: remove bogus assert in event_music_player_respawn()
91  * 
92  * 97    5/03/98 1:54a Lawrance
93  * Fix event music problems related to respawning
94  * 
95  * 96    4/03/98 12:56a Lawrance
96  * Fix bug with music not starting in the first mission
97  * 
98  * 95    4/01/98 6:46p Lawrance
99  * Lower default music volume 
100  *
101  * $NoKeywords: $
102  */
103
104
105 #include        "pstypes.h"
106 #include "eventmusic.h"
107 #include "object.h"
108 #include "ship.h"
109 #include "linklist.h"
110 #include "missionload.h"        /* for Builtin_mission_names[] */
111 #include "missionparse.h"
112 #include "timer.h"
113 #include "freespace.h"
114 #include "audiostr.h"
115 #include "missioncampaign.h"
116 #include "sound.h"
117 #include "time.h"
118 #include "cmdline.h"
119 #include "missiongoals.h"
120 #include "localize.h"
121
122 #pragma optimize("", off)
123
124 #define DEFAULT_MASTER_EVENT_MUSIC_VOLUME       0.5f
125
126 #define HULL_VALUE_TO_PLAY_INTENSE_BATTLE_MUSIC 0.75f
127
128 ////////////////////////////
129 // Globals
130 ////////////////////////////
131 int Event_Music_battle_started = 0;
132 float Master_event_music_volume = DEFAULT_MASTER_EVENT_MUSIC_VOLUME;                    // range is 0->1
133
134 // array that holds which soundtrack is used for which mission (data comes from music.tbl)
135 //int Mission_soundtracks[MAX_CAMPAIGN_MISSIONS];
136
137 // array that holds which briefing track to play for which mission.  Index into Spooled_music[][].
138 //int Mission_briefingmusic[MAX_CAMPAIGN_MISSIONS];
139
140 typedef struct tagSNDPATTERN {
141         int default_next_pattern;       // Needed so the next_pattern member can be reset
142         int next_pattern;                               // Next pattern to play at loop time (can be same pattern)
143         int default_loop_for;           // Needed so the loop_for variable can be reset
144         int loop_for;                                   // Number of times to loop before switching to next pattern
145         int handle;                                             // handle to open audio stream
146         int force_pattern;                      // flag to indicate that we want to not continue loop, but go to next_pattern
147         int can_force;                                  // whether this pattern can be interrupted
148         int bytes_per_measure;          // number of bytes in a measure
149         float num_measures;                             // number of measures in wave file
150 }       SNDPATTERN;
151
152 SNDPATTERN      Patterns[MAX_PATTERNS]; // holds data on sections of a SoundTrack
153
154 // Holds filenames for the different sections of a soundtrack
155 SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS];
156 int Num_soundtracks;
157 int Current_soundtrack_num;     // Active soundtrack for the current mission.. index into Soundtracks[]
158
159 #define PATTERN_DELAY   1000    // in ms
160 int Current_pattern = -1;               // currently playing part of track
161 int Pending_pattern = -1;
162 int Pattern_timer_id = 0;
163
164 // File Globals
165 static int Num_enemy_arrivals;
166 static int Num_friendly_arrivals;
167
168 #define ARRIVAL_INTERVAL_TIMESTAMP  5000
169 #define BATTLE_CHECK_INTERVAL                   15000
170 static int Battle_over_timestamp;
171 static int Mission_over_timestamp;
172 static int Victory2_music_played;
173 static int Next_arrival_timestamp;
174 static int Check_for_battle_music;
175
176 // stores the number of measures for the different patterns (data from music.tbl)
177 float   Pattern_num_measures[MAX_SOUNDTRACKS][MAX_PATTERNS];
178
179 // stores the number of bytes per measure (data from music.tbl)
180 int     Pattern_bytes_per_measure[MAX_SOUNDTRACKS][MAX_PATTERNS];
181
182 char* Pattern_names[MAX_PATTERNS] =
183 {
184 //XSTR:OFF
185         "NRML_1",       // Normal Song 1
186         "AARV_1",       // Allied Arrival 1
187         "EARV_1",       // Enemy Arrival 1
188         "BTTL_1",       // Battle Song 1
189         "BTTL_2",       // Battle Song 2
190         "BTTL_3",       // Battle Song 3
191         "AARV_2",       // Allied Arrival 2
192         "EARV_2",       // Enemy Arrival 2
193         "VICT_1",       // Victory Song 1
194         "VICT_2",       // Victory Song 2
195         "FAIL_1"                // Goal Failed 1
196         "DEAD_1"                // Death Song 1
197 //XSTR:ON
198 };
199
200 char* Pattern_description[MAX_PATTERNS] =
201 {
202 //XSTR:OFF
203         "normal 1",
204         "friendly arrival 1",
205         "enemy arrival 2",
206         "battle 1",
207         "battle 2",
208         "battle 3",
209         "friendly arrival 2",
210         "enemey arrival 2",
211         "victory 1",
212         "victory 2",
213         "goal failed 1"
214         "death "
215 //XSTR:ON
216 };
217
218 int Pattern_loop_for[MAX_PATTERNS] =
219 {
220         1,      // Normal Song 1
221         1,      // Allied Arrival 1
222         1,      // Enemy Arrival 1
223         1,      // Battle Song 1
224         1,      // Battle Song 2
225         1,      // Battle Song 3
226         1,      // Allied Arrival 2
227         1,      // Enemy Arrival 2
228         1,      // Victory Song 1
229         1,      // Victory Song 2
230         1, // Goal Failed 1
231         1       // Death Song 1
232 };
233
234 int Pattern_default_next[MAX_PATTERNS] =
235 {
236         SONG_NRML_1,    // NRML_1 progresses to NRML_1 by default
237         SONG_NRML_1,    // AARV_1 progresses to NRML_1 by default
238         SONG_BTTL_1,    // EARV_1 progresses to BTTL_1 by default
239         SONG_BTTL_2,    // BTTL_1 progresses to BTTL_2 by default
240         SONG_BTTL_3,    // BTTL_2 progresses to BTTL_3 by default
241         SONG_BTTL_1,    // BTTL_3 progresses to BTTL_1 by default
242         SONG_BTTL_2,    // AARV_2 progresses to BTTL_2 by default
243         SONG_BTTL_3,    // EARV_2 progresses to BTTL_3 by default
244         SONG_NRML_1,    // VICT_1 progresses to NRML_1 by default
245         SONG_NRML_1,    // VICT_2 progresses to NRML_1 by default
246         SONG_NRML_1,    //      FAIL_1 progresses to NRML_1 by default
247         -1                                      // no music plays after dead
248 };
249
250
251 // Certain patterns can be interrupted (such as the long-playing NRML and BTTL tracks).  
252 // Other shorter tracks (such as arrivals) play their entire duration.
253 int Pattern_can_force[MAX_PATTERNS] =
254 {
255         TRUE,           // NRML_1 
256         FALSE,  // AARV_1 
257         FALSE,  // EARV_1 
258         TRUE,           // BTTL_1
259         TRUE,           // BTTL_2 
260         TRUE,           // BTTL_3
261         FALSE,  // AARV_2 
262         FALSE,  // EARV_2 
263         FALSE,  // VICT_1 
264         TRUE,           // VICT_2 
265         FALSE,  // FAIL_1
266         TRUE            // DEAD_1
267 };
268
269
270 int Event_music_enabled = TRUE;
271 static int Event_music_inited = FALSE;
272 static int Event_music_level_inited = FALSE;
273 static int Event_music_begun = FALSE;
274
275 // forward function declarations
276 int hostile_ships_present();
277 int hostile_ships_to_arrive();
278 extern int hud_target_invalid_awacs(object *objp);
279
280 // Holds file names of spooled music that is played at menus, briefings, credits etc.
281 // Indexed into by a #define enumeration of the different kinds of spooled music
282 menu_music Spooled_music[MAX_SPOOLED_MUSIC];
283 int Num_music_files;                            // Number of spooled music files
284
285 // Array that holds indicies into Spooled_music[], these specify which music is played in breifing/debriefing
286 int Mission_music[NUM_SCORES];  
287
288 // -------------------------------------------------------------------------------------------------
289 // event_music_init() 
290 //
291 // Called once at game start-up to parse music.tbl and set some state variables
292 //
293 void event_music_init()
294 {
295         if ( snd_is_inited() == FALSE ) {
296                 Event_music_enabled = FALSE;
297                 return;
298         }
299
300         if ( Cmdline_freespace_no_music ) {
301                 return;
302         }
303
304         if ( Event_music_inited == TRUE )
305                 return;
306
307         event_music_parse_musictbl();
308         Event_music_inited = TRUE;
309         Event_music_begun = FALSE;
310 }
311
312 // -------------------------------------------------------------------------------------------------
313 // event_music_close() 
314 //
315 // Called once at game end
316 //
317 void event_music_close()
318 {
319         if ( Event_music_inited == FALSE )
320                 return;
321
322         Event_music_inited = FALSE;
323 }
324
325 // -------------------------------------------------------------------------------------------------
326 // event_music_force_switch() 
327 //
328 // Performs a switch between patterns.  Sets the cutoff limit for the pattern that is being
329 // switch to.
330 //
331 void event_music_force_switch()
332 {
333         if ( Event_music_enabled == FALSE )
334                 return;
335
336         if ( Event_music_level_inited == FALSE )
337                 return;
338
339         int new_pattern;
340         Patterns[Current_pattern].loop_for = Patterns[Current_pattern].default_loop_for;
341
342         new_pattern = Patterns[Current_pattern].next_pattern;
343
344         if ( (new_pattern == SONG_BTTL_3) && (Patterns[SONG_BTTL_3].handle == -1) ) {
345                 if ( Current_pattern == SONG_BTTL_2 ) {
346                         new_pattern = SONG_BTTL_1;
347                 } else {
348                         new_pattern = SONG_BTTL_2;
349                 }
350         } else {
351                 if (Current_pattern == SONG_BTTL_3 && new_pattern == SONG_BTTL_1) {
352                         // AL 06-24-99: maybe switch to battle 2 if hull is less than 70%
353                         if (Player_obj != NULL && Player_ship != NULL) {
354                                 Assert(Player_ship->ship_info_index >= 0);
355                                 Assert(Ship_info[Player_ship->ship_info_index].initial_hull_strength != 0);
356                                 float integrity = Player_obj->hull_strength / Ship_info[Player_ship->ship_info_index].initial_hull_strength;
357                                 if (integrity < HULL_VALUE_TO_PLAY_INTENSE_BATTLE_MUSIC) {
358                                         new_pattern = SONG_BTTL_2;
359                                 }
360                         }
361                 }
362         }
363
364         if ( new_pattern == -1 ) {
365                 return;
366         }
367
368         if ( Patterns[new_pattern].num_measures == 0 )
369                 return; // invalid pattern
370
371         Assert(new_pattern >= 0 && new_pattern < MAX_PATTERNS);
372         audiostream_play(Patterns[new_pattern].handle, Master_event_music_volume, 0);   // no looping
373         audiostream_set_byte_cutoff(Patterns[new_pattern].handle, fl2i(Patterns[new_pattern].num_measures * Patterns[new_pattern].bytes_per_measure) );
374         Patterns[Current_pattern].next_pattern = Patterns[Current_pattern].default_next_pattern;
375         Patterns[Current_pattern].force_pattern = FALSE;
376         nprintf(("EVENTMUSIC", "EVENTMUSIC => switching to %s from %s\n", Pattern_names[new_pattern], Pattern_names[Current_pattern]));
377         Current_pattern = new_pattern;
378 }
379
380 // -------------------------------------------------------------------------------------------------
381 // event_music_do_frame() 
382 //
383 // Called once per game frame, to check for transitions of patterns (and to start the music off at
384 // the beginning).
385 //
386 void event_music_do_frame()
387 {
388         if ( Event_music_level_inited == FALSE ) {
389                 return;
390         }
391
392         if ( Event_music_enabled == FALSE ) {
393                 return;
394         }
395
396         // start off the music delayed
397         if ( timestamp_elapsed(Pattern_timer_id) ) {
398                 Pattern_timer_id = 0;
399                 Event_music_begun = TRUE;
400                 if ( Current_pattern != -1 ) {
401                         Assert(Patterns[Current_pattern].handle >= 0 );
402                         audiostream_play(Patterns[Current_pattern].handle, Master_event_music_volume, 0);       // no looping
403                         audiostream_set_byte_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].bytes_per_measure) );
404                 }
405         }
406
407         if ( Event_music_begun == FALSE ) {
408                 return;
409         }
410
411         if ( Current_pattern != -1 ) {
412                 SNDPATTERN *pat;
413                 pat = &Patterns[Current_pattern];
414
415                 // First case: switching to a different track since first track is almost at end
416                 if ( audiostream_done_reading(pat->handle) ) {
417                         event_music_force_switch();     
418                 }
419                 // Second case: looping back to start of same track since at the end
420                 else if ( !audiostream_is_playing(pat->handle) && !audiostream_is_paused(pat->handle) ) {
421                         audiostream_stop(pat->handle);  // stop current and rewind
422                         pat->loop_for--;
423                         if ( pat->loop_for > 0 ) {
424                                 audiostream_play(pat->handle, Master_event_music_volume, 0);    // no looping
425                                 audiostream_set_byte_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].bytes_per_measure) );
426                         }
427                         else {
428                                 event_music_force_switch();
429                         }
430                 }
431                 // Third case: switching to a different track by interruption
432                 else if ( (pat->force_pattern == TRUE && pat->can_force == TRUE) ) {
433                         int bytes_streamed = audiostream_get_bytes_committed(pat->handle);
434                         int measures_played = bytes_streamed / pat->bytes_per_measure;
435                         if ( measures_played < pat->num_measures ) {
436                                 audiostream_set_byte_cutoff(pat->handle, pat->bytes_per_measure * (measures_played+1) );
437                                 pat->force_pattern = FALSE;
438                                 pat->loop_for = 0;
439                         }
440                 }
441
442                 // We want to go back to NRML track music if all the hostiles have been 
443                 // destroyed, and we are still playing the battle music
444                 if ( Current_pattern == SONG_BTTL_1 || Current_pattern == SONG_BTTL_2 || Current_pattern == SONG_BTTL_3 ) {
445                         if ( timestamp_elapsed(Battle_over_timestamp) && Event_Music_battle_started == 1) {
446                                 //Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
447                                 if ( hostile_ships_present() == FALSE ) {
448                                         if ( Patterns[Current_pattern].next_pattern != SONG_VICT_2 ) {
449                                                 Patterns[Current_pattern].next_pattern = SONG_NRML_1;
450                                                 Patterns[Current_pattern].force_pattern = TRUE;
451                                                 Event_Music_battle_started = 0;
452                                         }
453                                 }
454                         }
455                 }
456
457                 if (Event_Music_battle_started == 0) {
458                         if (Current_pattern == SONG_NRML_1) {
459                                 if (timestamp_elapsed(Check_for_battle_music)) {
460                                         Check_for_battle_music = timestamp(1000);
461                                         if (hostile_ships_present() == TRUE) {
462                                                 Patterns[Current_pattern].next_pattern = SONG_BTTL_1;
463                                                 Patterns[Current_pattern].force_pattern = TRUE;
464                                         }
465                                 }
466                         }
467                 }
468
469                 if ( !Victory2_music_played ) {
470                         if ( timestamp_elapsed(Mission_over_timestamp) ) {
471                                 Mission_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
472                                 if ( mission_goals_met() && (!hostile_ships_present()) ) {
473                                         Patterns[Current_pattern].next_pattern = SONG_VICT_2;
474                                         Patterns[Current_pattern].force_pattern = TRUE;
475                                         Victory2_music_played = 1;
476                                 }
477                         }
478                 }
479         }
480 }
481
482 // -------------------------------------------------------------------------------------------------
483 // event_music_level_init() 
484 //
485 // Called at the start of a mission (level).  Sets up the pattern data, and kicks off the
486 // first track to play().
487 //
488 // input:       force_soundtrack        =>              OPTIONAL parameter (default value -1)
489 //                                                                                              forces the soundtrack to ignore the music.tbl assignment
490 //
491 void event_music_level_init(int force_soundtrack)
492 {
493         int                                     i;
494         SOUNDTRACK_INFO *strack;
495
496         if ( Cmdline_freespace_no_music ) {
497                 return;
498         }
499
500         if ( !audiostream_is_inited() )
501                 return;
502
503         if ( Event_music_level_inited == TRUE )
504                 return;
505
506         Current_pattern = -1;
507
508         if ( Event_music_inited == FALSE )
509                 return;
510
511
512         if ( force_soundtrack != -1 ) {
513                 Current_soundtrack_num = force_soundtrack;
514         }
515
516         if ( Current_soundtrack_num < 0 ) {
517                 return;
518 /*
519                 // okay, assign a random soundtrack if one exists
520                 if ( Num_soundtracks > 0 ) {
521                         Current_soundtrack_num = rand()%Num_soundtracks;
522                         nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Picking random event music soundtrack: %s\n", Soundtracks[Current_soundtrack_num].name));
523                 } else {
524                         return;
525                 }
526 */
527         }
528
529         Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < Num_soundtracks);
530         strack = &Soundtracks[Current_soundtrack_num];
531
532         // open the pattern files, and get ready to play them
533         for ( i = 0; i < strack->num_patterns; i++ ) {
534                 if ( !stricmp(NOX("none.wav"), strack->pattern_fnames[i]) ) {
535                         Patterns[i].handle = -1;        
536                         continue;
537                 }
538
539                 Patterns[i].handle = audiostream_open( strack->pattern_fnames[i], ASF_EVENTMUSIC );
540
541                 if ( Patterns[i].handle >= 0 ) {
542                         Event_music_level_inited = TRUE;
543                         Event_music_enabled = TRUE;
544                 }
545
546                 Patterns[i].next_pattern = Pattern_default_next[i];
547                 Patterns[i].default_next_pattern = Pattern_default_next[i];
548                 Patterns[i].loop_for = Pattern_loop_for[i];
549                 Patterns[i].default_loop_for = Pattern_loop_for[i];
550                 Patterns[i].force_pattern = FALSE;
551                 Patterns[i].can_force = Pattern_can_force[i];
552                 Patterns[i].bytes_per_measure = Pattern_bytes_per_measure[Current_soundtrack_num][i];
553                 Patterns[i].num_measures = Pattern_num_measures[Current_soundtrack_num][i];
554         }
555
556         Num_enemy_arrivals = 0;
557         Num_friendly_arrivals = 0;
558         Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
559         Mission_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
560         Next_arrival_timestamp = timestamp(1);
561         Victory2_music_played = 0;
562         Check_for_battle_music = 0;
563
564         if ( Event_music_level_inited ) {
565                 if ( force_soundtrack != -1 )  {
566                         event_music_first_pattern();
567                 }
568         }
569 }
570
571 // -------------------------------------------------------------------------------------------------
572 // event_music_first_pattern() 
573 //
574 // Picks the first pattern to play, based on whether the battle has started.  Delay start
575 // by PATTERN_DELAY
576 //
577 void event_music_first_pattern()
578 {
579         if ( Event_music_inited == FALSE ) {
580                 return;
581         }
582
583         if ( Event_music_enabled == FALSE ) {
584                 return;
585         }
586
587         if ( Event_music_level_inited == FALSE ) {
588                 event_music_level_init();
589         }
590
591         if ( Event_music_level_inited == FALSE ) {
592                 return;
593         }
594
595         if ( Event_music_begun == TRUE ) {
596                 return;
597         }
598
599         if ( Current_pattern != -1 ) {
600                 if (  audiostream_is_playing(Patterns[Current_pattern].handle) )
601                         audiostream_stop( Patterns[Current_pattern].handle );
602         }
603
604         Pattern_timer_id = 2000;        // start music delay
605         
606         Event_music_begun = FALSE;
607         if ( Event_Music_battle_started == TRUE ) {
608                 Current_pattern = SONG_BTTL_1;
609         }
610         else {
611                 Current_pattern = SONG_NRML_1;
612         }
613 }
614
615 // -------------------------------------------------------------------------------------------------
616 // event_music_level_close() 
617 //
618 // Called at the end of each mission (level).  Stops any playing patterns by fading them out.
619 //
620 void event_music_level_close()
621 {
622         int i;
623
624         if ( Event_music_level_inited == FALSE )
625                 return;
626
627         if ( Current_soundtrack_num >= 0 && Current_soundtrack_num < MAX_SOUNDTRACKS ) {
628                 SOUNDTRACK_INFO *strack;
629    
630                 Assert( Current_soundtrack_num >= 0 && Current_soundtrack_num < MAX_SOUNDTRACKS );
631                 strack = &Soundtracks[Current_soundtrack_num];
632
633                 // close the pattern files
634                 for ( i = 0; i < strack->num_patterns; i++ ) {
635                         if ( i == Current_pattern ) {
636                                 if (  audiostream_is_playing(Patterns[Current_pattern].handle) )
637                                         audiostream_close_file( Patterns[i].handle );
638                                 else
639                                         audiostream_close_file( Patterns[i].handle, 0 );
640                         }
641                         else
642                                 audiostream_close_file( Patterns[i].handle, 0 );
643                 }
644         } else {
645                 // close em all down then
646                 audiostream_close_all(0);
647         }
648
649         Current_pattern = -1;
650         Event_music_level_inited = FALSE;
651         Event_Music_battle_started = FALSE;
652         Event_music_enabled = 0;
653         Event_music_begun = FALSE;
654 }
655
656 // -------------------------------------------------------------------------------------------------
657 // event_music_battle_start() 
658 //
659 // Start the battle music.  If the music is already started before, do nothing.
660 //
661 int event_music_battle_start()
662 {       
663         if ( !hostile_ships_present() ) {
664                 return 0;
665         }
666
667         //      No special tracks in training.
668         if ( The_mission.game_type & MISSION_TYPE_TRAINING )
669                 return -1;
670
671         // Check to see if we've already started off the battle song
672         if ( Event_Music_battle_started == 1 ) {
673                 return 0;
674         }
675
676         if ( Event_music_enabled == FALSE )
677                 return -1;
678
679         if ( Event_music_level_inited == FALSE )
680                 return -1;
681
682         if ( Current_pattern == SONG_BTTL_1 )
683                 return 0;       // already playing
684
685         if ( Current_pattern == SONG_DEAD_1 )
686                 return 0;       // death is the last song to play
687
688         if ( Current_pattern != -1 ) {
689                 Patterns[Current_pattern].next_pattern = SONG_BTTL_1;
690                 Patterns[Current_pattern].force_pattern = TRUE;
691         }
692
693         Event_Music_battle_started = 1; // keep track of this state though, need on restore
694         Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
695
696         return 0;
697 }
698
699 // -------------------------------------------------------------------------------------------------
700 // event_music_enemy_arrival() 
701 //
702 // An enemy has arrived, play an enemy arrival pattern.
703 //
704 int event_music_enemy_arrival()
705 {
706         if ( Event_music_enabled == FALSE ) {
707                 return -1;
708         }
709
710         if ( Event_music_level_inited == FALSE ) {
711                 return -1;
712         }
713
714         int next_pattern;
715         if ( Event_Music_battle_started == TRUE ) {
716                 next_pattern = SONG_EARV_2;
717         }
718         else {
719                 next_pattern = SONG_EARV_1;
720         }
721
722         if ( Current_pattern == next_pattern )
723                 return 0;       // already playing
724
725         if ( Current_pattern == SONG_DEAD_1 )
726                 return 0;       // death is the last song to play
727
728         if ( (Current_pattern == SONG_VICT_1) || (Current_pattern == SONG_VICT_1) )
729                 return 0;
730
731         if ( Patterns[Current_pattern].next_pattern != Patterns[Current_pattern].default_next_pattern )
732                 return 0;       // don't squash a pending pattern
733
734         Num_enemy_arrivals++;
735
736         // AL 7-25-99: If hull is less than 70% then switch to battle 2 or 3, otherwise switch to 1 or 2
737         bool play_intense_battle_music = false;
738         if (Player_obj != NULL && Player_ship != NULL) {
739                 Assert(Player_ship->ship_info_index >= 0);
740                 Assert(Ship_info[Player_ship->ship_info_index].initial_hull_strength != 0);
741                 float integrity = Player_obj->hull_strength / Ship_info[Player_ship->ship_info_index].initial_hull_strength;
742                 if (integrity < HULL_VALUE_TO_PLAY_INTENSE_BATTLE_MUSIC) {
743                         play_intense_battle_music = true;
744                 }
745         }
746
747         if (play_intense_battle_music == true) {
748                 if (Current_pattern == SONG_BTTL_2) {
749                         Patterns[next_pattern].next_pattern = SONG_BTTL_3;
750                 } else {
751                         Patterns[next_pattern].next_pattern = SONG_BTTL_2;
752                 }
753         } else {
754                 if (Current_pattern == SONG_BTTL_1) {
755                         Patterns[next_pattern].next_pattern = SONG_BTTL_2;
756                 } else if (Current_pattern == SONG_BTTL_2) {
757                         Patterns[next_pattern].next_pattern = SONG_BTTL_3;
758                 } else {
759                         Patterns[next_pattern].next_pattern = SONG_BTTL_1;
760                 }
761         }
762
763         /*
764         // AL 11-03-97:
765         // Alternate between BTTL_2 and BTTL_3 following enemy arrivals
766         if ( Num_enemy_arrivals & 1 ) {
767                 Patterns[next_pattern].next_pattern = SONG_BTTL_2;
768         } else {
769                 if ( Patterns[SONG_BTTL_3].handle != -1 ) {
770                         Patterns[next_pattern].next_pattern = SONG_BTTL_3;
771                 } else {
772                         Patterns[next_pattern].next_pattern = SONG_BTTL_2;
773                 }
774         }
775         */
776
777         if ( Current_pattern != -1 ) {
778                 Patterns[Current_pattern].next_pattern = next_pattern;
779                 Patterns[Current_pattern].force_pattern = TRUE;
780         }
781
782         Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
783
784         return 0;
785 }
786
787 // -------------------------------------------------------------------------------------------------
788 // event_music_friendly_arrival() 
789 //
790 // An friendly has arrived, play a friendly arrival pattern.
791 //
792 int event_music_friendly_arrival()
793 {
794         if ( Event_music_enabled == FALSE )
795                 return -1;
796
797         if ( Event_music_level_inited == FALSE )
798                 return -1;
799
800         if (timestamp_elapsed(Next_arrival_timestamp) == false) {
801                 return 0;
802         }
803
804         int next_pattern;
805         if ( Event_Music_battle_started == TRUE ) {
806                 next_pattern = SONG_AARV_2;
807         }
808         else {
809                 next_pattern = SONG_AARV_1;
810         }
811
812         if ( Current_pattern == next_pattern )
813                 return 0;       // already playing
814
815         if ( Current_pattern == SONG_DEAD_1 )
816                 return 0;       // death is the last song to play
817
818         if ( (Current_pattern == SONG_VICT_1) || (Current_pattern == SONG_VICT_1) )
819                 return 0;
820
821         if ( Patterns[Current_pattern].next_pattern != Patterns[Current_pattern].default_next_pattern )
822                 return 0;       // don't squash a pending pattern
823
824         // After the second friendly arrival, default to SONG_BTTL_3
825         Num_friendly_arrivals++;
826
827         if ( Current_pattern != -1 ) {
828                 // AL 06-24-99: always overlay allied arrivals
829                 /*
830                 if (next_pattern == SONG_AARV_1) {
831                         Patterns[Current_pattern].next_pattern = next_pattern;
832                         Patterns[Current_pattern].force_pattern = TRUE;
833                 } else {
834                 */
835                         Assert(Patterns[SONG_AARV_1].handle >= 0 );
836                         audiostream_play(Patterns[SONG_AARV_1].handle, Master_event_music_volume, 0);   // no looping
837                         audiostream_set_byte_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].bytes_per_measure) );
838                 //}
839         }
840
841         Next_arrival_timestamp = timestamp(ARRIVAL_INTERVAL_TIMESTAMP);
842
843         Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
844
845         return 0;
846 }
847
848 //      Play arrival music keyed to team "team".
849 void event_music_arrival(int team)
850 {
851         //      No friendly arrival music in a training mission.
852         if ( The_mission.game_type & MISSION_TYPE_TRAINING )
853                 return;
854
855         if ( Player_ship->team == team ) {
856                 event_music_friendly_arrival();
857         } else {
858                 event_music_enemy_arrival();
859         }
860 }
861
862 // -------------------------------------------------------------------------------------------------
863 // event_music_primary_goals_met() 
864 //
865 // A primary goal has failed
866 //
867 int event_music_primary_goal_failed()
868 {
869         int next_pattern;
870
871         //      No special tracks in training.
872         if ( The_mission.game_type & MISSION_TYPE_TRAINING )
873                 return -1;
874
875         if ( Event_music_enabled == FALSE )
876                 return -1;
877
878         if ( Event_music_level_inited == FALSE )
879                 return -1;
880
881         if ( Current_pattern == SONG_DEAD_1 )
882                 return 0;       // death is the last song to play
883
884         if ( Patterns[SONG_FAIL_1].handle < 0 ) // can't play if music file doesn't exist
885                 return 0;
886
887         if ( hostile_ships_present() ) {
888                 next_pattern = SONG_BTTL_1;
889         }
890         else {
891                 next_pattern = SONG_NRML_1;
892                 Event_Music_battle_started = 0;
893         }
894
895         if ( Current_pattern != -1 ) {
896                 Patterns[Current_pattern].next_pattern = next_pattern;
897                 Patterns[Current_pattern].force_pattern = TRUE;
898         }
899
900         return 0;
901 }
902
903 // -------------------------------------------------------------------------------------------------
904 // event_music_primary_goals_met() 
905 //
906 // A goal has been achieved, play the appropriate victory music.
907 //
908 int event_music_primary_goals_met()
909 {
910         int next_pattern = SONG_VICT_1;
911
912         //      No special tracks in training.
913         if ( The_mission.game_type & MISSION_TYPE_TRAINING )
914                 return -1;
915
916         if ( Event_music_enabled == FALSE )
917                 return -1;
918
919         if ( Event_music_level_inited == FALSE )
920                 return -1;
921
922         if ( (Current_pattern == SONG_VICT_1) || (Current_pattern == SONG_VICT_2) )
923                 return 0;       // already playing
924
925         if ( Current_pattern == SONG_DEAD_1 )
926                 return 0;       // death is the last song to play
927
928         if ( hostile_ships_present() ) {
929                 Patterns[SONG_VICT_1].next_pattern = SONG_BTTL_1;
930         }
931         else {
932                 Patterns[SONG_VICT_1].next_pattern = SONG_VICT_2;
933                 Event_Music_battle_started = 0;
934
935                 // If the mission goals aren't met (or there are no goals), or if victory 2 music has already played, then go
936                 // to the next default track
937                 if ( !mission_goals_met() || Victory2_music_played || (Num_goals == 0)) {
938                         Patterns[next_pattern].next_pattern = Patterns[next_pattern].default_next_pattern;
939                 } else {
940                         Victory2_music_played = 1;
941                 }
942         }
943
944         if ( Current_pattern != -1 ) {
945                 Patterns[Current_pattern].next_pattern = next_pattern;
946                 Patterns[Current_pattern].force_pattern = TRUE;
947         }
948
949         return 0;
950 }
951
952 // -------------------------------------------------------------------------------------------------
953 // event_music_player_death() 
954 //
955 // The player has died, play death pattern.
956 //
957 int event_music_player_death()
958 {
959         if ( Event_music_enabled == FALSE )
960                 return -1;
961
962         if ( Event_music_level_inited == FALSE )
963                 return -1;
964
965         if ( Current_pattern == SONG_DEAD_1 )
966                 return 0;       // already playing
967
968         if ( Current_pattern != -1 ) {
969                 Patterns[Current_pattern].next_pattern = SONG_DEAD_1;
970                 Patterns[Current_pattern].force_pattern = TRUE;
971         }
972
973         return 0;
974 }
975
976 // -------------------------------------------------------------------------------------------------
977 // event_music_player_respawn() 
978 //
979 // Player has respawned (multiplayer only)
980 //
981 int event_music_player_respawn()
982 {
983         if ( Event_music_enabled == FALSE )
984                 return -1;
985
986         if ( Event_music_level_inited == FALSE )
987                 return -1;
988
989 //      Assert(Current_pattern == SONG_DEAD_1);
990
991         Event_Music_battle_started = 0;
992         Patterns[Current_pattern].next_pattern = SONG_NRML_1;
993         Patterns[Current_pattern].force_pattern = TRUE;
994
995         return 0;
996 }
997
998 // -------------------------------------------------------------------------------------------------
999 // event_music_player_respawn_as_observer() 
1000 //
1001 // Player has respawned (multiplayer only)
1002 //
1003 int event_music_player_respawn_as_observer()
1004 {
1005         if ( Event_music_enabled == FALSE )
1006                 return -1;
1007
1008         if ( Event_music_level_inited == FALSE )
1009                 return -1;
1010
1011         if ( Current_pattern >= 0 ) {
1012                 if ( audiostream_is_playing(Patterns[Current_pattern].handle) ) {
1013                         audiostream_stop(Patterns[Current_pattern].handle);
1014                         Current_pattern = -1;
1015                 }
1016         }
1017
1018         return 0;
1019 }
1020
1021 // -------------------------------------------------------------------------------------------------
1022 // event_music_parse_musictbl() will parse the music.tbl file, and set up the Mission_songs[]
1023 // array
1024 //
1025 void event_music_parse_musictbl()
1026 {
1027         char fname[MAX_FILENAME_LEN];
1028         char line_buf[128];
1029         int rval;
1030
1031         int num_patterns = 0;
1032
1033         Num_music_files = 0;
1034         Num_soundtracks = 0;            // Global
1035         event_music_reset_choices();
1036
1037         if ((rval = setjmp(parse_abort)) != 0) {
1038                 Error(LOCATION, "Unable to parse music.tbl!  Code = %i.\n", rval);
1039
1040         } else {
1041                 // open localization
1042                 lcl_ext_open();
1043
1044                 read_file_text("music.tbl");
1045                 reset_parse();          
1046
1047                 // Loop through all the sound-tracks
1048                 while (required_string_either("#Menu Music Start","#SoundTrack Start")) {
1049                         Assert(Num_soundtracks < MAX_SOUNDTRACKS);
1050                         required_string("#SoundTrack Start");
1051                         required_string("$SoundTrack Name:");
1052                         stuff_string(Soundtracks[Num_soundtracks].name, F_NAME, NULL);
1053                         while (required_string_either("#SoundTrack End","$Name:")) {
1054                                 Assert( num_patterns < MAX_PATTERNS );
1055                                 required_string("$Name:");
1056                                 stuff_string(line_buf, F_NAME, NULL);
1057
1058                                 // line_buf holds 3 fields:  filename, num measures, bytes per measure
1059
1060                                 char *token;
1061                                 int count = 0;
1062                                 token = strtok( line_buf, NOX(" ,\t"));
1063                                 strcpy(fname, token);
1064                                 while ( token != NULL ) {
1065                                         token = strtok( NULL, NOX(" ,\t") );
1066                                         if ( token == NULL ) {
1067                                                 Assert(count == 2 );
1068                                                 break;
1069                                         }
1070
1071                                         if ( count == 0 ) {
1072                                                 Pattern_num_measures[Num_soundtracks][num_patterns] = (float)atof(token);
1073
1074                                         } else {
1075                                                 Pattern_bytes_per_measure[Num_soundtracks][num_patterns] = atoi(token);
1076                                         }
1077
1078                                         count++;
1079                                 }       // end while
1080
1081                                 // convert from samples per measure to bytes per measure
1082                                 Pattern_bytes_per_measure[Num_soundtracks][num_patterns] *= 2;
1083                                 strcpy(Soundtracks[Num_soundtracks].pattern_fnames[num_patterns], fname);
1084                                 num_patterns++;
1085                         }
1086
1087                         required_string("#SoundTrack End");
1088                         Soundtracks[Num_soundtracks].num_patterns = num_patterns;
1089                         Num_soundtracks++;
1090                         num_patterns = 0;
1091                 }
1092
1093                 // Parse the menu music section
1094                 required_string("#Menu Music Start");
1095                 while (required_string_either("#Menu Music End","$Name:")) {
1096                         Assert( Num_music_files < MAX_SPOOLED_MUSIC );
1097
1098                         required_string("$Name:");
1099                         stuff_string(fname, F_PATHNAME, NULL);
1100                         Assert( strlen(fname) < (NAME_LENGTH-1) );
1101                         strcpy( Spooled_music[Num_music_files].name, fname );
1102
1103                         required_string("$Filename:");
1104                         stuff_string(fname, F_PATHNAME, NULL);
1105                         if ( stricmp(fname, NOX("none.wav"))  ) {
1106                                 Assert( strlen(fname) < (MAX_FILENAME_LEN-1) );
1107                                 strcpy( Spooled_music[Num_music_files].filename, fname );
1108                         }
1109
1110                         Num_music_files++;                      
1111                 }
1112
1113                 required_string("#Menu Music End");
1114
1115                 // close localization
1116                 lcl_ext_close();
1117         }
1118 }
1119
1120 // -------------------------------------------------------------------------------------------------
1121 // event_music_change_pattern()
1122 //
1123 // Force a particular pattern to play.  This is used for debugging purposes.
1124 //
1125 void event_music_change_pattern(int new_pattern)
1126 {
1127         if ( Event_music_enabled == FALSE ) {
1128                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
1129                 return;
1130         }
1131
1132         if ( Event_music_level_inited == FALSE ) {
1133                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
1134                 return;
1135         }
1136
1137         if ( Current_pattern == new_pattern )
1138                 return; // already playing
1139
1140         if ( Current_pattern != -1 ) {
1141                 Patterns[Current_pattern].next_pattern = new_pattern;
1142                 Patterns[Current_pattern].force_pattern = TRUE;
1143         }
1144 }
1145
1146 // -------------------------------------------------------------------------------------------------
1147 // event_music_return_current_pattern()
1148 //
1149 // Simply return what the current pattern being played is.  Don't want to make global.
1150 //
1151 int event_music_return_current_pattern()
1152 {
1153         return Current_pattern;
1154 }
1155
1156 // -------------------------------------------------------------------------------------------------
1157 // event_music_disable()
1158 //
1159 // Stop any patterns that are playing, and prevent any further patterns from playing (ie
1160 // set Event_music_enabled = FALSE).  We don't uninit event music, since it might be toggled
1161 // back on this level.
1162 //
1163 void event_music_disable()
1164 {
1165         if ( Event_music_level_inited == FALSE )
1166                 return;
1167
1168         if ( Event_music_enabled == FALSE )
1169                 return;
1170
1171         if (Current_pattern == -1)
1172                 return;
1173
1174         Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
1175         if (  audiostream_is_playing(Patterns[Current_pattern].handle) ) {
1176                         audiostream_stop(Patterns[Current_pattern].handle);     // stop current and rewind
1177         }
1178
1179         Event_music_begun = FALSE;
1180         Event_music_enabled = FALSE;
1181         Current_pattern = -1;
1182 }
1183
1184 // -------------------------------------------------------------------------------------------------
1185 // event_music_enable()
1186 //
1187 // Init the event music (ie load the patterns) if required.  Set up the first song to play, and
1188 // set Event_music_enabled = TRUE to allow patterns to play.
1189 //
1190 void event_music_enable()
1191 {
1192         if ( Event_music_enabled == TRUE )
1193                 return;
1194
1195         Event_music_enabled = TRUE;
1196
1197         if ( Event_music_level_inited == FALSE ) {
1198                 event_music_level_init();
1199                 // start the first pattern to play (delayed)
1200                 if ( Game_mode & GM_IN_MISSION ) {
1201                         event_music_first_pattern();
1202                 }
1203         }
1204         else {
1205                 // start a new pattern
1206                 Event_music_begun = FALSE;
1207                 Pattern_timer_id = timestamp(150);
1208                 event_music_start_default();
1209         }
1210 }
1211
1212 // -------------------------------------------------------------------------------------------------
1213 // event_music_start_default()
1214 //
1215 //      Start playing a default track, based on how far the mission has progressed
1216 //
1217 void event_music_start_default()
1218 {       
1219         int next_pattern;
1220
1221         if ( Event_Music_battle_started == TRUE ) {
1222                 if ( hostile_ships_present() ) {
1223                         next_pattern = SONG_BTTL_1;
1224                 }
1225                 else {
1226                         Event_Music_battle_started = FALSE;
1227                         next_pattern = SONG_NRML_1;
1228                 }
1229         }
1230         else
1231                 next_pattern = SONG_NRML_1;     
1232
1233         if ( Current_pattern == -1 ) {
1234                 Current_pattern = next_pattern;
1235         }
1236         else {
1237                 Patterns[Current_pattern].next_pattern = next_pattern;
1238                 Patterns[Current_pattern].force_pattern = TRUE;
1239         }
1240
1241 }
1242
1243 // -------------------------------------------------------------------------------------------------
1244 // event_music_pause()
1245 //
1246 //      Stop any playing pattern, but don't rewind.
1247 //
1248 void event_music_pause()
1249 {
1250         if ( Event_music_enabled == FALSE ) {
1251                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
1252                 return;
1253         }
1254
1255         if ( Event_music_level_inited == FALSE ) {
1256                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
1257                 return;
1258         }
1259
1260         if (Current_pattern == -1)
1261                 return;
1262
1263         Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
1264         if (  audiostream_is_playing(Patterns[Current_pattern].handle) ) {
1265                         audiostream_stop(Patterns[Current_pattern].handle, 0);  // stop current and don't rewind
1266         }
1267 }
1268
1269 // -------------------------------------------------------------------------------------------------
1270 // event_music_unpause()
1271 //
1272 //      Start the Current_pattern if it is paused.
1273 //
1274 void event_music_unpause()
1275 {
1276         if ( Event_music_enabled == FALSE ) {
1277                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
1278                 return;
1279         }
1280
1281         if ( Event_music_level_inited == FALSE ) {
1282                 nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
1283                 return;
1284         }
1285
1286         if (Current_pattern == -1)
1287                 return;
1288
1289         Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
1290         if ( audiostream_is_paused(Patterns[Current_pattern].handle) == TRUE ) {
1291                 audiostream_play(Patterns[Current_pattern].handle, Master_event_music_volume, 0);       // no looping
1292                 audiostream_set_byte_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].bytes_per_measure) );
1293         }
1294 }
1295
1296 // -------------------------------------------------------------------------------------------------
1297 // event_music_set_volume_all()
1298 //
1299 //      Set the volume of the event driven music.  Used when using the game-wide music volume is changed
1300 // by the user.
1301 //
1302 void event_music_set_volume_all(float volume)
1303 {
1304         audiostream_set_volume_all(volume, ASF_EVENTMUSIC);
1305 }
1306
1307 // ----------------------------------------------------------------------
1308 // hostile_ships_present()
1309 //
1310 // Determine if there are any non-friendly ships in existance
1311 //
1312 // returns: 1 =>        there are non-friendly ships in existance
1313 //                              0 =>  any ships in existance are friendly
1314 int hostile_ships_present()
1315 {
1316         ship            *shipp;
1317         ship_obj *so;
1318
1319         for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
1320                 shipp = &Ships[Objects[so->objnum].instance];
1321
1322                 // check if ship if enemy ship
1323                 if ( (shipp->team == Player_ship->team) && (Player_ship->team != TEAM_TRAITOR)  )
1324                         continue;
1325
1326                 // check if ship is threatening
1327                 if ( (shipp->flags & (SF_DISABLED|SF_DYING|SF_DEPARTING)) || (ship_subsys_disrupted(shipp, SUBSYSTEM_ENGINE)) ) 
1328                         continue;
1329         
1330                 // check if ship is flyable
1331                 if ( Ship_info[shipp->ship_info_index].flags & SIF_NOT_FLYABLE ) {
1332                         continue;
1333                 }
1334
1335                 // check if ship is visible by player's team
1336                 if ( hud_target_invalid_awacs(&Objects[so->objnum]) == 1 ) {
1337                         continue;
1338                 }
1339
1340                 return 1;
1341         }
1342         return 0;
1343 }
1344
1345 // ----------------------------------------------------------------------
1346 // hostile_ships_to_arrive()
1347 //
1348 // Determine if there are any non-friendly ships yet to arrive
1349 //
1350 // NOTE: neutral ships are considered hostile for the purpose of event music
1351 //
1352 int hostile_ships_to_arrive()
1353 {
1354         p_object *p_objp;
1355
1356         p_objp = GET_FIRST(&ship_arrival_list);
1357         while( p_objp != END_OF_LIST(&ship_arrival_list) )      {
1358                 if ( (p_objp->team != Player_ship->team) && !(p_objp->flags & P_SF_CANNOT_ARRIVE) ) {
1359                         return 1;
1360                 }
1361                 p_objp = GET_NEXT(p_objp);
1362         }
1363         return 0;
1364 }
1365
1366 // ----------------------------------------------------------------
1367 // event_music_get_info()
1368 //
1369 // Return information about the event music in the buffer outbuf
1370 // NOTE: callers to this function are advised to allocate a 256 byte buffer
1371 void event_music_get_info(char *outbuf)
1372 {
1373         if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE || Current_pattern == -1 ) {
1374                 sprintf(outbuf,XSTR( "Event music is not playing", 213));
1375         }
1376         else {  
1377                 sprintf(outbuf,XSTR( "soundtrack: %s [%s]", 214), Soundtracks[Current_soundtrack_num].name, Pattern_description[Current_pattern]);
1378         }
1379 }
1380
1381 // ----------------------------------------------------------------
1382 // event_music_next_soundtrack()
1383 //
1384 // input:       delta           =>              1 or -1, depending if you want to go to next or previous song
1385 //
1386 // returns: New soundtrack number if successfully changed, otherwise return -1
1387 //
1388 int event_music_next_soundtrack(int delta)
1389 {
1390         int new_soundtrack;
1391
1392         if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE ) {
1393                 return -1;
1394         }
1395                 
1396         new_soundtrack = Current_soundtrack_num + delta;
1397         if ( new_soundtrack >= Num_soundtracks )
1398                 new_soundtrack = 0;
1399
1400         event_music_level_close();
1401         event_music_level_init(new_soundtrack);
1402
1403         return Current_soundtrack_num;
1404 }
1405
1406 // ----------------------------------------------------------------
1407 // event_music_get_soundtrack_name()
1408 //
1409 // Return information about the event music in the buffer outbuf
1410 // NOTE: callers to this function are advised to allocate a NAME_LENGTH buffer
1411 void event_music_get_soundtrack_name(char *outbuf)
1412 {
1413         if ( Event_music_enabled == FALSE || Event_music_level_inited == FALSE ) {
1414                 strcpy(outbuf, XSTR( "Event music is not playing", 213));
1415         }
1416         else {
1417                 sprintf(outbuf, Soundtracks[Current_soundtrack_num].name);
1418         }
1419 }
1420
1421 // set the current soundtrack based on name
1422 void event_music_set_soundtrack(char *name)
1423 {
1424         int i;
1425
1426         // find the correct index for the event music
1427         for ( i = 0; i < Num_soundtracks; i++ ) {
1428                 if ( !stricmp(name, Soundtracks[i].name) ) {
1429                         Current_soundtrack_num = i;
1430                         break;
1431                 }
1432         }
1433
1434         if ( i == Num_soundtracks ) {
1435                 Current_soundtrack_num = -1;
1436                 mprintf(("Current soundtrack set to -1 in event_music_set_soundtrack\n"));
1437         }
1438 }
1439
1440 int event_music_get_spooled_music_index(char *name)
1441 {
1442         // find the correct index for the event music
1443         for ( int i = 0; i < Num_music_files; i++ ) {
1444                 if ( !stricmp(name, Spooled_music[i].name) ) {
1445                         return i;
1446                 }
1447         }
1448
1449         return -1;
1450 }
1451
1452 // set a score based on name
1453 void event_music_set_score(int score_index, char *name)
1454 {
1455         Assert(score_index < NUM_SCORES);
1456
1457         // find the correct index for the event music
1458         Mission_music[score_index] = event_music_get_spooled_music_index(name);
1459 }
1460
1461 // reset what sort of music is to be used for this mission
1462 void event_music_reset_choices()
1463 {
1464         Current_soundtrack_num = -1;
1465         mprintf(("Current soundtrack set to -1 in event_music_reset_choices\n"));
1466         Mission_music[SCORE_BRIEFING] = -1;
1467         event_music_set_score(SCORE_DEBRIEF_SUCCESS, "Success");
1468         event_music_set_score(SCORE_DEBRIEF_AVERAGE, "Average");
1469         event_music_set_score(SCORE_DEBRIEF_FAIL, "Failure");
1470         //Mission_music[SCORE_DEBRIEF_SUCCESS] = MUSIC_DEBRIEF_SUCCESS_1;
1471         //Mission_music[SCORE_DEBRIEF_FAIL] = MUSIC_DEBRIEF_FAIL_1;
1472 }
1473
1474 void event_music_hostile_ship_destroyed()
1475 {
1476         Battle_over_timestamp = timestamp(BATTLE_CHECK_INTERVAL);
1477 }
1478
1479
1480 #pragma optimize("", on)