void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) { SoundHookIter iter; IPluginFunction *pFunc; cell_t res = static_cast<ResultType>(Pl_Continue); cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation)); char buffer[PLATFORM_MAX_PATH]; strcpy(buffer, pSample); for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++) { int players[64], size; size = _FillInPlayers(players, &filter); pFunc = (*iter); pFunc->PushArray(players, 64, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&size); pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&iEntIndex); pFunc->PushCellByRef(&iChannel); pFunc->PushFloatByRef(&flVolume); pFunc->PushCellByRef(&sndlevel); pFunc->PushCellByRef(&iPitch); pFunc->PushCellByRef(&iFlags); g_InSoundHook = true; pFunc->Execute(&res); g_InSoundHook = false; switch (res) { case Pl_Handled: case Pl_Stop: { RETURN_META(MRES_SUPERCEDE); } case Pl_Changed: { CellRecipientFilter crf; crf.Initialize(players, size); RETURN_META_NEWPARAMS( MRES_IGNORED, static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); } } } }
void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #endif { SoundHookIter iter; IPluginFunction *pFunc; cell_t res = static_cast<ResultType>(Pl_Continue); cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation)); char buffer[PLATFORM_MAX_PATH]; strcpy(buffer, pSample); char soundEntry[PLATFORM_MAX_PATH] = ""; #if SOURCE_ENGINE >= SE_PORTAL2 Q_strncpy(soundEntry, pSoundEntry, sizeof(soundEntry)); #endif #if SOURCE_ENGINE < SE_PORTAL2 int nSeed = 0; #endif for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++) { int players[SM_MAXPLAYERS], size; size = _FillInPlayers(players, &filter); pFunc = (*iter); pFunc->PushArray(players, SM_ARRAYSIZE(players), SM_PARAM_COPYBACK); pFunc->PushCellByRef(&size); pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&iEntIndex); pFunc->PushCellByRef(&iChannel); pFunc->PushFloatByRef(&flVolume); pFunc->PushCellByRef(&sndlevel); pFunc->PushCellByRef(&iPitch); pFunc->PushCellByRef(&iFlags); pFunc->PushStringEx(soundEntry, sizeof(soundEntry), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&nSeed); g_InSoundHook = true; pFunc->Execute(&res); g_InSoundHook = false; switch (res) { case Pl_Handled: case Pl_Stop: { #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_SUPERCEDE, -1); #else RETURN_META(MRES_SUPERCEDE); #endif } case Pl_Changed: { /* Client validation */ for (int i = 0; i < size; i++) { int client = players[i]; IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (!pPlayer) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Client index %d is invalid", client); } else if (!pPlayer->IsInGame()) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Client %d is not connected", client); } else { continue; } #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_IGNORED, -1 ); #else return; #endif } #if SOURCE_ENGINE >= SE_PORTAL2 if (strcmp(pSoundEntry, soundEntry) != 0 || strcmp(pSample, buffer) != 0) { if (strcmp(soundEntry, buffer) == 0) nSoundEntryHash = -1; else if (strcmp(soundEntry, "") != 0) nSoundEntryHash = GenerateSoundEntryHash(soundEntry); } #endif CellRecipientFilter crf; crf.Initialize(players, size); #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE_NEWPARAMS( MRES_IGNORED, -1, static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 RETURN_META_NEWPARAMS( MRES_IGNORED, static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #else RETURN_META_NEWPARAMS( MRES_IGNORED, static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #endif } } } #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_IGNORED, -1 ); #endif }
void FX_TracerSound( const Vector &start, const Vector &end, int iTracerType ) { const char *pszSoundName = NULL; float flWhizDist = TRACER_MAX_HEAR_DIST; float flMinWhizTime = TRACER_SOUND_TIME_MIN; float flMaxWhizTime = TRACER_SOUND_TIME_MAX; Vector vecListenOrigin = MainViewOrigin(); switch( iTracerType ) { case TRACER_TYPE_DEFAULT: { pszSoundName = "Bullets.DefaultNearmiss"; flWhizDist = 24; Ray_t bullet, listener; bullet.Init( start, end ); Vector vecLower = vecListenOrigin; vecLower.z -= LISTENER_HEIGHT; listener.Init( vecListenOrigin, vecLower ); float s, t; IntersectRayWithRay( bullet, listener, s, t ); t = clamp( t, 0, 1 ); vecListenOrigin.z -= t * LISTENER_HEIGHT; } break; case TRACER_TYPE_GUNSHIP: pszSoundName = "Bullets.GunshipNearmiss"; break; case TRACER_TYPE_STRIDER: pszSoundName = "Bullets.StriderNearmiss"; break; case TRACER_TYPE_WATERBULLET: pszSoundName = "Underwater.BulletImpact"; flWhizDist = 48; flMinWhizTime = 0.3f; flMaxWhizTime = 0.6f; break; default: return; } if( !pszSoundName ) return; // Is it time yet? float dt = g_BulletWhiz.m_nextWhizTime - gpGlobals->curtime; if ( dt > 0 ) return; // Did the thing pass close enough to our head? float vDist = CalcDistanceSqrToLineSegment( vecListenOrigin, start, end ); if ( vDist >= (flWhizDist * flWhizDist) ) return; CSoundParameters params; if( C_BaseEntity::GetParametersForSound( pszSoundName, params, NULL ) ) { // Get shot direction Vector shotDir; VectorSubtract( end, start, shotDir ); VectorNormalize( shotDir ); CLocalPlayerFilter filter; enginesound->EmitSound( filter, SOUND_FROM_WORLD, CHAN_STATIC, params.soundname, params.volume, SNDLVL_TO_ATTN(params.soundlevel), 0, params.pitch, &start, &shotDir, false); } // FIXME: This has a bad behavior when both bullet + strider shots are whizzing by at the same time // Could use different timers for the different types. // Don't play another bullet whiz for this client until this time has run out g_BulletWhiz.m_nextWhizTime = gpGlobals->curtime + random->RandomFloat( flMinWhizTime, flMaxWhizTime ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void FX_TFTracerSound( const Vector &start, const Vector &end, int iTracerType ) { // don't play on very short hits if ( ( start - end ).Length() < 200 ) return; const char *pszSoundName = "Bullets.DefaultNearmiss"; float flWhizDist = 64; Vector vecListenOrigin = MainViewOrigin(); switch( iTracerType ) { case TRACER_TYPE_DEFAULT: flWhizDist = 96; // fall through ! default: { Ray_t bullet, listener; bullet.Init( start, end ); Vector vecLower = vecListenOrigin; vecLower.z -= LISTENER_HEIGHT; listener.Init( vecListenOrigin, vecLower ); float s, t; IntersectRayWithRay( bullet, listener, s, t ); t = clamp( t, 0, 1 ); vecListenOrigin.z -= t * LISTENER_HEIGHT; } break; } static float flNextWhizTime = 0; // Is it time yet? float dt = flNextWhizTime - gpGlobals->curtime; if ( dt > 0 ) return; // Did the thing pass close enough to our head? float vDist = CalcDistanceSqrToLineSegment( vecListenOrigin, start, end ); if ( vDist >= (flWhizDist * flWhizDist) ) return; CSoundParameters params; if( C_BaseEntity::GetParametersForSound( pszSoundName, params, NULL ) ) { // Get shot direction Vector shotDir; VectorSubtract( end, start, shotDir ); VectorNormalize( shotDir ); CLocalPlayerFilter filter; enginesound->EmitSound( filter, SOUND_FROM_WORLD, CHAN_STATIC, params.soundname, params.volume, SNDLVL_TO_ATTN(params.soundlevel), 0, params.pitch, 0, &start, &shotDir, false); } // Don't play another bullet whiz for this client until this time has run out flNextWhizTime = gpGlobals->curtime + 0.1f; }