//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include #include #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 #include #include "hud_closecaption.h" #define CRecipientFilter C_RecipientFilter #endif /*#if defined( CLIENT_DLL ) #include "OverCharged/fmod_manager.h" #endif*/ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #include "OverCharged/Tools/SharedVars.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;// *GP->newPitch; 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 ); } static ConVarRef HostPitch("host_timescale"); static ConVarRef WeaponSwitchFade("oc_player_weap_selection_enable_fade"); #include #include #include #include struct SoundStruct { string_t m_pSoundName; int m_nSongGuid; int entindex; /*IRecipientFilter* filter; string_t m_pSoundName; soundlevel_t m_SoundLevel; float m_flVolume; int m_nFlags; float m_nPitch; Vector m_pOrigin; float m_flSoundTime; int m_nSpeakerEntity; float m_pflSoundDuration; int m_nSpecialDSP;*/ //mutable CUtlVector< Vector > m_UtlVecSoundOrigin; }; //std::vector *allSounds;//EmitSound_t* CUtlVector> allSounds; /*void UpdateAllSounds2() { CUtlVector< SndInfo_t > sndlist; //CUtlVector< CUtlMemory > &sndlist; float timescale = HostPitch.GetFloat(); enginesound->GetActiveSounds(sndlist); enginesound->StopAllSounds(true); for (int i = 0; i < (int)sndlist.Count(); i++) { auto ep = sndlist.Element(i); float scaled_pitch = (ep.m_nChannel != CHAN_VOICE) ? ep.m_nPitch * timescale : ep.m_nPitch; ep.m_nPitch = scaled_pitch; #ifdef GAME_DLL CBaseEntity *pEntity = UTIL_EntityByIndex(ep.m_nSoundSource); #else C_BaseEntity *pEntity = ClientEntityList().GetEnt(ep.m_nSoundSource); #endif if (pEntity) { EmitSound_t params; params.m_nChannel = ep.m_nChannel; params.m_flVolume = ep.m_flVolume; params.m_nPitch = ep.m_nPitch; params.m_nSpeakerEntity = ep.m_nSpeakerEntity; pEntity->ModifyEmitSoundParams(const_cast< EmitSound_t& >(params)); } } //SoundEmitterSystem->OnRestoreAllSystems(); //allSounds->push_back(sample); //ReallocSoundList(); }*/ /*void UpdateAllSounds() { float timescale = HostPitch.GetFloat(); if (allSounds->size()) { for (int i = 0; i < (int)allSounds->size(); i++) { if (allSounds->at(i).ep != nullptr) { auto ep = allSounds->at(i).ep; float scaled_pitch = (ep->m_nChannel != CHAN_VOICE) ? ep->m_nPitch * timescale : ep->m_nPitch; ep->m_nPitch = scaled_pitch; //enginesound-> //CEnvMicrophone::ModifyEmitSoundParams(ep); #ifdef GAME_DLL CBaseEntity *pEntity = UTIL_EntityByIndex(allSounds->at(i).entindex); #else C_BaseEntity *pEntity = ClientEntityList().GetEnt(allSounds->at(i).entindex); #endif if (pEntity) { pEntity->ModifyEmitSoundParams(const_cast< EmitSound_t& >(*ep)); } } } } }*/ //std::vector *allSounds = new std::vector(); /*#define MaxSoundsCount 500 int count = 0; //EmitSound_t *allSounds = new EmitSound_t[MaxSoundsCount]; EmitSound_t allSounds[MaxSoundsCount]; CON_COMMAND(oc_updateLooping_sounds_server, "Flushes the client side soundscapes") { //if (listOfSounds.size()) { for (int i = 0; i <= count; i++) { float pitch = 1;//allSounds[i].m_nPitch; allSounds[i].m_nPitch = (pitch *= HostPitch->GetFloat()); } } }*/ //----------------------------------------------------------------------------- // 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 ) { //allSounds = new std::vector();//EmitSound_t* allSounds = CUtlVector>(); } /*void ReallocSoundList() { int count = allSounds->size(); if (count && count >= 100) { allSounds->erase(allSounds->begin()); }*/ /*if (allSounds->size()) { int i = 0; for (auto it = allSounds->begin(); it != allSounds->end();) { if (allSounds->at(i).ep == nullptr) { it = allSounds->erase(it); } else { ++it; } i++; } }*/ //} /*void AppendSounds2(SoundStruct sample) { allSounds->push_back(sample); ReallocSoundList(); }*/ /*void ReinitAllSounds() { enginesound->StopAllSounds(true); int count = allSounds->size(); if (count) { for (int i = 0; i < count; i++) { auto elem = allSounds->at(i); EmitSound_t ep; int entindex = elem.entindex; ep.m_pSoundName = elem.m_pSoundName.ToCStr(); ep.m_SoundLevel = elem.m_SoundLevel; ep.m_flVolume = elem.m_flVolume; ep.m_nFlags = elem.m_nFlags; ep.m_nPitch = elem.m_nPitch; ep.m_pOrigin = &elem.m_pOrigin; ep.m_flSoundTime = elem.m_flSoundTime; ep.m_nSpeakerEntity = elem.m_nSpeakerEntity; ep.m_pflSoundDuration = &elem.m_pflSoundDuration; ep.m_nSpecialDSP = elem.m_nSpecialDSP; //ep.m_UtlVecSoundOrigin = elem.m_UtlVecSoundOrigin; EmitSound(*elem.filter, entindex, ep); } } }*/ 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); HostPitch = cvar->FindVar("host_timescale"); WeaponSwitchFade = cvar->FindVar("oc_player_weap_selection_enable_fade"); 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 ); HostPitch = cvar->FindVar("host_timescale"); // 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 ) { /*EmitSound_t ep_params = ep; ep_params.m_nPitch *= GP->newPitch;*/ /*if (ep.m_nChannel == CHAN_VOICE) { allSounds[count] = ep; count++; if (count >= MaxSoundsCount) count = 0; }*/ //listOfSounds.push_back(ep1); //allSounds->push_back(ep); // 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;// *GP->newPitch; }*/ if (ep.m_nChannel != CHAN_VOICE) { params.pitch = ep.m_nPitch; //DevMsg("GP->newPitch: %.2f \n", GP->newPitch); params.pitch *= HostPitch.GetFloat();//GP->newPitch; params.pitchhigh *= HostPitch.GetFloat();//GP->newPitch; params.pitchlow *= HostPitch.GetFloat();// GP->newPitch; } else { 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,// *GP->newPitch, 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,// *GP->newPitch, 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)" ); float scaled_pitch = (ep.m_nChannel != CHAN_VOICE) ? ep.m_nPitch * HostPitch.GetFloat() : ep.m_nPitch;//GP->newPitch; //DevMsg("entindex: %i \n", entindex); /*SoundStruct sdst; sdst.filter = &filter; sdst.entindex = entindex; sdst.m_flSoundTime = ep.m_flSoundTime; AppendSounds2(sdst);*/ /*SoundStruct sdst; string_t sndName = (string_t&)ep.m_pSoundName; sdst.m_pSoundName = sndName; sdst.m_nSongGuid = 0;//enginesound->GetGuidForLastSoundEmitted(); sdst.entindex = entindex; allSounds.AddToTail(sdst); if (allSounds.Count() > 50) allSounds.Remove(0);*/ if (WeaponSwitchFade.GetInt()) { #ifdef GAME_DLL CBasePlayer *pPlayer = (CBasePlayer*)UTIL_EntityByIndex(entindex); #else C_BasePlayer *pPlayer = (C_BasePlayer*)ClientEntityList().GetEnt(entindex); #endif if (pPlayer && Q_stristr(ep.m_pSoundName, "Player.WeaponSelection") || Q_stristr(ep.m_pSoundName, "Player.Deny") || Q_stristr(ep.m_pSoundName, "Player.Use")) { scaled_pitch = 100.0f; } } #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, scaled_pitch,//ep.m_nPitch,// *GP->newPitch, ep.m_pOrigin, ep.m_flSoundTime, ep.m_UtlVecSoundOrigin ); if ( bSwallowed ) return; #endif /*#if defined( CLIENT_DLL ) const char *wav = soundemitterbase->GetWavFileForSound(ep.m_pSoundName, GENDER_NONE); FMODManager()->PlayAmbientSound(wav, true); DevMsg("%s \n", wav); #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, scaled_pitch,//ep.m_nPitch,// * GP->newPitch, 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;// *GP->newPitch; } if( iFlags & SND_CHANGE_VOL ) { params.volume = flVolume; } #if defined( CLIENT_DLL ) enginesound->EmitAmbientSound( params.soundname, params.volume, params.pitch/* * GP->newPitch*/, iFlags, soundtime ); #else engine->EmitAmbientSound(entindex, origin, params.soundname, params.volume, params.soundlevel, iFlags, params.pitch/* * GP->newPitch*/, 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,// * GP->newPitch, &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/* * GP->newPitch*/, flags, soundtime ); #else engine->EmitAmbientSound(entindex, origin, pSample, volume, soundlevel, flags, pitch/* * GP->newPitch*/, 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/* * GP->newPitch*/, soundtime, duration); } } }; static CSoundEmitterSystem g_SoundEmitterSystem( "CSoundEmitterSystem" ); IGameSystem *SoundEmitterSystem() { return &g_SoundEmitterSystem; } CSoundEmitterSystem* GetSoundEmitterSystem() { 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( "---------------------------\nTotal 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" ) ); /*EmitSound_t paramsNew = params; paramsNew.m_nPitch *= GP->newPitch;*/ #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" ) ); /*EmitSound_t paramsNew = params; paramsNew.m_nPitch *= GP->newPitch;*/ #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/* * GP->newPitch*/, soundtime); #else enginesound->EmitAmbientSound( name, vol, pitch/* * GP->newPitch*/, 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/* * GP->newPitch*/, 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 ¶ms, const char *actormodel ) { gender_t gender = soundemitterbase->GetActorGender( actormodel ); return soundemitterbase->GetParametersForSound( soundname, params, gender ); } bool CBaseEntity::GetParametersForSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters ¶ms, 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( "SoundEmitterSystem.cpp: 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 ); } void CBaseEntity::UpdateAllSounds() { /*HostPitch = cvar->FindVar("host_timescale"); float flPitchScale = HostPitch.GetFloat(); int count = allSounds.Count();//soundemitterbase->GetSoundCount();//sndlist.Count(); for (int i = 0; i < count; i++) { auto sndStr = allSounds.Element(i); auto sndName = sndStr.m_pSoundName; HSOUNDSCRIPTHANDLE handle = (HSOUNDSCRIPTHANDLE)soundemitterbase->GetSoundIndex(STRING(sndName)); if (handle == SOUNDEMITTER_INVALID_HANDLE) continue; CSoundParametersInternal *params; params = soundemitterbase->InternalGetParametersForSound((int)handle); if (!params) { continue; } int c = params->NumSoundNames(); for (int j = 0; j < c; ++j) { char const *wavename = soundemitterbase->GetWaveName(params->GetSoundNames()[j].symbol); params->SetPitch(flPitchScale*100.f); soundemitterbase->UpdateSoundParameters(wavename, *params); } }*/ //#if defined( CLIENT_DLL ) HostPitch = cvar->FindVar("host_timescale"); float flPitchScale = HostPitch.GetFloat(); //CUtlVector> &sndlist = CUtlVector>(); //enginesound->GetActiveSounds(sndlist); int count = allSounds.Count();//soundemitterbase->GetSoundCount();//sndlist.Count(); for (int i = 0; i < count; i++) { auto sndStr = allSounds.Element(i); auto idx = soundemitterbase->GetSoundIndex(STRING(sndStr.m_pSoundName)); if (soundemitterbase->IsValidIndex(idx)) { auto sndName = sndStr.m_pSoundName; CSoundParametersInternal params; params.CopyFrom(*soundemitterbase->InternalGetParametersForSound(idx)); //auto name = params.GetSoundNames()->symbol.String(); params.SetPitch(flPitchScale*100.f); soundemitterbase->UpdateSoundParameters(STRING(sndName), params); //CSoundEnvelopeController *m_pLoopSoundController = &CSoundEnvelopeController::GetController(); //CPASAttenuationFilter filter(this); //CSoundPatch *csound = CSoundEnvelopeController::GetController().//.SoundCreate(filter, sndStr.entindex, sndName.ToCStr()); //m_pLoopSoundController->SoundChangePitch(csound, flPitchScale*100.f, -0.01f); //m_pLoopSoundController->SystemUpdate(); } } #ifdef GAME_DLL CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); if (pPlayer) { if (!pPlayer->GetSlowMoIsEnabled() && !pPlayer->IsInSelectionSlowMo()) allSounds.RemoveAll(); } #endif //RefreshArray /*for (int i = 0; i < count; i++) { auto sndStr = allSounds.Element(i); if (!Q_strlen(STRING(sndStr.m_pSoundName))) continue; auto idx = soundemitterbase->GetSoundIndex(STRING(sndStr.m_pSoundName)); if (!soundemitterbase->IsValidIndex(idx)) { allSounds.Remove(i); continue; } if (!enginesound->IsSoundStillPlaying(idx))//(sndStr.m_nSongGuid)) { allSounds.Remove(i); } }*/ //#endif /*HostPitch = cvar->FindVar("host_timescale"); float flPitchScale = HostPitch.GetFloat(); int i = 0; while (i >= 0) { if (!enginesound->IsSoundStillPlaying(i)) continue; auto sndName = soundemitterbase->GetSoundName(i); CSoundParametersInternal params; params.CopyFrom(*soundemitterbase->InternalGetParametersForSound(i)); params.SetPitch(flPitchScale*100.f); soundemitterbase->UpdateSoundParameters(sndName, params); i = soundemitterbase->Next(i); }*/ /*for (int i = 0; i < soundemitterbase->GetSoundCount(); i++) { auto sndName = soundemitterbase->GetSoundName(i); CSoundParametersInternal params; params.CopyFrom(*soundemitterbase->InternalGetParametersForSound(i)); float flPitch = params.GetPitch().start; float flPitchLength = params.GetPitch().range; //float div = flPitch / flPitchScale; params.SetPitch(flPitchScale*100.f);//(flPitch * flPitchScale, flPitchLength); soundemitterbase->UpdateSoundParameters(sndName, params); }*/ } /*#if !defined( CLIENT_DLL ) CON_COMMAND(oc_update_all_sounds, "Flushes the client side soundscapes") { GetSoundEmitterSystem()->ReinitAllSounds(); } #endif*/