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