extensions/sdktools/vsound.cpp
author David Anderson <dvander@alliedmods.net>
Sat Feb 07 22:32:55 2009 -0500 (2009-02-07)
changeset 2563 2860ef1261b2
parent 2289 44045ead61cd
child 2746 8d68569b9648
permissions -rw-r--r--
Renamed translation file with deprecated naming scheme.
ds@1114
     1
/**
ds@1114
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1233
     4
 * SourceMod SDKTools Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
ds@1114
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1233
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1233
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1233
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
ds@1114
    28
 *
ds@1114
    29
 * Version: $Id$
ds@1114
    30
 */
ds@1114
    31
faluco@1735
    32
#include "vsound.h"
faluco@1735
    33
#include <IForwardSys.h>
faluco@1735
    34
faluco@1735
    35
SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float);
faluco@1735
    36
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);
faluco@1735
    37
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);
faluco@1735
    38
faluco@1735
    39
bool g_InSoundHook = false;
faluco@1735
    40
faluco@1735
    41
/***************************
faluco@1735
    42
*                          *
faluco@1735
    43
* Sound Related Hook Class *
faluco@1735
    44
*                          *
faluco@1735
    45
****************************/
faluco@1735
    46
faluco@1735
    47
size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter)
faluco@1735
    48
{
faluco@1735
    49
	size_t size = static_cast<size_t>(pFilter->GetRecipientCount());
faluco@1735
    50
faluco@1735
    51
	for (size_t i=0; i<size; i++)
faluco@1735
    52
	{
faluco@1735
    53
		pl_array[i] = pFilter->GetRecipientIndex(i);
faluco@1735
    54
	}
faluco@1735
    55
faluco@1735
    56
	return size;
faluco@1735
    57
}
faluco@1735
    58
faluco@1735
    59
void SoundHooks::_IncRefCounter(int type)
faluco@1735
    60
{
faluco@1735
    61
	if (type == NORMAL_SOUND_HOOK)
faluco@1735
    62
	{
faluco@1735
    63
		if (m_NormalCount++ == 0)
faluco@1735
    64
		{
faluco@1735
    65
			SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
faluco@1735
    66
			SH_ADD_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
faluco@1735
    67
		}
faluco@1735
    68
	}
faluco@1735
    69
	else if (type == AMBIENT_SOUND_HOOK)
faluco@1735
    70
	{
faluco@1735
    71
		if (m_AmbientCount++ == 0)
faluco@1735
    72
		{
faluco@1735
    73
			SH_ADD_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
faluco@1735
    74
		}
faluco@1735
    75
	}
faluco@1735
    76
}
faluco@1735
    77
faluco@1735
    78
void SoundHooks::_DecRefCounter(int type)
faluco@1735
    79
{
faluco@1735
    80
	if (type == NORMAL_SOUND_HOOK)
faluco@1735
    81
	{
faluco@1735
    82
		if (--m_NormalCount == 0)
faluco@1735
    83
		{
faluco@1735
    84
			SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
faluco@1735
    85
			SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
faluco@1735
    86
		}
faluco@1735
    87
	}
faluco@1735
    88
	else if (type == AMBIENT_SOUND_HOOK)
faluco@1735
    89
	{
faluco@1735
    90
		if (--m_AmbientCount == 0)
faluco@1735
    91
		{
faluco@1735
    92
			SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
faluco@1735
    93
		}
faluco@1735
    94
	}
faluco@1735
    95
}
faluco@1735
    96
faluco@1735
    97
void SoundHooks::Initialize()
faluco@1735
    98
{
faluco@1735
    99
	plsys->AddPluginsListener(this);
faluco@1735
   100
}
faluco@1735
   101
faluco@1735
   102
void SoundHooks::Shutdown()
faluco@1735
   103
{
faluco@1735
   104
	plsys->RemovePluginsListener(this);
faluco@1735
   105
	if (m_NormalCount)
faluco@1735
   106
	{
faluco@1735
   107
		SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound, false);
faluco@1735
   108
		SH_REMOVE_HOOK_MEMFUNC(IEngineSound, EmitSound, engsound, this, &SoundHooks::OnEmitSound2, false);
faluco@1735
   109
	}
faluco@1735
   110
	if (m_AmbientCount)
faluco@1735
   111
	{
faluco@1735
   112
		SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, EmitAmbientSound, engine, this, &SoundHooks::OnEmitAmbientSound, false);
faluco@1735
   113
	}
faluco@1735
   114
}
faluco@1735
   115
faluco@1735
   116
void SoundHooks::OnPluginUnloaded(IPlugin *plugin)
faluco@1735
   117
{
faluco@1735
   118
	SoundHookIter iter;
faluco@1735
   119
	IPluginContext *pContext = plugin->GetBaseContext();
faluco@1735
   120
faluco@1735
   121
	if (m_AmbientCount)
faluco@1735
   122
	{
faluco@1735
   123
		for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); )
faluco@1735
   124
		{
faluco@1735
   125
			if ((*iter)->GetParentContext() == pContext)
faluco@1735
   126
			{
faluco@1735
   127
				iter = m_AmbientFuncs.erase(iter);
faluco@1735
   128
				_DecRefCounter(AMBIENT_SOUND_HOOK);
faluco@1735
   129
			}
faluco@1735
   130
			else
faluco@1735
   131
			{
faluco@1735
   132
				iter++;
faluco@1735
   133
			}
faluco@1735
   134
		}
faluco@1735
   135
	}
faluco@1735
   136
	if (m_NormalCount)
faluco@1735
   137
	{
faluco@1735
   138
		for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); )
faluco@1735
   139
		{
faluco@1735
   140
			if ((*iter)->GetParentContext() == pContext)
faluco@1735
   141
			{
faluco@1735
   142
				iter = m_NormalFuncs.erase(iter);
faluco@1735
   143
				_DecRefCounter(NORMAL_SOUND_HOOK);
faluco@1735
   144
			}
faluco@1735
   145
			else
faluco@1735
   146
			{
faluco@1735
   147
				iter++;
faluco@1735
   148
			}
faluco@1735
   149
		}
faluco@1735
   150
	}
faluco@1735
   151
}
faluco@1735
   152
faluco@1735
   153
void SoundHooks::AddHook(int type, IPluginFunction *pFunc)
faluco@1735
   154
{
faluco@1735
   155
	if (type == NORMAL_SOUND_HOOK)
faluco@1735
   156
	{
faluco@1735
   157
		m_NormalFuncs.push_back(pFunc);
faluco@1735
   158
		_IncRefCounter(NORMAL_SOUND_HOOK);
faluco@1735
   159
	}
faluco@1735
   160
	else if (type == AMBIENT_SOUND_HOOK)
faluco@1735
   161
	{
faluco@1735
   162
		m_AmbientFuncs.push_back(pFunc);
faluco@1735
   163
		_IncRefCounter(AMBIENT_SOUND_HOOK);
faluco@1735
   164
	}
faluco@1735
   165
}
faluco@1735
   166
faluco@1735
   167
bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc)
faluco@1735
   168
{
faluco@1735
   169
	SoundHookIter iter;
faluco@1735
   170
	if (type == NORMAL_SOUND_HOOK)
faluco@1735
   171
	{
faluco@1735
   172
		if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end())
faluco@1735
   173
		{
faluco@1735
   174
			m_NormalFuncs.erase(iter);
faluco@1735
   175
			_DecRefCounter(NORMAL_SOUND_HOOK);
faluco@1735
   176
			return true;
faluco@1735
   177
		}
faluco@1735
   178
		else
faluco@1735
   179
		{
faluco@1735
   180
			return false;
faluco@1735
   181
		}
faluco@1735
   182
	}
faluco@1735
   183
	else if (type == AMBIENT_SOUND_HOOK)
faluco@1735
   184
	{
faluco@1735
   185
		if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end())
faluco@1735
   186
		{
faluco@1735
   187
			m_AmbientFuncs.erase(iter);
faluco@1735
   188
			_DecRefCounter(AMBIENT_SOUND_HOOK);
faluco@1735
   189
			return true;
faluco@1735
   190
		}
faluco@1735
   191
		else
faluco@1735
   192
		{
faluco@1735
   193
			return false;
faluco@1735
   194
		}
faluco@1735
   195
	}
faluco@1735
   196
faluco@1735
   197
	return false;
faluco@1735
   198
}
faluco@1735
   199
faluco@1735
   200
void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, 
faluco@1735
   201
									soundlevel_t soundlevel, int fFlags, int pitch, float delay)
faluco@1735
   202
{
faluco@1735
   203
	SoundHookIter iter;
faluco@1735
   204
	IPluginFunction *pFunc;
faluco@1735
   205
	cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
faluco@1735
   206
	cell_t res = static_cast<ResultType>(Pl_Continue);
faluco@1735
   207
	char buffer[PLATFORM_MAX_PATH];
faluco@1735
   208
	strcpy(buffer, samp);
faluco@1735
   209
faluco@1735
   210
	for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++)
faluco@1735
   211
	{
faluco@1735
   212
		pFunc = (*iter);
faluco@1735
   213
		pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
faluco@1735
   214
		pFunc->PushCellByRef(&entindex);
faluco@1735
   215
		pFunc->PushFloatByRef(&vol);
faluco@1735
   216
		pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&soundlevel));
faluco@1735
   217
		pFunc->PushCellByRef(&pitch);
faluco@1735
   218
		pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK);
faluco@1735
   219
		pFunc->PushCellByRef(&fFlags);
faluco@1735
   220
		pFunc->PushFloatByRef(&delay);
faluco@1735
   221
		g_InSoundHook = true;
faluco@1735
   222
		pFunc->Execute(&res);
faluco@1735
   223
		g_InSoundHook = false;
faluco@1735
   224
faluco@1735
   225
		switch (res)
faluco@1735
   226
		{
faluco@1735
   227
		case Pl_Handled:
faluco@1735
   228
		case Pl_Stop:
faluco@1735
   229
			{
faluco@1735
   230
				RETURN_META(MRES_SUPERCEDE);
faluco@1735
   231
			}
faluco@1735
   232
		case Pl_Changed:
faluco@1735
   233
			{
faluco@1735
   234
				Vector vec2;
faluco@1735
   235
				vec2.x = sp_ctof(vec[0]);
faluco@1735
   236
				vec2.y = sp_ctof(vec[1]);
faluco@1735
   237
				vec2.z = sp_ctof(vec[2]);
faluco@1735
   238
				RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, 
faluco@1735
   239
										(entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay));
faluco@1735
   240
			}
faluco@1735
   241
		}
faluco@1735
   242
	}
faluco@1735
   243
}
faluco@1735
   244
faluco@1735
   245
void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, 
faluco@1735
   246
							 float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, 
faluco@1735
   247
							 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions, 
faluco@1735
   248
							 float soundtime, int speakerentity)
faluco@1735
   249
{
faluco@1735
   250
	SoundHookIter iter;
faluco@1735
   251
	IPluginFunction *pFunc;
faluco@1735
   252
	cell_t res = static_cast<ResultType>(Pl_Continue);
faluco@1735
   253
	char buffer[PLATFORM_MAX_PATH];
faluco@1735
   254
	strcpy(buffer, pSample);
faluco@1735
   255
faluco@1735
   256
	for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
faluco@1735
   257
	{
faluco@1735
   258
		int players[64], size;
faluco@1735
   259
		size = _FillInPlayers(players, &filter);
faluco@1735
   260
		pFunc = (*iter);
faluco@1735
   261
faluco@1735
   262
		pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
faluco@1735
   263
		pFunc->PushCellByRef(&size);
faluco@1735
   264
		pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
faluco@1735
   265
		pFunc->PushCellByRef(&iEntIndex);
faluco@1735
   266
		pFunc->PushCellByRef(&iChannel);
faluco@1735
   267
		pFunc->PushFloatByRef(&flVolume);
faluco@1735
   268
		pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&iSoundlevel));
faluco@1735
   269
		pFunc->PushCellByRef(&iPitch);
faluco@1735
   270
		pFunc->PushCellByRef(&iFlags);
faluco@1735
   271
		g_InSoundHook = true;
faluco@1735
   272
		pFunc->Execute(&res);
faluco@1735
   273
		g_InSoundHook = false;
faluco@1735
   274
faluco@1735
   275
		switch (res)
faluco@1735
   276
		{
faluco@1735
   277
		case Pl_Handled:
faluco@1735
   278
		case Pl_Stop:
faluco@1735
   279
			{
faluco@1735
   280
				RETURN_META(MRES_SUPERCEDE);
faluco@1735
   281
			}
faluco@1735
   282
		case Pl_Changed:
faluco@1735
   283
			{
faluco@1735
   284
				CellRecipientFilter crf;
faluco@1735
   285
				crf.Initialize(players, size);
faluco@1735
   286
				RETURN_META_NEWPARAMS(
faluco@1735
   287
					MRES_IGNORED,
faluco@1735
   288
					static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, soundlevel_t, 
faluco@1735
   289
					int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), 
faluco@1735
   290
					(crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin, 
faluco@1735
   291
					pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
faluco@1735
   292
					);
faluco@1735
   293
			}
faluco@1735
   294
		}
faluco@1735
   295
	}
faluco@1735
   296
}
faluco@1735
   297
faluco@1735
   298
void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, 
faluco@1735
   299
							 float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, 
faluco@1735
   300
							 const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions, 
faluco@1735
   301
							 float soundtime, int speakerentity)
faluco@1735
   302
{
faluco@1735
   303
	SoundHookIter iter;
faluco@1735
   304
	IPluginFunction *pFunc;
faluco@1735
   305
	cell_t res = static_cast<ResultType>(Pl_Continue);
faluco@1735
   306
	cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation));
faluco@1735
   307
	char buffer[PLATFORM_MAX_PATH];
faluco@1735
   308
	strcpy(buffer, pSample);
faluco@1735
   309
faluco@1735
   310
	for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++)
faluco@1735
   311
	{
faluco@1735
   312
		int players[64], size;
faluco@1735
   313
		size = _FillInPlayers(players, &filter);
faluco@1735
   314
		pFunc = (*iter);
faluco@1735
   315
faluco@1735
   316
		pFunc->PushArray(players, 64, SM_PARAM_COPYBACK);
faluco@1735
   317
		pFunc->PushCellByRef(&size);
faluco@1735
   318
		pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
faluco@1735
   319
		pFunc->PushCellByRef(&iEntIndex);
faluco@1735
   320
		pFunc->PushCellByRef(&iChannel);
faluco@1735
   321
		pFunc->PushFloatByRef(&flVolume);
faluco@1735
   322
		pFunc->PushCellByRef(&sndlevel);
faluco@1735
   323
		pFunc->PushCellByRef(&iPitch);
faluco@1735
   324
		pFunc->PushCellByRef(&iFlags);
faluco@1735
   325
		g_InSoundHook = true;
faluco@1735
   326
		pFunc->Execute(&res);
faluco@1735
   327
		g_InSoundHook = false;
faluco@1735
   328
faluco@1735
   329
		switch (res)
faluco@1735
   330
		{
faluco@1735
   331
		case Pl_Handled:
faluco@1735
   332
		case Pl_Stop:
faluco@1735
   333
			{
faluco@1735
   334
				RETURN_META(MRES_SUPERCEDE);
faluco@1735
   335
			}
faluco@1735
   336
		case Pl_Changed:
faluco@1735
   337
			{
faluco@1735
   338
				CellRecipientFilter crf;
faluco@1735
   339
				crf.Initialize(players, size);
faluco@1735
   340
				RETURN_META_NEWPARAMS(
faluco@1735
   341
					MRES_IGNORED,
faluco@1735
   342
					static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, float, 
faluco@1735
   343
					int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), 
faluco@1735
   344
					(crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), 
faluco@1735
   345
					iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity)
faluco@1735
   346
					);
faluco@1735
   347
			}
faluco@1735
   348
		}
faluco@1735
   349
	}
faluco@1735
   350
}
faluco@1735
   351
faluco@1735
   352
/************************
faluco@1735
   353
*                       *
faluco@1735
   354
* Sound Related Natives *
faluco@1735
   355
*                       *
faluco@1735
   356
*************************/
faluco@1735
   357
faluco@1735
   358
SoundHooks s_SoundHooks;
dvander@1047
   359
dvander@1047
   360
static cell_t PrefetchSound(IPluginContext *pContext, const cell_t *params)
dvander@1047
   361
{
dvander@1047
   362
	char *name;
dvander@1047
   363
	pContext->LocalToString(params[1], &name);
dvander@1047
   364
dvander@1047
   365
	engsound->PrefetchSound(name);
dvander@1047
   366
dvander@1047
   367
	return 1;
dvander@1047
   368
}
dvander@1047
   369
dvander@1047
   370
static cell_t GetSoundDuration(IPluginContext *pContext, const cell_t *params)
dvander@1047
   371
{
dvander@1047
   372
	char *name;
dvander@1047
   373
	pContext->LocalToString(params[1], &name);
dvander@1047
   374
dvander@1047
   375
	return sp_ftoc(engsound->GetSoundDuration(name));
dvander@1047
   376
}
dvander@1047
   377
dvander@1047
   378
static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params)
dvander@1047
   379
{
dvander@1047
   380
	cell_t entity;
dvander@1047
   381
	Vector pos;
dvander@1047
   382
	char *name;
dvander@1047
   383
	float vol, delay;
dvander@1047
   384
	int pitch, flags, level;
dvander@1047
   385
dvander@1047
   386
	entity = params[3];
dvander@1047
   387
dvander@1047
   388
	cell_t *addr;
dvander@1047
   389
	pContext->LocalToPhysAddr(params[2], &addr);
dvander@1047
   390
	pos.x = sp_ctof(addr[0]);
dvander@1047
   391
	pos.y = sp_ctof(addr[1]);
dvander@1047
   392
	pos.z = sp_ctof(addr[2]);
dvander@1047
   393
dvander@1047
   394
	pContext->LocalToString(params[1], &name);
dvander@1047
   395
dvander@1047
   396
	vol = sp_ctof(params[6]);
dvander@1047
   397
	level = params[4];
dvander@1047
   398
	flags = params[5];
dvander@1047
   399
	pitch = params[7];
dvander@1047
   400
	delay = sp_ctof(params[8]);
dvander@1047
   401
faluco@1735
   402
	if (g_InSoundHook)
faluco@1735
   403
	{
faluco@1735
   404
		ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
faluco@1735
   405
	}
faluco@1735
   406
	else
faluco@1735
   407
	{
faluco@1735
   408
		engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay);
faluco@1735
   409
	}
dvander@1047
   410
dvander@1047
   411
	return 1;
dvander@1047
   412
}
dvander@1047
   413
dvander@1047
   414
static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params)
dvander@1047
   415
{
dvander@1047
   416
	int client = params[1];
dvander@1047
   417
	if (client < 1 || client > playerhelpers->GetMaxClients())
dvander@1047
   418
	{
dvander@1047
   419
		return pContext->ThrowNativeError("Client index %d is not valid", client);
dvander@1047
   420
	}
dvander@1047
   421
dvander@1047
   422
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
dvander@1047
   423
	if (!player->IsInGame())
dvander@1047
   424
	{
dvander@1047
   425
		return pContext->ThrowNativeError("Client index %d is not in game", client);
dvander@1047
   426
	}
dvander@1047
   427
dvander@1047
   428
	engine->FadeClientVolume(player->GetEdict(),
dvander@1047
   429
		sp_ctof(params[2]),
dvander@1047
   430
		sp_ctof(params[3]),
dvander@1047
   431
		sp_ctof(params[4]),
dvander@1047
   432
		sp_ctof(params[5]));
dvander@1047
   433
dvander@1047
   434
	return 1;
dvander@1047
   435
}
dvander@1047
   436
dvander@1047
   437
static cell_t StopSound(IPluginContext *pContext, const cell_t *params)
dvander@1047
   438
{
dvander@1047
   439
	int entity = params[1];
dvander@1047
   440
	int channel = params[2];
dvander@1047
   441
dvander@1047
   442
	char *name;
dvander@1047
   443
	pContext->LocalToString(params[3], &name);
dvander@1047
   444
dvander@1047
   445
	engsound->StopSound(entity, channel, name);
dvander@1047
   446
dvander@1047
   447
	return 1;
dvander@1047
   448
}
dvander@1047
   449
dvander@1047
   450
static cell_t EmitSound(IPluginContext *pContext, const cell_t *params)
dvander@1047
   451
{
ds@2112
   452
	cell_t *addr, *cl_array;
dvander@1047
   453
	CellRecipientFilter crf;
ds@2112
   454
	unsigned int numClients;
ds@2112
   455
	int client;
ds@2112
   456
	IGamePlayer *pPlayer = NULL;
ds@2112
   457
ds@2112
   458
	pContext->LocalToPhysAddr(params[1], &cl_array);
ds@2112
   459
	numClients = params[2];
ds@2112
   460
ds@2112
   461
	/* Client validation */
ds@2112
   462
	for (unsigned int i = 0; i < numClients; i++)
ds@2112
   463
	{
ds@2112
   464
		client = cl_array[i];
ds@2112
   465
		pPlayer = playerhelpers->GetGamePlayer(client);
ds@2112
   466
ds@2112
   467
		if (!pPlayer)
ds@2112
   468
		{
ds@2112
   469
			return pContext->ThrowNativeError("Client index %d is invalid", client);
ds@2112
   470
		} else if (!pPlayer->IsInGame()) {
ds@2112
   471
			return pContext->ThrowNativeError("Client %d is not connected", client);
ds@2112
   472
		}
ds@2112
   473
	}
ds@2112
   474
ds@2112
   475
	crf.Initialize(cl_array, numClients);
dvander@1047
   476
dvander@1047
   477
	char *sample;
dvander@1047
   478
	pContext->LocalToString(params[3], &sample);
dvander@1047
   479
	
dvander@1047
   480
	int entity = params[4];
dvander@1047
   481
	int channel = params[5];
dvander@1047
   482
	int level = params[6];
dvander@1047
   483
	int flags = params[7];
dvander@1047
   484
	float vol = sp_ctof(params[8]);
dvander@1047
   485
	int pitch = params[9];
dvander@1047
   486
	int speakerentity = params[10];
dvander@1047
   487
dvander@1047
   488
	Vector *pOrigin = NULL, origin;
dvander@1047
   489
	Vector *pDir = NULL, dir;
dvander@1047
   490
dvander@1047
   491
	pContext->LocalToPhysAddr(params[11], &addr);
dvander@1047
   492
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
dvander@1047
   493
	{
dvander@1047
   494
		pOrigin = &origin;
dvander@1047
   495
		origin.x = sp_ctof(addr[0]);
dvander@1047
   496
		origin.y = sp_ctof(addr[1]);
dvander@1047
   497
		origin.z = sp_ctof(addr[2]);
dvander@1047
   498
	}
dvander@1047
   499
dvander@1047
   500
	pContext->LocalToPhysAddr(params[12], &addr);
dvander@1047
   501
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
dvander@1047
   502
	{
dvander@1047
   503
		pDir = &dir;
dvander@1047
   504
		dir.x = sp_ctof(addr[0]);
dvander@1047
   505
		dir.y = sp_ctof(addr[1]);
dvander@1047
   506
		dir.z = sp_ctof(addr[2]);
dvander@1047
   507
	}
dvander@1047
   508
dvander@1047
   509
	bool updatePos = params[13] ? true : false;
dvander@1047
   510
	float soundtime = sp_ctof(params[14]);
dvander@1047
   511
dvander@1047
   512
	CUtlVector<Vector> *pOrigVec = NULL;
dvander@1047
   513
	CUtlVector<Vector> origvec;
dvander@1047
   514
	if (params[0] > 14)
dvander@1047
   515
	{
dvander@1047
   516
		pOrigVec = &origvec;
dvander@1047
   517
		for (cell_t i = 15; i <= params[0]; i++)
dvander@1047
   518
		{
dvander@1047
   519
			Vector vec;
dvander@1047
   520
			pContext->LocalToPhysAddr(params[i], &addr);
dvander@1047
   521
			vec.x = sp_ctof(addr[0]);
dvander@1047
   522
			vec.y = sp_ctof(addr[1]);
dvander@1047
   523
			vec.z = sp_ctof(addr[2]);
dvander@1047
   524
			origvec.AddToTail(vec);
dvander@1047
   525
		}
dvander@1047
   526
	}
dvander@1047
   527
dvander@1047
   528
	/* If we're going to a "local player" and this is a dedicated server,
dvander@1047
   529
	 * intelligently redirect each sound.
dvander@1047
   530
	 */
dvander@1047
   531
dvander@1048
   532
	if (entity == -2 && engine->IsDedicatedServer())
dvander@1047
   533
	{
ds@2112
   534
		for (unsigned int i = 0; i < numClients; i++)
dvander@1047
   535
		{
dvander@1047
   536
			cell_t player[1];
ds@2112
   537
			player[0] = cl_array[i];
dvander@1047
   538
			crf.Reset();
dvander@1047
   539
			crf.Initialize(player, 1);
faluco@1735
   540
			if (g_InSoundHook)
faluco@1735
   541
			{
faluco@1735
   542
				SH_CALL(enginesoundPatch, 
faluco@1735
   543
					static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, 
faluco@1735
   544
					soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
faluco@1735
   545
					(&IEngineSound::EmitSound))
faluco@1735
   546
					(crf, 
faluco@1735
   547
					player[0], 
faluco@1735
   548
					channel, 
faluco@1735
   549
					sample, 
faluco@1735
   550
					vol, 
faluco@1735
   551
					(soundlevel_t)level, 
faluco@1735
   552
					flags, 
faluco@1735
   553
					pitch, 
faluco@1735
   554
					pOrigin,
faluco@1735
   555
					pDir,
faluco@1735
   556
					pOrigVec,
faluco@1735
   557
					updatePos,
faluco@1735
   558
					soundtime,
faluco@1735
   559
					speakerentity);
faluco@1735
   560
			}
faluco@1735
   561
			else
faluco@1735
   562
			{
faluco@1735
   563
				engsound->EmitSound(crf, 
faluco@1735
   564
					player[0], 
faluco@1735
   565
					channel, 
faluco@1735
   566
					sample, 
faluco@1735
   567
					vol, 
faluco@1735
   568
					(soundlevel_t)level, 
faluco@1735
   569
					flags, 
faluco@1735
   570
					pitch, 
faluco@1735
   571
					pOrigin,
faluco@1735
   572
					pDir,
faluco@1735
   573
					pOrigVec,
faluco@1735
   574
					updatePos,
faluco@1735
   575
					soundtime,
faluco@1735
   576
					speakerentity);
faluco@1735
   577
			}
faluco@1735
   578
		}
faluco@1735
   579
	} else {
faluco@1735
   580
		if (g_InSoundHook)
faluco@1735
   581
		{
faluco@1735
   582
			SH_CALL(enginesoundPatch, 
faluco@1735
   583
				static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char*, float, 
faluco@1735
   584
				soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>
faluco@1735
   585
				(&IEngineSound::EmitSound))
faluco@1735
   586
				(crf, 
faluco@1735
   587
				entity, 
dvander@1047
   588
				channel, 
dvander@1047
   589
				sample, 
dvander@1047
   590
				vol, 
dvander@1047
   591
				(soundlevel_t)level, 
dvander@1047
   592
				flags, 
dvander@1047
   593
				pitch, 
dvander@1047
   594
				pOrigin,
dvander@1047
   595
				pDir,
dvander@1047
   596
				pOrigVec,
dvander@1047
   597
				updatePos,
dvander@1047
   598
				soundtime,
dvander@1047
   599
				speakerentity);
dvander@1047
   600
		}
faluco@1735
   601
		else
faluco@1735
   602
		{
faluco@1735
   603
			engsound->EmitSound(crf, 
faluco@1735
   604
				entity, 
faluco@1735
   605
				channel, 
faluco@1735
   606
				sample, 
faluco@1735
   607
				vol, 
faluco@1735
   608
				(soundlevel_t)level, 
faluco@1735
   609
				flags, 
faluco@1735
   610
				pitch, 
faluco@1735
   611
				pOrigin,
faluco@1735
   612
				pDir,
faluco@1735
   613
				pOrigVec,
faluco@1735
   614
				updatePos,
faluco@1735
   615
				soundtime,
faluco@1735
   616
				speakerentity);
faluco@1735
   617
		}
dvander@1047
   618
	}
dvander@1047
   619
dvander@1047
   620
	return 1;
dvander@1047
   621
}
dvander@1047
   622
dvander@1047
   623
static cell_t EmitSentence(IPluginContext *pContext, const cell_t *params)
dvander@1047
   624
{
dvander@1047
   625
	cell_t *addr;
ds@2112
   626
	CellRecipientFilter crf;
ds@2112
   627
	unsigned int numClients;
ds@2112
   628
	int client;
ds@2112
   629
	IGamePlayer *pPlayer = NULL;
dvander@1047
   630
dvander@1047
   631
	pContext->LocalToPhysAddr(params[1], &addr);
ds@2112
   632
	numClients = params[2];
ds@2112
   633
ds@2112
   634
	/* Client validation */
ds@2112
   635
	for (unsigned int i = 0; i < numClients; i++)
ds@2112
   636
	{
ds@2112
   637
		client = addr[i];
ds@2112
   638
		pPlayer = playerhelpers->GetGamePlayer(client);
ds@2112
   639
ds@2112
   640
		if (!pPlayer)
ds@2112
   641
		{
ds@2112
   642
			return pContext->ThrowNativeError("Client index %d is invalid", client);
ds@2112
   643
		} else if (!pPlayer->IsInGame()) {
ds@2112
   644
			return pContext->ThrowNativeError("Client %d is not connected", client);
ds@2112
   645
		}
ds@2112
   646
	}
ds@2112
   647
ds@2112
   648
	crf.Initialize(addr, numClients);
dvander@1047
   649
dvander@1047
   650
	int sentence = params[3];
dvander@1047
   651
	int entity = params[4];
dvander@1047
   652
	int channel = params[5];
dvander@1047
   653
	int level = params[6];
dvander@1047
   654
	int flags = params[7];
dvander@1047
   655
	float vol = sp_ctof(params[8]);
dvander@1047
   656
	int pitch = params[9];
dvander@1047
   657
	int speakerentity = params[10];
dvander@1047
   658
dvander@1047
   659
	Vector *pOrigin = NULL, origin;
dvander@1047
   660
	Vector *pDir = NULL, dir;
dvander@1047
   661
dvander@1047
   662
	pContext->LocalToPhysAddr(params[11], &addr);
dvander@1047
   663
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
dvander@1047
   664
	{
dvander@1047
   665
		pOrigin = &origin;
dvander@1047
   666
		origin.x = sp_ctof(addr[0]);
dvander@1047
   667
		origin.y = sp_ctof(addr[1]);
dvander@1047
   668
		origin.z = sp_ctof(addr[2]);
dvander@1047
   669
	}
dvander@1047
   670
dvander@1047
   671
	pContext->LocalToPhysAddr(params[12], &addr);
dvander@1047
   672
	if (addr != pContext->GetNullRef(SP_NULL_VECTOR))
dvander@1047
   673
	{
dvander@1047
   674
		pDir = &dir;
dvander@1047
   675
		dir.x = sp_ctof(addr[0]);
dvander@1047
   676
		dir.y = sp_ctof(addr[1]);
dvander@1047
   677
		dir.z = sp_ctof(addr[2]);
dvander@1047
   678
	}
dvander@1047
   679
dvander@1047
   680
	bool updatePos = params[13] ? true : false;
dvander@1047
   681
	float soundtime = sp_ctof(params[14]);
dvander@1047
   682
dvander@1047
   683
	CUtlVector<Vector> *pOrigVec = NULL;
dvander@1047
   684
	CUtlVector<Vector> origvec;
dvander@1047
   685
	if (params[0] > 14)
dvander@1047
   686
	{
dvander@1047
   687
		pOrigVec = &origvec;
dvander@1047
   688
		for (cell_t i = 15; i <= params[0]; i++)
dvander@1047
   689
		{
dvander@1047
   690
			Vector vec;
dvander@1047
   691
			pContext->LocalToPhysAddr(params[i], &addr);
dvander@1047
   692
			vec.x = sp_ctof(addr[0]);
dvander@1047
   693
			vec.y = sp_ctof(addr[1]);
dvander@1047
   694
			vec.z = sp_ctof(addr[2]);
dvander@1047
   695
			origvec.AddToTail(vec);
dvander@1047
   696
		}
dvander@1047
   697
	}
dvander@1047
   698
dvander@1047
   699
	engsound->EmitSentenceByIndex(crf, 
dvander@1047
   700
		entity, 
dvander@1047
   701
		channel, 
dvander@1047
   702
		sentence, 
dvander@1047
   703
		vol, 
dvander@1047
   704
		(soundlevel_t)level, 
dvander@1047
   705
		flags, 
dvander@1047
   706
		pitch, 
dvander@1047
   707
		pOrigin,
dvander@1047
   708
		pDir,
dvander@1047
   709
		pOrigVec,
dvander@1047
   710
		updatePos,
dvander@1047
   711
		soundtime,
dvander@1047
   712
		speakerentity);
dvander@1047
   713
dvander@1047
   714
	return 1;
dvander@1047
   715
}
dvander@1047
   716
faluco@1735
   717
static cell_t smn_AddAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
faluco@1735
   718
{
faluco@1735
   719
	IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
faluco@1735
   720
	if (!pFunc)
faluco@1735
   721
	{
faluco@1735
   722
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
faluco@1735
   723
	}
faluco@1735
   724
faluco@1735
   725
	s_SoundHooks.AddHook(AMBIENT_SOUND_HOOK, pFunc);
faluco@1735
   726
faluco@1735
   727
	return 1;
faluco@1735
   728
}
faluco@1735
   729
faluco@1735
   730
static cell_t smn_AddNormalSoundHook(IPluginContext *pContext, const cell_t *params)
faluco@1735
   731
{
faluco@1735
   732
	IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
faluco@1735
   733
	if (!pFunc)
faluco@1735
   734
	{
faluco@1735
   735
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
faluco@1735
   736
	}
faluco@1735
   737
faluco@1735
   738
	s_SoundHooks.AddHook(NORMAL_SOUND_HOOK, pFunc);
faluco@1735
   739
faluco@1735
   740
	return 1;
faluco@1735
   741
}
faluco@1735
   742
faluco@1735
   743
static cell_t smn_RemoveAmbientSoundHook(IPluginContext *pContext, const cell_t *params)
faluco@1735
   744
{
faluco@1735
   745
	IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
faluco@1735
   746
	if (!pFunc)
faluco@1735
   747
	{
faluco@1735
   748
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
faluco@1735
   749
	}
faluco@1735
   750
faluco@1735
   751
	if (!s_SoundHooks.RemoveHook(AMBIENT_SOUND_HOOK, pFunc))
faluco@1735
   752
	{
faluco@1735
   753
		return pContext->ThrowNativeError("Invalid hooked function");
faluco@1735
   754
	}
faluco@1735
   755
faluco@1735
   756
	return 1;
faluco@1735
   757
}
faluco@1735
   758
faluco@1735
   759
static cell_t smn_RemoveNormalSoundHook(IPluginContext *pContext, const cell_t *params)
faluco@1735
   760
{
faluco@1735
   761
	IPluginFunction *pFunc = pContext->GetFunctionById(params[1]);
faluco@1735
   762
	if (!pFunc)
faluco@1735
   763
	{
faluco@1735
   764
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
faluco@1735
   765
	}
faluco@1735
   766
faluco@1735
   767
	if (!s_SoundHooks.RemoveHook(NORMAL_SOUND_HOOK, pFunc))
faluco@1735
   768
	{
faluco@1735
   769
		return pContext->ThrowNativeError("Invalid hooked function");
faluco@1735
   770
	}
faluco@1735
   771
faluco@1735
   772
	return 1;
faluco@1735
   773
}
faluco@1735
   774
dvander@1047
   775
sp_nativeinfo_t g_SoundNatives[] = 
dvander@1047
   776
{
faluco@1735
   777
	{"EmitAmbientSound",		EmitAmbientSound},
faluco@1735
   778
	{"EmitSentence",			EmitSentence},
faluco@1735
   779
	{"EmitSound",				EmitSound},
faluco@1735
   780
	{"FadeClientVolume",		FadeClientVolume},
faluco@1735
   781
	{"GetSoundDuration",		GetSoundDuration},
faluco@1735
   782
	{"PrefetchSound",			PrefetchSound},
faluco@1735
   783
	{"StopSound",				StopSound},
faluco@1735
   784
	{"AddAmbientSoundHook",		smn_AddAmbientSoundHook},
faluco@1735
   785
	{"AddNormalSoundHook",		smn_AddNormalSoundHook},
faluco@1735
   786
	{"RemoveAmbientSoundHook",	smn_RemoveAmbientSoundHook},
faluco@1735
   787
	{"RemoveNormalSoundHook",	smn_RemoveNormalSoundHook},
faluco@1735
   788
	{NULL,						NULL},
dvander@1047
   789
};