ds@1114: /** ds@1114: * vim: set ts=4 : ds@1330: * ============================================================================= dvander@1233: * SourceMod SDKTools Extension ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. ds@1330: * ============================================================================= ds@1114: * ds@1330: * This program is free software; you can redistribute it and/or modify it under ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the ds@1330: * Free Software Foundation. dvander@1233: * ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ds@1330: * details. dvander@1233: * ds@1330: * You should have received a copy of the GNU General Public License along with ds@1330: * this program. If not, see . dvander@1233: * ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants ds@1330: * this exception to all derivative works. AlliedModders LLC defines further ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), ds@1330: * or . ds@1114: * ds@1114: * Version: $Id$ ds@1114: */ ds@1114: faluco@1735: #include "vsound.h" faluco@1735: #include faluco@1735: faluco@1735: SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float); skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 0, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); skamonkey@3515: SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 1, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: SH_DECL_HOOK15_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); skamonkey@3564: SH_DECL_HOOK15_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); skamonkey@3515: #else faluco@1735: SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); faluco@1735: SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); skamonkey@3515: #endif faluco@1735: faluco@1735: bool g_InSoundHook = false; faluco@1735: faluco@1735: /*************************** faluco@1735: * * faluco@1735: * Sound Related Hook Class * faluco@1735: * * faluco@1735: ****************************/ faluco@1735: pred@2760: cell_t SoundReferenceToIndex(cell_t ref) pred@2760: { pred@2760: if (ref == 0 || ref == -1 || ref == -2) pred@2760: { pred@2760: return ref; pred@2760: } pred@2760: pred@2760: return gamehelpers->ReferenceToIndex(ref); pred@2760: } pred@2760: faluco@1735: size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter) faluco@1735: { faluco@1735: size_t size = static_cast(pFilter->GetRecipientCount()); faluco@1735: faluco@1735: for (size_t i=0; iGetRecipientIndex(&index, i); skamonkey@3918: #else skamonkey@3918: index = pFilter->GetRecipientIndex(i); skamonkey@3918: #endif skamonkey@3918: pl_array[i] = index; faluco@1735: } faluco@1735: faluco@1735: return size; faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::_IncRefCounter(int type) faluco@1735: { faluco@1735: if (type == NORMAL_SOUND_HOOK) faluco@1735: { faluco@1735: if (m_NormalCount++ == 0) faluco@1735: { kyle@3819: SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); kyle@3819: SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); faluco@1735: } faluco@1735: } faluco@1735: else if (type == AMBIENT_SOUND_HOOK) faluco@1735: { faluco@1735: if (m_AmbientCount++ == 0) faluco@1735: { kyle@3819: SH_ADD_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::_DecRefCounter(int type) faluco@1735: { faluco@1735: if (type == NORMAL_SOUND_HOOK) faluco@1735: { faluco@1735: if (--m_NormalCount == 0) faluco@1735: { kyle@3819: SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); kyle@3819: SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); faluco@1735: } faluco@1735: } faluco@1735: else if (type == AMBIENT_SOUND_HOOK) faluco@1735: { faluco@1735: if (--m_AmbientCount == 0) faluco@1735: { kyle@3819: SH_REMOVE_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::Initialize() faluco@1735: { faluco@1735: plsys->AddPluginsListener(this); faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::Shutdown() faluco@1735: { faluco@1735: plsys->RemovePluginsListener(this); faluco@1735: if (m_NormalCount) faluco@1735: { kyle@3819: SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); kyle@3819: SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); faluco@1735: } faluco@1735: if (m_AmbientCount) faluco@1735: { kyle@3819: SH_REMOVE_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::OnPluginUnloaded(IPlugin *plugin) faluco@1735: { faluco@1735: SoundHookIter iter; faluco@1735: IPluginContext *pContext = plugin->GetBaseContext(); faluco@1735: faluco@1735: if (m_AmbientCount) faluco@1735: { faluco@1735: for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); ) faluco@1735: { faluco@1735: if ((*iter)->GetParentContext() == pContext) faluco@1735: { faluco@1735: iter = m_AmbientFuncs.erase(iter); faluco@1735: _DecRefCounter(AMBIENT_SOUND_HOOK); faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: iter++; faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: if (m_NormalCount) faluco@1735: { faluco@1735: for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); ) faluco@1735: { faluco@1735: if ((*iter)->GetParentContext() == pContext) faluco@1735: { faluco@1735: iter = m_NormalFuncs.erase(iter); faluco@1735: _DecRefCounter(NORMAL_SOUND_HOOK); faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: iter++; faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::AddHook(int type, IPluginFunction *pFunc) faluco@1735: { faluco@1735: if (type == NORMAL_SOUND_HOOK) faluco@1735: { faluco@1735: m_NormalFuncs.push_back(pFunc); faluco@1735: _IncRefCounter(NORMAL_SOUND_HOOK); faluco@1735: } faluco@1735: else if (type == AMBIENT_SOUND_HOOK) faluco@1735: { faluco@1735: m_AmbientFuncs.push_back(pFunc); faluco@1735: _IncRefCounter(AMBIENT_SOUND_HOOK); faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc) faluco@1735: { faluco@1735: SoundHookIter iter; faluco@1735: if (type == NORMAL_SOUND_HOOK) faluco@1735: { faluco@1735: if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end()) faluco@1735: { faluco@1735: m_NormalFuncs.erase(iter); faluco@1735: _DecRefCounter(NORMAL_SOUND_HOOK); faluco@1735: return true; faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: return false; faluco@1735: } faluco@1735: } faluco@1735: else if (type == AMBIENT_SOUND_HOOK) faluco@1735: { faluco@1735: if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end()) faluco@1735: { faluco@1735: m_AmbientFuncs.erase(iter); faluco@1735: _DecRefCounter(AMBIENT_SOUND_HOOK); faluco@1735: return true; faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: return false; faluco@1735: } faluco@1735: } faluco@1735: faluco@1735: return false; faluco@1735: } faluco@1735: faluco@1735: void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, faluco@1735: soundlevel_t soundlevel, int fFlags, int pitch, float delay) faluco@1735: { faluco@1735: SoundHookIter iter; faluco@1735: IPluginFunction *pFunc; faluco@1735: cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)}; faluco@1735: cell_t res = static_cast(Pl_Continue); faluco@1735: char buffer[PLATFORM_MAX_PATH]; faluco@1735: strcpy(buffer, samp); faluco@1735: faluco@1735: for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++) faluco@1735: { faluco@1735: pFunc = (*iter); faluco@1735: pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&entindex); faluco@1735: pFunc->PushFloatByRef(&vol); faluco@1735: pFunc->PushCellByRef(reinterpret_cast(&soundlevel)); faluco@1735: pFunc->PushCellByRef(&pitch); faluco@1735: pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&fFlags); faluco@1735: pFunc->PushFloatByRef(&delay); faluco@1735: g_InSoundHook = true; faluco@1735: pFunc->Execute(&res); faluco@1735: g_InSoundHook = false; faluco@1735: faluco@1735: switch (res) faluco@1735: { faluco@1735: case Pl_Handled: faluco@1735: case Pl_Stop: faluco@1735: { faluco@1735: RETURN_META(MRES_SUPERCEDE); faluco@1735: } faluco@1735: case Pl_Changed: faluco@1735: { faluco@1735: Vector vec2; faluco@1735: vec2.x = sp_ctof(vec[0]); faluco@1735: vec2.y = sp_ctof(vec[1]); faluco@1735: vec2.z = sp_ctof(vec[2]); faluco@1735: RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, faluco@1735: (entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay)); faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: } faluco@1735: skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, skamonkey@3515: float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, skamonkey@3515: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, skamonkey@3515: float soundtime, int speakerentity) skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, skamonkey@3564: float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, skamonkey@3564: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, skamonkey@3564: float soundtime, int speakerentity) skamonkey@3515: #else faluco@1735: void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, faluco@1735: float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, faluco@1735: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, faluco@1735: float soundtime, int speakerentity) skamonkey@3515: #endif faluco@1735: { faluco@1735: SoundHookIter iter; faluco@1735: IPluginFunction *pFunc; faluco@1735: cell_t res = static_cast(Pl_Continue); faluco@1735: char buffer[PLATFORM_MAX_PATH]; faluco@1735: strcpy(buffer, pSample); faluco@1735: faluco@1735: for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++) faluco@1735: { faluco@1735: int players[64], size; faluco@1735: size = _FillInPlayers(players, &filter); faluco@1735: pFunc = (*iter); faluco@1735: faluco@1735: pFunc->PushArray(players, 64, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&size); faluco@1735: pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&iEntIndex); faluco@1735: pFunc->PushCellByRef(&iChannel); faluco@1735: pFunc->PushFloatByRef(&flVolume); faluco@1735: pFunc->PushCellByRef(reinterpret_cast(&iSoundlevel)); faluco@1735: pFunc->PushCellByRef(&iPitch); faluco@1735: pFunc->PushCellByRef(&iFlags); faluco@1735: g_InSoundHook = true; faluco@1735: pFunc->Execute(&res); faluco@1735: g_InSoundHook = false; faluco@1735: faluco@1735: switch (res) faluco@1735: { faluco@1735: case Pl_Handled: faluco@1735: case Pl_Stop: faluco@1735: { skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE(MRES_SUPERCEDE, -1); skamonkey@3515: #else faluco@1735: RETURN_META(MRES_SUPERCEDE); skamonkey@3515: #endif faluco@1735: } faluco@1735: case Pl_Changed: faluco@1735: { faluco@1735: CellRecipientFilter crf; faluco@1735: crf.Initialize(players, size); skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE_NEWPARAMS( skamonkey@3515: MRES_IGNORED, skamonkey@3515: -1, skamonkey@3515: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), skamonkey@3515: (crf, iEntIndex, iChannel, buffer, -1, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin, skamonkey@3515: pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) skamonkey@3515: ); skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: RETURN_META_NEWPARAMS( skamonkey@3564: MRES_IGNORED, skamonkey@3564: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), skamonkey@3564: (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, iSpecialDSP, pOrigin, skamonkey@3564: pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) skamonkey@3564: ); skamonkey@3515: #else faluco@1735: RETURN_META_NEWPARAMS( faluco@1735: MRES_IGNORED, faluco@1735: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), faluco@1735: (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin, faluco@1735: pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) faluco@1735: ); skamonkey@3515: #endif faluco@1735: } faluco@1735: } faluco@1735: } skamonkey@3515: skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE(MRES_IGNORED, -1 ); skamonkey@3515: #endif faluco@1735: } faluco@1735: skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, skamonkey@3515: float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, skamonkey@3515: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, skamonkey@3515: float soundtime, int speakerentity) skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, skamonkey@3564: float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, skamonkey@3564: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, skamonkey@3564: float soundtime, int speakerentity) skamonkey@3515: #else faluco@1735: void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, faluco@1735: float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, faluco@1735: const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, faluco@1735: float soundtime, int speakerentity) skamonkey@3515: #endif faluco@1735: { faluco@1735: SoundHookIter iter; faluco@1735: IPluginFunction *pFunc; faluco@1735: cell_t res = static_cast(Pl_Continue); faluco@1735: cell_t sndlevel = static_cast(ATTN_TO_SNDLVL(flAttenuation)); faluco@1735: char buffer[PLATFORM_MAX_PATH]; faluco@1735: strcpy(buffer, pSample); faluco@1735: faluco@1735: for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++) faluco@1735: { faluco@1735: int players[64], size; faluco@1735: size = _FillInPlayers(players, &filter); faluco@1735: pFunc = (*iter); faluco@1735: faluco@1735: pFunc->PushArray(players, 64, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&size); faluco@1735: pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); faluco@1735: pFunc->PushCellByRef(&iEntIndex); faluco@1735: pFunc->PushCellByRef(&iChannel); faluco@1735: pFunc->PushFloatByRef(&flVolume); faluco@1735: pFunc->PushCellByRef(&sndlevel); faluco@1735: pFunc->PushCellByRef(&iPitch); faluco@1735: pFunc->PushCellByRef(&iFlags); faluco@1735: g_InSoundHook = true; faluco@1735: pFunc->Execute(&res); faluco@1735: g_InSoundHook = false; faluco@1735: faluco@1735: switch (res) faluco@1735: { faluco@1735: case Pl_Handled: faluco@1735: case Pl_Stop: faluco@1735: { skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE(MRES_SUPERCEDE, -1); skamonkey@3515: #else faluco@1735: RETURN_META(MRES_SUPERCEDE); skamonkey@3515: #endif faluco@1735: } faluco@1735: case Pl_Changed: faluco@1735: { faluco@1735: CellRecipientFilter crf; faluco@1735: crf.Initialize(players, size); skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE_NEWPARAMS( skamonkey@3515: MRES_IGNORED, skamonkey@3515: -1, skamonkey@3515: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), skamonkey@3515: (crf, iEntIndex, iChannel, buffer, -1, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), skamonkey@3515: nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) skamonkey@3515: ); skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: RETURN_META_NEWPARAMS( skamonkey@3564: MRES_IGNORED, skamonkey@3564: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), skamonkey@3564: (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), skamonkey@3564: iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) skamonkey@3564: ); skamonkey@3515: #else faluco@1735: RETURN_META_NEWPARAMS( faluco@1735: MRES_IGNORED, skamonkey@3515: static_cast *, bool, float, int)>(&IEngineSound::EmitSound), faluco@1735: (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), faluco@1735: iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) faluco@1735: ); skamonkey@3515: #endif faluco@1735: } faluco@1735: } faluco@1735: } skamonkey@3515: skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: RETURN_META_VALUE(MRES_IGNORED, -1 ); skamonkey@3515: #endif faluco@1735: } faluco@1735: faluco@1735: /************************ faluco@1735: * * faluco@1735: * Sound Related Natives * faluco@1735: * * faluco@1735: *************************/ faluco@1735: faluco@1735: SoundHooks s_SoundHooks; dvander@1047: dvander@1047: static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params) dvander@1047: { dvander@1047: char *name; dvander@1047: pContext->LocalToString(params[1], &name); dvander@1047: dvander@1047: engsound->PrefetchSound(name); dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: dvander@1047: static cell_t GetSoundDuration(IPluginContext *pContext, const cell_t *params) dvander@1047: { dvander@1047: char *name; dvander@1047: pContext->LocalToString(params[1], &name); dvander@1047: dvander@1047: return sp_ftoc(engsound->GetSoundDuration(name)); dvander@1047: } dvander@1047: dvander@1047: static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params) dvander@1047: { dvander@1047: cell_t entity; dvander@1047: Vector pos; dvander@1047: char *name; dvander@1047: float vol, delay; dvander@1047: int pitch, flags, level; dvander@1047: pred@2760: entity = SoundReferenceToIndex(params[3]); dvander@1047: dvander@1047: cell_t *addr; dvander@1047: pContext->LocalToPhysAddr(params[2], &addr); dvander@1047: pos.x = sp_ctof(addr[0]); dvander@1047: pos.y = sp_ctof(addr[1]); dvander@1047: pos.z = sp_ctof(addr[2]); dvander@1047: dvander@1047: pContext->LocalToString(params[1], &name); dvander@1047: dvander@1047: vol = sp_ctof(params[6]); dvander@1047: level = params[4]; dvander@1047: flags = params[5]; dvander@1047: pitch = params[7]; dvander@1047: delay = sp_ctof(params[8]); dvander@1047: faluco@1735: if (g_InSoundHook) faluco@1735: { faluco@1735: ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); faluco@1735: } dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: dvander@1047: static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params) dvander@1047: { dvander@1047: int client = params[1]; dvander@1047: if (client < 1 || client > playerhelpers->GetMaxClients()) dvander@1047: { dvander@1047: return pContext->ThrowNativeError("Client index %d is not valid", client); dvander@1047: } dvander@1047: dvander@1047: IGamePlayer *player = playerhelpers->GetGamePlayer(client); dvander@1047: if (!player->IsInGame()) dvander@1047: { dvander@1047: return pContext->ThrowNativeError("Client index %d is not in game", client); dvander@1047: } dvander@1047: skamonkey@3913: engine->FadeClientVolume( skamonkey@3913: #if SOURCE_ENGINE == SE_DOTA skamonkey@3913: player->GetIndex(), skamonkey@3913: #else skamonkey@3913: player->GetEdict(), skamonkey@3913: #endif dvander@1047: sp_ctof(params[2]), dvander@1047: sp_ctof(params[3]), dvander@1047: sp_ctof(params[4]), dvander@1047: sp_ctof(params[5])); dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: dvander@1047: static cell_t StopSound(IPluginContext *pContext, const cell_t *params) dvander@1047: { pred@2760: int entity = SoundReferenceToIndex(params[1]); dvander@1047: int channel = params[2]; dvander@1047: dvander@1047: char *name; dvander@1047: pContext->LocalToString(params[3], &name); dvander@1047: skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: engsound->StopSound(entity, channel, name, -1); skamonkey@3515: #else dvander@1047: engsound->StopSound(entity, channel, name); skamonkey@3515: #endif dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: dvander@1047: static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) dvander@1047: { ds@2112: cell_t *addr, *cl_array; dvander@1047: CellRecipientFilter crf; ds@2112: unsigned int numClients; ds@2112: int client; ds@2112: IGamePlayer *pPlayer = NULL; ds@2112: ds@2112: pContext->LocalToPhysAddr(params[1], &cl_array); ds@2112: numClients = params[2]; ds@2112: ds@2112: /* Client validation */ ds@2112: for (unsigned int i = 0; i < numClients; i++) ds@2112: { ds@2112: client = cl_array[i]; ds@2112: pPlayer = playerhelpers->GetGamePlayer(client); ds@2112: ds@2112: if (!pPlayer) ds@2112: { ds@2112: return pContext->ThrowNativeError("Client index %d is invalid", client); ds@2112: } else if (!pPlayer->IsInGame()) { ds@2112: return pContext->ThrowNativeError("Client %d is not connected", client); ds@2112: } ds@2112: } ds@2112: ds@2112: crf.Initialize(cl_array, numClients); dvander@1047: dvander@1047: char *sample; dvander@1047: pContext->LocalToString(params[3], &sample); dvander@1047: pred@2760: int entity = SoundReferenceToIndex(params[4]); dvander@1047: int channel = params[5]; dvander@1047: int level = params[6]; dvander@1047: int flags = params[7]; dvander@1047: float vol = sp_ctof(params[8]); dvander@1047: int pitch = params[9]; dvander@1047: int speakerentity = params[10]; dvander@1047: dvander@1047: Vector *pOrigin = NULL, origin; dvander@1047: Vector *pDir = NULL, dir; dvander@1047: dvander@1047: pContext->LocalToPhysAddr(params[11], &addr); dvander@1047: if (addr != pContext->GetNullRef(SP_NULL_VECTOR)) dvander@1047: { dvander@1047: pOrigin = &origin; dvander@1047: origin.x = sp_ctof(addr[0]); dvander@1047: origin.y = sp_ctof(addr[1]); dvander@1047: origin.z = sp_ctof(addr[2]); dvander@1047: } dvander@1047: dvander@1047: pContext->LocalToPhysAddr(params[12], &addr); dvander@1047: if (addr != pContext->GetNullRef(SP_NULL_VECTOR)) dvander@1047: { dvander@1047: pDir = &dir; dvander@1047: dir.x = sp_ctof(addr[0]); dvander@1047: dir.y = sp_ctof(addr[1]); dvander@1047: dir.z = sp_ctof(addr[2]); dvander@1047: } dvander@1047: dvander@1047: bool updatePos = params[13] ? true : false; dvander@1047: float soundtime = sp_ctof(params[14]); dvander@1047: dvander@1047: CUtlVector *pOrigVec = NULL; dvander@1047: CUtlVector origvec; dvander@1047: if (params[0] > 14) dvander@1047: { dvander@1047: pOrigVec = &origvec; dvander@1047: for (cell_t i = 15; i <= params[0]; i++) dvander@1047: { dvander@1047: Vector vec; dvander@1047: pContext->LocalToPhysAddr(params[i], &addr); dvander@1047: vec.x = sp_ctof(addr[0]); dvander@1047: vec.y = sp_ctof(addr[1]); dvander@1047: vec.z = sp_ctof(addr[2]); dvander@1047: origvec.AddToTail(vec); dvander@1047: } dvander@1047: } dvander@1047: dvander@1047: /* If we're going to a "local player" and this is a dedicated server, dvander@1047: * intelligently redirect each sound. dvander@1047: */ dvander@1047: dvander@1048: if (entity == -2 && engine->IsDedicatedServer()) dvander@1047: { ds@2112: for (unsigned int i = 0; i < numClients; i++) dvander@1047: { dvander@1047: cell_t player[1]; ds@2112: player[0] = cl_array[i]; dvander@1047: crf.Reset(); dvander@1047: crf.Initialize(player, 1); skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: if (g_InSoundHook) skamonkey@3515: { skamonkey@3515: SH_CALL(enginesoundPatch, skamonkey@3515: static_cast *, bool, float, int)> skamonkey@3515: skamonkey@3515: (&IEngineSound::EmitSound)) skamonkey@3515: (crf, skamonkey@3515: player[0], skamonkey@3515: channel, skamonkey@3515: sample, skamonkey@3515: -1, skamonkey@3515: sample, skamonkey@3515: vol, skamonkey@3515: (soundlevel_t)level, skamonkey@3515: 0, skamonkey@3515: flags, skamonkey@3515: pitch, skamonkey@3515: pOrigin, skamonkey@3515: pDir, skamonkey@3515: pOrigVec, skamonkey@3515: updatePos, skamonkey@3515: soundtime, skamonkey@3515: speakerentity); skamonkey@3515: } skamonkey@3515: else skamonkey@3515: { skamonkey@3515: engsound->EmitSound(crf, skamonkey@3515: player[0], skamonkey@3515: channel, skamonkey@3515: sample, skamonkey@3515: -1, skamonkey@3515: sample, skamonkey@3515: vol, skamonkey@3515: (soundlevel_t)level, skamonkey@3515: 0, skamonkey@3515: flags, skamonkey@3515: pitch, skamonkey@3515: pOrigin, skamonkey@3515: pDir, skamonkey@3515: pOrigVec, skamonkey@3515: updatePos, skamonkey@3515: soundtime, skamonkey@3515: speakerentity); skamonkey@3515: } skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: if (g_InSoundHook) skamonkey@3564: { skamonkey@3564: SH_CALL(enginesoundPatch, skamonkey@3564: static_cast *, bool, float, int)> skamonkey@3564: (&IEngineSound::EmitSound)) skamonkey@3564: (crf, skamonkey@3564: player[0], skamonkey@3564: channel, skamonkey@3564: sample, skamonkey@3564: vol, skamonkey@3564: (soundlevel_t)level, skamonkey@3564: flags, skamonkey@3564: pitch, skamonkey@3564: 0, skamonkey@3564: pOrigin, skamonkey@3564: pDir, skamonkey@3564: pOrigVec, skamonkey@3564: updatePos, skamonkey@3564: soundtime, skamonkey@3564: speakerentity); skamonkey@3564: } skamonkey@3564: else skamonkey@3564: { skamonkey@3564: engsound->EmitSound(crf, skamonkey@3564: player[0], skamonkey@3564: channel, skamonkey@3564: sample, skamonkey@3564: vol, skamonkey@3564: (soundlevel_t)level, skamonkey@3564: flags, skamonkey@3564: pitch, skamonkey@3564: 0, skamonkey@3564: pOrigin, skamonkey@3564: pDir, skamonkey@3564: pOrigVec, skamonkey@3564: updatePos, skamonkey@3564: soundtime, skamonkey@3564: speakerentity); skamonkey@3564: } skamonkey@3515: #else faluco@1735: if (g_InSoundHook) faluco@1735: { faluco@1735: SH_CALL(enginesoundPatch, faluco@1735: static_cast *, bool, float, int)> faluco@1735: (&IEngineSound::EmitSound)) faluco@1735: (crf, faluco@1735: player[0], faluco@1735: channel, faluco@1735: sample, faluco@1735: vol, faluco@1735: (soundlevel_t)level, faluco@1735: flags, faluco@1735: pitch, faluco@1735: pOrigin, faluco@1735: pDir, faluco@1735: pOrigVec, faluco@1735: updatePos, faluco@1735: soundtime, faluco@1735: speakerentity); faluco@1735: } faluco@1735: else faluco@1735: { faluco@1735: engsound->EmitSound(crf, faluco@1735: player[0], faluco@1735: channel, faluco@1735: sample, faluco@1735: vol, faluco@1735: (soundlevel_t)level, faluco@1735: flags, faluco@1735: pitch, faluco@1735: pOrigin, faluco@1735: pDir, faluco@1735: pOrigVec, faluco@1735: updatePos, faluco@1735: soundtime, faluco@1735: speakerentity); faluco@1735: } skamonkey@3515: #endif faluco@1735: } faluco@1735: } else { skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: if (g_InSoundHook) skamonkey@3515: { skamonkey@3515: SH_CALL(enginesoundPatch, skamonkey@3515: static_cast *, bool, float, int)> skamonkey@3515: (&IEngineSound::EmitSound)) skamonkey@3515: (crf, skamonkey@3515: entity, skamonkey@3515: channel, skamonkey@3515: sample, skamonkey@3515: -1, skamonkey@3515: sample, skamonkey@3515: vol, skamonkey@3515: (soundlevel_t)level, skamonkey@3515: 0, skamonkey@3515: flags, skamonkey@3515: pitch, skamonkey@3515: pOrigin, skamonkey@3515: pDir, skamonkey@3515: pOrigVec, skamonkey@3515: updatePos, skamonkey@3515: soundtime, skamonkey@3515: speakerentity); skamonkey@3515: } skamonkey@3515: else skamonkey@3515: { skamonkey@3515: engsound->EmitSound(crf, skamonkey@3515: entity, skamonkey@3515: channel, skamonkey@3515: sample, skamonkey@3515: -1, skamonkey@3515: sample, skamonkey@3515: vol, skamonkey@3515: (soundlevel_t)level, skamonkey@3515: 0, skamonkey@3515: flags, skamonkey@3515: pitch, skamonkey@3515: pOrigin, skamonkey@3515: pDir, skamonkey@3515: pOrigVec, skamonkey@3515: updatePos, skamonkey@3515: soundtime, skamonkey@3515: speakerentity); skamonkey@3515: } skamonkey@3613: #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3564: if (g_InSoundHook) skamonkey@3564: { skamonkey@3564: SH_CALL(enginesoundPatch, skamonkey@3564: static_cast *, bool, float, int)> skamonkey@3564: (&IEngineSound::EmitSound)) skamonkey@3564: (crf, skamonkey@3564: entity, skamonkey@3564: channel, skamonkey@3564: sample, skamonkey@3564: vol, skamonkey@3564: (soundlevel_t)level, skamonkey@3564: flags, skamonkey@3564: pitch, skamonkey@3564: 0, skamonkey@3564: pOrigin, skamonkey@3564: pDir, skamonkey@3564: pOrigVec, skamonkey@3564: updatePos, skamonkey@3564: soundtime, skamonkey@3564: speakerentity); skamonkey@3564: } skamonkey@3564: else skamonkey@3564: { skamonkey@3564: engsound->EmitSound(crf, skamonkey@3564: entity, skamonkey@3564: channel, skamonkey@3564: sample, skamonkey@3564: vol, skamonkey@3564: (soundlevel_t)level, skamonkey@3564: flags, skamonkey@3564: pitch, skamonkey@3564: 0, skamonkey@3564: pOrigin, skamonkey@3564: pDir, skamonkey@3564: pOrigVec, skamonkey@3564: updatePos, skamonkey@3564: soundtime, skamonkey@3564: speakerentity); skamonkey@3564: } skamonkey@3515: #else faluco@1735: if (g_InSoundHook) faluco@1735: { faluco@1735: SH_CALL(enginesoundPatch, faluco@1735: static_cast *, bool, float, int)> faluco@1735: (&IEngineSound::EmitSound)) faluco@1735: (crf, faluco@1735: entity, dvander@1047: channel, dvander@1047: sample, dvander@1047: vol, dvander@1047: (soundlevel_t)level, dvander@1047: flags, dvander@1047: pitch, dvander@1047: pOrigin, dvander@1047: pDir, dvander@1047: pOrigVec, dvander@1047: updatePos, dvander@1047: soundtime, dvander@1047: speakerentity); dvander@1047: } faluco@1735: else faluco@1735: { faluco@1735: engsound->EmitSound(crf, faluco@1735: entity, faluco@1735: channel, faluco@1735: sample, faluco@1735: vol, faluco@1735: (soundlevel_t)level, faluco@1735: flags, faluco@1735: pitch, faluco@1735: pOrigin, faluco@1735: pDir, faluco@1735: pOrigVec, faluco@1735: updatePos, faluco@1735: soundtime, faluco@1735: speakerentity); faluco@1735: } skamonkey@3515: #endif dvander@1047: } dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: dvander@1047: static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params) dvander@1047: { dvander@1047: cell_t *addr; ds@2112: CellRecipientFilter crf; ds@2112: unsigned int numClients; ds@2112: int client; ds@2112: IGamePlayer *pPlayer = NULL; dvander@1047: dvander@1047: pContext->LocalToPhysAddr(params[1], &addr); ds@2112: numClients = params[2]; ds@2112: ds@2112: /* Client validation */ ds@2112: for (unsigned int i = 0; i < numClients; i++) ds@2112: { ds@2112: client = addr[i]; ds@2112: pPlayer = playerhelpers->GetGamePlayer(client); ds@2112: ds@2112: if (!pPlayer) ds@2112: { ds@2112: return pContext->ThrowNativeError("Client index %d is invalid", client); ds@2112: } else if (!pPlayer->IsInGame()) { ds@2112: return pContext->ThrowNativeError("Client %d is not connected", client); ds@2112: } ds@2112: } ds@2112: ds@2112: crf.Initialize(addr, numClients); dvander@1047: dvander@1047: int sentence = params[3]; pred@2760: int entity = SoundReferenceToIndex(params[4]); dvander@1047: int channel = params[5]; dvander@1047: int level = params[6]; dvander@1047: int flags = params[7]; dvander@1047: float vol = sp_ctof(params[8]); dvander@1047: int pitch = params[9]; dvander@1047: int speakerentity = params[10]; dvander@1047: dvander@1047: Vector *pOrigin = NULL, origin; dvander@1047: Vector *pDir = NULL, dir; dvander@1047: dvander@1047: pContext->LocalToPhysAddr(params[11], &addr); dvander@1047: if (addr != pContext->GetNullRef(SP_NULL_VECTOR)) dvander@1047: { dvander@1047: pOrigin = &origin; dvander@1047: origin.x = sp_ctof(addr[0]); dvander@1047: origin.y = sp_ctof(addr[1]); dvander@1047: origin.z = sp_ctof(addr[2]); dvander@1047: } dvander@1047: dvander@1047: pContext->LocalToPhysAddr(params[12], &addr); dvander@1047: if (addr != pContext->GetNullRef(SP_NULL_VECTOR)) dvander@1047: { dvander@1047: pDir = &dir; dvander@1047: dir.x = sp_ctof(addr[0]); dvander@1047: dir.y = sp_ctof(addr[1]); dvander@1047: dir.z = sp_ctof(addr[2]); dvander@1047: } dvander@1047: dvander@1047: bool updatePos = params[13] ? true : false; dvander@1047: float soundtime = sp_ctof(params[14]); dvander@1047: dvander@1047: CUtlVector *pOrigVec = NULL; dvander@1047: CUtlVector origvec; dvander@1047: if (params[0] > 14) dvander@1047: { dvander@1047: pOrigVec = &origvec; dvander@1047: for (cell_t i = 15; i <= params[0]; i++) dvander@1047: { dvander@1047: Vector vec; dvander@1047: pContext->LocalToPhysAddr(params[i], &addr); dvander@1047: vec.x = sp_ctof(addr[0]); dvander@1047: vec.y = sp_ctof(addr[1]); dvander@1047: vec.z = sp_ctof(addr[2]); dvander@1047: origvec.AddToTail(vec); dvander@1047: } dvander@1047: } dvander@1047: dvander@1047: engsound->EmitSentenceByIndex(crf, dvander@1047: entity, dvander@1047: channel, dvander@1047: sentence, dvander@1047: vol, dvander@1047: (soundlevel_t)level, skamonkey@3515: #if SOURCE_ENGINE >= SE_PORTAL2 skamonkey@3515: 0, skamonkey@3515: #endif dvander@1047: flags, dvander@1047: pitch, skamonkey@3613: #if SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS skamonkey@3566: 0, skamonkey@3566: #endif dvander@1047: pOrigin, dvander@1047: pDir, dvander@1047: pOrigVec, dvander@1047: updatePos, dvander@1047: soundtime, dvander@1047: speakerentity); dvander@1047: dvander@1047: return 1; dvander@1047: } dvander@1047: faluco@1735: static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params) faluco@1735: { faluco@1735: IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); faluco@1735: if (!pFunc) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); faluco@1735: } faluco@1735: faluco@1735: s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc); faluco@1735: faluco@1735: return 1; faluco@1735: } faluco@1735: faluco@1735: static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params) faluco@1735: { faluco@1735: IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); faluco@1735: if (!pFunc) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); faluco@1735: } faluco@1735: faluco@1735: s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc); faluco@1735: faluco@1735: return 1; faluco@1735: } faluco@1735: faluco@1735: static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params) faluco@1735: { faluco@1735: IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); faluco@1735: if (!pFunc) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); faluco@1735: } faluco@1735: faluco@1735: if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc)) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid hooked function"); faluco@1735: } faluco@1735: faluco@1735: return 1; faluco@1735: } faluco@1735: faluco@1735: static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params) faluco@1735: { faluco@1735: IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); faluco@1735: if (!pFunc) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); faluco@1735: } faluco@1735: faluco@1735: if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc)) faluco@1735: { faluco@1735: return pContext->ThrowNativeError("Invalid hooked function"); faluco@1735: } faluco@1735: faluco@1735: return 1; faluco@1735: } faluco@1735: javalia@3384: static cell_t smn_GetDistGainFromSoundLevel(IPluginContext *pContext, const cell_t *params) javalia@3384: { javalia@3384: int decibel = params[1]; javalia@3384: float distance = sp_ctof(params[2]); javalia@3384: skamonkey@3385: return sp_ftoc(engsound->GetDistGainFromSoundLevel((soundlevel_t)decibel, distance)); javalia@3384: } javalia@3384: dvander@1047: sp_nativeinfo_t g_SoundNatives[] = dvander@1047: { faluco@1735: {"EmitAmbientSound", EmitAmbientSound}, faluco@1735: {"EmitSentence", EmitSentence}, faluco@1735: {"EmitSound", EmitSound}, faluco@1735: {"FadeClientVolume", FadeClientVolume}, faluco@1735: {"GetSoundDuration", GetSoundDuration}, faluco@1735: {"PrefetchSound", PrefetchSound}, faluco@1735: {"StopSound", StopSound}, faluco@1735: {"AddAmbientSoundHook", smn_AddAmbientSoundHook}, faluco@1735: {"AddNormalSoundHook", smn_AddNormalSoundHook}, faluco@1735: {"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook}, faluco@1735: {"RemoveNormalSoundHook", smn_RemoveNormalSoundHook}, javalia@3384: {"GetDistGainFromSoundLevel", smn_GetDistGainFromSoundLevel}, faluco@1735: {NULL, NULL}, dvander@1047: };