Updated for CS:S sync (r=asherkin).
3 * =============================================================================
4 * SourceMod SDKTools Extension
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
33 #include <IForwardSys.h>
35 SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float);
36 #if SOURCE_ENGINE >= SE_PORTAL2
37 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<Vector> *, bool, float, int);
38 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<Vector> *, bool, float, int);
39 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
40 SH_DECL_HOOK15_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
41 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<Vector> *, bool, float, int);
43 SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
44 SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int);
47 bool g_InSoundHook = false;
49 /***************************
51 * Sound Related Hook Class *
53 ****************************/
55 cell_t SoundReferenceToIndex(cell_t ref)
57 if (ref == 0 || ref == -1 || ref == -2)
62 return gamehelpers->ReferenceToIndex(ref);
65 size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
67 size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
69 for (size_t i=0; i<size; i++)
71 pl_array[i] = pFilter->GetRecipientIndex(i);
77 void SoundHooks::_IncRefCounter(int type)
79 if (type == NORMAL_SOUND_HOOK)
81 if (m_NormalCount++ == 0)
83 SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
84 SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
87 else if (type == AMBIENT_SOUND_HOOK)
89 if (m_AmbientCount++ == 0)
91 SH_ADD_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
96 void SoundHooks::_DecRefCounter(int type)
98 if (type == NORMAL_SOUND_HOOK)
100 if (--m_NormalCount == 0)
102 SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
103 SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
106 else if (type == AMBIENT_SOUND_HOOK)
108 if (--m_AmbientCount == 0)
110 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
115 void SoundHooks::Initialize()
117 plsys->AddPluginsListener(this);
120 void SoundHooks::Shutdown()
122 plsys->RemovePluginsListener(this);
125 SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
126 SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
130 SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
134 void SoundHooks::OnPluginUnloaded(IPlugin *plugin)
137 IPluginContext *pContext = plugin->GetBaseContext();
141 for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); )
143 if ((*iter)->GetParentContext() == pContext)
145 iter = m_AmbientFuncs.erase(iter);
146 _DecRefCounter(AMBIENT_SOUND_HOOK);
156 for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); )
158 if ((*iter)->GetParentContext() == pContext)
160 iter = m_NormalFuncs.erase(iter);
161 _DecRefCounter(NORMAL_SOUND_HOOK);
171 void SoundHooks::AddHook(int type, IPluginFunction *pFunc)
173 if (type == NORMAL_SOUND_HOOK)
175 m_NormalFuncs.push_back(pFunc);
176 _IncRefCounter(NORMAL_SOUND_HOOK);
178 else if (type == AMBIENT_SOUND_HOOK)
180 m_AmbientFuncs.push_back(pFunc);
181 _IncRefCounter(AMBIENT_SOUND_HOOK);
185 bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc)
188 if (type == NORMAL_SOUND_HOOK)
190 if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end())
192 m_NormalFuncs.erase(iter);
193 _DecRefCounter(NORMAL_SOUND_HOOK);
201 else if (type == AMBIENT_SOUND_HOOK)
203 if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end())
205 m_AmbientFuncs.erase(iter);
206 _DecRefCounter(AMBIENT_SOUND_HOOK);
218 void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol,
219 soundlevel_t soundlevel, int fFlags, int pitch, float delay)
222 IPluginFunction *pFunc;
223 cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
224 cell_t res = static_cast<ResultType>(Pl_Continue);
225 char buffer[PLATFORM_MAX_PATH];
226 strcpy(buffer, samp);
228 for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++)
231 pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
232 pFunc->PushCellByRef(&entindex);
233 pFunc->PushFloatByRef(&vol);
234 pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&soundlevel));
235 pFunc->PushCellByRef(&pitch);
236 pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK);
237 pFunc->PushCellByRef(&fFlags);
238 pFunc->PushFloatByRef(&delay);
239 g_InSoundHook = true;
240 pFunc->Execute(&res);
241 g_InSoundHook = false;
248 RETURN_META(MRES_SUPERCEDE);
253 vec2.x = sp_ctof(vec[0]);
254 vec2.y = sp_ctof(vec[1]);
255 vec2.z = sp_ctof(vec[2]);
256 RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound,
257 (entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay));
263 #if SOURCE_ENGINE >= SE_PORTAL2
264 int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
265 float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
266 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
267 float soundtime, int speakerentity)
268 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
269 void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
270 float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin,
271 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
272 float soundtime, int speakerentity)
274 void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
275 float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin,
276 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
277 float soundtime, int speakerentity)
281 IPluginFunction *pFunc;
282 cell_t res = static_cast<ResultType>(Pl_Continue);
283 char buffer[PLATFORM_MAX_PATH];
284 strcpy(buffer, pSample);
286 for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
288 int players[64], size;
289 size = _FillInPlayers(players, &filter);
292 pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
293 pFunc->PushCellByRef(&size);
294 pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
295 pFunc->PushCellByRef(&iEntIndex);
296 pFunc->PushCellByRef(&iChannel);
297 pFunc->PushFloatByRef(&flVolume);
298 pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&iSoundlevel));
299 pFunc->PushCellByRef(&iPitch);
300 pFunc->PushCellByRef(&iFlags);
301 g_InSoundHook = true;
302 pFunc->Execute(&res);
303 g_InSoundHook = false;
310 #if SOURCE_ENGINE >= SE_PORTAL2
311 RETURN_META_VALUE(MRES_SUPERCEDE, -1);
313 RETURN_META(MRES_SUPERCEDE);
318 CellRecipientFilter crf;
319 crf.Initialize(players, size);
320 #if SOURCE_ENGINE >= SE_PORTAL2
321 RETURN_META_VALUE_NEWPARAMS(
324 static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float, soundlevel_t,
325 int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
326 (crf, iEntIndex, iChannel, buffer, -1, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin,
327 pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
329 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
330 RETURN_META_NEWPARAMS(
332 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, soundlevel_t,
333 int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
334 (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, iSpecialDSP, pOrigin,
335 pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
338 RETURN_META_NEWPARAMS(
340 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, soundlevel_t,
341 int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
342 (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin,
343 pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
350 #if SOURCE_ENGINE >= SE_PORTAL2
351 RETURN_META_VALUE(MRES_IGNORED, -1 );
355 #if SOURCE_ENGINE >= SE_PORTAL2
356 int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample,
357 float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin,
358 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
359 float soundtime, int speakerentity)
360 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
361 void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
362 float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin,
363 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
364 float soundtime, int speakerentity)
366 void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample,
367 float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin,
368 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions,
369 float soundtime, int speakerentity)
373 IPluginFunction *pFunc;
374 cell_t res = static_cast<ResultType>(Pl_Continue);
375 cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation));
376 char buffer[PLATFORM_MAX_PATH];
377 strcpy(buffer, pSample);
379 for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
381 int players[64], size;
382 size = _FillInPlayers(players, &filter);
385 pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
386 pFunc->PushCellByRef(&size);
387 pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
388 pFunc->PushCellByRef(&iEntIndex);
389 pFunc->PushCellByRef(&iChannel);
390 pFunc->PushFloatByRef(&flVolume);
391 pFunc->PushCellByRef(&sndlevel);
392 pFunc->PushCellByRef(&iPitch);
393 pFunc->PushCellByRef(&iFlags);
394 g_InSoundHook = true;
395 pFunc->Execute(&res);
396 g_InSoundHook = false;
403 #if SOURCE_ENGINE >= SE_PORTAL2
404 RETURN_META_VALUE(MRES_SUPERCEDE, -1);
406 RETURN_META(MRES_SUPERCEDE);
411 CellRecipientFilter crf;
412 crf.Initialize(players, size);
413 #if SOURCE_ENGINE >= SE_PORTAL2
414 RETURN_META_VALUE_NEWPARAMS(
417 static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float,
418 int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
419 (crf, iEntIndex, iChannel, buffer, -1, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
420 nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
422 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
423 RETURN_META_NEWPARAMS(
425 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float,
426 int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
427 (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
428 iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
431 RETURN_META_NEWPARAMS(
433 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float,
434 int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound),
435 (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)),
436 iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
443 #if SOURCE_ENGINE >= SE_PORTAL2
444 RETURN_META_VALUE(MRES_IGNORED, -1 );
448 /************************
450 * Sound Related Natives *
452 *************************/
454 SoundHooks s_SoundHooks;
456 static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params)
459 pContext->LocalToString(params[1], &name);
461 engsound->PrefetchSound(name);
466 static cell_t GetSoundDuration(IPluginContext *pContext, const cell_t *params)
469 pContext->LocalToString(params[1], &name);
471 return sp_ftoc(engsound->GetSoundDuration(name));
474 static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params)
480 int pitch, flags, level;
482 entity = SoundReferenceToIndex(params[3]);
485 pContext->LocalToPhysAddr(params[2], &addr);
486 pos.x = sp_ctof(addr[0]);
487 pos.y = sp_ctof(addr[1]);
488 pos.z = sp_ctof(addr[2]);
490 pContext->LocalToString(params[1], &name);
492 vol = sp_ctof(params[6]);
496 delay = sp_ctof(params[8]);
500 ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
504 engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
510 static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params)
512 int client = params[1];
513 if (client < 1 || client > playerhelpers->GetMaxClients())
515 return pContext->ThrowNativeError("Client index %d is not valid", client);
518 IGamePlayer *player = playerhelpers->GetGamePlayer(client);
519 if (!player->IsInGame())
521 return pContext->ThrowNativeError("Client index %d is not in game", client);
524 engine->FadeClientVolume(player->GetEdict(),
533 static cell_t StopSound(IPluginContext *pContext, const cell_t *params)
535 int entity = SoundReferenceToIndex(params[1]);
536 int channel = params[2];
539 pContext->LocalToString(params[3], &name);
541 #if SOURCE_ENGINE >= SE_PORTAL2
542 engsound->StopSound(entity, channel, name, -1);
544 engsound->StopSound(entity, channel, name);
550 static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
552 cell_t *addr, *cl_array;
553 CellRecipientFilter crf;
554 unsigned int numClients;
556 IGamePlayer *pPlayer = NULL;
558 pContext->LocalToPhysAddr(params[1], &cl_array);
559 numClients = params[2];
561 /* Client validation */
562 for (unsigned int i = 0; i < numClients; i++)
564 client = cl_array[i];
565 pPlayer = playerhelpers->GetGamePlayer(client);
569 return pContext->ThrowNativeError("Client index %d is invalid", client);
570 } else if (!pPlayer->IsInGame()) {
571 return pContext->ThrowNativeError("Client %d is not connected", client);
575 crf.Initialize(cl_array, numClients);
578 pContext->LocalToString(params[3], &sample);
580 int entity = SoundReferenceToIndex(params[4]);
581 int channel = params[5];
582 int level = params[6];
583 int flags = params[7];
584 float vol = sp_ctof(params[8]);
585 int pitch = params[9];
586 int speakerentity = params[10];
588 Vector *pOrigin = NULL, origin;
589 Vector *pDir = NULL, dir;
591 pContext->LocalToPhysAddr(params[11], &addr);
592 if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
595 origin.x = sp_ctof(addr[0]);
596 origin.y = sp_ctof(addr[1]);
597 origin.z = sp_ctof(addr[2]);
600 pContext->LocalToPhysAddr(params[12], &addr);
601 if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
604 dir.x = sp_ctof(addr[0]);
605 dir.y = sp_ctof(addr[1]);
606 dir.z = sp_ctof(addr[2]);
609 bool updatePos = params[13] ? true : false;
610 float soundtime = sp_ctof(params[14]);
612 CUtlVector<Vector> *pOrigVec = NULL;
613 CUtlVector<Vector> origvec;
617 for (cell_t i = 15; i <= params[0]; i++)
620 pContext->LocalToPhysAddr(params[i], &addr);
621 vec.x = sp_ctof(addr[0]);
622 vec.y = sp_ctof(addr[1]);
623 vec.z = sp_ctof(addr[2]);
624 origvec.AddToTail(vec);
628 /* If we're going to a "local player" and this is a dedicated server,
629 * intelligently redirect each sound.
632 if (entity == -2 && engine->IsDedicatedServer())
634 for (unsigned int i = 0; i < numClients; i++)
637 player[0] = cl_array[i];
639 crf.Initialize(player, 1);
640 #if SOURCE_ENGINE >= SE_PORTAL2
643 SH_CALL(enginesoundPatch,
644 static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
645 soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
647 (&IEngineSound::EmitSound))
668 engsound->EmitSound(crf,
686 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
689 SH_CALL(enginesoundPatch,
690 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
691 soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
692 (&IEngineSound::EmitSound))
711 engsound->EmitSound(crf,
730 SH_CALL(enginesoundPatch,
731 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
732 soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
733 (&IEngineSound::EmitSound))
751 engsound->EmitSound(crf,
769 #if SOURCE_ENGINE >= SE_PORTAL2
772 SH_CALL(enginesoundPatch,
773 static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char*, unsigned int, const char*, float,
774 soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
775 (&IEngineSound::EmitSound))
796 engsound->EmitSound(crf,
814 #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
817 SH_CALL(enginesoundPatch,
818 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
819 soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
820 (&IEngineSound::EmitSound))
839 engsound->EmitSound(crf,
858 SH_CALL(enginesoundPatch,
859 static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float,
860 soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
861 (&IEngineSound::EmitSound))
879 engsound->EmitSound(crf,
900 static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
903 CellRecipientFilter crf;
904 unsigned int numClients;
906 IGamePlayer *pPlayer = NULL;
908 pContext->LocalToPhysAddr(params[1], &addr);
909 numClients = params[2];
911 /* Client validation */
912 for (unsigned int i = 0; i < numClients; i++)
915 pPlayer = playerhelpers->GetGamePlayer(client);
919 return pContext->ThrowNativeError("Client index %d is invalid", client);
920 } else if (!pPlayer->IsInGame()) {
921 return pContext->ThrowNativeError("Client %d is not connected", client);
925 crf.Initialize(addr, numClients);
927 int sentence = params[3];
928 int entity = SoundReferenceToIndex(params[4]);
929 int channel = params[5];
930 int level = params[6];
931 int flags = params[7];
932 float vol = sp_ctof(params[8]);
933 int pitch = params[9];
934 int speakerentity = params[10];
936 Vector *pOrigin = NULL, origin;
937 Vector *pDir = NULL, dir;
939 pContext->LocalToPhysAddr(params[11], &addr);
940 if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
943 origin.x = sp_ctof(addr[0]);
944 origin.y = sp_ctof(addr[1]);
945 origin.z = sp_ctof(addr[2]);
948 pContext->LocalToPhysAddr(params[12], &addr);
949 if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
952 dir.x = sp_ctof(addr[0]);
953 dir.y = sp_ctof(addr[1]);
954 dir.z = sp_ctof(addr[2]);
957 bool updatePos = params[13] ? true : false;
958 float soundtime = sp_ctof(params[14]);
960 CUtlVector<Vector> *pOrigVec = NULL;
961 CUtlVector<Vector> origvec;
965 for (cell_t i = 15; i <= params[0]; i++)
968 pContext->LocalToPhysAddr(params[i], &addr);
969 vec.x = sp_ctof(addr[0]);
970 vec.y = sp_ctof(addr[1]);
971 vec.z = sp_ctof(addr[2]);
972 origvec.AddToTail(vec);
976 engsound->EmitSentenceByIndex(crf,
982 #if SOURCE_ENGINE >= SE_PORTAL2
987 #if SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
1000 static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
1002 IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
1005 return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
1008 s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc);
1013 static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params)
1015 IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
1018 return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
1021 s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc);
1026 static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
1028 IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
1031 return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
1034 if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc))
1036 return pContext->ThrowNativeError("Invalid hooked function");
1042 static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params)
1044 IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
1047 return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
1050 if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc))
1052 return pContext->ThrowNativeError("Invalid hooked function");
1058 static cell_t smn_GetDistGainFromSoundLevel(IPluginContext *pContext, const cell_t *params)
1060 int decibel = params[1];
1061 float distance = sp_ctof(params[2]);
1063 return sp_ftoc(engsound->GetDistGainFromSoundLevel((soundlevel_t)decibel, distance));
1066 sp_nativeinfo_t g_SoundNatives[] =
1068 {"EmitAmbientSound", EmitAmbientSound},
1069 {"EmitSentence", EmitSentence},
1070 {"EmitSound", EmitSound},
1071 {"FadeClientVolume", FadeClientVolume},
1072 {"GetSoundDuration", GetSoundDuration},
1073 {"PrefetchSound", PrefetchSound},
1074 {"StopSound", StopSound},
1075 {"AddAmbientSoundHook", smn_AddAmbientSoundHook},
1076 {"AddNormalSoundHook", smn_AddNormalSoundHook},
1077 {"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook},
1078 {"RemoveNormalSoundHook", smn_RemoveNormalSoundHook},
1079 {"GetDistGainFromSoundLevel", smn_GetDistGainFromSoundLevel},