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