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 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.
 Note:If the sound is playing while a player is outside of the sound's PAS/PVS/attenuation, and then enters its visiblity, the player will not hear the sound. This may be a problem for looping sounds or sounds with long durations, in which case the following workarounds can be used:
Note:If the sound is playing while a player is outside of the sound's PAS/PVS/attenuation, and then enters its visiblity, the player will not hear the sound. This may be a problem for looping sounds or sounds with long durations, in which case the following workarounds can be used:
- Use the RECIPIENT_FILTER_GLOBAL/RECIPIENT_FILTER_TEAMfilter. The sound will still "play" outside of the range, but at no volume.
- Play the sound to the player individually using RECIPIENT_FILTER_SINGLE_PLAYERwhen they enter a given area, e.g. via a trigger.
- Create a soundscape which automatically deals with this on a per-player basis
 Warning:Looping sounds will NOT stop automatically on round restart or when an entity is destroyed. You must manually stop them with the
Warning:Looping sounds will NOT stop automatically on round restart or when an entity is destroyed. You must manually stop them with the SND_STOP flag.
 Tip:The best time to stop looping sounds is during the
Tip:The best time to stop looping sounds is during the 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,volumeandpitchparameters. However the latter two can be forcefully overriden by adding theSND_CHANGE_VOLorSND_CHANGE_PITCHflags 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 theoriginparameter. 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 entityparameter forRECIPIENT_FILTER_PASandRECIPIENT_FILTER_PVSfilters. | |||||||||||||||||||||||||||||||||||||||
| 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 delayif 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_PLAYERwill play sounds only to the specified player here, orRECIPIENT_FILTER_PVSwill 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 filterby 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
local players = []
players.append(GetListenServerHost())
EmitSoundFiltered
({
	sound_name  = "vo/engineer_medic03.mp3"
	sound_level = 80
	entity      = Entities.FindByName(null, "speaker")
}, players)
 Confirm:
 Confirm: