//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
# include "cbase.h"
# include <ctype.h>
# include <KeyValues.h>
# include "engine/IEngineSound.h"
# include "SoundEmitterSystem/isoundemittersystembase.h"
# include "igamesystem.h"
# include "soundchars.h"
# include "filesystem.h"
# include "tier0/vprof.h"
# include "checksum_crc.h"
# include "tier0/icommandline.h"
# if defined( TF_CLIENT_DLL ) || defined( TF_DLL )
# include "tf_shareddefs.h"
# include "tf_classdata.h"
# endif
// NVNT haptic utils
# include "haptics/haptic_utils.h"
# ifndef CLIENT_DLL
# include "envmicrophone.h"
# include "sceneentity.h"
# else
# include <vgui_controls/Controls.h>
# include <vgui/IVGui.h>
# include "hud_closecaption.h"
# define CRecipientFilter C_RecipientFilter
# endif
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
static ConVar sv_soundemitter_trace ( " sv_soundemitter_trace " , " 0 " , FCVAR_REPLICATED , " Show all EmitSound calls including their symbolic name and the actual wave file they resolved to \n " ) ;
# ifdef STAGING_ONLY
static ConVar sv_snd_filter ( " sv_snd_filter " , " " , FCVAR_REPLICATED , " Filters out all sounds not containing the specified string before being emitted \n " ) ;
# endif // STAGING_ONLY
extern ISoundEmitterSystemBase * soundemitterbase ;
static ConVar * g_pClosecaption = NULL ;
# ifdef _XBOX
int LookupStringFromCloseCaptionToken ( char const * token ) ;
const wchar_t * GetStringForIndex ( int index ) ;
# endif
static bool g_bPermitDirectSoundPrecache = false ;
# if !defined( CLIENT_DLL )
void ClearModelSoundsCache ( ) ;
# endif // !CLIENT_DLL
void WaveTrace ( char const * wavname , char const * funcname )
{
if ( IsX360 ( ) & & ! IsDebug ( ) )
{
return ;
}
static CUtlSymbolTable s_WaveTrace ;
// Make sure we only show the message once
if ( UTL_INVAL_SYMBOL = = s_WaveTrace . Find ( wavname ) )
{
DevMsg ( " %s directly referenced wave %s (should use game_sounds.txt system instead) \n " ,
funcname , wavname ) ;
s_WaveTrace . AddString ( wavname ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &src -
//-----------------------------------------------------------------------------
EmitSound_t : : EmitSound_t ( const CSoundParameters & src )
{
m_nChannel = src . channel ;
m_pSoundName = src . soundname ;
m_flVolume = src . volume ;
m_SoundLevel = src . soundlevel ;
m_nFlags = 0 ;
m_nPitch = src . pitch ;
m_nSpecialDSP = 0 ;
m_pOrigin = 0 ;
m_flSoundTime = ( src . delay_msec = = 0 ) ? 0.0f : gpGlobals - > curtime + ( ( float ) src . delay_msec / 1000.0f ) ;
m_pflSoundDuration = 0 ;
m_bEmitCloseCaption = true ;
m_bWarnOnMissingCloseCaption = false ;
m_bWarnOnDirectWaveReference = false ;
m_nSpeakerEntity = - 1 ;
}
void Hack_FixEscapeChars ( char * str )
{
int len = Q_strlen ( str ) + 1 ;
char * i = str ;
char * o = ( char * ) _alloca ( len ) ;
char * osave = o ;
while ( * i )
{
if ( * i = = ' \\ ' )
{
switch ( * ( i + 1 ) )
{
case ' n ' :
* o = ' \n ' ;
+ + i ;
break ;
default :
* o = * i ;
break ;
}
}
else
{
* o = * i ;
}
+ + i ;
+ + o ;
}
* o = 0 ;
Q_strncpy ( str , osave , len ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CSoundEmitterSystem : public CBaseGameSystem
{
public :
virtual char const * Name ( ) { return " CSoundEmitterSystem " ; }
# if !defined( CLIENT_DLL )
bool m_bLogPrecache ;
FileHandle_t m_hPrecacheLogFile ;
CUtlSymbolTable m_PrecachedScriptSounds ;
public :
CSoundEmitterSystem ( char const * pszName ) :
m_bLogPrecache ( false ) ,
m_hPrecacheLogFile ( FILESYSTEM_INVALID_HANDLE )
{
}
void LogPrecache ( char const * soundname )
{
if ( ! m_bLogPrecache )
return ;
// Make sure we only show the message once
if ( UTL_INVAL_SYMBOL ! = m_PrecachedScriptSounds . Find ( soundname ) )
return ;
if ( m_hPrecacheLogFile = = FILESYSTEM_INVALID_HANDLE )
{
StartLog ( ) ;
}
m_PrecachedScriptSounds . AddString ( soundname ) ;
if ( m_hPrecacheLogFile ! = FILESYSTEM_INVALID_HANDLE )
{
filesystem - > Write ( " \" " , 1 , m_hPrecacheLogFile ) ;
filesystem - > Write ( soundname , Q_strlen ( soundname ) , m_hPrecacheLogFile ) ;
filesystem - > Write ( " \" \n " , 2 , m_hPrecacheLogFile ) ;
}
else
{
Warning ( " Disabling precache logging due to file i/o problem!!! \n " ) ;
m_bLogPrecache = false ;
}
}
void StartLog ( )
{
m_PrecachedScriptSounds . RemoveAll ( ) ;
if ( ! m_bLogPrecache )
return ;
if ( FILESYSTEM_INVALID_HANDLE ! = m_hPrecacheLogFile )
{
return ;
}
filesystem - > CreateDirHierarchy ( " reslists " , " DEFAULT_WRITE_PATH " ) ;
// open the new level reslist
char path [ _MAX_PATH ] ;
Q_snprintf ( path , sizeof ( path ) , " reslists \\ %s.snd " , gpGlobals - > mapname . ToCStr ( ) ) ;
m_hPrecacheLogFile = filesystem - > Open ( path , " wt " , " GAME " ) ;
}
void FinishLog ( )
{
if ( FILESYSTEM_INVALID_HANDLE ! = m_hPrecacheLogFile )
{
filesystem - > Close ( m_hPrecacheLogFile ) ;
m_hPrecacheLogFile = FILESYSTEM_INVALID_HANDLE ;
}
m_PrecachedScriptSounds . RemoveAll ( ) ;
}
# else
CSoundEmitterSystem ( char const * name )
{
}
# endif
// IServerSystem stuff
virtual bool Init ( )
{
Assert ( soundemitterbase ) ;
# if !defined( CLIENT_DLL )
m_bLogPrecache = CommandLine ( ) - > CheckParm ( " -makereslists " ) ? true : false ;
# endif
g_pClosecaption = cvar - > FindVar ( " closecaption " ) ;
Assert ( g_pClosecaption ) ;
return soundemitterbase - > ModInit ( ) ;
}
virtual void Shutdown ( )
{
Assert ( soundemitterbase ) ;
# if !defined( CLIENT_DLL )
FinishLog ( ) ;
# endif
soundemitterbase - > ModShutdown ( ) ;
}
void ReloadSoundEntriesInList ( IFileList * pFilesToReload )
{
soundemitterbase - > ReloadSoundEntriesInList ( pFilesToReload ) ;
}
virtual void TraceEmitSound ( char const * fmt , . . . )
{
if ( ! sv_soundemitter_trace . GetBool ( ) )
return ;
va_list argptr ;
char string [ 256 ] ;
va_start ( argptr , fmt ) ;
Q_vsnprintf ( string , sizeof ( string ) , fmt , argptr ) ;
va_end ( argptr ) ;
// Spew to console
Msg ( " %s %s " , CBaseEntity : : IsServer ( ) ? " (sv) " : " (cl) " , string ) ;
}
// Precache all wave files referenced in wave or rndwave keys
virtual void LevelInitPreEntity ( )
{
char mapname [ 256 ] ;
# if !defined( CLIENT_DLL )
StartLog ( ) ;
Q_snprintf ( mapname , sizeof ( mapname ) , " maps/%s " , STRING ( gpGlobals - > mapname ) ) ;
# else
Q_strncpy ( mapname , engine - > GetLevelName ( ) , sizeof ( mapname ) ) ;
# endif
Q_FixSlashes ( mapname ) ;
Q_strlower ( mapname ) ;
// Load in any map specific overrides
char scriptfile [ 512 ] ;
# if defined( TF_CLIENT_DLL ) || defined( TF_DLL )
if ( V_stristr ( mapname , " mvm " ) )
{
V_strncpy ( scriptfile , " scripts/mvm_level_sounds.txt " , sizeof ( scriptfile ) ) ;
if ( filesystem - > FileExists ( " scripts/mvm_level_sounds.txt " , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( " scripts/mvm_level_sounds.txt " ) ;
}
if ( filesystem - > FileExists ( " scripts/mvm_level_sound_tweaks.txt " , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( " scripts/mvm_level_sound_tweaks.txt " ) ;
}
if ( filesystem - > FileExists ( " scripts/game_sounds_vo_mvm.txt " , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( " scripts/game_sounds_vo_mvm.txt " , true ) ;
}
if ( filesystem - > FileExists ( " scripts/game_sounds_vo_mvm_mighty.txt " , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( " scripts/game_sounds_vo_mvm_mighty.txt " , true ) ;
}
g_pTFPlayerClassDataMgr - > AddAdditionalPlayerDeathSounds ( ) ;
}
else
{
Q_StripExtension ( mapname , scriptfile , sizeof ( scriptfile ) ) ;
Q_strncat ( scriptfile , " _level_sounds.txt " , sizeof ( scriptfile ) , COPY_ALL_CHARACTERS ) ;
if ( filesystem - > FileExists ( scriptfile , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( scriptfile ) ;
}
}
# else
Q_StripExtension ( mapname , scriptfile , sizeof ( scriptfile ) ) ;
Q_strncat ( scriptfile , " _level_sounds.txt " , sizeof ( scriptfile ) , COPY_ALL_CHARACTERS ) ;
if ( filesystem - > FileExists ( scriptfile , " GAME " ) )
{
soundemitterbase - > AddSoundOverrides ( scriptfile ) ;
}
# endif
# if !defined( CLIENT_DLL )
for ( int i = soundemitterbase - > First ( ) ; i ! = soundemitterbase - > InvalidIndex ( ) ; i = soundemitterbase - > Next ( i ) )
{
CSoundParametersInternal * pParams = soundemitterbase - > InternalGetParametersForSound ( i ) ;
if ( pParams - > ShouldPreload ( ) )
{
InternalPrecacheWaves ( i ) ;
}
}
# endif
}
virtual void LevelInitPostEntity ( )
{
}
virtual void LevelShutdownPostEntity ( )
{
soundemitterbase - > ClearSoundOverrides ( ) ;
# if !defined( CLIENT_DLL )
FinishLog ( ) ;
# endif
}
void InternalPrecacheWaves ( int soundIndex )
{
CSoundParametersInternal * internal = soundemitterbase - > InternalGetParametersForSound ( soundIndex ) ;
if ( ! internal )
return ;
int waveCount = internal - > NumSoundNames ( ) ;
if ( ! waveCount )
{
DevMsg ( " CSoundEmitterSystem: sounds.txt entry '%s' has no waves listed under 'wave' or 'rndwave' key!!! \n " ,
soundemitterbase - > GetSoundName ( soundIndex ) ) ;
}
else
{
g_bPermitDirectSoundPrecache = true ;
for ( int wave = 0 ; wave < waveCount ; wave + + )
{
CBaseEntity : : PrecacheSound ( soundemitterbase - > GetWaveName ( internal - > GetSoundNames ( ) [ wave ] . symbol ) ) ;
}
g_bPermitDirectSoundPrecache = false ;
}
}
void InternalPrefetchWaves ( int soundIndex )
{
CSoundParametersInternal * internal = soundemitterbase - > InternalGetParametersForSound ( soundIndex ) ;
if ( ! internal )
return ;
int waveCount = internal - > NumSoundNames ( ) ;
if ( ! waveCount )
{
DevMsg ( " CSoundEmitterSystem: sounds.txt entry '%s' has no waves listed under 'wave' or 'rndwave' key!!! \n " ,
soundemitterbase - > GetSoundName ( soundIndex ) ) ;
}
else
{
for ( int wave = 0 ; wave < waveCount ; wave + + )
{
CBaseEntity : : PrefetchSound ( soundemitterbase - > GetWaveName ( internal - > GetSoundNames ( ) [ wave ] . symbol ) ) ;
}
}
}
HSOUNDSCRIPTHANDLE PrecacheScriptSound ( const char * soundname )
{
int soundIndex = soundemitterbase - > GetSoundIndex ( soundname ) ;
if ( ! soundemitterbase - > IsValidIndex ( soundIndex ) )
{
if ( Q_stristr ( soundname , " .wav " ) | | Q_strstr ( soundname , " .mp3 " ) )
{
g_bPermitDirectSoundPrecache = true ;
CBaseEntity : : PrecacheSound ( soundname ) ;
g_bPermitDirectSoundPrecache = false ;
return SOUNDEMITTER_INVALID_HANDLE ;
}
# if !defined( CLIENT_DLL )
if ( soundname [ 0 ] )
{
static CUtlSymbolTable s_PrecacheScriptSoundFailures ;
// Make sure we only show the message once
if ( UTL_INVAL_SYMBOL = = s_PrecacheScriptSoundFailures . Find ( soundname ) )
{
DevMsg ( " PrecacheScriptSound '%s' failed, no such sound script entry \n " , soundname ) ;
s_PrecacheScriptSoundFailures . AddString ( soundname ) ;
}
}
# endif
return ( HSOUNDSCRIPTHANDLE ) soundIndex ;
}
# if !defined( CLIENT_DLL )
LogPrecache ( soundname ) ;
# endif
InternalPrecacheWaves ( soundIndex ) ;
return ( HSOUNDSCRIPTHANDLE ) soundIndex ;
}
void PrefetchScriptSound ( const char * soundname )
{
int soundIndex = soundemitterbase - > GetSoundIndex ( soundname ) ;
if ( ! soundemitterbase - > IsValidIndex ( soundIndex ) )
{
if ( Q_stristr ( soundname , " .wav " ) | | Q_strstr ( soundname , " .mp3 " ) )
{
CBaseEntity : : PrefetchSound ( soundname ) ;
}
return ;
}
InternalPrefetchWaves ( soundIndex ) ;
}
public :
void EmitSoundByHandle ( IRecipientFilter & filter , int entindex , const EmitSound_t & ep , HSOUNDSCRIPTHANDLE & handle )
{
// Pull data from parameters
CSoundParameters params ;
// Try to deduce the actor's gender
gender_t gender = GENDER_NONE ;
CBaseEntity * ent = CBaseEntity : : Instance ( entindex ) ;
if ( ent )
{
char const * actorModel = STRING ( ent - > GetModelName ( ) ) ;
gender = soundemitterbase - > GetActorGender ( actorModel ) ;
}
if ( ! soundemitterbase - > GetParametersForSoundEx ( ep . m_pSoundName , handle , params , gender , true ) )
{
return ;
}
if ( ! params . soundname [ 0 ] )
return ;
# ifdef STAGING_ONLY
if ( sv_snd_filter . GetString ( ) [ 0 ] & & ! V_stristr ( params . soundname , sv_snd_filter . GetString ( ) ) )
{
return ;
}
# endif // STAGING_ONLY
if ( ! Q_strncasecmp ( params . soundname , " vo " , 2 ) & &
! ( params . channel = = CHAN_STREAM | |
params . channel = = CHAN_VOICE | |
params . channel = = CHAN_VOICE2 ) )
{
DevMsg ( " EmitSound: Voice wave file %s doesn't specify CHAN_VOICE, CHAN_VOICE2 or CHAN_STREAM for sound %s \n " ,
params . soundname , ep . m_pSoundName ) ;
}
// handle SND_CHANGEPITCH/SND_CHANGEVOL and other sound flags.etc.
if ( ep . m_nFlags & SND_CHANGE_PITCH )
{
params . pitch = ep . m_nPitch ;
}
if ( ep . m_nFlags & SND_CHANGE_VOL )
{
params . volume = ep . m_flVolume ;
}
# if !defined( CLIENT_DLL )
bool bSwallowed = CEnvMicrophone : : OnSoundPlayed (
entindex ,
params . soundname ,
params . soundlevel ,
params . volume ,
ep . m_nFlags ,
params . pitch ,
ep . m_pOrigin ,
ep . m_flSoundTime ,
ep . m_UtlVecSoundOrigin ) ;
if ( bSwallowed )
return ;
# endif
# if defined( _DEBUG ) && !defined( CLIENT_DLL )
if ( ! enginesound - > IsSoundPrecached ( params . soundname ) )
{
Msg ( " Sound %s:%s was not precached \n " , ep . m_pSoundName , params . soundname ) ;
}
# endif
float st = ep . m_flSoundTime ;
if ( ! st & &
params . delay_msec ! = 0 )
{
st = gpGlobals - > curtime + ( float ) params . delay_msec / 1000.f ;
}
enginesound - > EmitSound (
filter ,
entindex ,
params . channel ,
params . soundname ,
params . volume ,
( soundlevel_t ) params . soundlevel ,
ep . m_nFlags ,
params . pitch ,
ep . m_nSpecialDSP ,
ep . m_pOrigin ,
NULL ,
& ep . m_UtlVecSoundOrigin ,
true ,
st ,
ep . m_nSpeakerEntity ) ;
if ( ep . m_pflSoundDuration )
{
* ep . m_pflSoundDuration = enginesound - > GetSoundDuration ( params . soundname ) ;
}
TraceEmitSound ( " EmitSound: '%s' emitted as '%s' (ent %i) \n " ,
ep . m_pSoundName , params . soundname , entindex ) ;
// Don't caption modulations to the sound
if ( ! ( ep . m_nFlags & ( SND_CHANGE_PITCH | SND_CHANGE_VOL ) ) )
{
EmitCloseCaption ( filter , entindex , params , ep ) ;
}
# if defined( WIN32 ) && !defined( _X360 )
// NVNT notify the haptics system of this sound
HapticProcessSound ( ep . m_pSoundName , entindex ) ;
# endif
}
void EmitSound ( IRecipientFilter & filter , int entindex , const EmitSound_t & ep )
{
VPROF ( " CSoundEmitterSystem::EmitSound (calls engine) " ) ;
# ifdef STAGING_ONLY
if ( sv_snd_filter . GetString ( ) [ 0 ] & & ! V_stristr ( ep . m_pSoundName , sv_snd_filter . GetString ( ) ) )
{
return ;
}
# endif // STAGING_ONLY
if ( ep . m_pSoundName & &
( Q_stristr ( ep . m_pSoundName , " .wav " ) | |
Q_stristr ( ep . m_pSoundName , " .mp3 " ) | |
ep . m_pSoundName [ 0 ] = = ' ! ' ) )
{
# if !defined( CLIENT_DLL )
bool bSwallowed = CEnvMicrophone : : OnSoundPlayed (
entindex ,
ep . m_pSoundName ,
ep . m_SoundLevel ,
ep . m_flVolume ,
ep . m_nFlags ,
ep . m_nPitch ,
ep . m_pOrigin ,
ep . m_flSoundTime ,
ep . m_UtlVecSoundOrigin ) ;
if ( bSwallowed )
return ;
# endif
if ( ep . m_bWarnOnDirectWaveReference & &
Q_stristr ( ep . m_pSoundName , " .wav " ) )
{
WaveTrace ( ep . m_pSoundName , " Emitsound " ) ;
}
# if defined( _DEBUG ) && !defined( CLIENT_DLL )
if ( ! enginesound - > IsSoundPrecached ( ep . m_pSoundName ) )
{
Msg ( " Sound %s was not precached \n " , ep . m_pSoundName ) ;
}
# endif
enginesound - > EmitSound (
filter ,
entindex ,
ep . m_nChannel ,
ep . m_pSoundName ,
ep . m_flVolume ,
ep . m_SoundLevel ,
ep . m_nFlags ,
ep . m_nPitch ,
ep . m_nSpecialDSP ,
ep . m_pOrigin ,
NULL ,
& ep . m_UtlVecSoundOrigin ,
true ,
ep . m_flSoundTime ,
ep . m_nSpeakerEntity ) ;
if ( ep . m_pflSoundDuration )
{
* ep . m_pflSoundDuration = enginesound - > GetSoundDuration ( ep . m_pSoundName ) ;
}
TraceEmitSound ( " EmitSound: Raw wave emitted '%s' (ent %i) \n " ,
ep . m_pSoundName , entindex ) ;
return ;
}
if ( ep . m_hSoundScriptHandle = = SOUNDEMITTER_INVALID_HANDLE )
{
ep . m_hSoundScriptHandle = ( HSOUNDSCRIPTHANDLE ) soundemitterbase - > GetSoundIndex ( ep . m_pSoundName ) ;
}
if ( ep . m_hSoundScriptHandle = = - 1 )
return ;
EmitSoundByHandle ( filter , entindex , ep , ep . m_hSoundScriptHandle ) ;
}
void EmitCloseCaption ( IRecipientFilter & filter , int entindex , bool fromplayer , char const * token , CUtlVector < Vector > & originlist , float duration , bool warnifmissing /*= false*/ )
{
// No close captions in multiplayer...
if ( gpGlobals - > maxClients > 1 | | ( gpGlobals - > maxClients = = 1 & & ! g_pClosecaption - > GetBool ( ) ) )
{
return ;
}
// A negative duration means fill it in from the wav file if possible
if ( duration < 0.0f )
{
char const * wav = soundemitterbase - > GetWavFileForSound ( token , GENDER_NONE ) ;
if ( wav )
{
duration = enginesound - > GetSoundDuration ( wav ) ;
}
else
{
duration = 2.0f ;
}
}
char lowercase [ 256 ] ;
Q_strncpy ( lowercase , token , sizeof ( lowercase ) ) ;
Q_strlower ( lowercase ) ;
if ( Q_strstr ( lowercase , " \\ " ) )
{
Hack_FixEscapeChars ( lowercase ) ;
}
// NOTE: We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing
// all players from it!!!!
CRecipientFilter filterCopy ;
filterCopy . CopyFrom ( ( CRecipientFilter & ) filter ) ;
// Remove any players who don't want close captions
CBaseEntity : : RemoveRecipientsIfNotCloseCaptioning ( ( CRecipientFilter & ) filterCopy ) ;
# if !defined( CLIENT_DLL )
{
// Defined in sceneentity.cpp
bool AttenuateCaption ( const char * token , const Vector & listener , CUtlVector < Vector > & soundorigins ) ;
if ( filterCopy . GetRecipientCount ( ) > 0 )
{
int c = filterCopy . GetRecipientCount ( ) ;
for ( int i = c - 1 ; i > = 0 ; - - i )
{
CBasePlayer * player = UTIL_PlayerByIndex ( filterCopy . GetRecipientIndex ( i ) ) ;
if ( ! player )
continue ;
Vector playerOrigin = player - > GetAbsOrigin ( ) ;
if ( AttenuateCaption ( lowercase , playerOrigin , originlist ) )
{
filterCopy . RemoveRecipient ( player ) ;
}
}
}
}
# endif
// Anyone left?
if ( filterCopy . GetRecipientCount ( ) > 0 )
{
# if !defined( CLIENT_DLL )
byte byteflags = 0 ;
if ( warnifmissing )
{
byteflags | = CLOSE_CAPTION_WARNIFMISSING ;
}
if ( fromplayer )
{
byteflags | = CLOSE_CAPTION_FROMPLAYER ;
}
CBaseEntity * pActor = CBaseEntity : : Instance ( entindex ) ;
if ( pActor )
{
char const * pszActorModel = STRING ( pActor - > GetModelName ( ) ) ;
gender_t gender = soundemitterbase - > GetActorGender ( pszActorModel ) ;
if ( gender = = GENDER_MALE )
{
byteflags | = CLOSE_CAPTION_GENDER_MALE ;
}
else if ( gender = = GENDER_FEMALE )
{
byteflags | = CLOSE_CAPTION_GENDER_FEMALE ;
}
}
// Send caption and duration hint down to client
UserMessageBegin ( filterCopy , " CloseCaption " ) ;
WRITE_STRING ( lowercase ) ;
WRITE_SHORT ( MIN ( 255 , ( int ) ( duration * 10.0f ) ) ) ,
WRITE_BYTE ( byteflags ) ,
MessageEnd ( ) ;
# else
// Direct dispatch
CHudCloseCaption * cchud = GET_HUDELEMENT ( CHudCloseCaption ) ;
if ( cchud )
{
cchud - > ProcessCaption ( lowercase , duration , fromplayer ) ;
}
# endif
}
}
void EmitCloseCaption ( IRecipientFilter & filter , int entindex , const CSoundParameters & params , const EmitSound_t & ep )
{
// No close captions in multiplayer...
if ( gpGlobals - > maxClients > 1 | | ( gpGlobals - > maxClients = = 1 & & ! g_pClosecaption - > GetBool ( ) ) )
{
return ;
}
if ( ! ep . m_bEmitCloseCaption )
{
return ;
}
// NOTE: We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing
// all players from it!!!!
CRecipientFilter filterCopy ;
filterCopy . CopyFrom ( ( CRecipientFilter & ) filter ) ;
// Remove any players who don't want close captions
CBaseEntity : : RemoveRecipientsIfNotCloseCaptioning ( ( CRecipientFilter & ) filterCopy ) ;
// Anyone left?
if ( filterCopy . GetRecipientCount ( ) < = 0 )
{
return ;
}
float duration = 0.0f ;
if ( ep . m_pflSoundDuration )
{
duration = * ep . m_pflSoundDuration ;
}
else
{
duration = enginesound - > GetSoundDuration ( params . soundname ) ;
}
bool fromplayer = false ;
CBaseEntity * ent = CBaseEntity : : Instance ( entindex ) ;
if ( ent )
{
while ( ent )
{
if ( ent - > IsPlayer ( ) )
{
fromplayer = true ;
break ;
}
ent = ent - > GetOwnerEntity ( ) ;
}
}
EmitCloseCaption ( filter , entindex , fromplayer , ep . m_pSoundName , ep . m_UtlVecSoundOrigin , duration , ep . m_bWarnOnMissingCloseCaption ) ;
}
void EmitAmbientSound ( int entindex , const Vector & origin , const char * soundname , float flVolume , int iFlags , int iPitch , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
// Pull data from parameters
CSoundParameters params ;
if ( ! soundemitterbase - > GetParametersForSound ( soundname , params , GENDER_NONE ) )
{
return ;
}
# ifdef STAGING_ONLY
if ( sv_snd_filter . GetString ( ) [ 0 ] & & ! V_stristr ( params . soundname , sv_snd_filter . GetString ( ) ) )
{
return ;
}
# endif // STAGING_ONLY
if ( iFlags & SND_CHANGE_PITCH )
{
params . pitch = iPitch ;
}
if ( iFlags & SND_CHANGE_VOL )
{
params . volume = flVolume ;
}
# if defined( CLIENT_DLL )
enginesound - > EmitAmbientSound ( params . soundname , params . volume , params . pitch , iFlags , soundtime ) ;
# else
engine - > EmitAmbientSound ( entindex , origin , params . soundname , params . volume , params . soundlevel , iFlags , params . pitch , soundtime ) ;
# endif
bool needsCC = ! ( iFlags & ( SND_STOP | SND_CHANGE_VOL | SND_CHANGE_PITCH ) ) ;
float soundduration = 0.0f ;
if ( duration | | needsCC )
{
soundduration = enginesound - > GetSoundDuration ( params . soundname ) ;
if ( duration )
{
* duration = soundduration ;
}
}
TraceEmitSound ( " EmitAmbientSound: '%s' emitted as '%s' (ent %i) \n " ,
soundname , params . soundname , entindex ) ;
// We only want to trigger the CC on the start of the sound, not on any changes or halting of the sound
if ( needsCC )
{
CRecipientFilter filter ;
filter . AddAllPlayers ( ) ;
filter . MakeReliable ( ) ;
CUtlVector < Vector > dummy ;
EmitCloseCaption ( filter , entindex , false , soundname , dummy , soundduration , false ) ;
}
}
void StopSoundByHandle ( int entindex , const char * soundname , HSOUNDSCRIPTHANDLE & handle )
{
if ( handle = = SOUNDEMITTER_INVALID_HANDLE )
{
handle = ( HSOUNDSCRIPTHANDLE ) soundemitterbase - > GetSoundIndex ( soundname ) ;
}
if ( handle = = SOUNDEMITTER_INVALID_HANDLE )
return ;
CSoundParametersInternal * params ;
params = soundemitterbase - > InternalGetParametersForSound ( ( int ) handle ) ;
if ( ! params )
{
return ;
}
// HACK: we have to stop all sounds if there are > 1 in the rndwave section...
int c = params - > NumSoundNames ( ) ;
for ( int i = 0 ; i < c ; + + i )
{
char const * wavename = soundemitterbase - > GetWaveName ( params - > GetSoundNames ( ) [ i ] . symbol ) ;
Assert ( wavename ) ;
enginesound - > StopSound (
entindex ,
params - > GetChannel ( ) ,
wavename ) ;
TraceEmitSound ( " StopSound: '%s' stopped as '%s' (ent %i) \n " ,
soundname , wavename , entindex ) ;
}
}
void StopSound ( int entindex , const char * soundname )
{
HSOUNDSCRIPTHANDLE handle = ( HSOUNDSCRIPTHANDLE ) soundemitterbase - > GetSoundIndex ( soundname ) ;
if ( handle = = SOUNDEMITTER_INVALID_HANDLE )
{
return ;
}
StopSoundByHandle ( entindex , soundname , handle ) ;
}
void StopSound ( int iEntIndex , int iChannel , const char * pSample )
{
if ( pSample & & ( Q_stristr ( pSample , " .wav " ) | | Q_stristr ( pSample , " .mp3 " ) | | pSample [ 0 ] = = ' ! ' ) )
{
enginesound - > StopSound ( iEntIndex , iChannel , pSample ) ;
TraceEmitSound ( " StopSound: Raw wave stopped '%s' (ent %i) \n " ,
pSample , iEntIndex ) ;
}
else
{
// Look it up in sounds.txt and ignore other parameters
StopSound ( iEntIndex , pSample ) ;
}
}
void EmitAmbientSound ( int entindex , const Vector & origin , const char * pSample , float volume , soundlevel_t soundlevel , int flags , int pitch , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
# ifdef STAGING_ONLY
if ( sv_snd_filter . GetString ( ) [ 0 ] & & ! V_stristr ( pSample , sv_snd_filter . GetString ( ) ) )
{
return ;
}
# endif // STAGING_ONLY
# if !defined( CLIENT_DLL )
CUtlVector < Vector > dummyorigins ;
// Loop through all registered microphones and tell them the sound was just played
// NOTE: This means that pitch shifts/sound changes on the original ambient will not be reflected in the re-broadcasted sound
bool bSwallowed = CEnvMicrophone : : OnSoundPlayed (
entindex ,
pSample ,
soundlevel ,
volume ,
flags ,
pitch ,
& origin ,
soundtime ,
dummyorigins ) ;
if ( bSwallowed )
return ;
# endif
if ( pSample & & ( Q_stristr ( pSample , " .wav " ) | | Q_stristr ( pSample , " .mp3 " ) ) )
{
# if defined( CLIENT_DLL )
enginesound - > EmitAmbientSound ( pSample , volume , pitch , flags , soundtime ) ;
# else
engine - > EmitAmbientSound ( entindex , origin , pSample , volume , soundlevel , flags , pitch , soundtime ) ;
# endif
if ( duration )
{
* duration = enginesound - > GetSoundDuration ( pSample ) ;
}
TraceEmitSound ( " EmitAmbientSound: Raw wave emitted '%s' (ent %i) \n " ,
pSample , entindex ) ;
}
else
{
EmitAmbientSound ( entindex , origin , pSample , volume , flags , pitch , soundtime , duration ) ;
}
}
} ;
static CSoundEmitterSystem g_SoundEmitterSystem ( " CSoundEmitterSystem " ) ;
IGameSystem * SoundEmitterSystem ( )
{
return & g_SoundEmitterSystem ;
}
# if defined( CLIENT_DLL )
void ReloadSoundEntriesInList ( IFileList * pFilesToReload )
{
g_SoundEmitterSystem . ReloadSoundEntriesInList ( pFilesToReload ) ;
}
# endif
void S_SoundEmitterSystemFlush ( void )
{
# if !defined( CLIENT_DLL )
if ( ! UTIL_IsCommandIssuedByServerAdmin ( ) )
return ;
# endif
// save the current soundscape
// kill the system
g_SoundEmitterSystem . Shutdown ( ) ;
// restart the system
g_SoundEmitterSystem . Init ( ) ;
# if !defined( CLIENT_DLL )
// Redo precache all wave files... (this should work now that we have dynamic string tables)
g_SoundEmitterSystem . LevelInitPreEntity ( ) ;
// These store raw sound indices for faster precaching, blow them away.
ClearModelSoundsCache ( ) ;
# endif
// TODO: when we go to a handle system, we'll need to invalidate handles somehow
}
# if defined( CLIENT_DLL )
CON_COMMAND_F ( cl_soundemitter_flush , " Flushes the sounds.txt system (client only) " , FCVAR_CHEAT )
# else
CON_COMMAND_F ( sv_soundemitter_flush , " Flushes the sounds.txt system (server only) " , FCVAR_DEVELOPMENTONLY )
# endif
{
S_SoundEmitterSystemFlush ( ) ;
}
# if !defined(_RETAIL)
# if !defined( CLIENT_DLL )
# if !defined( _XBOX )
CON_COMMAND_F ( sv_soundemitter_filecheck , " Report missing wave files for sounds and game_sounds files. " , FCVAR_DEVELOPMENTONLY )
{
if ( ! UTIL_IsCommandIssuedByServerAdmin ( ) )
return ;
int missing = soundemitterbase - > CheckForMissingWavFiles ( true ) ;
DevMsg ( " --------------------------- \n Total missing files %i \n " , missing ) ;
}
CON_COMMAND_F ( sv_findsoundname , " Find sound names which reference the specified wave files. " , FCVAR_DEVELOPMENTONLY )
{
if ( ! UTIL_IsCommandIssuedByServerAdmin ( ) )
return ;
if ( args . ArgC ( ) ! = 2 )
return ;
int c = soundemitterbase - > GetSoundCount ( ) ;
int i ;
char const * search = args [ 1 ] ;
if ( ! search )
return ;
for ( i = 0 ; i < c ; i + + )
{
CSoundParametersInternal * internal = soundemitterbase - > InternalGetParametersForSound ( i ) ;
if ( ! internal )
continue ;
int waveCount = internal - > NumSoundNames ( ) ;
if ( waveCount > 0 )
{
for ( int wave = 0 ; wave < waveCount ; wave + + )
{
char const * wavefilename = soundemitterbase - > GetWaveName ( internal - > GetSoundNames ( ) [ wave ] . symbol ) ;
if ( Q_stristr ( wavefilename , search ) )
{
char const * soundname = soundemitterbase - > GetSoundName ( i ) ;
char const * scriptname = soundemitterbase - > GetSourceFileForSound ( i ) ;
Msg ( " Referenced by '%s:%s' -- %s \n " , scriptname , soundname , wavefilename ) ;
}
}
}
}
}
# endif // !_XBOX
# else
void Playgamesound_f ( const CCommand & args )
{
CBasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pPlayer )
{
if ( args . ArgC ( ) > 2 )
{
Vector position = pPlayer - > EyePosition ( ) ;
Vector forward ;
pPlayer - > GetVectors ( & forward , NULL , NULL ) ;
position + = atof ( args [ 2 ] ) * forward ;
CPASAttenuationFilter filter ( pPlayer ) ;
EmitSound_t params ;
params . m_pSoundName = args [ 1 ] ;
params . m_pOrigin = & position ;
params . m_flVolume = 0.0f ;
params . m_nPitch = 0 ;
g_SoundEmitterSystem . EmitSound ( filter , 0 , params ) ;
}
else
{
pPlayer - > EmitSound ( args [ 1 ] ) ;
}
}
else
{
Msg ( " Can't play until a game is started. \n " ) ;
// UNDONE: Make something like this work?
//CBroadcastRecipientFilter filter;
//g_SoundEmitterSystem.EmitSound( filter, 1, args[1], 0.0, 0, 0, &vec3_origin, 0, NULL );
}
}
static int GamesoundCompletion ( const char * partial , char commands [ COMMAND_COMPLETION_MAXITEMS ] [ COMMAND_COMPLETION_ITEM_LENGTH ] )
{
int current = 0 ;
const char * cmdname = " playgamesound " ;
char * substring = NULL ;
int substringLen = 0 ;
if ( Q_strstr ( partial , cmdname ) & & strlen ( partial ) > strlen ( cmdname ) + 1 )
{
substring = ( char * ) partial + strlen ( cmdname ) + 1 ;
substringLen = strlen ( substring ) ;
}
for ( int i = soundemitterbase - > GetSoundCount ( ) - 1 ; i > = 0 & & current < COMMAND_COMPLETION_MAXITEMS ; i - - )
{
const char * pSoundName = soundemitterbase - > GetSoundName ( i ) ;
if ( pSoundName )
{
if ( ! substring | | ! Q_strncasecmp ( pSoundName , substring , substringLen ) )
{
Q_snprintf ( commands [ current ] , sizeof ( commands [ current ] ) , " %s %s " , cmdname , pSoundName ) ;
current + + ;
}
}
}
return current ;
}
static ConCommand Command_Playgamesound ( " playgamesound " , Playgamesound_f , " Play a sound from the game sounds txt file " , FCVAR_CLIENTCMD_CAN_EXECUTE | FCVAR_SERVER_CAN_EXECUTE , GamesoundCompletion ) ;
# endif
# endif
//-----------------------------------------------------------------------------
// Purpose: Non-static override for doing the general case of CPASAttenuationFilter( this ), and EmitSound( filter, entindex(), etc. );
// Input : *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( const char * soundname , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
//VPROF( "CBaseEntity::EmitSound" );
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
CPASAttenuationFilter filter ( this , soundname ) ;
EmitSound_t params ;
params . m_pSoundName = soundname ;
params . m_flSoundTime = soundtime ;
params . m_pflSoundDuration = duration ;
params . m_bWarnOnDirectWaveReference = true ;
EmitSound ( filter , entindex ( ) , params ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Non-static override for doing the general case of CPASAttenuationFilter( this ), and EmitSound( filter, entindex(), etc. );
// Input : *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( const char * soundname , HSOUNDSCRIPTHANDLE & handle , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
// VPROF( "CBaseEntity::EmitSound" );
CPASAttenuationFilter filter ( this , soundname , handle ) ;
EmitSound_t params ;
params . m_pSoundName = soundname ;
params . m_flSoundTime = soundtime ;
params . m_pflSoundDuration = duration ;
params . m_bWarnOnDirectWaveReference = true ;
EmitSound ( filter , entindex ( ) , params , handle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : filter -
// iEntIndex -
// *soundname -
// *pOrigin -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( IRecipientFilter & filter , int iEntIndex , const char * soundname , const Vector * pOrigin /*= NULL*/ , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
if ( ! soundname )
return ;
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
// VPROF( "CBaseEntity::EmitSound" );
EmitSound_t params ;
params . m_pSoundName = soundname ;
params . m_flSoundTime = soundtime ;
params . m_pOrigin = pOrigin ;
params . m_pflSoundDuration = duration ;
params . m_bWarnOnDirectWaveReference = true ;
EmitSound ( filter , iEntIndex , params , params . m_hSoundScriptHandle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : filter -
// iEntIndex -
// *soundname -
// *pOrigin -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( IRecipientFilter & filter , int iEntIndex , const char * soundname , HSOUNDSCRIPTHANDLE & handle , const Vector * pOrigin /*= NULL*/ , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
//VPROF( "CBaseEntity::EmitSound" );
EmitSound_t params ;
params . m_pSoundName = soundname ;
params . m_flSoundTime = soundtime ;
params . m_pOrigin = pOrigin ;
params . m_pflSoundDuration = duration ;
params . m_bWarnOnDirectWaveReference = true ;
EmitSound ( filter , iEntIndex , params , handle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : filter -
// iEntIndex -
// params -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( IRecipientFilter & filter , int iEntIndex , const EmitSound_t & params )
{
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
# ifdef GAME_DLL
CBaseEntity * pEntity = UTIL_EntityByIndex ( iEntIndex ) ;
# else
C_BaseEntity * pEntity = ClientEntityList ( ) . GetEnt ( iEntIndex ) ;
# endif
if ( pEntity )
{
pEntity - > ModifyEmitSoundParams ( const_cast < EmitSound_t & > ( params ) ) ;
}
// VPROF( "CBaseEntity::EmitSound" );
// Call into the sound emitter system...
g_SoundEmitterSystem . EmitSound ( filter , iEntIndex , params ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : filter -
// iEntIndex -
// params -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitSound ( IRecipientFilter & filter , int iEntIndex , const EmitSound_t & params , HSOUNDSCRIPTHANDLE & handle )
{
VPROF_BUDGET ( " CBaseEntity::EmitSound " , _T ( " CBaseEntity::EmitSound " ) ) ;
# ifdef GAME_DLL
CBaseEntity * pEntity = UTIL_EntityByIndex ( iEntIndex ) ;
# else
C_BaseEntity * pEntity = ClientEntityList ( ) . GetEnt ( iEntIndex ) ;
# endif
if ( pEntity )
{
pEntity - > ModifyEmitSoundParams ( const_cast < EmitSound_t & > ( params ) ) ;
}
// VPROF( "CBaseEntity::EmitSound" );
// Call into the sound emitter system...
g_SoundEmitterSystem . EmitSoundByHandle ( filter , iEntIndex , params , handle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : StopSound ( const char * soundname )
{
# if defined( CLIENT_DLL )
if ( entindex ( ) = = - 1 )
{
// If we're a clientside entity, we need to use the soundsourceindex instead of the entindex
StopSound ( GetSoundSourceIndex ( ) , soundname ) ;
return ;
}
# endif
StopSound ( entindex ( ) , soundname ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : StopSound ( const char * soundname , HSOUNDSCRIPTHANDLE & handle )
{
# if defined( CLIENT_DLL )
if ( entindex ( ) = = - 1 )
{
// If we're a clientside entity, we need to use the soundsourceindex instead of the entindex
StopSound ( GetSoundSourceIndex ( ) , soundname ) ;
return ;
}
# endif
g_SoundEmitterSystem . StopSoundByHandle ( entindex ( ) , soundname , handle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : iEntIndex -
// *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : StopSound ( int iEntIndex , const char * soundname )
{
g_SoundEmitterSystem . StopSound ( iEntIndex , soundname ) ;
}
void CBaseEntity : : StopSound ( int iEntIndex , int iChannel , const char * pSample )
{
g_SoundEmitterSystem . StopSound ( iEntIndex , iChannel , pSample ) ;
}
soundlevel_t CBaseEntity : : LookupSoundLevel ( const char * soundname )
{
return soundemitterbase - > LookupSoundLevel ( soundname ) ;
}
soundlevel_t CBaseEntity : : LookupSoundLevel ( const char * soundname , HSOUNDSCRIPTHANDLE & handle )
{
return soundemitterbase - > LookupSoundLevelByHandle ( soundname , handle ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *entity -
// origin -
// flags -
// *soundname -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitAmbientSound ( int entindex , const Vector & origin , const char * soundname , int flags , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
g_SoundEmitterSystem . EmitAmbientSound ( entindex , origin , soundname , 0.0 , flags , 0 , soundtime , duration ) ;
}
// HACK HACK: Do we need to pull the entire SENTENCEG_* wrapper over to the client .dll?
# if defined( CLIENT_DLL )
int SENTENCEG_Lookup ( const char * sample )
{
return engine - > SentenceIndexFromName ( sample + 1 ) ;
}
# endif
void UTIL_EmitAmbientSound ( int entindex , const Vector & vecOrigin , const char * samp , float vol , soundlevel_t soundlevel , int fFlags , int pitch , float soundtime /*= 0.0f*/ , float * duration /*=NULL*/ )
{
# ifdef STAGING_ONLY
if ( sv_snd_filter . GetString ( ) [ 0 ] & & ! V_stristr ( samp , sv_snd_filter . GetString ( ) ) )
{
return ;
}
# endif // STAGING_ONLY
if ( samp & & * samp = = ' ! ' )
{
int sentenceIndex = SENTENCEG_Lookup ( samp ) ;
if ( sentenceIndex > = 0 )
{
char name [ 32 ] ;
Q_snprintf ( name , sizeof ( name ) , " !%d " , sentenceIndex ) ;
# if !defined( CLIENT_DLL )
engine - > EmitAmbientSound ( entindex , vecOrigin , name , vol , soundlevel , fFlags , pitch , soundtime ) ;
# else
enginesound - > EmitAmbientSound ( name , vol , pitch , fFlags , soundtime ) ;
# endif
if ( duration )
{
* duration = enginesound - > GetSoundDuration ( name ) ;
}
g_SoundEmitterSystem . TraceEmitSound ( " UTIL_EmitAmbientSound: Sentence emitted '%s' (ent %i) \n " ,
name , entindex ) ;
}
}
else
{
g_SoundEmitterSystem . EmitAmbientSound ( entindex , vecOrigin , samp , vol , soundlevel , fFlags , pitch , soundtime , duration ) ;
}
}
static const char * UTIL_TranslateSoundName ( const char * soundname , const char * actormodel )
{
Assert ( soundname ) ;
if ( Q_stristr ( soundname , " .wav " ) | | Q_stristr ( soundname , " .mp3 " ) )
{
if ( Q_stristr ( soundname , " .wav " ) )
{
WaveTrace ( soundname , " UTIL_TranslateSoundName " ) ;
}
return soundname ;
}
return soundemitterbase - > GetWavFileForSound ( soundname , actormodel ) ;
}
void CBaseEntity : : GenderExpandString ( char const * in , char * out , int maxlen )
{
soundemitterbase - > GenderExpandString ( STRING ( GetModelName ( ) ) , in , out , maxlen ) ;
}
bool CBaseEntity : : GetParametersForSound ( const char * soundname , CSoundParameters & params , const char * actormodel )
{
gender_t gender = soundemitterbase - > GetActorGender ( actormodel ) ;
return soundemitterbase - > GetParametersForSound ( soundname , params , gender ) ;
}
bool CBaseEntity : : GetParametersForSound ( const char * soundname , HSOUNDSCRIPTHANDLE & handle , CSoundParameters & params , const char * actormodel )
{
gender_t gender = soundemitterbase - > GetActorGender ( actormodel ) ;
return soundemitterbase - > GetParametersForSoundEx ( soundname , handle , params , gender ) ;
}
HSOUNDSCRIPTHANDLE CBaseEntity : : PrecacheScriptSound ( const char * soundname )
{
# if !defined( CLIENT_DLL )
return g_SoundEmitterSystem . PrecacheScriptSound ( soundname ) ;
# else
return soundemitterbase - > GetSoundIndex ( soundname ) ;
# endif
}
void CBaseEntity : : PrefetchScriptSound ( const char * soundname )
{
g_SoundEmitterSystem . PrefetchScriptSound ( soundname ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *soundname -
// Output : float
//-----------------------------------------------------------------------------
float CBaseEntity : : GetSoundDuration ( const char * soundname , char const * actormodel )
{
return enginesound - > GetSoundDuration ( PSkipSoundChars ( UTIL_TranslateSoundName ( soundname , actormodel ) ) ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : filter -
// *token -
// duration -
// warnifmissing -
//-----------------------------------------------------------------------------
void CBaseEntity : : EmitCloseCaption ( IRecipientFilter & filter , int entindex , char const * token , CUtlVector < Vector > & soundorigin , float duration , bool warnifmissing /*= false*/ )
{
bool fromplayer = false ;
CBaseEntity * ent = CBaseEntity : : Instance ( entindex ) ;
while ( ent )
{
if ( ent - > IsPlayer ( ) )
{
fromplayer = true ;
break ;
}
ent = ent - > GetOwnerEntity ( ) ;
}
g_SoundEmitterSystem . EmitCloseCaption ( filter , entindex , fromplayer , token , soundorigin , duration , warnifmissing ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
// preload -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CBaseEntity : : PrecacheSound ( const char * name )
{
if ( IsPC ( ) & & ! g_bPermitDirectSoundPrecache )
{
Warning ( " Direct precache of %s \n " , name ) ;
}
// If this is out of order, warn
if ( ! CBaseEntity : : IsPrecacheAllowed ( ) )
{
if ( ! enginesound - > IsSoundPrecached ( name ) )
{
Assert ( ! " CBaseEntity::PrecacheSound: too late " ) ;
Warning ( " Late precache of %s \n " , name ) ;
}
}
bool bret = enginesound - > PrecacheSound ( name , true ) ;
return bret ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
//-----------------------------------------------------------------------------
void CBaseEntity : : PrefetchSound ( const char * name )
{
enginesound - > PrefetchSound ( name ) ;
}