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.
== Parameters ==
Name 	Type 	Default 	Description 	 	 	
sound_name 	string 	 	Name of sound. Can be raw filename or soundscript.	 	 	
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:
{| class="standard-table" style="width:100%"	Name	Value	Description
CHAN_REPLACE 	-1 	Used by console commands 	 	 	 	
CHAN_AUTO 	0 	Automatic channel 	 	 	 	
CHAN_WEAPON 	1 	Weapon sounds 	 	 	 	
CHAN_VOICE 	2 	Character voices 	 	 	 	
CHAN_ITEM 	3 	Items 	 	 	 	
CHAN_BODY 	4 	Impacts, ragdolls and footsteps 	 	 	 	
CHAN_STREAM 	5 	"Stream from static or dynamic area" 	 	 	 	
CHAN_STATIC 	6 	Constant or background sounds. Valve recommends this to be used for looping ambient sounds, uninterrupted looping sounds or "one-shot" sounds	 	 	 	
CHAN_VOICE2 	7 	Announcer 	 	 	 	
CHAN_VOICE_BASE	8 - 107	Allocated for player voice chat (100 channels) 	 	 	 	
== 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)