Page 1 of 1

Using play-sound in Spring

Posted: 14 Oct 2005, 03:32
by Gnomre
As we all know, Spring has supported the "play-sound" command in scripts since 0.63b1:

-Added support for loading TA:K COB files and implemented the TA:K-specific opcode play-sound.

This allows a unitmaker to play any sound he wants (a wav file in the /sounds/ directory) at any volume at any point in the script. This is useful, since now we can do things such as running engine sounds while units move, foot step noises, or anything else of that nature.

Getting it to work isn't as simple as that makes it appear, though. After bothering Fnordia for a while, we finally got it working nicely.

Since I use scriptor, that's all this little guide is written for. I don't think any other compilers would be up to this task anyway. First of all, you must be compiling in TA:K mode. You can either click the little green TAK button in the scriptor GUI or you can put the following line at the beginning of your script:

#define TAK

Secondly, you cannot use the stock SmokeUnit.h file. If your unit uses SmokeUnit and you want it to play sounds, you can't right off the bat. This is because TAK handled smoking units differently than TA, mainly with a different function, but the point is if you try to compile with the original SmokeUnit you will crash scriptor.

So, to rectify this, I've made a hacked up Spring-sound-ready Smokeunit.h. It's available for download by clicking here. Simply put this .h file in your Includes directory, and then change the line:

#include "smokeunit.h"

in any scripts you want to play sounds in with:

#include "springsmoke.h"

And everything will compile and work just fine (barring other errors on your part, of course). You don't have to make this change for units that don't use play-sound.

Then, to use play-sound, you just type in the following line:

play-sound("filename", 1);

where filename is the filename of the .wav file in the /sounds/ directory to play, and 1 is the volume. There is no limit to volume afaik. For reference, I had to use a volume value of 10 for the Raven's explosion sound to make it about the same volume as it is normally in game. There's no limit to what functions it can be played in, as far as I know, but I'm sure putting a play-sound in a repeating loop without a sleep wouldn't be a good thing.

Posted: 14 Oct 2005, 12:27
by GrOuNd_ZeRo
That'd be sweet for tanks and planes! that's real cool Gnome!

Posted: 14 Oct 2005, 23:01
by Tim Blokdijk
Put it in the wiki?

Posted: 26 Oct 2005, 05:03
by Gnomre
Just a random update to this:

After further experimenting, putting play-sound in StartMoving() does not loop, at least not without doing while( TRUE ), and last time I tried that in Spring it froze up (I imagine because it's an infinite loop). It will only play the sound in StartMoving() once, UNLESS (this is the important part!) the unit is in first person control! If the unit is being manually controlled, StartMoving() is apparently continuously called. I call this the Zwzsg Effect, in honor of zwzsg's battle with the constantly-being-called AimPrimary() function.

Anyway, what this means is that with some crafty scripting, you could probably make engine noises (such as a running engine) when a unit is in first person control. Ok, the scripting isn't all that crafty. It'd be along these lines:

Code: Select all

StartMoving() {
	if( TRUE ) {
		play-sound("filename", 5);
		sleep X;
	}
}
Where X is the length of the sound in milliseconds. This is necessary because otherwise the game just continuously starts the sound without waiting to start it again. Also note my volume in that example--sounds in first person are far louder than normal. You should take into consideration the fact that the sound will be played one time every time the unit is issued an order which results in moving in third person as well. Finally, remember that this little first-person engine sound hack is purely conjecture on my part, I haven't actually tested it yet but from what I have done with StartMoving() and play-sound it should work.

Posted: 27 Oct 2005, 00:40
by zwzsg
Actually, the battle was short, as soon as I figured out that my problems came from AimPrimary being constantly re-called, I "protected" all the aiming script of my Spring unit from then on.

Your script workaround doesn't seem right to me. I know Cavedog's script use if( TRUE ) alot, but still TRUE being always true not matter what, a if(TRUE) {...} is the same as not having any if, right?

What I'd advise to use would be more:

Code: Select all

static-var DoingTheMovingSound;

Create()
	{
	DoingTheMovingSound=FALSE;// Don't forget the initialisation!
	....
	....
	}


StartMoving()
	{
	if(DoingTheMovingSound)
		{return;}
	DoingTheMovingSound=TRUE;
	play-sound("filename", 5);
	sleep X;
	DoingTheMovingSound=FALSE;
	}

Posted: 27 Oct 2005, 01:32
by Gnomre
It only calls StartMoving() once during normal operation, and exactly a bazillion times per second in first person view. Your way would possibly work better, like I said, I haven't tried it yet myself.

Posted: 28 Oct 2005, 00:03
by Archangel of Death
Ok, I can understand why it has to keep calling Startmoving. Now I also understand why all these new units seem to use this MotionControl() function, and how to make stuff walk right when being controlled.

Wouldn't it be nice if we could detect when a unit was being piloted? *hint hint :wink: *

Posted: 28 Oct 2005, 12:29
by yuritch
Wouldn't something like this work better?

Code: Select all

static-var isMoving;

SoundControl()
{
	while(TRUE)
	{
		if(isMoving)
		{
			play-sound("engine", 2);
		}
		//Adjust according to sound length
		sleep 200;
	}
}

Create()
{
	isMoving = FALSE;
	start-script SoundControl();
	...
}

StartMoving()
{
	play-sound("engine_start", 2);
	//wait till it's played completely
	sleep 200;
	isMoving = TRUE;

	...
}

StopMoving()
{
	isMoving = FALSE;
	//wait till engine sound stops
	sleep 200;
	play-sound("engine_stop", 2);
	...
}
This should make engine sound while the unit is moving, with special start and stop sounds (which will play every time the unit is issued new order, even if it didn't stop, might need tweaking to work around that).