Team Fortress 2/Scripting/Script Functions/EmitSoundEx
Function Description
void EmitSoundEx(table parameters)
Flexible way of playing sounds. All parameters except sound_name
are optional. Sounds must be precached first using PrecacheSound
or PrecacheScriptSound
, or they won't play. Sounds can be played in raw or soundscript form, and filtered to everyone, on a per-team or per-player basis. Volume, pitch, channel and attenuation level can be controlled, and the sound can play from a fixed position or relative to an entity. It is also possible to stop or adjust sounds already playing on the entity using special flags such as SND_CHANGE_VOL
or SND_CHANGE_PITCH
.
- Use the
RECIPIENT_FILTER_GLOBAL
/RECIPIENT_FILTER_TEAM
filter. The sound will still "play" outside of the range, but at no volume. - Play the sound to the player individually using
RECIPIENT_FILTER_SINGLE_PLAYER
when they enter a given area, e.g. via a trigger. - Create a soundscape which automatically deals with this on a per-player basis
SND_STOP
flag.
scorestats_accumulated_update
event. This event is fired right before all map entities are cleaned up. On players, stop the sound in the player_disconnect
event.Parameters
Name | Type | Default | Description | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
sound_name
|
string
|
Name of sound. Can be raw filename or soundscript.
Note:Soundscripts override the
channel , volume and pitch parameters. However the latter two can be forcefully overriden by adding the SND_CHANGE_VOL or SND_CHANGE_PITCH flags respectively. | ||||||||||||||||||||||||||||||||||||||||
channel
|
int
|
0 | Channel ID on which to play the sound. Channel values below have special behavior, all other channels behave normally. List of special channels:
| |||||||||||||||||||||||||||||||||||||||
volume
|
float
|
1.0 | Volume of sound, in normalized 0 - 1 range. Tip:Sounds may be hard to hear even at full volume. Naming custom sounds according to the soundmixer can be used to make them naturally louder.
| |||||||||||||||||||||||||||||||||||||||
sound_level
Note:Type the name of this parameter carefully. This has been a frequent mistake!
|
int
|
0 | Sound attenuation in decibels. The default value of 0 will make it play globally. See this page for real world equivalents. If the sound has non-zero attenuation, it will play from the entity 's origin if present, otherwise it uses the origin parameter.
Tip:To convert radius in Hammer units to decibels (similar to ambient_generic), use the following formula:
local soundlevel = (40 + (20 * log10(radius / 36.0))).tointeger();
| |||||||||||||||||||||||||||||||||||||||
flags
|
int
|
0 | Special sound flags. List of flags available:
| |||||||||||||||||||||||||||||||||||||||
pitch
|
int
|
100 | Pitch of the sound. | |||||||||||||||||||||||||||||||||||||||
special_dsp
|
int
|
0 | DSP effect to use on this sound. | |||||||||||||||||||||||||||||||||||||||
origin
|
Vector
|
0 0 0 | Overwrites sound origin if specified.
Note:If not specified, the origin will be fetched from the
entity parameter for RECIPIENT_FILTER_PAS and RECIPIENT_FILTER_PVS filters. | |||||||||||||||||||||||||||||||||||||||
delay
|
float
|
How far to skip into the sound playback, in seconds. The value must be negative!
Bug:Many (but not all) MP3 files cannot be skipped past a certain point depending on how the file was saved/compressed. The amount you are able to skip is not consistent, however it is usually around 30-35 seconds. "music/hl2_song2.mp3" for example will seemingly allow you to skip to any point in the song, while "music/hl2_song31.mp3" will only allow you to skip up to 35.8 seconds, and "music/hl2_song26_trainstation1.mp3" will only allow you to skip up to 32.9 seconds. WAV files are not affected by this. [todo tested in?]Todo: Is there any practical effect from a positive delay value?
| ||||||||||||||||||||||||||||||||||||||||
sound_time
|
float
|
Absolute time to delay sound until, NOT the duration. Overrides delay if specified. Todo: Might require the SND_DELAY flag to be set.
| ||||||||||||||||||||||||||||||||||||||||
entity
|
handle
|
null | Entity to emit the sound from. This is also used by certain filters. e.g. RECIPIENT_FILTER_SINGLE_PLAYER will play sounds only to the specified player here, or RECIPIENT_FILTER_PVS will build a PVS filter originating from this entity.
Note:The entity specified must be an edict, i.e. clients are aware of it's existence.
| |||||||||||||||||||||||||||||||||||||||
speaker_entity
|
handle
|
null | Entity which will *speak* the sound. This is not the sound as the actual owner of the sound, see above. | |||||||||||||||||||||||||||||||||||||||
filter_type
Note:Type the name of this parameter carefully. This has been frequently written as
filter by mistake! |
int
|
0 | Specifies what entities can hear this entity. See Constants.EScriptRecipientFilter. | |||||||||||||||||||||||||||||||||||||||
filter_param
|
int
|
-1 | Specifies an extra option to the filter. Currently only used by RECIPIENT_FILTER_TEAM , which uses this to specify which team to play to.
|
Flags
It may be useful to define these flags for extra readability.
::SND_NOFLAGS <- 0
::SND_CHANGE_VOL <- 1
::SND_CHANGE_PITCH <- 2
::SND_STOP <- 4
::SND_SPAWNING <- 8
::SND_DELAY <- 16
::SND_STOP_LOOPING <- 32
::SND_SPEAKER <- 64
::SND_SHOULDPAUSE <- 128
::SND_IGNORE_PHONEMES <- 256
::SND_IGNORE_NAME <- 512
::SND_DO_NOT_OVERWRITE_EXISTING_ON_CHANNEL <- 1024
Example Usage
// sounds should be precached once before use
PrecacheScriptSound("Game.Domination");
// play the sound to everyone around yourself
EmitSoundEx({
sound_name = "Game.Domination",
origin = GetListenServerHost().GetCenter(),
filter_type = Constants.EScriptRecipientFilter.RECIPIENT_FILTER_GLOBAL
});
Playing to specific players
It may be useful to play a sound to a specific list of players only, and/or with the sound originating from a source rather than globally.
This abuses a feature of PAS filtering, where players that are too far away won't hear the sound. This moves their view very, very far away and then sets it back after sending the sound to achieve arbitrary filtering.
function EmitSoundFiltered(params, included_players)
{
local origin = Vector()
local exclude_offset = Vector(99999, 99999, 99999)
local players = {}
for (local player; player = Entities.FindByClassname(player, "player");)
{
if (included_players.find(player) == null)
{
players[player] <- NetProps.GetPropVector(player, "m_vecViewOffset")
NetProps.SetPropVector(player, "m_vecViewOffset", exclude_offset)
}
}
params.filter_type <- 1 // RECIPIENT_FILTER_PAS_ATTENUATION
EmitSoundEx(params)
foreach (player, offset in players)
NetProps.SetPropVector(player, "m_vecViewOffset", offset)
}
// example usage that plays the sound only to the host and originating from an entity named "speaker"
local players = []
players.append(GetListenServerHost())
EmitSoundFiltered
({
sound_name = "vo/engineer_medic03.mp3"
sound_level = 80
entity = Entities.FindByName(null, "speaker")
}, players)