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.
217 lines
5.5 KiB
217 lines
5.5 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "cbase.h" |
|
#include "ModelSoundsCache.h" |
|
#include "studio.h" |
|
#include "eventlist.h" |
|
#include "scriptevent.h" |
|
|
|
extern ISoundEmitterSystemBase *soundemitterbase; |
|
|
|
CStudioHdr *ModelSoundsCache_LoadModel( char const *filename ); |
|
void ModelSoundsCache_PrecacheScriptSound( const char *soundname ); |
|
void ModelSoundsCache_FinishModel( CStudioHdr *hdr ); |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *hdr - |
|
// Output : static void |
|
//----------------------------------------------------------------------------- |
|
|
|
void VerifySequenceIndex( CStudioHdr *pstudiohdr ); |
|
|
|
// HACK: This must match the #define in cl_animevent.h in the client .dll code!!! |
|
#define CL_EVENT_SOUND 5004 |
|
#define CL_EVENT_FOOTSTEP_LEFT 6004 |
|
#define CL_EVENT_FOOTSTEP_RIGHT 6005 |
|
#define CL_EVENT_MFOOTSTEP_LEFT 6006 |
|
#define CL_EVENT_MFOOTSTEP_RIGHT 6007 |
|
|
|
|
|
extern ISoundEmitterSystemBase *soundemitterbase; |
|
|
|
CModelSoundsCache::CModelSoundsCache() |
|
{ |
|
} |
|
|
|
CModelSoundsCache::CModelSoundsCache( const CModelSoundsCache& src ) |
|
{ |
|
sounds = src.sounds; |
|
} |
|
|
|
char const *CModelSoundsCache::GetSoundName( int index ) |
|
{ |
|
return soundemitterbase->GetSoundName( sounds[ index ] ); |
|
} |
|
|
|
void CModelSoundsCache::Save( CUtlBuffer& buf ) |
|
{ |
|
buf.PutShort( sounds.Count() ); |
|
|
|
for ( int i = 0; i < sounds.Count(); ++i ) |
|
{ |
|
buf.PutString( GetSoundName( i ) ); |
|
} |
|
} |
|
|
|
void CModelSoundsCache::Restore( CUtlBuffer& buf ) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
unsigned short c; |
|
|
|
c = (unsigned short)buf.GetShort(); |
|
|
|
for ( int i = 0; i < c; ++i ) |
|
{ |
|
char soundname[ 512 ]; |
|
|
|
buf.GetString( soundname, sizeof( soundname ) ); |
|
|
|
int idx = soundemitterbase->GetSoundIndex( soundname ); |
|
if ( idx != -1 ) |
|
{ |
|
Assert( idx <= 65535 ); |
|
if ( sounds.Find( idx ) == sounds.InvalidIndex() ) |
|
{ |
|
sounds.AddToTail( (unsigned short)idx ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CModelSoundsCache::Rebuild( char const *filename ) |
|
{ |
|
sounds.RemoveAll(); |
|
|
|
CStudioHdr *hdr = ModelSoundsCache_LoadModel( filename ); |
|
|
|
if ( hdr ) |
|
{ |
|
// Precache all sounds referenced in animation events |
|
BuildAnimationEventSoundList( hdr, sounds ); |
|
ModelSoundsCache_FinishModel( hdr ); |
|
} |
|
} |
|
|
|
void CModelSoundsCache::PrecacheSoundList() |
|
{ |
|
for ( int i = 0; i < sounds.Count(); ++i ) |
|
{ |
|
ModelSoundsCache_PrecacheScriptSound( GetSoundName( i ) ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Static method |
|
// Input : sounds - |
|
// *soundname - |
|
//----------------------------------------------------------------------------- |
|
void CModelSoundsCache::FindOrAddScriptSound( CUtlVector< unsigned short >& sounds, char const *soundname ) |
|
{ |
|
int soundindex = soundemitterbase->GetSoundIndex( soundname ); |
|
if ( soundindex != -1 ) |
|
{ |
|
// Only add it once per model... |
|
if ( sounds.Find( soundindex ) == sounds.InvalidIndex() ) |
|
{ |
|
MEM_ALLOC_CREDIT(); |
|
sounds.AddToTail( soundindex ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Static method |
|
// Input : *hdr - |
|
// sounds - |
|
//----------------------------------------------------------------------------- |
|
void CModelSoundsCache::BuildAnimationEventSoundList( CStudioHdr *hdr, CUtlVector< unsigned short >& sounds ) |
|
{ |
|
Assert( hdr ); |
|
|
|
// force animation event resolution!!! |
|
VerifySequenceIndex( hdr ); |
|
|
|
// Find all animation events which fire off sound script entries... |
|
for ( int iSeq=0; iSeq < hdr->GetNumSeq(); iSeq++ ) |
|
{ |
|
mstudioseqdesc_t *pSeq = &hdr->pSeqdesc( iSeq ); |
|
|
|
// Now read out all the sound events with their timing |
|
for ( int iEvent=0; iEvent < (int)pSeq->numevents; iEvent++ ) |
|
{ |
|
mstudioevent_t *pEvent = pSeq->pEvent( iEvent ); |
|
|
|
switch ( pEvent->event ) |
|
{ |
|
default: |
|
{ |
|
if ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM ) |
|
{ |
|
if ( pEvent->event == AE_SV_PLAYSOUND ) |
|
{ |
|
FindOrAddScriptSound( sounds, pEvent->pszOptions() ); |
|
} |
|
} |
|
} |
|
break; |
|
// Old-style client .dll animation event |
|
case CL_EVENT_SOUND: |
|
{ |
|
FindOrAddScriptSound( sounds, pEvent->pszOptions() ); |
|
} |
|
break; |
|
case CL_EVENT_FOOTSTEP_LEFT: |
|
case CL_EVENT_FOOTSTEP_RIGHT: |
|
{ |
|
char soundname[256]; |
|
char const *options = pEvent->pszOptions(); |
|
if ( !options || !options[0] ) |
|
{ |
|
options = "NPC_CombineS"; |
|
} |
|
|
|
Q_snprintf( soundname, 256, "%s.RunFootstepLeft", options ); |
|
FindOrAddScriptSound( sounds, soundname ); |
|
Q_snprintf( soundname, 256, "%s.RunFootstepRight", options ); |
|
FindOrAddScriptSound( sounds, soundname ); |
|
Q_snprintf( soundname, 256, "%s.FootstepLeft", options ); |
|
FindOrAddScriptSound( sounds, soundname ); |
|
Q_snprintf( soundname, 256, "%s.FootstepRight", options ); |
|
FindOrAddScriptSound( sounds, soundname ); |
|
} |
|
break; |
|
case AE_CL_PLAYSOUND: |
|
{ |
|
if ( !( pEvent->type & AE_TYPE_CLIENT ) ) |
|
break; |
|
|
|
if ( pEvent->pszOptions()[0] ) |
|
{ |
|
FindOrAddScriptSound( sounds, pEvent->pszOptions() ); |
|
} |
|
else |
|
{ |
|
Warning( "-- Error --: empty soundname, .qc error on AE_CL_PLAYSOUND in model %s, sequence %s, animevent # %i\n", |
|
hdr->pszName(), pSeq->pszLabel(), iEvent+1 ); |
|
} |
|
} |
|
break; |
|
case SCRIPT_EVENT_SOUND: |
|
{ |
|
FindOrAddScriptSound( sounds, pEvent->pszOptions() ); |
|
} |
|
break; |
|
|
|
case SCRIPT_EVENT_SOUND_VOICE: |
|
{ |
|
FindOrAddScriptSound( sounds, pEvent->pszOptions() ); |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
} |