OK, then first things first.
The OnStart() function is called by the engine the first time the player enters a map. The game then invokes OnEnter(), but OnEnter() is also called every time the player comes back to the map (if level design allows for backtracking). OnLeave() is called every time the player exits the map.
(BTW, don'g get confused when I write
FuntionName() - I just use the () as a way of quickly
distinguishing functions from other names, like variables and such, when
talking about it in forums; the actual parameter list is ommited, if
any.)
Now, this isn't very useful in itself for the purposes of scripting sounds, except that you can call PreloadSound() there (in OnEnter() func).
But, what you can do there is hook up functions that are going to respond to various events, usually collisions.
Normally, you'd have a Script Area placed in the map, in a strategic location, and then play a sound when the player collides with it, or maybe you'd check for a collision with an entity, or something along those lines.
Let's say you have a passageway, and you want some scary sound to play when the player emerges from it. You'd place a script area named at the end of the passageway (so that the player must hit it). Let's also say you named it "AreaScarySound".
In the corresponding script file, in OnStart(), you'd then call the AddEntityColideCallback() function to tell the script what should happen on player-ScriptArea collision.
Now, this may look intimidating now, but bear with me, it's rather simple.
This is the declaration of the AddEntityColideCallback() function (note: this is the
declaration, so this is not how you call it, this just describes the format of the function; also white space doesn't matter here - I formatted the code in this way so that it's easier to read):
void AddEntityCollideCallback(
string& parentColliderName,
string& childColliderName,
string& callbackFunction,
bool deleteCallbackAfterCall,
int whenToCall
);
The parentColliderName and childColliderName are simply the names of the objects you want the engine to check for collisions. The callbackFunction parameter is the important one: it's a name of another function in your script that should be called when the collision is detected (known as the "callback" function). It can be any function, but it has to have a certain "format" - I'll come back to that in a moment. The deleteCallbackAfterCall parameter can be either
true or
false. If
true, the callback function will be called only after the first collision; if
false, the callback will be invoked every time a collision is detected.
The last parameter tells the engine when exactly the callback should be called during a collision event; value of 1 means only on enter (when they first overlap), -1 means only on leave (when they stop overlapping), and 0 means on both.
The callback function is defined by you elsewhere in the file, and it has this format:
void YourFuncName(string &in parent, string &in child, int state)
All of it's parameters are input parameters, and are passed in by the engine when the function is called (on a collision event), so that you can use them to check some things. The state parameter here has the same meaning as the whenToCall parameter above, except it can only be 1 (enter), or -1 (leave).
So, how it all looks when you put it together?
void OnStart()
{
AddEntityCollideCallback("Player", "AreaScarySound", "PlayScarySound", true, -1);
// other stuff omitted...
}
// other functions omitted...
void PlayScarySound(string &in parent, string &in child, int state)
{
PlaySoundAtEntity("id.my.scary.sound", "general_wind_whirl.snt", "Player", 0.5f, false);
}
Aaaand - that's it.
A few comments. Note that the 3rd parameter to AddEntityCollideCallback() is the name of the callback function, as you defined it below. It has to match
exactly - even in casing, since the script language is case-sensitive (you can't write, say "playSCARYSounD"). The next parameter behind it is set to true, so the callback will be invoked only once, and -1 tells the engine that the callback is called when the Player leaves the script area's volume.
The other function, PlaySoundAtEntity(), takes string as a first parameter, that will be used as an internal id of the sound resource. You can put there anything you want; later on, you can use it in the StopSound() function to tell it which sound should be stopped (if it's a looping sound). The next parameter is the sound you want to be played - here in the example I used ""general_wind_whirl.snt", which comes with Amnesia.
That's pretty much it.