Merge pull request #65 from powerlord/master
New functions for SDKTools to get information from game_sound files (r=psychonic).
This commit is contained in:
commit
ffa1887c48
@ -66,6 +66,7 @@ IPlayerInfoManager *playerinfomngr = NULL;
|
||||
ICvar *icvar = NULL;
|
||||
IServer *iserver = NULL;
|
||||
CGlobalVars *gpGlobals;
|
||||
ISoundEmitterSystemBase *soundemitterbase = NULL;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
IServerTools *servertools = NULL;
|
||||
@ -258,6 +259,7 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
GET_V_IFACE_ANY(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION);
|
||||
#endif
|
||||
GET_V_IFACE_ANY(GetEngineFactory, soundemitterbase, ISoundEmitterSystemBase, SOUNDEMITTERSYSTEM_INTERFACE_VERSION);
|
||||
|
||||
gpGlobals = ismm->GetCGlobals();
|
||||
enginePatch = SH_GET_CALLCLASS(engine);
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include <convar.h>
|
||||
#include <iserver.h>
|
||||
#include <cdll_int.h>
|
||||
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
#include <itoolentity.h>
|
||||
@ -124,6 +125,7 @@ extern CGlobalVars *gpGlobals;
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
extern IServerTools *servertools;
|
||||
#endif
|
||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||
/* Interfaces from SourceMod */
|
||||
extern IBinTools *g_pBinTools;
|
||||
extern IGameConfig *g_pGameConf;
|
||||
|
@ -512,6 +512,74 @@ RETURN_META_NEWPARAMS(
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetSoundParams(CSoundParameters *soundParams, const char *soundname, cell_t entindex)
|
||||
{
|
||||
if ( !soundname[0] )
|
||||
return false;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||
HSOUNDSCRIPTHASH index = (HSOUNDSCRIPTHASH)soundemitterbase->GetSoundIndex(soundname);
|
||||
#else
|
||||
HSOUNDSCRIPTHANDLE index = (HSOUNDSCRIPTHANDLE)soundemitterbase->GetSoundIndex(soundname);
|
||||
#endif
|
||||
if (!soundemitterbase->IsValidIndex(index))
|
||||
return false;
|
||||
|
||||
gender_t gender = GENDER_NONE;
|
||||
|
||||
// I don't know if gender applies to any mutliplayer games, but just in case...
|
||||
// Of course, if it's SOUND_FROM_PLAYER, we have no idea which gender it is
|
||||
int ent = SoundReferenceToIndex(entindex);
|
||||
if (ent > 0)
|
||||
{
|
||||
edict_t *edict = gamehelpers->EdictOfIndex(ent);
|
||||
if (edict != NULL && !edict->IsFree())
|
||||
{
|
||||
IServerEntity *serverEnt = edict->GetIServerEntity();
|
||||
if (serverEnt != NULL)
|
||||
{
|
||||
const char *actormodel = STRING(serverEnt->GetModelName());
|
||||
gender = soundemitterbase->GetActorGender(actormodel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return soundemitterbase->GetParametersForSoundEx(soundname, index, *soundParams, gender);
|
||||
}
|
||||
|
||||
bool InternalPrecacheScriptSound(const char *soundname)
|
||||
{
|
||||
int soundIndex = soundemitterbase->GetSoundIndex(soundname);
|
||||
if (!soundemitterbase->IsValidIndex(soundIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CSoundParametersInternal *internal = soundemitterbase->InternalGetParametersForSound(soundIndex);
|
||||
|
||||
if (!internal)
|
||||
return false;
|
||||
|
||||
int waveCount = internal->NumSoundNames();
|
||||
|
||||
if (!waveCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int wave = 0; wave < waveCount; wave++)
|
||||
{
|
||||
const char* waveName = soundemitterbase->GetWaveName(internal->GetSoundNames()[wave].symbol);
|
||||
// return true even if we precache no new wavs
|
||||
if (!engsound->IsSoundPrecached(waveName))
|
||||
{
|
||||
engsound->PrecacheSound(waveName);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/************************
|
||||
* *
|
||||
* Sound Related Natives *
|
||||
@ -1135,6 +1203,51 @@ static cell_t smn_GetDistGainFromSoundLevel(IPluginContext *pContext, const cell
|
||||
return sp_ftoc(engsound->GetDistGainFromSoundLevel((soundlevel_t)decibel, distance));
|
||||
}
|
||||
|
||||
// native bool:GetGameSoundParams(const String:gameSound[], &channel, &soundLevel, &Float:volume, &pitch, String:sample[], maxlength, entity=SOUND_FROM_WORLD)
|
||||
static cell_t smn_GetGameSoundParams(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *soundname;
|
||||
pContext->LocalToString(params[1], &soundname);
|
||||
|
||||
CSoundParameters soundParams;
|
||||
|
||||
if (!GetSoundParams(&soundParams, soundname, params[8]))
|
||||
return false;
|
||||
|
||||
cell_t *channel;
|
||||
cell_t *fakeVolume;
|
||||
cell_t *pitch;
|
||||
cell_t *soundLevel;
|
||||
|
||||
pContext->LocalToPhysAddr(params[2], &channel);
|
||||
pContext->LocalToPhysAddr(params[3], &soundLevel);
|
||||
pContext->LocalToPhysAddr(params[4], &fakeVolume);
|
||||
pContext->LocalToPhysAddr(params[5], &pitch);
|
||||
|
||||
*channel = soundParams.channel;
|
||||
*pitch = soundParams.pitch;
|
||||
*soundLevel = (cell_t)soundParams.soundlevel;
|
||||
*fakeVolume = sp_ftoc(soundParams.volume);
|
||||
|
||||
pContext->StringToLocal(params[6], params[7], soundParams.soundname);
|
||||
|
||||
// Precache the sound we're returning
|
||||
if (!engsound->IsSoundPrecached(soundParams.soundname))
|
||||
{
|
||||
InternalPrecacheScriptSound(soundname);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// native bool:PrecacheScriptSound(const String:soundname[])
|
||||
static cell_t smn_PrecacheScriptSound(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *soundname;
|
||||
pContext->LocalToString(params[1], &soundname);
|
||||
return InternalPrecacheScriptSound(soundname);
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_SoundNatives[] =
|
||||
{
|
||||
{"EmitAmbientSound", EmitAmbientSound},
|
||||
@ -1149,5 +1262,7 @@ sp_nativeinfo_t g_SoundNatives[] =
|
||||
{"RemoveAmbientSoundHook", smn_RemoveAmbientSoundHook},
|
||||
{"RemoveNormalSoundHook", smn_RemoveNormalSoundHook},
|
||||
{"GetDistGainFromSoundLevel", smn_GetDistGainFromSoundLevel},
|
||||
{"GetGameSoundParams", smn_GetGameSoundParams},
|
||||
{"PrecacheScriptSound", smn_PrecacheScriptSound},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
@ -448,3 +448,229 @@ stock ATTN_TO_SNDLEVEL(Float:attn)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameters for a game sound.
|
||||
*
|
||||
* Game sounds are found in a game's scripts/game_sound.txt or other files
|
||||
* referenced from it
|
||||
*
|
||||
* Note that if a game sound has a rndwave section, one of them will be returned
|
||||
* at random.
|
||||
*
|
||||
* @param gameSound Name of game sound.
|
||||
* @param channel Channel to emit with.
|
||||
* @param level Sound level.
|
||||
* @param volume Sound volume.
|
||||
* @param pitch Sound pitch.
|
||||
* @param sample Sound file name relative to the "sounds" folder.
|
||||
* @param maxlength Maximum length of sample string buffer.
|
||||
* @param entity Entity the sound is being emitted from.
|
||||
* @return True if the sound was successfully retrieved, false if it
|
||||
* was not found
|
||||
*/
|
||||
native bool:GetGameSoundParams(const String:gameSound[],
|
||||
&channel,
|
||||
&soundLevel,
|
||||
&Float:volume,
|
||||
&pitch,
|
||||
String:sample[],
|
||||
maxlength,
|
||||
entity=SOUND_FROM_PLAYER);
|
||||
|
||||
/**
|
||||
* Emits a game sound to a list of clients.
|
||||
*
|
||||
* Game sounds are found in a game's scripts/game_sound.txt or other files
|
||||
* referenced from it
|
||||
*
|
||||
* Note that if a game sound has a rndwave section, one of them will be returned
|
||||
* at random.
|
||||
*
|
||||
* @param clients Array of client indexes.
|
||||
* @param numClients Number of clients in the array.
|
||||
* @param gameSound Name of game sound.
|
||||
* @param entity Entity to emit from.
|
||||
* @param flags Sound flags.
|
||||
* @param speakerentity Unknown.
|
||||
* @param origin Sound origin.
|
||||
* @param dir Sound direction.
|
||||
* @param updatePos Unknown (updates positions?)
|
||||
* @param soundtime Alternate time to play sound for.
|
||||
* @return True if the sound was played successfully, false if it failed
|
||||
* @error Invalid client index.
|
||||
*/
|
||||
stock bool:EmitGameSound(const clients[],
|
||||
numClients,
|
||||
const String:gameSound[],
|
||||
entity = SOUND_FROM_PLAYER,
|
||||
flags = SND_NOFLAGS,
|
||||
speakerentity = -1,
|
||||
const Float:origin[3] = NULL_VECTOR,
|
||||
const Float:dir[3] = NULL_VECTOR,
|
||||
bool:updatePos = true,
|
||||
Float:soundtime = 0.0)
|
||||
{
|
||||
new channel;
|
||||
new level;
|
||||
new Float:volume;
|
||||
new pitch;
|
||||
new String:sample[PLATFORM_MAX_PATH];
|
||||
|
||||
if (GetGameSoundParams(gameSound, channel, level, volume, pitch, sample, sizeof(sample), entity))
|
||||
{
|
||||
EmitSound(clients, numClients, sample, entity, channel, level, flags, volume, pitch, speakerentity, origin, dir, updatePos, soundtime);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an ambient game sound.
|
||||
*
|
||||
* Game sounds are found in a game's scripts/game_sound.txt or other files
|
||||
* referenced from it
|
||||
*
|
||||
* Note that if a game sound has a rndwave section, one of them will be returned
|
||||
* at random.
|
||||
*
|
||||
* @param gameSound Name of game sound.
|
||||
* @param pos Origin of sound.
|
||||
* @param entity Entity index to associate sound with.
|
||||
* @param flags Sound flags.
|
||||
* @param delay Play delay.
|
||||
* @noreturn
|
||||
*/
|
||||
stock bool:EmitAmbientGameSound(const String:gameSound[],
|
||||
const Float:pos[3],
|
||||
entity = SOUND_FROM_WORLD,
|
||||
flags = SND_NOFLAGS,
|
||||
Float:delay = 0.0)
|
||||
{
|
||||
new channel; // This is never actually used for Ambients, but it's a mandatory field to GetGameSoundParams
|
||||
new level;
|
||||
new Float:volume;
|
||||
new pitch;
|
||||
new String:sample[PLATFORM_MAX_PATH];
|
||||
|
||||
if (GetGameSoundParams(gameSound, channel, level, volume, pitch, sample, sizeof(sample), entity))
|
||||
{
|
||||
EmitAmbientSound(sample, pos, entity, level, flags, volume, pitch, delay);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to emit a game sound to one client.
|
||||
*
|
||||
* Game sounds are found in a game's scripts/game_sound.txt or other files
|
||||
* referenced from it
|
||||
*
|
||||
* Note that if a game sound has a rndwave section, one of them will be returned
|
||||
* at random.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param gameSound Name of game sound.
|
||||
* @param entity Entity to emit from.
|
||||
* @param flags Sound flags.
|
||||
* @param speakerentity Unknown.
|
||||
* @param origin Sound origin.
|
||||
* @param dir Sound direction.
|
||||
* @param updatePos Unknown (updates positions?)
|
||||
* @param soundtime Alternate time to play sound for.
|
||||
* @noreturn
|
||||
* @error Invalid client index.
|
||||
*/
|
||||
stock bool:EmitGameSoundToClient(client,
|
||||
const String:gameSound[],
|
||||
entity = SOUND_FROM_PLAYER,
|
||||
flags = SND_NOFLAGS,
|
||||
speakerentity = -1,
|
||||
const Float:origin[3] = NULL_VECTOR,
|
||||
const Float:dir[3] = NULL_VECTOR,
|
||||
bool:updatePos = true,
|
||||
Float:soundtime = 0.0)
|
||||
{
|
||||
new clients[1];
|
||||
clients[0] = client;
|
||||
/* Save some work for SDKTools and remove SOUND_FROM_PLAYER references */
|
||||
entity = (entity == SOUND_FROM_PLAYER) ? client : entity;
|
||||
return EmitGameSound(clients, 1, gameSound, entity, flags,
|
||||
speakerentity, origin, dir, updatePos, soundtime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to emit game sound to all clients.
|
||||
*
|
||||
* Game sounds are found in a game's scripts/game_sound.txt or other files
|
||||
* referenced from it
|
||||
*
|
||||
* Note that if a game sound has a rndwave section, one of them will be returned
|
||||
* at random.
|
||||
*
|
||||
* @param gameSound Name of game sound.
|
||||
* @param entity Entity to emit from.
|
||||
* @param flags Sound flags.
|
||||
* @param speakerentity Unknown.
|
||||
* @param origin Sound origin.
|
||||
* @param dir Sound direction.
|
||||
* @param updatePos Unknown (updates positions?)
|
||||
* @param soundtime Alternate time to play sound for.
|
||||
* @noreturn
|
||||
* @error Invalid client index.
|
||||
*/
|
||||
stock bool:EmitGameSoundToAll(const String:gameSound[],
|
||||
entity = SOUND_FROM_PLAYER,
|
||||
flags = SND_NOFLAGS,
|
||||
speakerentity = -1,
|
||||
const Float:origin[3] = NULL_VECTOR,
|
||||
const Float:dir[3] = NULL_VECTOR,
|
||||
bool:updatePos = true,
|
||||
Float:soundtime = 0.0)
|
||||
{
|
||||
new clients[MaxClients];
|
||||
new total = 0;
|
||||
|
||||
for (new i=1; i<=MaxClients; i++)
|
||||
{
|
||||
if (IsClientInGame(i))
|
||||
{
|
||||
clients[total++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!total)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return EmitGameSound(clients, total, gameSound, entity, flags,
|
||||
speakerentity, origin, dir, updatePos, soundtime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Precache a game sound.
|
||||
*
|
||||
* Most games will precache all game sounds on map start, but this is not guaranteed...
|
||||
* Team Fortress 2 is known to not pre-cache MvM game mode sounds on non-MvM maps.
|
||||
*
|
||||
* Due to the above, this native should be called before any calls to GetGameSoundParams,
|
||||
* EmitGameSound*, or EmitAmbientGameSound.
|
||||
*
|
||||
* It should be safe to pass already precached game sounds to this function.
|
||||
*
|
||||
* Note: It precaches all files for a game sound.
|
||||
*
|
||||
* @param soundname Game sound to precache
|
||||
*
|
||||
* @return True if the game sound was found, false if sound did not exist
|
||||
* or had no files
|
||||
*/
|
||||
native bool:PrecacheScriptSound(const String:soundname[]);
|
||||
|
Loading…
Reference in New Issue
Block a user