/////////////////////////////// /// Music.zh /// /// v1.3.0 - 3rd July, 2017 /// /// By: ZoriaRPG /// //////////////////////////////////////////////////////////////////////////////////////////////////// /// A series of FFCs, and utility functions for playing MIDIs, Enhanced Music, and Sound Effects /// //////////////////////////////////////////////////////////////////////////////////////////////////// //import "std.zh" //import "string.zh" const int MIDI_DEFEATBOSS = 0; //Set to default midi to play for Victory Music. //ZC will use this if enhanced Victory music is not available. const int DEFAULT_BOSS_MUSIC = 0; //Sets a default boss music file to play. /////////////// /// SCRIPTS /// /////////////// ///////////////////// /// Sound Effects /// ///////////////////// // Ties SFX to an item, that is otherwise normally hardcoded. used for the Sonic Wand in LoE. item script playSound{ void run(int sfx){ Game->PlaySound(sfx); } } ///////////////// /// MIDI Only /// ///////////////// //Plays MIDI specified at D0. Place on a screen, to change the MIDI for that screen, only. //Plays at all times on that screen, and uses no conditions. ffc script playMIDI{ void run(int midiNumber){ Game->PlayMIDI(midiNumber); } } ///////////////////////// /// Conditional MIDIs /// ///////////////////////// //play a MIDI while an enemy with a specific ID is on-screen ffc script NPC_MIDI{ void run(int npc_ID, int midi){ //int originalMIDi = //share these two //int originalMusic[3] = //midi, enh music, track //store the normal midi or music //check for the npc and while it is on-screen //change the midi //if it dies, change back int q[4]; npc n; bool found; int enh_music[256] = {0}; Game->GetDMapMusicFilename(Game->GetCurDMap(), enh_music); int enh_trk = Game->GetDMapMusicTrack(Game->GetCurDMap()); for ( q[0] = 0; q[0] < 256; q[0]++ ) { if ( enh_music[q] == ' ' ) enh_music[q] = 0; } //kill the space. bool enhanced = ( enh_music[0] != 0 ); //is the dmap music enhanced? int originalmusic = Game->DMapMIDI[Game->GetCurDMap()]; while(true){ for ( q[0] = Screen->NumNPCs(); q[0] > 0; q[0]-- ) { n = Screen->LoadNPC(q); if ( n->ID == npc_ID ) { q[1] = 1; break; } q[1] = 0; } if ( q[1] ) { if ( !q[2] ) { Game->DMapMIDI[Game->GetCurDMap()] = midi; q[2] = 1; } } if ( q[2] ) { if ( !q[1] ) { //the enemy died. if ( enhanced ) Game->PlayEnhancedMusic(enh_music, enh_trk); if ( !enhanced ) Game->DMapMIDI[Game->GetCurDMap()] = originalmusic; } } Waitframe(); } } } //play enhanced music while an enemy with a specific ID is on-screen ffc script NPC_Music{ void run(int npc_ID, int music_string, int track){ //int originalMIDi = //share these two //int originalMusic[3] = //midi, enh music, track //store the normal midi or music //check for the npc and while it is on-screen //change the midi //if it dies, change back int q[4]; npc n; bool found; int enh_music[256] = {0}; Game->GetDMapMusicFilename(Game->GetCurDMap(), enh_music); for ( q[0] = 0; q[0] < 256; q[0]++ ) { if ( enh_music[q] == ' ' ) enh_music[q] = 0; } //kill the space. int enh_trk = Game->GetDMapMusicTrack(Game->GetCurDMap()); bool enhanced = ( enh_music[0] != 0 ); //is the dmap music enhanced? int originalmusic = Game->DMapMIDI[Game->GetCurDMap()]; while(true){ for ( q[0] = Screen->NumNPCs(); q[0] > 0; q[0]-- ) { n = Screen->LoadNPC(q); if ( n->ID == npc_ID ) { q[1] = 1; break; } q[1] = 0; } if ( q[1] ) { if ( !q[2] ) { PlayEnhMusicFile(music_string, track); q[2] = 1; } } if ( q[2] ) { if ( !q[1] ) { //the enemy died. if ( enhanced ) Game->PlayEnhancedMusic(enh_music, enh_trk); if ( !enhanced ) Game->DMapMIDI[Game->GetCurDMap()] = originalmusic; } } Waitframe(); } } } // These scripts will play MIDI files based on conditions set in the script args. // D0: MIDI file to play while boss is on the screen. // D1: The Screen Register (Screen->D[reg]) to use. // D2: Victory MIDI to play when boss is defeated. If set to 0, the MIDI set by constant MIDI_DEFEATBOSS plays. // D3: The duration of the victory music. // // If set to 0, the track will not play. // If set to greater than 0, the track will play for a specific duration, as follows: // To set using minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion: // e.g. 00005.0260 is 5 mins, 26 seconds. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds. // If you wish to specify the duration in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames. // e.g. 10526.1023 = 5,261,023 frames. // e.g. 10001.3591 = 13,591 frames. // // D4: The enemy ID of the 'boss': // // A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or... // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead. ffc script BossMusic{ void run(int bossMIDI, int reg, int victoryMIDI, int vict_dur, int enem){ Waitframes(6); int curScreen = Game->GetCurScreen(); int dat = Game->GetScreenD(curScreen,reg); if ( dat == 0 ) { if ( bossMIDI > 0 ) { Game->PlayMIDI(bossMIDI); } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); } } int curDMap = Game->GetCurDMap(); int stdMIDI = Game->DMapMIDI[curDMap]; int VictoryClockMethod = _GetDigit(vict_dur, 4); int dur; if ( VictoryClockMethod == 0 ) { dur = MusicFrames(vict_dur); //Convert victory music into frames. } if ( VictoryClockMethod > 0 ) { dur = _GetPartialArg(vict_dur,3,8); //Use the full value of loopBossMusic as frame in int. } while(true){ dat = Game->GetScreenD(curScreen,reg); if ( enem == -1 && !Screen->NumNPCs() ) { Game->SetScreenD(curScreen,reg,1); } if ( enem == 0 ) { //Should we do anything special? //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1. //-1 if we do it based on all enemies being dead. //A positive value trips it if there are no enemies of that ID on the screen. } if ( enem > 0 && !NumNPCsOf(enem) ){ Game->SetScreenD(curScreen,reg,1); } dat = Game->GetScreenD(curScreen,reg); if ( dat > 0 ) { if ( dur > 0 ) { if ( victoryMIDI > 0 ) { Game->PlayMIDI(MIDI_DEFEATBOSS); } else { Game->PlayMIDI(MIDI_DEFEATBOSS); } for ( int q = 0; q <= dur; q++ ) { Waitframe(); } } Game->PlayMIDI(stdMIDI); } Waitframe(); } } } ////////////////////// /// Enhanced Music /// ////////////////////// /// These scripts will play 'enhanced music', using values set in script args. /// If an enhanced music file is not available (e.g. the player does not have it, or elects /// not to use it, then they will play a back-up MIDI file, also set by script args. // D0: MIDI number to default to for this boss, if no enhanced music is available. // Split argument, high and low at decimal point: // #####.xxxx -> Backup MIDI file to play if enhanced BOSS music is not available. // xxxxx.#### -> Backup MIDI file to play if enhanced VICTORY music is not available. // D1: Screen->D reg to set/check. // D2: The duration of the victory music. // If set to 0, the track will not play. // If set to greater than 0, the track will play for a specific duration, as follows: // To set using minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion: // e.g. 00005.0260 is 5 mins, 26 seconds. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds. // If you wish to specify the duration in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames. // e.g. 10526.1023 = 5,261,023 frames. // e.g. 10001.3591 = 13,591 frames. // // D3: The STRING number, and track number, for Boss Music. Split arg, high and low at decimal point: // #####.xxxx -> The file number. // xxxxx.#### -> The track number to play. // Uses string ID from internal strings table. // D4: The STRING number, and track number, for Victory Music. Split arg, high and low at decimal point: // #####.xxxx -> The file number. // xxxxx.#### -> The track number to play. // Uses string ID from internal strings table. // D5: The point in the track to pause, then loop // // If set to 0, the track with loop only when it ends. // If set to greater than 0, the track will loop befor eit ends, as follows: // To loop by setting minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion: // e.g. 00005.0260 is 5 mins, 26 seconds. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds. // If you wish to specify the loop in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames. // e.g. 10526.1023 = 5,261,023 frames. // e.g. 10001.3591 = 13,591 frames. // // D6: This value instructs the FFC to set Screen->D[reg] = 1 when enemies are dead. // A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or... // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead. // // D7: If set to '1' or above, this will trace informationt o allegro.log for you as debug datum. //Version 0.44 - Strings set by String Table (ZQuest String Editor, not hardcoded) ffc script BossMusicEnhanced_InternalStrings{ //Credit Moosh for reminding me that reading internal strings in the string table is a thing. void run(int midiNumber_victoryMidiNumber, int reg, int vict_dur, float musicBoss_trkBoss, float musicVictory_trkVictory, float loopBossMusic, int enem, int debug){ int curScreen = Game->GetCurScreen(); int curDMAP = Game->GetCurDMap(); int curDmap = Game->GetCurDMap(); int dat = Game->GetScreenD(curScreen,reg); int stdMIDI = Game->DMapMIDI[curDMAP]; int dmapMusicBuffer[512]=" "; Game->GetDMapMusicFilename(curDMAP, dmapMusicBuffer); int midiNumber = _GetHighArgument(midiNumber_victoryMidiNumber); //#####.xxxx int victoryMIDI = _GetLowArgument(midiNumber_victoryMidiNumber); //xxxxx.#### int musicBoss = _GetHighArgument(musicBoss_trkBoss); //#####.xxxx int trkBoss = _GetLowArgument(musicBoss_trkBoss); //xxxxx.#### int musicVictory = _GetHighArgument(musicVictory_trkVictory); int mv[]="musicVictory = "; TraceS(mv); Trace(musicVictory); int trkVictory = _GetLowArgument(musicVictory_trkVictory); //xxxxx.#### int dmapTrack = Game->GetDMapMusicTrack(curDMAP); int q; int boss_buffer[255]=" "; //two-digit number, plus four-digit extension, plus NULL. int victory_buffer[255]=" "; //Buffer for Victory Music Filename. Game->GetMessage(musicVictory, victory_buffer); Game->GetMessage(musicBoss, boss_buffer); //Print filenames to allegro.log. if ( debug ) { int loading[]="Attempting to load file: "; TraceNL(); TraceS(loading); TraceNL(); TraceS(boss_buffer); TraceNL(); TraceS(loading); TraceNL(); TraceS(victory_buffer); TraceNL(); } int playingBoss[]="Playing Boss Music"; int playingVictory[]="Playing Victory Music"; int errLoading[]="Error loading track."; int LoopClockMethod = _GetDigit(loopBossMusic, 4); //Convert mins and seconds. int BossMusicDuration; if ( LoopClockMethod == 0 ) { BossMusicDuration = MusicFrames(loopBossMusic); //Convert loopBossMusic into time. } if ( LoopClockMethod > 0 ) { BossMusicDuration = _GetPartialArg(loopBossMusic,3,8); //Use the full value of loopBossMusic as frame in int. } int VictoryClockMethod = _GetDigit(vict_dur, 4); int dur; if ( VictoryClockMethod == 0 ) { dur = MusicFrames(vict_dur); //Convert victory music into frames. } if ( VictoryClockMethod > 0 ) { dur = _GetPartialArg(vict_dur,3,8); //Use the full value of loopBossMusic as frame in int. } for ( q = 0; q < 256; q++ ) { if ( boss_buffer[q] == ' ' ) boss_buffer[q] = 0; } //kill the space. for ( q = 0; q < 256; q++ ) { if ( victory_buffer[q] == ' ' ) victory_buffer[q] = 0; } //kill the space. bool playing = false; while(true){ Waitframes(5); dat = Game->GetScreenD(curScreen,reg); Waitframes(6); //Wait for enemies to spawn. //Set Screen->D[reg] = 1 if the enemy is dead. if ( enem == -1 && !Screen->NumNPCs() ) { Game->SetScreenD(curScreen,reg,1); } if ( enem == 0 ) { //Should we do anything special? //A zero value is intended to be used if we don't want the FFC to set Screen->D to 1. //-1 if we do it based on all enemies being dead. //A positive value trips it if there are no enemies of that ID on the screen. } if ( enem > 0 && !NumNPCsOf(enem) ){ Game->SetScreenD(curScreen,reg,1); } dat = Game->GetScreenD(curScreen,reg); if ( dat == 0 && loopBossMusic == 0 && !playing ){ Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); if ( midiNumber > 0 ) { Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default music if midiNumber is set to '0'. } } playing = true; } if ( dat == 0 && loopBossMusic > 0 ){ //set up music loop for ( int q = BossMusicDuration; q >=0; q-- ){ if ( q == BossMusicDuration && dat == 0 ) { Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } } if ( enem == -1 && !Screen->NumNPCs() ) { Game->SetScreenD(curScreen,reg,1); } if ( enem == 0 ) { //Should we do anything special? //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1. //-1 if we do it based on all enemies being dead. //A positive value trips it if there are no enemies of that ID on the screen. } if ( enem > 0 && !NumNPCsOf(enem) ){ Game->SetScreenD(curScreen,reg,1); } dat = Game->GetScreenD(curScreen,reg); if ( dat > 0 ) { break; } Waitframe(); } } if ( dat == 0 && loopBossMusic == 0 && !playing ){ Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); if ( midiNumber > 0 ) { Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Plays default if not specified. } } playing = true; } dat = Game->GetScreenD(curScreen,reg); if ( dat > 0 ) { if ( dur > 0 ) { Game->PlayEnhancedMusic(victory_buffer, trkVictory); TraceS(playingVictory); if ( ! Game->PlayEnhancedMusic(victory_buffer, trkVictory) ) { TraceS(errLoading); if ( victoryMIDI > 0 ) { Game->PlayMIDI(victoryMIDI); } else { Game->PlayMIDI(MIDI_DEFEATBOSS); //Plays default if Victory MIDI not specified. } } for ( int q = 0; q <= dur; q++ ) { Waitframe(); //Pause for duration of victory music. } } Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack); if ( ! Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack) ) { Game->PlayMIDI(stdMIDI); } Quit(); } Waitframe(); } } } // D0: MIDI number to default to for this boss, if no enhanced music is available. // Split argument, high and low at decimal point: // #####.xxxx -> Backup MIDI file to play if enhanced BOSS music is not available. // xxxxx.#### -> Backup MIDI file to play if enhanced VICTORY music is not available. // D1: Screen->D reg to set/check. // D2: Set to a value of '1' or higher, to use durations. // D3: Sets file type for both enhanced music tracks. Split argument, high and low at decimal point: // xxx##.xxxx -> Type for Boss Music file // xxxxx.xx## -> Type for Victory Music file // D4: The file number, and track number, for Boss Music. Split arg, high and low at decimal point: // #####.xxxx -> The file number. // xxxxx.#### -> The track number to play. // D5: The file number, and track number, for Victory Music. Split arg, high and low at decimal point: // #####.xxxx -> The file number. // xxxxx.#### -> The track number to play. // D6: The point in the track to pause, then loop. // // If set to 0, the track with loop only when it ends. // If set to greater than 0, the track will loop befor eit ends, as follows: // To loop by setting minutes, and seconds, set up minutes as the integer portion of the arg, and seconds as the decimal portion: // e.g. 00005.0260 is 5 mins, 26 seconds. // This works to a fineness of 1/10 second, so 00010.0136 is 10 minutes, 13.6 seconds. // If you wish to specify the loop in frames, set the ten-thousands place to '1', and the rest of the value to the number of frames. // e.g. 10526.1023 = 5,261,023 frames. // e.g. 10001.3591 = 13,591 frames. // // D7: This value instructs the FFC to set Screen->D[reg] = 1 when enemies are dead. // #####.xxxx -> A value of zero here, instructs the FFC not to change the Screen->D[reg] value. Leave this at zero, if the enemy does this. // Otherwise, set this to -1 (negative one) if you want the Victory music to play when all screen NPCs are dead...or... // a positive value matching an enemy ID that is on the screen, if you want to play the Victory music when all enemies with that ID are dead. // xxxxx.#### -> Set to '1' or higher to enable debugging reports to allegro.log. // //Version 0.44 (Numbered Files) ffc script BossMusicEnhanced{ void run(int midiNumber_victoryMidiNumber, int reg, int victoryDur, float musicType_musicTypeVictory, float musicBoss_trkBoss, float musicVictory_trkVictory, float loopBossMusic, int enem_debug){ int curScreen = Game->GetCurScreen(); int curDMAP = Game->GetCurDMap(); int curDmap = Game->GetCurDMap(); int dat = Game->GetScreenD(curScreen,reg); int stdMIDI = Game->DMapMIDI[curDMAP]; int enem = _GetHighArgument(enem_debug); int debug= _GetLowArgument(enem_debug); int dmapMusicBuffer[512]=" "; Game->GetDMapMusicFilename(curDMAP, dmapMusicBuffer); int midiNumber = _GetHighArgument(midiNumber_victoryMidiNumber); //#####.xxxx int victoryMIDI = _GetLowArgument(midiNumber_victoryMidiNumber); //xxxxx.#### int musicType = _GetHighArgument(musicType_musicTypeVictory); //xxx##.xxxx int musicType_Victory = _GetLowArgument(musicType_musicTypeVictory); //xxxxx.xx## int musicBoss = _GetHighArgument(musicBoss_trkBoss); //#####.xxxx int trkBoss = _GetLowArgument(musicBoss_trkBoss); //xxxxx.#### int musicVictory = _GetHighArgument(musicVictory_trkVictory); //#####.xxxx int trkVictory = _GetLowArgument(musicVictory_trkVictory); //xxxxx.#### int dmapTrack = Game->GetDMapMusicTrack(curDMAP); int mp3[]=".mp3"; int vgm[]=".vgm"; int nsf[]=".nsf"; int ogg[]=".ogg"; int s3m[]=".s3m"; int mod[]=".mod"; int spc[]=".spc"; int gym[]=".gym"; int gbs[]=".gbs"; int it_format[]=".it"; int xm[]=".xm"; int boss_buffer[7]=" "; //two-digit number, plus four-digit extension, plus NULL. int victory_buffer[7]=" "; //Buffer for Victory Music Filename. int strBoss[2]=" "; //The two digit value of musicBoss arg. int strVictory[2]=" "; //The two digit value of musicVictory is stored here. //int bossMusic[]=" "; //Must read value from enhBoss, append .mp3 to it, and ///Set up Boss Music Filename String itoa(strBoss, musicBoss); //Copy the value of arg musicBoss into string strBoss. strncpy(boss_buffer, strBoss, 2); //Copy filename (two-digit number) to buffer. if ( musicType == 0 ) strcat(boss_buffer, mp3); //Append datatype to buffer (MP3) else if ( musicType == 1 ) strcat(boss_buffer, vgm); //Append datatype to buffer ( Video Game Music format) else if ( musicType == 2 ) strcat(boss_buffer, nsf); //Append datatype to buffer ( NES Sound File ) else if ( musicType == 3 ) strcat(boss_buffer, ogg); //Append datatype to buffer ( The Xiph.org open music format ) else if ( musicType == 4 ) strcat(boss_buffer, s3m); //Append datatype to buffer ( ScreamTracker 3 module file ) else if ( musicType == 5 ) strcat(boss_buffer, mod); //Append datatype to buffer ( Tracker Module file ) else if ( musicType == 6 ) strcat(boss_buffer, spc); //Append datatype to buffer ( Super NES / SuFami soound file ) else if ( musicType == 7 ) strcat(boss_buffer, gym); //Append datatype to buffer ( Genesis / Megadrive sound file ) else if ( musicType == 8 ) strcat(boss_buffer, gbs); //Append datatype to buffer ( Gameboy sound file ) else if ( musicType == 9 ) strcat(boss_buffer, it_format); //Append datatype to buffer ( Impulse Tracker audio file ) else if ( musicType == 10 ) strcat(boss_buffer, xm); //Append datatype to buffer ( Triton FastTracker 2 'Extended Module' format } ///Other formats. //Set up Victory Music Filename String itoa(strVictory, musicVictory); //Copy the value of arg musicVictory into string strVictory. strncpy(victory_buffer, strVictory, 2); //Copy filename (two-digit number) to buffer. if ( musicType_Victory == 0 ) strcat(victory_buffer, mp3); //Append datatype to buffer (MP3) else if ( musicType_Victory == 1 ) strcat(victory_buffer, vgm); //Append datatype to buffer ( Video Game Music format) else if ( musicType_Victory == 2 ) strcat(victory_buffer, nsf); //Append datatype to buffer ( NES Sound File ) else if ( musicType_Victory == 3 ) strcat(victory_buffer, ogg); //Append datatype to buffer ( The Xiph.org open music format ) else if ( musicType_Victory == 4 ) strcat(victory_buffer, s3m); //Append datatype to buffer ( ScreamTracker 3 module file ) else if ( musicType_Victory == 5 ) strcat(victory_buffer, mod); //Append datatype to buffer ( Tracker Module file ) else if ( musicType_Victory == 6 ) strcat(victory_buffer, spc); //Append datatype to buffer ( Super NES / SuFami soound file ) else if ( musicType_Victory == 7 ) strcat(victory_buffer, gym); //Append datatype to buffer ( Genesis / Megadrive sound file ) else if ( musicType_Victory == 8 ) strcat(victory_buffer, gbs); //Append datatype to buffer ( Gameboy sound file ) else if ( musicType_Victory == 9 ) strcat(victory_buffer, it_format); //Append datatype to buffer ( Impulse Tracker audio file ) else if ( musicType_Victory == 10 ) strcat(victory_buffer, xm); //Append datatype to buffer ( Triton FastTracker 2 'Extended Module' format } ///Other formats. //Print filenames to allegro.log. if ( debug ) { int loading[]="Attempting to load file: "; TraceNL(); TraceS(loading); TraceNL(); TraceS(boss_buffer); TraceNL(); TraceS(loading); TraceNL(); TraceS(victory_buffer); TraceNL(); } int playingBoss[]="Playing Boss Music"; int playingVictory[]="Playing Victory Music"; int errLoading[]="Error loading track."; int LoopClockMethod = _GetDigit(loopBossMusic, 4); //Convert mins and seconds. int BossMusicDuration; if ( LoopClockMethod == 0 ) { BossMusicDuration = MusicFrames(loopBossMusic); //Convert loopBossMusic into time. } if ( LoopClockMethod > 0 ) { BossMusicDuration = _GetPartialArg(loopBossMusic,3,8); //Use the full value of loopBossMusic as frame in int. } int VictoryDuration; int VictoryDurMethod = _GetDigit(victoryDur, 4); if ( VictoryDurMethod == 0 ) { VictoryDuration = MusicFrames(victoryDur); //Convert loopBossMusic into time. } if ( VictoryDurMethod > 0 ) { VictoryDuration = _GetPartialArg(victoryDur,3,8); //Use the full value of loopBossMusic as frame in int. } bool playing = false; while(true){ dat = Game->GetScreenD(curScreen,reg); Waitframes(6); //Wait for enemies to spawn. //Set Screen->D[reg] = 1 if the enemy is dead. if ( enem == -1 && !Screen->NumNPCs() ) { Game->SetScreenD(curScreen,reg,1); } if ( enem == 0 ) { //Should we do anything special? //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1. //-1 if we do it based on all enemies being dead. //A positive value trips it if there are no enemies of that ID on the screen. } if ( enem > 0 && !NumNPCsOf(enem) ){ Game->SetScreenD(curScreen,reg,1); } dat = Game->GetScreenD(curScreen,reg); if ( dat == 0 && loopBossMusic == 0 && !playing ){ Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); if ( midiNumber > 0 ) { Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned. } } playing = true; } if ( dat == 0 && loopBossMusic > 0 ){ //set up music loop for ( int q = BossMusicDuration; q >=0; q-- ){ if ( q == BossMusicDuration && dat == 0 ) { Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); if ( midiNumber > 0 ) { Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned. } } } if ( enem == -1 && !Screen->NumNPCs() ) { Game->SetScreenD(curScreen,reg,1); } if ( enem == 0 ) { //Should we do anything special? //A zero value is intended to be used if we don;t want the FFC to set Screen->D to 1. //-1 if we do it based on all enemies being dead. //A positive value trips it if there are no enemies of that ID on the screen. } if ( enem > 0 && !NumNPCsOf(enem) ){ Game->SetScreenD(curScreen,reg,1); } dat = Game->GetScreenD(curScreen,reg); if ( dat > 0 ) { break; } Waitframe(); } } if ( dat == 0 && loopBossMusic == 0 && !playing ){ Game->PlayEnhancedMusic(boss_buffer, trkBoss); TraceS(playingBoss); if ( ! Game->PlayEnhancedMusic(boss_buffer, trkBoss) ) { TraceS(errLoading); if ( midiNumber > 0 ) { Game->PlayMIDI(midiNumber); //Play MIDI if enhanced music is not available. } else { Game->PlayMIDI(DEFAULT_BOSS_MUSIC); //Play default if not assigned. } } playing = true; } dat = Game->GetScreenD(curScreen,reg); if ( dat > 0 ) { if ( VictoryDuration > 0 ) { Game->PlayEnhancedMusic(victory_buffer, trkVictory); TraceS(playingVictory); if ( ! Game->PlayEnhancedMusic(victory_buffer, trkVictory) ) { TraceS(errLoading); if ( victoryMIDI > 0 ) { Game->PlayMIDI(victoryMIDI); } else { Game->PlayMIDI(MIDI_DEFEATBOSS); } } for ( int q = 0; q <= VictoryDuration; q++ ) { Waitframe(); //Pause for duration of victory music. } } Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack); if ( ! Game->PlayEnhancedMusic(dmapMusicBuffer, dmapTrack) ) { Game->PlayMIDI(stdMIDI); } Quit(); } Waitframe(); } } } ///////////////// /// FUNCTIONS /// ///////////////// //Pass a float to either of these, to convert raw float into mins and seconds as: // #####.xxxx = # mins x seconds. Example: // 00003.0050 = 3 mins, 5 seconds. // 00001.0012 = 1 minute, 5.2 seconds. //Timers are functional to a total clock of 3579 seconds (59 mins, 39 seconds). int MusicSeconds(float seconds){ int music_seconds = _GetLowArgument(seconds); return music_seconds * 6; } int MusicMinutes(float mins){ int music_minutes = _GetHighArgument(mins); return music_minutes * 360; } //Returns total time in frames, so that ZC understands it. int MusicFrames(float val){ int mins = MusicMinutes(val); int seconds = MusicSeconds(val); return mins+seconds; } int _GetRemainderAsInt(int v) { int r = (v - (v << 0)) * 10000; return r; } // This function breaks up the value of an argument into individual digits. It is combined with the function GetDigit below. int _GetDigit(int n, int place){ //GetDigit and related functions by Gleeok place = Clamp(place, -4, 4); if(place < 0){ n = _GetRemainderAsInt(n); place += 4; } int r = ((n / Pow(10, place)) % 10) << 0; return r; } int _GetHighArgument(int arg) { return arg >> 0; } int _GetLowArgument(int arg) { return (arg - (arg >> 0)) * 10000; } int _GetPartialArg(int arg, int place, int num){ place = Clamp(place, -4, 4); int r; int adj = 1; for(int i = num-1; i > -1; i--){ if(place - i < -4) continue; r += _GetDigit(arg, place - i) * adj; adj *= 10; } return r; } // Plays enhanced music file by reading the string 'str_id' from Quest->Strings, at a specified track 'track_id'. // If track_id is positive, it uses this track. // If track_id is negative, it uses the message string equal to the inverse value (so -20 is string ID 20) // to set the track ID. // Returns true if playing, false otherwise. bool PlayEnhMusicFile(int str_id, int track_id){ int musicBuffer[256]=" "; int track_buffer[256]=" "; int q; int trk; Game->GetMessage(str_id, musicBuffer); if ( track_id < 0 ) { Game->GetMessage((track_id * -1), track_buffer); for ( q = 0; q < 256; q++ ) { if ( track_buffer[q] == ' ' ) track_buffer[q] = 0; } //Kill GetMessage trailing spaces. trk = atoi(track_buffer); } else trk = track_id; //Kill GetMessage trailing spaces. for ( q = 0; q < 256; q++ ) { if ( musicBuffer[q] == ' ' ) musicBuffer[q] = 0; } return ( Game->PlayEnhancedMusic(musicBuffer, trk) ); } int Legacy_PlayEnhMusicFile(int str_id, int track_id) { if ( PlayEnhMusicFile(str_id, track_id) ) return 1; return 0; }