|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Entities relating to in-level sound effects.
//
// env_speaker: used for public address announcements over loudspeakers.
// This tries not to drown out talking NPCs.
//
// env_soundscape: controls what sound script an area uses.
//
//=============================================================================//
#include "cbase.h"
#include "player.h"
#include "mathlib/mathlib.h"
#include "ai_speech.h"
#include "stringregistry.h"
#include "gamerules.h"
#include "game.h"
#include <ctype.h>
#include "entitylist.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#include "ndebugoverlay.h"
#include "soundscape.h"
#include "igamesystem.h"
#include "keyvalues.h"
#include "filesystem.h"
#include "ambientgeneric.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// =================== ROOM SOUND FX ==========================================
// ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ======================================
int fSentencesInit = false;
// ===================== SENTENCE GROUPS, MAIN ROUTINES ========================
// given sentence group index, play random sentence for given entity.
// returns sentenceIndex - which sentence was picked
// Ipick is only needed if you plan on stopping the sound before playback is done (see SENTENCEG_Stop).
// sentenceIndex can be used to find the name/length of the sentence
int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, float volume, soundlevel_t soundlevel, int flags, int pitch) { char name[64]; int ipick;
if (!fSentencesInit) return -1;
name[0] = 0;
ipick = engine->SentenceGroupPick( isentenceg, name, sizeof( name ) ); if (ipick > 0 && name) { int sentenceIndex = SENTENCEG_Lookup( name ); CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); return sentenceIndex; }
return -1; }
//-----------------------------------------------------------------------------
// Picks a sentence, but doesn't play it
//-----------------------------------------------------------------------------
int SENTENCEG_PickRndSz(const char *szgroupname) { char name[64]; int ipick; int isentenceg;
if (!fSentencesInit) return -1;
name[0] = 0;
isentenceg = engine->SentenceGroupIndexFromName(szgroupname); if (isentenceg < 0) { Warning( "No such sentence group %s\n", szgroupname ); return -1; }
ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name )); if (ipick >= 0 && name[0]) { return SENTENCEG_Lookup( name ); } return -1; }
//-----------------------------------------------------------------------------
// Plays a sentence by sentence index
//-----------------------------------------------------------------------------
void SENTENCEG_PlaySentenceIndex( edict_t *entity, int iSentenceIndex, float volume, soundlevel_t soundlevel, int flags, int pitch ) { if ( iSentenceIndex >= 0 ) { CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, iSentenceIndex, volume, soundlevel, flags, pitch ); } }
int SENTENCEG_PlayRndSz(edict_t *entity, const char *szgroupname, float volume, soundlevel_t soundlevel, int flags, int pitch) { char name[64]; int ipick; int isentenceg;
if (!fSentencesInit) return -1;
name[0] = 0;
isentenceg = engine->SentenceGroupIndexFromName(szgroupname); if (isentenceg < 0) { Warning( "No such sentence group %s\n", szgroupname ); return -1; }
ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name )); if (ipick >= 0 && name[0]) { int sentenceIndex = SENTENCEG_Lookup( name ); CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); return sentenceIndex; }
return -1; }
// play sentences in sequential order from sentence group. Reset after last sentence.
int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szgroupname, float volume, soundlevel_t soundlevel, int flags, int pitch, int ipick, int freset) { char name[64]; int ipicknext; int isentenceg;
if (!fSentencesInit) return -1;
name[0] = 0;
isentenceg = engine->SentenceGroupIndexFromName(szgroupname); if (isentenceg < 0) return -1;
ipicknext = engine->SentenceGroupPickSequential(isentenceg, name, sizeof( name ), ipick, freset); if (ipicknext >= 0 && name[0]) { int sentenceIndex = SENTENCEG_Lookup( name ); CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); return sentenceIndex; } return -1; }
#if 0
// for this entity, for the given sentence within the sentence group, stop
// the sentence.
void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick) { char buffer[64]; char sznum[8]; if (!fSentencesInit) return;
if (isentenceg < 0 || ipick < 0) return;
Q_snprintf(buffer,sizeof(buffer),"!%s%d", engine->SentenceGroupNameFromIndex( isentenceg ), ipick );
UTIL_StopSound(entity, CHAN_VOICE, buffer); } #endif
// open sentences.txt, scan for groups, build rgsentenceg
// Should be called from world spawn, only works on the
// first call and is ignored subsequently.
void SENTENCEG_Init() { if (fSentencesInit) return;
engine->PrecacheSentenceFile( "scripts/sentences.txt" ); fSentencesInit = true; }
// convert sentence (sample) name to !sentencenum, return !sentencenum
int SENTENCEG_Lookup(const char *sample) { return engine->SentenceIndexFromName( sample + 1 ); }
int SENTENCEG_GetIndex(const char *szrootname) { return engine->SentenceGroupIndexFromName( szrootname ); }
void UTIL_RestartAmbientSounds( void ) { CAmbientGeneric *pAmbient = NULL; while ( ( pAmbient = (CAmbientGeneric*) gEntList.FindEntityByClassname( pAmbient, "ambient_generic" ) ) != NULL ) { if (pAmbient->m_fActive ) { if ( strstr( STRING( pAmbient->m_iszSound ), "mp3" ) ) { pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds
} pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds
} } }
// play a specific sentence over the HEV suit speaker - just pass player entity, and !sentencename
void UTIL_EmitSoundSuit(edict_t *entity, const char *sample) { float fvol; int pitch = PITCH_NORM;
fvol = suitvolume.GetFloat(); if (random->RandomInt(0,1)) pitch = random->RandomInt(0,6) + 98;
// If friendlies are talking, reduce the volume of the suit
if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) { fvol *= 0.3; }
if (fvol > 0.05) { CPASAttenuationFilter filter( GetContainingEntity( entity ) ); filter.MakeReliable();
EmitSound_t ep; ep.m_nChannel = CHAN_STATIC; ep.m_pSoundName = sample; ep.m_flVolume = fvol; ep.m_SoundLevel = SNDLVL_NORM; ep.m_nPitch = pitch;
CBaseEntity::EmitSound( filter, ENTINDEX(entity), ep ); } }
// play a sentence, randomly selected from the passed in group id, over the HEV suit speaker
int UTIL_EmitGroupIDSuit(edict_t *entity, int isentenceg) { float fvol; int pitch = PITCH_NORM; int sentenceIndex = -1;
fvol = suitvolume.GetFloat(); if (random->RandomInt(0,1)) pitch = random->RandomInt(0,6) + 98;
// If friendlies are talking, reduce the volume of the suit
if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) { fvol *= 0.3; }
if (fvol > 0.05) sentenceIndex = SENTENCEG_PlayRndI(entity, isentenceg, fvol, SNDLVL_NORM, 0, pitch);
return sentenceIndex; }
// play a sentence, randomly selected from the passed in groupname
int UTIL_EmitGroupnameSuit(edict_t *entity, const char *groupname) { float fvol; int pitch = PITCH_NORM; int sentenceIndex = -1;
fvol = suitvolume.GetFloat(); if (random->RandomInt(0,1)) pitch = random->RandomInt(0,6) + 98;
// If friendlies are talking, reduce the volume of the suit
if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) { fvol *= 0.3; }
if (fvol > 0.05) sentenceIndex = SENTENCEG_PlayRndSz(entity, groupname, fvol, SNDLVL_NORM, 0, pitch);
return sentenceIndex; }
// ===================== MATERIAL TYPE DETECTION, MAIN ROUTINES ========================
//
// Used to detect the texture the player is standing on, map the
// texture name to a material type. Play footstep sound based
// on material type.
char TEXTURETYPE_Find( trace_t *ptr ) { const surfacedata_t *psurfaceData = physprops->GetSurfaceData( ptr->surface.surfaceProps );
return psurfaceData->game.material; }
|