|
|
|
|
//====== Copyright <EFBFBD> 1996-2005, Valve Corporation, All rights reserved. =======
|
|
|
|
|
//
|
|
|
|
|
// Purpose:
|
|
|
|
|
//
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
|
|
#include "cbase.h"
|
|
|
|
|
#include "ModelSoundsCache.h"
|
|
|
|
|
#include "studio.h"
|
|
|
|
|
#include "eventlist.h"
|
|
|
|
|
#include "scriptevent.h"
|
|
|
|
|
|
|
|
|
|
// NOTE: This has to be the last file included!
|
|
|
|
|
#include "tier0/memdbgon.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 = (mstudioevent_for_client_server_t*)pSeq->pEvent( iEvent );
|
|
|
|
|
|
|
|
|
|
int nEvent = pEvent->Event();
|
|
|
|
|
|
|
|
|
|
switch ( nEvent )
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
if ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM )
|
|
|
|
|
{
|
|
|
|
|
if ( nEvent == 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|