You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
8.2 KiB
264 lines
8.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
// Soundent.h - the entity that spawns when the world |
|
// spawns, and handles the world's active and free sound |
|
// lists. |
|
|
|
#ifndef SOUNDENT_H |
|
#define SOUNDENT_H |
|
|
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
enum |
|
{ |
|
MAX_WORLD_SOUNDS_SP = 64, // Maximum number of sounds handled by the world at one time in single player. |
|
// This is also the number of entries saved in a savegame file (for b/w compatibility). |
|
|
|
MAX_WORLD_SOUNDS_MP = 128 // The sound array size is set this large but we'll only use gpGlobals->maxPlayers+32 entries in mp. |
|
}; |
|
|
|
enum |
|
{ |
|
SOUND_NONE = 0, |
|
SOUND_COMBAT = 0x00000001, |
|
SOUND_WORLD = 0x00000002, |
|
SOUND_PLAYER = 0x00000004, |
|
SOUND_DANGER = 0x00000008, |
|
SOUND_BULLET_IMPACT = 0x00000010, |
|
SOUND_CARCASS = 0x00000020, |
|
SOUND_MEAT = 0x00000040, |
|
SOUND_GARBAGE = 0x00000080, |
|
SOUND_THUMPER = 0x00000100, // keeps certain creatures at bay |
|
SOUND_BUGBAIT = 0x00000200, // gets the antlion's attention |
|
SOUND_PHYSICS_DANGER = 0x00000400, |
|
SOUND_DANGER_SNIPERONLY = 0x00000800, // only scares the sniper NPC. |
|
SOUND_MOVE_AWAY = 0x00001000, |
|
SOUND_PLAYER_VEHICLE = 0x00002000, |
|
SOUND_READINESS_LOW = 0x00004000, // Changes listener's readiness (Player Companion only) |
|
SOUND_READINESS_MEDIUM = 0x00008000, |
|
SOUND_READINESS_HIGH = 0x00010000, |
|
|
|
// Contexts begin here. |
|
SOUND_CONTEXT_FROM_SNIPER = 0x00100000, // additional context for SOUND_DANGER |
|
SOUND_CONTEXT_GUNFIRE = 0x00200000, // Added to SOUND_COMBAT |
|
SOUND_CONTEXT_MORTAR = 0x00400000, // Explosion going to happen here. |
|
SOUND_CONTEXT_COMBINE_ONLY = 0x00800000, // Only combine can hear sounds marked this way |
|
SOUND_CONTEXT_REACT_TO_SOURCE = 0x01000000, // React to sound source's origin, not sound's location |
|
SOUND_CONTEXT_EXPLOSION = 0x02000000, // Context added to SOUND_COMBAT, usually. |
|
SOUND_CONTEXT_EXCLUDE_COMBINE = 0x04000000, // Combine do NOT hear this |
|
SOUND_CONTEXT_DANGER_APPROACH = 0x08000000, // Treat as a normal danger sound if you see the source, otherwise turn to face source. |
|
SOUND_CONTEXT_ALLIES_ONLY = 0x10000000, // Only player allies can hear this sound |
|
SOUND_CONTEXT_PLAYER_VEHICLE = 0x20000000, // HACK: need this because we're not treating the SOUND_xxx values as true bit values! See switch in OnListened. |
|
|
|
ALL_CONTEXTS = 0xFFF00000, |
|
|
|
ALL_SCENTS = SOUND_CARCASS | SOUND_MEAT | SOUND_GARBAGE, |
|
|
|
ALL_SOUNDS = 0x000FFFFF & ~ALL_SCENTS, |
|
|
|
}; |
|
|
|
// Make as many of these as you want. |
|
enum |
|
{ |
|
SOUNDENT_CHANNEL_UNSPECIFIED = 0, |
|
SOUNDENT_CHANNEL_REPEATING, |
|
SOUNDENT_CHANNEL_REPEATED_DANGER, // for things that make danger sounds frequently. |
|
SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER, |
|
SOUNDENT_CHANNEL_WEAPON, |
|
SOUNDENT_CHANNEL_INJURY, |
|
SOUNDENT_CHANNEL_BULLET_IMPACT, |
|
SOUNDENT_CHANNEL_NPC_FOOTSTEP, |
|
SOUNDENT_CHANNEL_SPOOKY_NOISE, // made by zombies in darkness |
|
SOUNDENT_CHANNEL_ZOMBINE_GRENADE, |
|
}; |
|
|
|
enum |
|
{ |
|
SOUNDLIST_EMPTY = -1 |
|
}; |
|
|
|
#define SOUNDENT_VOLUME_MACHINEGUN 1500.0 |
|
#define SOUNDENT_VOLUME_SHOTGUN 1500.0 |
|
#define SOUNDENT_VOLUME_PISTOL 1500.0 |
|
#define SOUNDENT_VOLUME_EMPTY 500.0 // volume of the "CLICK" when you have no bullets |
|
|
|
enum |
|
{ |
|
SOUND_PRIORITY_VERY_LOW = -2, |
|
SOUND_PRIORITY_LOW, |
|
SOUND_PRIORITY_NORMAL = 0, |
|
SOUND_PRIORITY_HIGH, |
|
SOUND_PRIORITY_VERY_HIGH, |
|
SOUND_PRIORITY_HIGHEST, |
|
}; |
|
|
|
//========================================================= |
|
// CSound - an instance of a sound in the world. |
|
//========================================================= |
|
class CSound |
|
{ |
|
DECLARE_SIMPLE_DATADESC(); |
|
|
|
public: |
|
bool DoesSoundExpire() const; |
|
float SoundExpirationTime() const; |
|
void SetSoundOrigin( const Vector &vecOrigin ) { m_vecOrigin = vecOrigin; } |
|
const Vector& GetSoundOrigin( void ) { return m_vecOrigin; } |
|
const Vector& GetSoundReactOrigin( void ); |
|
bool FIsSound( void ); |
|
bool FIsScent( void ); |
|
bool IsSoundType( int nSoundFlags ) const; |
|
int SoundType( ) const; |
|
int SoundContext() const; |
|
int SoundTypeNoContext( ) const; |
|
int Volume( ) const; |
|
float OccludedVolume() { return m_iVolume * m_flOcclusionScale; } |
|
int NextSound() const; |
|
void Reset ( void ); |
|
int SoundChannel( void ) const; |
|
bool ValidateOwner() const; |
|
|
|
EHANDLE m_hOwner; // sound's owner |
|
EHANDLE m_hTarget; // Sounds's target - an odd concept. For a gunfire sound, the target is the entity being fired at |
|
int m_iVolume; // how loud the sound is |
|
float m_flOcclusionScale; // How loud the sound is when occluded by the world. (volume * occlusionscale) |
|
int m_iType; // what type of sound this is |
|
int m_iNextAudible; // temporary link that NPCs use to build a list of audible sounds |
|
|
|
private: |
|
void Clear ( void ); |
|
|
|
float m_flExpireTime; // when the sound should be purged from the list |
|
short m_iNext; // index of next sound in this list ( Active or Free ) |
|
bool m_bNoExpirationTime; |
|
int m_ownerChannelIndex; |
|
|
|
Vector m_vecOrigin; // sound's location in space |
|
|
|
bool m_bHasOwner; // Lets us know if this sound was created with an owner. In case the owner goes null. |
|
|
|
#ifdef DEBUG |
|
int m_iMyIndex; // debugging |
|
#endif |
|
|
|
friend class CSoundEnt; |
|
}; |
|
|
|
inline bool CSound::DoesSoundExpire() const |
|
{ |
|
return m_bNoExpirationTime == false; |
|
} |
|
|
|
inline float CSound::SoundExpirationTime() const |
|
{ |
|
return m_bNoExpirationTime ? FLT_MAX : m_flExpireTime; |
|
} |
|
|
|
inline bool CSound::IsSoundType( int nSoundFlags ) const |
|
{ |
|
return (m_iType & nSoundFlags) != 0; |
|
} |
|
|
|
inline int CSound::SoundType( ) const |
|
{ |
|
return m_iType; |
|
} |
|
|
|
inline int CSound::SoundContext( ) const |
|
{ |
|
return m_iType & ALL_CONTEXTS; |
|
} |
|
|
|
inline int CSound::SoundTypeNoContext( ) const |
|
{ |
|
return m_iType & ~ALL_CONTEXTS; |
|
} |
|
|
|
inline int CSound::Volume( ) const |
|
{ |
|
return m_iVolume; |
|
} |
|
|
|
inline int CSound::NextSound() const |
|
{ |
|
return m_iNext; |
|
} |
|
|
|
inline int CSound::SoundChannel( void ) const |
|
{ |
|
return m_ownerChannelIndex; |
|
} |
|
|
|
// The owner is considered valid if: |
|
// -The sound never had an assigned owner (quite common) |
|
// -The sound was assigned an owner and that owner still exists |
|
inline bool CSound::ValidateOwner( void ) const |
|
{ |
|
return ( !m_bHasOwner || (m_hOwner.Get() != NULL) ); |
|
} |
|
|
|
//========================================================= |
|
// CSoundEnt - a single instance of this entity spawns when |
|
// the world spawns. The SoundEnt's job is to update the |
|
// world's Free and Active sound lists. |
|
//========================================================= |
|
class CSoundEnt : public CPointEntity |
|
{ |
|
DECLARE_DATADESC(); |
|
|
|
public: |
|
DECLARE_CLASS( CSoundEnt, CPointEntity ); |
|
|
|
// Construction, destruction |
|
static bool InitSoundEnt(); |
|
static void ShutdownSoundEnt(); |
|
|
|
CSoundEnt(); |
|
virtual ~CSoundEnt(); |
|
|
|
virtual void OnRestore(); |
|
void Precache ( void ); |
|
void Spawn( void ); |
|
void Think( void ); |
|
void Initialize ( void ); |
|
int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } |
|
|
|
static void InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration, CBaseEntity *pOwner = NULL, int soundChannelIndex = SOUNDENT_CHANNEL_UNSPECIFIED, CBaseEntity *pSoundTarget = NULL ); |
|
static void FreeSound ( int iSound, int iPrevious ); |
|
static int ActiveList( void );// return the head of the active list |
|
static int FreeList( void );// return the head of the free list |
|
static CSound* SoundPointerForIndex( int iIndex );// return a pointer for this index in the sound list |
|
static CSound* GetLoudestSoundOfType( int iType, const Vector &vecEarPosition ); |
|
static int ClientSoundIndex ( edict_t *pClient ); |
|
|
|
bool IsEmpty( void ); |
|
int ISoundsInList ( int iListType ); |
|
int IAllocSound ( void ); |
|
int FindOrAllocateSound( CBaseEntity *pOwner, int soundChannelIndex ); |
|
|
|
private: |
|
int m_iFreeSound; // index of the first sound in the free sound list |
|
int m_iActiveSound; // indes of the first sound in the active sound list |
|
int m_cLastActiveSounds; // keeps track of the number of active sounds at the last update. (for diagnostic work) |
|
CSound m_SoundPool[ MAX_WORLD_SOUNDS_MP ]; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Inline methods |
|
//----------------------------------------------------------------------------- |
|
inline bool CSoundEnt::IsEmpty( void ) |
|
{ |
|
return m_iActiveSound == SOUNDLIST_EMPTY; |
|
} |
|
|
|
|
|
#endif //SOUNDENT_H
|
|
|