Kalidus
Junior Member
Posts: 5
Threads: 1
Joined: Apr 2013
Reputation:
0
|
Scripting an on/off radio
Hey!
I have now hit my first scripting wall and hope you guys can help. I have a map where I have a static model radio placed at a table. I want to be able to interact with it to turn it on and off. So far I have the following "items" in my scene:
1. The radio - a static model.
2. Script Area around the radio. Area name field = radioarea. PlayerInteractCallback field = Radio.
3. Sound entity (the little speaker icon). Name field = radio1. It is set to Active, and I have not defined a Sound Entity file to it, as I will do this through the script.
I want the music to play only within the area I have defined on the sound entity, and not across the entire map. I have looked through the wiki and searched the forum and Google, but I haven't been able to get it working. Any help would be appreciated!
HPS file:
void OnStart()
{
PreloadSound("radio.snt");
SetEntityPlayerInteractCallback("PlayerInteract", "radioarea", "Radio", true, 1);
}
void Radio(string &in asParent, string &in asChild, int alState)
{
PlaySoundAtEntity("radio1", "radio.snt", "radioarea", 0.0, false);
}
SNT file:
<SOUNDENTITY>
<SOUNDS>
<Main>
<Sound File="radio" />
</Main>
</SOUNDS>
<PROPERTIES Volume="0.5" MinDistance="1" MaxDistance="8" Random="1" Interval="0" FadeEnd="False" FadeStart="False" Stream="False" Loop="False" Use3D="True" Blockable="False" BlockVolumeMul="0.8" Priority="0" />
</SOUNDENTITY>
(This post was last modified: 05-05-2013, 11:29 AM by Kalidus.)
|
|
05-03-2013, 05:48 PM |
|
Tomato Cat
Senior Member
Posts: 287
Threads: 2
Joined: Sep 2012
Reputation:
20
|
RE: Scripting an on/off radio
As far as turning the radio on/off goes, you can try something like this:
void OnStart() { SetLocalVarInt("RadioOn",0); SetEntityPlayerInteractCallback("radioarea","Radio",false); }
void Radio(string &in AsEntity) { if(GetLocalVarInt("RadioOn") == 0) { //Play sound etc AddDebugMessage("Radio on",false); SetLocalVarInt("RadioOn",1); } else { //Stop sound etc etc AddDebugMessage("Radio off",false); SetLocalVarInt("RadioOn",0); } }
That *should* work.
(This post was last modified: 05-03-2013, 06:54 PM by Tomato Cat.)
|
|
05-03-2013, 06:45 PM |
|
PutraenusAlivius
Posting Freak
Posts: 4,713
Threads: 75
Joined: Dec 2012
Reputation:
119
|
RE: Scripting an on/off radio
void OnStart()
{
SetLocalVarInt("Radio", 1); //The VarInt that makes it to go ON/OFF. 1 = OFF, 0 = ON PreloadSound("radio.snt"); //Preloaded sound.
SetEntityPlayerInteractCallback("PlayerInteract", "RadioPlay", false); //SEPIC have three arguments, not five.
}
void Radio(string &in asEntity) //You had the wrong syntax.
{ if(GetLocalVarInt("Radio") == 0) { PlaySoundAtEntity("", "radio.snt", "radioarea", 0.0, false); } else { StopSound("radio.snt", 0.5f); //Change 0.5f to how long you want the sound to fade out. }
}
"Veni, vidi, vici."
"I came, I saw, I conquered."
|
|
05-04-2013, 12:58 AM |
|
TheGreatCthulhu
Member
Posts: 213
Threads: 10
Joined: Oct 2010
Reputation:
32
|
RE: Scripting an on/off radio
Because of the way sound entities work(the ones you place in the level editor), if you happen to spawn inside their area of audibility, they start their playback as soon as the level starts.
So, to have a more precise control of timing, use the PlaySoundAtEntity function
as explained above. You can also use PlaySoundAtEntity to play any snt file; you don't have to have a corresponding sound entity in the level (essentially, it dynamically creates one for you).
To control the volume, and how far the sound is audible, you have to uncheck the "use default" checkbox on the Sound tab, or the sound entity will use the values defined in the snt file. If that doesn't work by any chance, or if you want to make the sound loop, you'll have to create your own snt file, but that's not hard to do. These are just plain text files which contain some additional information about the sound. You can make a copy of an existing one, rename it, open it in a plain text editor such as Notepad, Notepad++, Geany, or similar, and then just change a few values.
Here's how 00_creak.snt looks like (in redist\sounds\00\) - note the PROPERTIES tag:
<SOUNDENTITY>
<SOUNDS>
<Main>
<Sound File="00_creak" />
</Main>
</SOUNDS>
<PROPERTIES Volume="0.5" MinDistance="10" MaxDistance="30" Random="1" Interval="0" FadeEnd="False" FadeStart="False" Stream="False" Loop="True" Use3D="False" Blockable="False" BlockVolumeMul="0.7" Priority="0" />
</SOUNDENTITY>
Here's just the PROPERTIES tag in a more readable format, so that I can tell you what each the attributes is for:
<PROPERTIES
Volume="0.5"
MinDistance="10"
MaxDistance="30"
Random="1"
Interval="0"
FadeEnd="False"
FadeStart="False"
Stream="False"
Loop="True"
Use3D="False"
Blockable="False"
BlockVolumeMul="0.7"
Priority="0" />
- Volume is - well, volume, where 1.0 is 100% (i think you can go over that, as well as below)
- MinDistance - if > 0, then you can't hear the sound if you get too close
- MaxDistance - how far the sound can be heard
- Random - if, under the <Main> tag more than one snt file is specified, this will cause the game to randomly pick one for playback (see, for example, the file redist\sounds\03\03_rock_move.snt). You can leave this unchanged.
- Interval - not sure; either the interval between looping sounds, or the time before you can replay it, or something like that
- FadeStart/FadeEnd - I suppose it specifies at what "end" the sound should be faded in/out when fading is specified through the script.
- Stream - memory management stuff, leave as is.
- Loop - should the sound loop ("True") or not ("False")
- Use3D - use 3D sound / surround ("True") or not ("False")
- Blockable - based on HPL1, determines if the sound is blockable by walls and such, so that enemies can't react and to it, etc.
- BlockVolumeMul - the volume multiplier for the blocked sound; that is, how much % of the normal volume the blocked sound should have. In the example above, 0.7 means 70% (where "normal" means the volume specified in Volume)
- Priority - can be 0, 1, 2, 3... If the game encounters a situation where several sounds must be played back at the same time, if they are not the same priority, only the highest priority sound(s) will be audible.
P.S. In the code snippet in the previous post, there's a minor mistake, that you must correct for the code to work. In the SetEntityPlayerInteractCallback function call, one of the parameters says "RadioPlay", but the corresponding callback function, a few lines bellow, is named Radio.
The two must have the same name. So either change
void Radio(string &in asEntity)
to
void RadioPlay(string &in asEntity)
or leave it as is and change "RadioPlay" parameter to "Radio".
|
|
05-04-2013, 10:12 AM |
|
Daemian
Posting Freak
Posts: 1,129
Threads: 42
Joined: Dec 2012
Reputation:
49
|
RE: Scripting an on/off radio
Hey Cthulhu,
What if this radio is not an entity but an item in your inventory.
How do you capture its activation to turn music on/off?
Thank you.
|
|
05-04-2013, 10:44 AM |
|
TheGreatCthulhu
Member
Posts: 213
Threads: 10
Joined: Oct 2010
Reputation:
32
|
RE: Scripting an on/off radio
Hm... You mean, like, click on the item in the inventory to turn the radio on or off (silent hill style)? I think that's somewhat problematic, since items are really designed for two things - to be used on the world entities, and to be combined. These are the events that the game can "detect", IIRC, there's really no way for the script to detect a click on an inventory item. So, I guess you'd have to work something out using those. For example, you could have the items "Radio" and "Radio Batteries", combine them, and use AddCombineCallback to detect this event. Then, under the excuse that the batteries are nearly empty, you could use a timer to turn off the sound after a short while (and replace the combined item "Radio with batteries", with the empty "Radio").
To play the sound, you could simply use PlaySoundAtEntity, passing "Player" as the 3rd parameter (asEntity), or even the PlayGuiSound function.
Anyway, it's just an idea, you'll need to test it out a bit. I'll see if I can come up with something and get back to you, and in the meantime, maybe someone else will have an idea as well.
P.S. If you're making a full conversion: I've seen people were able to replace the lantern with a flashlight; I suppose you can also replace it with other things - like with a radio. In such a scenario, you could use SetLanternLitCallback to turn the radio on or off.
|
|
05-04-2013, 11:37 AM |
|
Kalidus
Junior Member
Posts: 5
Threads: 1
Joined: Apr 2013
Reputation:
0
|
RE: Scripting an on/off radio
Thanks for the nice and detailed answers so far guys! I have tried both Mr Credits and JustAnotherPlayer's scripts. Both of them makes me able to turn the radio on, but not off. When I turn it on, music plays. When I turn it off, the music keeps playing and if I turn it on again, the music track loads again behind the other one so it plays double... I can't find the reason for this, as the code seems logical and correct enough.
I have removed the Sound entity from the map so I just have the Script Area now, to emit the sound.
|
|
05-04-2013, 07:13 PM |
|
Tomato Cat
Senior Member
Posts: 287
Threads: 2
Joined: Sep 2012
Reputation:
20
|
RE: Scripting an on/off radio
Does playing/stopping it from the script area work?
(This post was last modified: 05-04-2013, 07:25 PM by Tomato Cat.)
|
|
05-04-2013, 07:20 PM |
|
TheGreatCthulhu
Member
Posts: 213
Threads: 10
Joined: Oct 2010
Reputation:
32
|
RE: Scripting an on/off radio
Both scripts are setup so that you can both start and stop the playback. In the first script, you have to add your own code for playback start and end. The second script (by JustAnotherPlayer) has all the code in place, but there's another problem with it that I overlooked earlier:
PlaySoundAtEntity("", "radio.snt", "radioarea", 0.0, false);
The first parameter, which can be left out as it was done here, is an internal ID of the (auto-generated) sound-entity that the game (and you) can use in other script functions to identify the specific sound-entity you want to affect. The ID is a string chosen by you.
The StopSound function takes this ID as a parameter, not the name of the sound file. (This is because you may have the same sound file played on several places, and you don't want to stop them all at once.)
So, change this:
PlaySoundAtEntity("", "radio.snt", "radioarea", 0.0, false);
to this (I've chosen to use "id.sound.radio"):
PlaySoundAtEntity("id.sound.radio", "radio.snt", "radioarea", 0.0, false);
and then, a in the else branch, change this:
StopSound("radio.snt", 0.5f);
to
StopSound("id.sound.radio", 0.5f);
Here's the revised version of the entire script:
void OnStart() { SetLocalVarInt("Radio", 1); //The VarInt that makes it to go ON/OFF. 1 = OFF, 0 = ON PreloadSound("radio.snt"); //Preloaded sound.
SetEntityPlayerInteractCallback("PlayerInteract", "RadioPlay", false); //SEPIC have three arguments, not five. }
void RadioPlay(string &in asEntity) //You had the wrong syntax. { if(GetLocalVarInt("Radio") == 0) { PlaySoundAtEntity("id.sound.radio", "radio.snt", "radioarea", 0.0, false); // 0.0 - fade in time } else { StopSound("id.sound.radio", 0.5f); //Change 0.5f to how long you want the sound to fade out. } }
That should do it.
|
|
05-04-2013, 08:25 PM |
|
Tomato Cat
Senior Member
Posts: 287
Threads: 2
Joined: Sep 2012
Reputation:
20
|
RE: Scripting an on/off radio
Wouldn't it also be necessary to increment/decrement the Radio variable in the case that the radio sound was to be toggled? Unless I had misinterpreted and this is not what the OP specified.
|
|
05-04-2013, 08:36 PM |
|
|