diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index a1b8fb5c..290ac288 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -35,6 +35,7 @@ #include "vhelpers.h" #include "vglobals.h" #include "tempents.h" +#include "vsound.h" #if defined ORANGEBOX_BUILD #define SDKTOOLS_GAME_FILE "sdktools.games.ep2" @@ -63,6 +64,8 @@ IServerGameClients *serverClients = NULL; IVoiceServer *voiceserver = NULL; IPlayerInfoManager *playerinfomngr = NULL; ICvar *icvar = NULL; +SourceHook::CallClass *enginePatch = NULL; +SourceHook::CallClass *enginesoundPatch = NULL; HandleType_t g_CallHandle = 0; HandleType_t g_TraceHandle = 0; @@ -149,6 +152,7 @@ void SDKTools::SDK_OnUnload() g_TEManager.Shutdown(); s_TempEntHooks.Shutdown(); + s_SoundHooks.Shutdown(); gameconfs->CloseGameConfigFile(g_pGameConf); playerhelpers->RemoveClientListener(&g_SdkTools); @@ -156,6 +160,17 @@ void SDKTools::SDK_OnUnload() SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false); + + if (enginePatch) + { + SH_RELEASE_CALLCLASS(enginePatch); + enginePatch = NULL; + } + if (enginesoundPatch) + { + SH_RELEASE_CALLCLASS(enginesoundPatch); + enginesoundPatch = NULL; + } } bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) @@ -170,6 +185,9 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); + enginePatch = SH_GET_CALLCLASS(engine); + enginesoundPatch = SH_GET_CALLCLASS(engsound); + return true; } @@ -179,6 +197,7 @@ void SDKTools::SDK_OnAllLoaded() g_TEManager.Initialize(); s_TempEntHooks.Initialize(); + s_SoundHooks.Initialize(); InitializeValveGlobals(); } diff --git a/extensions/sdktools/extension.h b/extensions/sdktools/extension.h index 79fcc0ab..7a331b55 100644 --- a/extensions/sdktools/extension.h +++ b/extensions/sdktools/extension.h @@ -108,5 +108,10 @@ extern HandleType_t g_CallHandle; extern HandleType_t g_TraceHandle; /* Call Wrappers */ extern ICallWrapper *g_pAcceptInput; +/* Call classes */ +extern SourceHook::CallClass *enginePatch; +extern SourceHook::CallClass *enginesoundPatch; + +#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func) #endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/sdktools/msvc8/sdktools.vcproj b/extensions/sdktools/msvc8/sdktools.vcproj index 4eeee64a..d5c6e484 100644 --- a/extensions/sdktools/msvc8/sdktools.vcproj +++ b/extensions/sdktools/msvc8/sdktools.vcproj @@ -770,6 +770,10 @@ RelativePath="..\vnatives.h" > + + + +SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float); +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); +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); + +bool g_InSoundHook = false; + +/*************************** +* * +* Sound Related Hook Class * +* * +****************************/ + +size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter) +{ + size_t size = static_cast(pFilter->GetRecipientCount()); + + for (size_t i=0; iGetRecipientIndex(i); + } + + return size; +} + +void SoundHooks::_IncRefCounter(int type) +{ + if (type == NORMAL_SOUND_HOOK) + { + if (m_NormalCount++ == 0) + { + SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false); + SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false); + } + } + else if (type == AMBIENT_SOUND_HOOK) + { + if (m_AmbientCount++ == 0) + { + SH_ADD_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false); + } + } +} + +void SoundHooks::_DecRefCounter(int type) +{ + if (type == NORMAL_SOUND_HOOK) + { + if (--m_NormalCount == 0) + { + SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false); + SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false); + } + } + else if (type == AMBIENT_SOUND_HOOK) + { + if (--m_AmbientCount == 0) + { + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false); + } + } +} + +void SoundHooks::Initialize() +{ + plsys->AddPluginsListener(this); +} + +void SoundHooks::Shutdown() +{ + plsys->RemovePluginsListener(this); + if (m_NormalCount) + { + SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false); + SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false); + } + if (m_AmbientCount) + { + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false); + } +} + +void SoundHooks::OnPluginUnloaded(IPlugin *plugin) +{ + SoundHookIter iter; + IPluginContext *pContext = plugin->GetBaseContext(); + + if (m_AmbientCount) + { + for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); ) + { + if ((*iter)->GetParentContext() == pContext) + { + iter = m_AmbientFuncs.erase(iter); + _DecRefCounter(AMBIENT_SOUND_HOOK); + } + else + { + iter++; + } + } + } + if (m_NormalCount) + { + for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); ) + { + if ((*iter)->GetParentContext() == pContext) + { + iter = m_NormalFuncs.erase(iter); + _DecRefCounter(NORMAL_SOUND_HOOK); + } + else + { + iter++; + } + } + } +} + +void SoundHooks::AddHook(int type, IPluginFunction *pFunc) +{ + if (type == NORMAL_SOUND_HOOK) + { + m_NormalFuncs.push_back(pFunc); + _IncRefCounter(NORMAL_SOUND_HOOK); + } + else if (type == AMBIENT_SOUND_HOOK) + { + m_AmbientFuncs.push_back(pFunc); + _IncRefCounter(AMBIENT_SOUND_HOOK); + } +} + +bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc) +{ + SoundHookIter iter; + if (type == NORMAL_SOUND_HOOK) + { + if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end()) + { + m_NormalFuncs.erase(iter); + _DecRefCounter(NORMAL_SOUND_HOOK); + return true; + } + else + { + return false; + } + } + else if (type == AMBIENT_SOUND_HOOK) + { + if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end()) + { + m_AmbientFuncs.erase(iter); + _DecRefCounter(AMBIENT_SOUND_HOOK); + return true; + } + else + { + return false; + } + } + + return false; +} + +void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, + soundlevel_t soundlevel, int fFlags, int pitch, float delay) +{ + SoundHookIter iter; + IPluginFunction *pFunc; + cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)}; + cell_t res = static_cast(Pl_Continue); + char buffer[PLATFORM_MAX_PATH]; + strcpy(buffer, samp); + + for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++) + { + pFunc = (*iter); + pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); + pFunc->PushCellByRef(&entindex); + pFunc->PushFloatByRef(&vol); + pFunc->PushCellByRef(reinterpret_cast(&soundlevel)); + pFunc->PushCellByRef(&pitch); + pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK); + pFunc->PushCellByRef(&fFlags); + pFunc->PushFloatByRef(&delay); + g_InSoundHook = true; + pFunc->Execute(&res); + g_InSoundHook = false; + + switch (res) + { + case Pl_Handled: + case Pl_Stop: + { + RETURN_META(MRES_SUPERCEDE); + } + case Pl_Changed: + { + Vector vec2; + vec2.x = sp_ctof(vec[0]); + vec2.y = sp_ctof(vec[1]); + vec2.z = sp_ctof(vec[2]); + RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, + (entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay)); + } + } + } +} + +void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, + float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, + const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, + float soundtime, int speakerentity) +{ + SoundHookIter iter; + IPluginFunction *pFunc; + cell_t res = static_cast(Pl_Continue); + 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(reinterpret_cast(&iSoundlevel)); + 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 *, bool, float, int)>(&IEngineSound::EmitSound), + (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, 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 *pUtlVecOrigins, bool bUpdatePositions, + float soundtime, int speakerentity) +{ + SoundHookIter iter; + IPluginFunction *pFunc; + cell_t res = static_cast(Pl_Continue); + cell_t sndlevel = static_cast(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 *, bool, float, int)>(&IEngineSound::EmitSound), + (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), + iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + ); + } + } + } +} + +/************************ +* * +* Sound Related Natives * +* * +*************************/ + +SoundHooks s_SoundHooks; static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params) { @@ -74,7 +399,14 @@ static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params) pitch = params[7]; delay = sp_ctof(params[8]); - engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); + if (g_InSoundHook) + { + ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); + } + else + { + engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); + } return 1; } @@ -186,8 +518,71 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) player[0] = pl_addr[i]; crf.Reset(); crf.Initialize(player, 1); - engsound->EmitSound(crf, - player[0], + if (g_InSoundHook) + { + SH_CALL(enginesoundPatch, + static_cast *, bool, float, int)> + (&IEngineSound::EmitSound)) + (crf, + player[0], + channel, + sample, + vol, + (soundlevel_t)level, + flags, + pitch, + pOrigin, + pDir, + pOrigVec, + updatePos, + soundtime, + speakerentity); + } + else + { + engsound->EmitSound(crf, + player[0], + channel, + sample, + vol, + (soundlevel_t)level, + flags, + pitch, + pOrigin, + pDir, + pOrigVec, + updatePos, + soundtime, + speakerentity); + } + } + } else { + if (g_InSoundHook) + { + SH_CALL(enginesoundPatch, + static_cast *, bool, float, int)> + (&IEngineSound::EmitSound)) + (crf, + entity, + channel, + sample, + vol, + (soundlevel_t)level, + flags, + pitch, + pOrigin, + pDir, + pOrigVec, + updatePos, + soundtime, + speakerentity); + } + else + { + engsound->EmitSound(crf, + entity, channel, sample, vol, @@ -201,21 +596,6 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) soundtime, speakerentity); } - } else { - engsound->EmitSound(crf, - entity, - channel, - sample, - vol, - (soundlevel_t)level, - flags, - pitch, - pOrigin, - pDir, - pOrigVec, - updatePos, - soundtime, - speakerentity); } return 1; @@ -296,14 +676,76 @@ static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params) +{ + IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); + } + + s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc); + + return 1; +} + +static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params) +{ + IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); + } + + s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc); + + return 1; +} + +static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params) +{ + IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); + } + + if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc)) + { + return pContext->ThrowNativeError("Invalid hooked function"); + } + + return 1; +} + +static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params) +{ + IPluginFunction *pFunc = pContext->GetFunctionById(params[1]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[1]); + } + + if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc)) + { + return pContext->ThrowNativeError("Invalid hooked function"); + } + + return 1; +} + sp_nativeinfo_t g_SoundNatives[] = { - {"EmitAmbientSound", EmitAmbientSound}, - {"EmitSentence", EmitSentence}, - {"EmitSound", EmitSound}, - {"FadeClientVolume", FadeClientVolume}, - {"GetSoundDuration", GetSoundDuration}, - {"PrefetchSound", PrefetchSound}, - {"StopSound", StopSound}, - {NULL, NULL}, + {"EmitAmbientSound", EmitAmbientSound}, + {"EmitSentence", EmitSentence}, + {"EmitSound", EmitSound}, + {"FadeClientVolume", FadeClientVolume}, + {"GetSoundDuration", GetSoundDuration}, + {"PrefetchSound", PrefetchSound}, + {"StopSound", StopSound}, + {"AddAmbientSoundHook", smn_AddAmbientSoundHook}, + {"AddNormalSoundHook", smn_AddNormalSoundHook}, + {"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook}, + {"RemoveNormalSoundHook", smn_RemoveNormalSoundHook}, + {NULL, NULL}, }; diff --git a/extensions/sdktools/vsound.h b/extensions/sdktools/vsound.h new file mode 100644 index 00000000..12f26530 --- /dev/null +++ b/extensions/sdktools/vsound.h @@ -0,0 +1,76 @@ +/** +* vim: set ts=4 : +* ============================================================================= +* SourceMod SDKTools Extension +* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. +* ============================================================================= +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU General Public License, version 3.0, as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +* details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +* As a special exception, AlliedModders LLC gives you permission to link the +* code of this program (as well as its derivative works) to "Half-Life 2," the +* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software +* by the Valve Corporation. You must obey the GNU General Public License in +* all respects for all other code used. Additionally, AlliedModders LLC grants +* this exception to all derivative works. AlliedModders LLC defines further +* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), +* or . +* +* Version: $Id$ +*/ + +#ifndef _INCLUDE_SOURCEMOD_VSOUND_H_ +#define _INCLUDE_SOURCEMOD_VSOUND_H_ + +#include +#include "extension.h" +#include "CellRecipientFilter.h" + +#define NORMAL_SOUND_HOOK 0 +#define AMBIENT_SOUND_HOOK 1 + +typedef SourceHook::List::iterator SoundHookIter; + +class SoundHooks : public IPluginsListener +{ +public: //IPluginsListener + void OnPluginUnloaded(IPlugin *plugin); +public: + void Initialize(); + void Shutdown(); + void AddHook(int type, IPluginFunction *pFunc); + bool RemoveHook(int type, IPluginFunction *pFunc); + void OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, + soundlevel_t soundlevel, int fFlags, int pitch, float delay); + void OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, + soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, + const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, + float soundtime, int speakerentity); + void 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 *pUtlVecOrigins, bool bUpdatePositions, + float soundtime, int speakerentity); +private: + size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter); + void _IncRefCounter(int type); + void _DecRefCounter(int type); +private: + SourceHook::List m_AmbientFuncs; + SourceHook::List m_NormalFuncs; + size_t m_NormalCount; + size_t m_AmbientCount; +}; + +extern SoundHooks s_SoundHooks; + +#endif //_INCLUDE_SOURCEMOD_VSOUND_H_ \ No newline at end of file diff --git a/plugins/include/core.inc b/plugins/include/core.inc index df31a96b..ca226e09 100644 --- a/plugins/include/core.inc +++ b/plugins/include/core.inc @@ -58,6 +58,7 @@ enum Function enum Action { Plugin_Continue = 0, /**< Continue with the original action */ + Plugin_Changed = 1, /**< Inputs or outputs have been overridden with new values */ Plugin_Handled = 3, /**< Handle the action at the end (don't call it) */ Plugin_Stop = 4, /**< Immediately stop the hook chain and handle the original */ }; diff --git a/plugins/include/sdktools_sound.inc b/plugins/include/sdktools_sound.inc index 93fd2372..c60c19a6 100644 --- a/plugins/include/sdktools_sound.inc +++ b/plugins/include/sdktools_sound.inc @@ -256,6 +256,77 @@ native EmitSentence(const clients[], Float:soundtime = 0.0, any:...); +/** + * Called when an ambient sound is about to be emitted to one or more clients. + * + * NOTICE: all parameters can be overwritten to modify the default behavior. + * + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity index associated to the sound. + * @param volume Volume (from 0.0 to 1.0). + * @param level Sound level (from 0 to 255). + * @param pitch Pitch (from 0 to 255). + * @param pos Origin of sound. + * @param flags Sound flags. + * @param delay Play delay. + * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + * Plugin_Changed when any parameter has been modified. + */ +functag AmbientSHook Action:public(String:sample[PLATFORM_MAX_PATH], &entity, &Float:volume, &level, &pitch, Float:pos[3], &flags, &Float:delay); + +/** + * Called when a sound is going to be emitted to one or more clients. + * NOTICE: all params can be overwritten to modify the default behaviour. + * + * @param clients Array of client indexes. + * @param numClients Number of clients in the array (modify this value if you add/remove elements from the client array). + * @param sample Sound file name relative to the "sounds" folder. + * @param entity Entity emitting the sound. + * @param channel Channel emitting the sound. + * @param volume Sound volume. + * @param level Sound level. + * @param pitch Sound pitch. + * @param flags Sound flags. + * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it, + * Plugin_Changed when any parameter has been modified. + */ +functag NormalSHook Action:public(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags); + +/** + * Hooks all played ambient sounds. + * + * @param hook Function to use as a hook. + * @noreturn + * @error Invalid function hook. + */ +native AddAmbientSoundHook(AmbientSHook:hook); + +/** + * Hooks all played normal sounds. + * + * @param hook Function to use as a hook. + * @noreturn + * @error Invalid function hook. + */ +native AddNormalSoundHook(NormalSHook:hook); + +/** + * Unhooks all played ambient sounds. + * + * @param hook Function used for the hook. + * @noreturn + * @error Invalid function hook. + */ +native RemoveAmbientSoundHook(AmbientSHook:hook); + +/** + * Unhooks all played normal sounds. + * + * @param hook Function used for the hook. + * @noreturn + * @error Invalid function hook. + */ +native RemoveNormalSoundHook(NormalSHook:hook); /** * Wrapper to emit sound to one client. diff --git a/public/IForwardSys.h b/public/IForwardSys.h index efa778e1..99149b64 100644 --- a/public/IForwardSys.h +++ b/public/IForwardSys.h @@ -65,6 +65,7 @@ namespace SourceMod enum ResultType { Pl_Continue = 0, /**< No result */ + Pl_Changed = 1, /**< Inputs or outputs have been overridden with new values */ Pl_Handled = 3, /**< Result was handled, stop at the end */ Pl_Stop = 4, /**< Result was handled, stop now */ };