Jump to content
Sign in to follow this  
celery

CLY Jukebox - play music and remember its progress!

Recommended Posts

CLY Jukebox

This script will play music tracks in succession. You can define the order of the tracks, their starting point and when they end. You can choose whether the list plays just once or loops, or you can choose to have them play indefinitely and randomly.

The script also remembers the progress of a track when you pause or save a game, and the track will resume from where it left off when the game is unpaused or loaded. Normally pausing causes the track to skip and savegames don't store audio progress.

Execute the script like this:

0=[0,["EP1_Track08",63,134,1],["EP1_Track14",0,255,0.8]] execVM "cly_jukebox.sqf"

[<0: no loop 1: loop 2: play random tracks indefinitely>,["track name",start mark,end mark,volume 0-1],[...]]

You can pause the music with CLY_jukeboxpause=true, which enables you to play some other track in the meanwhile, and CLY_jukeboxpause=false will resume playing the jukebox from where it left.

Stop the script with CLY_jukeboxkill=<fade out in seconds>. Starting a new jukebox will automatically end the current one.

cly_jukebox.sqf

//CLY Jukebox by Celery
//
//This script will let you play several music tracks in succession.
//Loading a savegame or visiting the ESC menu will not disrupt the music.
//
//Requires
// onPauseScript="cly_jukebox.sqf";
//in description.ext.
//
//Execute anywhere when needed with the required arguments.
//
//Example:
//0=[0,["EP1_Track08",63,134,1],["EP1_Track14",0,255,0.8]] execVM "cly_jukebox.sqf"
//Arguments:
//[loop,["track name",start mark,end mark,volume],[...]]
//Loop: <0: no loop  1: loop  2: play random tracks indefinitely>
//
//You can stop the script with CLY_jukeboxkill=<fade out in seconds>
//CLY_jukeboxkill=5 will fade the music to zero in 5 seconds and the script ends.
//
//You can pause the script with CLY_jukeboxpause=true and unpause with false.
////////////////////////////////////////////////////////////////////////////////////

//Resume track at correct mark after ESC or load
if (typeName (_this select 0)=="DISPLAY") exitWith {CLY_jukeboxresume=true};
if (isNil "CLY_jukeboxresumescript") then {
CLY_jukeboxresumescript=[] spawn {
	while {true} do {
		_loadcheck=[] spawn {disableSerialization;waitUntil {false}};
		waitUntil {scriptDone _loadcheck};
		CLY_jukeboxresume=true;
	};
};
};

_loop=_this select 0;
_tracks=[];
{if (typeName _x=="ARRAY") then {_tracks=_tracks+[_x]}} forEach _this;
if (count _tracks==0) exitWith {hint "No tracks recognized by CLY Jukebox!"};

_i=-1;
_track="";
_lasttrack="";
_volume=1;
_fadein=0;
_fadeout=0.3;
_trackstart=0;
_trackstarts=0;
_trackend=0;
_trackends=-1;
_duration=_trackend-_trackstart;
_resumedata=["",0];

//ID number of the script: prevents two scripts from running in parallel
if (!isNil "CLY_jukeboxid") then {CLY_jukeboxid=CLY_jukeboxid+1};
if (isNil "CLY_jukeboxid") then {CLY_jukeboxid=0};
_jukeboxid=CLY_jukeboxid;

//Kill switch: set to 0 or more and the jukebox will fade out in that many seconds
CLY_jukeboxkill=-1;

//Pause flag
CLY_jukeboxpause=false;

//Resume flag: will be true and makes music resume correctly when game is paused or loaded
CLY_jukeboxresume=false;

scopeName "main";
while {CLY_jukeboxkill<0 and CLY_jukeboxid==_jukeboxid and (_loop>0 or _i<count _tracks)} do {
//Select track
if (time>_trackends) then {
	_i=_i+1;
	if (_i>=count _tracks) then {
		if (_loop==0) then {CLY_jukeboxkill=1;breakTo "main"} else {_i=0};
	};

	_trackdata=[];
	if (_loop!=2) then {
		_trackdata=_tracks select _i;
	} else {
		_trackdata=_tracks select floor random count _tracks;
		while {_loop==2 and count _tracks>1 and _trackdata select 0==_lasttrack} do {
			_trackdata=_tracks select floor random count _tracks;
		};
	};
	_track=_trackdata select 0;
	_trackstart=_trackdata select 1;
	_trackend=_trackdata select 2;
	_volume=_trackdata select 3;
	_duration=_trackend-_trackstart;
	_fadein=0;
	if (_trackstart>0) then {_fadein=0.2};

	_fadeout fadeMusic 0;
	sleep _fadeout;
	_fadeout=1;

	if (CLY_jukeboxkill>=0 or CLY_jukeboxid!=_jukeboxid) then {breakTo "main"};

	_fadein fadeMusic _volume;
	playMusic [_track,_trackstart];

	_lasttrack=_track;
	_trackstarts=time;
	_trackends=time+_trackend-_trackstart;
	_resumedata=[_track,time-_trackstarts+_trackstart];

};

//Resume if ESC or loadgame
if (CLY_jukeboxresume) then {playMusic _resumedata;CLY_jukeboxresume=false};
_resumedata=[_track,time-_trackstarts+_trackstart];

//Jukebox pause
if (CLY_jukeboxpause) then {
	1 fadeMusic 0;
	sleep 1;
	waitUntil {!CLY_jukeboxpause};
	if (CLY_jukeboxkill<0 and CLY_jukeboxid==_jukeboxid) then {
		1 fadeMusic _volume;
		playMusic _resumedata;
	} else {
		breakTo "main";
	};
};

sleep 0.05;
};

if (CLY_jukeboxkill>=0) then {CLY_jukeboxkill fadeMusic 0};

description.ext:

onPauseScript="cly_jukebox.sqf";

Edited by Celery
  • Thanks 1

Share this post


Link to post
Share on other sites

Thx for the JukeBox. Celery! :)

I made a example mission and put it on our script section at Assault Mission Studio.

But i don't get the start mark/end mark to work.

dlicon.gif

CLY Jukebox by Celery

Edited by Imutep
Script updated!

Share this post


Link to post
Share on other sites
But i don't get the start mark/end mark to work.

Do you mean that the track doesn't start or end at those parts of the track? With the example arguments the first track should begin at the synth xylophone part of Revolver Jam.

Edited by Celery

Share this post


Link to post
Share on other sites

Sorry Celery...all works fine.

I changed the wrong track in the command line. Sorry! :)

Share this post


Link to post
Share on other sites

Awesome, mate! Thanks! Will definitely make use of this in BOTS! :D

Share this post


Link to post
Share on other sites

Just a minor cosmetic update, changed the name of the pause variable because it just occurred to me that one might want to play cutscene music with this script.

Share this post


Link to post
Share on other sites
My jukebox script can handle playlists and fadeouts. All you need to do is execute a playlist with the right conditions.

^ From my thread.

So, I'm unsure of how to link in conditions with this jukebox script. That, and I'm unsure exactly what you meant.

Cheers, though :)

Share this post


Link to post
Share on other sites
^ From my thread.

So, I'm unsure of how to link in conditions with this jukebox script. That, and I'm unsure exactly what you meant.

Cheers, though :)

Make a trigger with the condition you like, and on activation execute the script with the tracks that you want.

Share this post


Link to post
Share on other sites

Ahhh, alrighty.

I.e. if the nearestenemy blah blah is set to combat, and knowsabout player, play the 'danger' tracks... sound right to you? And just set to 'repeatedly', so it happens throughout whole game.

The Jukebox will understand when another trigger starts to play song Y instead of X, and will fade to it, instead of 2 songs at once, right?

Share this post


Link to post
Share on other sites
I.e. if the nearestenemy blah blah is set to combat, and knowsabout player, play the 'danger' tracks... sound right to you? And just set to 'repeatedly', so it happens throughout whole game.

That sounds about right.

The Jukebox will understand when another trigger starts to play song Y instead of X, and will fade to it, instead of 2 songs at once, right?

Yeah, a new jukebox will eliminate the older one. If you feel that the default fade is too short (0.3 sec), modify the _fadeout variable or intruduce a longer fadeout with 0=[] spawn {CLY_jukeboxkill=3;sleep 3;[trackdata] exec "cly_jukebox.sqs"} instead of just executing a new jukebox.

Share this post


Link to post
Share on other sites

Alrighty, thanks a lot :)

With 'startmark' & 'endmark', can it handle that itself? I.e. if I set start 0, and don't define end, it'll count as finished when the song is over?

EDIT:

Is there an option for 'fade in'?

Edited by HateDread

Share this post


Link to post
Share on other sites

The end mark is needed because the game doesn't know how long custom sounds are. If you want fade in, increase the value of the _fadein variable and remove the _trackstart check after it.

Share this post


Link to post
Share on other sites

Cheers, mate :)

Okay, so it's safe to use triggers/while statements that execute the script continuously? I.e. it won't just keep restarting the song at 0 each time?

And, when playing random songs, there's a significant pause before them. I know raising the time you mentioned earlier should increase the time of the fadeout, but not cause a silence between them? Also happens when starting a track randomly for the first time, i.e. with nothing before it - there is a pause of a few seconds. Any way around this?

I tried using the code the following way, but had no sound:

_Explore = '[2,["mx_explore_1",0,185,1],["mx_explore_2",0,186,1],["mx_explore_3",0,195,1],["mx_explore_4",0,196,1]] exec "cly_jukebox.sqs"';

_ExploreMusic = compile _Explore;

_Battle = '[2,["MWbattle1",0,127,1],["MWbattle2",0,125,1],["MWbattle3",0,134,1],["MWbattle4",0,154,1]] exec "cly_jukebox.sqs"';

_BattleMusic = compile _Battle;

While {true} do

{

if ((player distance Campfire1) > 75) then

{call _ExploreMusic;}

else {call _BattleMusic;};

Sleep 1;

};

I have checked the script itself, and hints fire when in place of the call command. Does this just not like being called?

Anyways, thanks a lot!

Share this post


Link to post
Share on other sites

You could try just executing the script within the while loop as compiling and calling a line in the same script is redundant. If you really need to call it, use curly brackets instead of quotes in the call script, and forget the compiling. The _fadeout variable affects the silence before the first song because it fades the music to zero and waits for that many seconds before starting to play, and the only cause that I can think of for pauses between songs is that their end mark is greater than their actual length.

Share this post


Link to post
Share on other sites

Script updated!

  • Rewrote the script and changed format to .sqf
  • Fixed random loop
  • Fixed CLY_jukeboxpause
  • Removed the need for "cly_jukeboxresume.sqf"

Since the script is now in .sqf, remember to change exec to execVM and introduce a script handle if you're executing the script in a trigger. The description.ext entry has also changed.

Edited by Celery

Share this post


Link to post
Share on other sites

Hey Celery, great script :D Can you help me with an issue where I where I want my track to repeat its-self again just the once but start from 48 seconds in.

0=[0,["Ambient07_Manhattan",0,100,0.9]],["Ambient07_Manhattan",48,105,0.9]]  execVM "cly_jukebox.sqf";

However I'm using this in a cutscene with setAccTime 0.2 and the whole timming of the tracks is out. Any ideas how I can make the 2nd track follow the first while using setAccTime. :confused:

Share this post


Link to post
Share on other sites

Well, you could play a single track, then wait 48*0.2 seconds and then play the remaining track.

Share this post


Link to post
Share on other sites

Great script Celery! I just had one question. Is there a way to sync up the music to all the clients if you have the jukebox play random tracks?

Share this post


Link to post
Share on other sites

It might be possible, I'll look into it.

Share this post


Link to post
Share on other sites
It might be possible, I'll look into it.

Thanks! I was just wondering, so don't break a sweat over it!

Share this post


Link to post
Share on other sites

Sorry for the necro, but is there a list of tracks defined somewhere/how are tracks defined?

To illustrate; I'm using this command:

[0,["EP1_Track04",0,176,1]] execVM "cly_jukebox.sqf";

, which plays EP1_Track04_Arrival.ogg song, but if that's how the songs are defined (first part of filename), how do you play the correct "EP1_Track13" song of which there are four (EP1_Track13_IronMountain.ogg, EP1_Track13_IronMountain_D1.ogg, EP1_Track13_IronMountain_D2.ogg, EP1_Track13_IronMountain_V.ogg)?

Edited by Outlawz7

Share this post


Link to post
Share on other sites

Place a trigger, select a music track for it, save the mission and look for the track name in mission.sqm.

Share this post


Link to post
Share on other sites

CLY_jukeboxkill=<fade out time in sec> not working! How to kill that jukebox with a help of trigger?:confused:

Share this post


Link to post
Share on other sites

:confused:I can't terminate this script at all. It either works forever from the start or is not working at all! HEEEELP!:confused:

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×