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