Dynamic NPC Footsteps
Jump to navigation
Jump to search
Note:This overrides all NPC footsteps; this means the Combine will not sound like they used to when they walk. An extra addition would need to be taken regarding another
↓
↓
Similar to Half-Life, Half-Life 2 contained no dynamic footsteps for NPCs; dynamic footsteps meaning that they change when different surfaces are walked on.
![Note.png](/w/images/thumb/c/cc/Note.png/10px-Note.png)
EmitSound
to still include the original sound.src\client\c_baseanimating.h
Includes
- vphysics_interface.h
Private Prototypes
virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity, bool left ); virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool left ); virtual surfacedata_t *GetGroundSurface();
src\client\c_baseanimating.cpp
Includes
- decals.h
- soundemittersystem/isoundemittersystembase.h
Player Cloned Functions
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
extern ConVar sv_footsteps;
void C_BaseAnimating::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity, bool left )
{
int fWalking;
float fvol;
Vector knee;
Vector feet;
float height;
if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS))
return;
if ( !sv_footsteps.GetFloat() )
return;
float groundspeed = vecVelocity.Length2DSqr();
bool movingalongground = ( groundspeed > 0.0f );
// To hear step sounds you must be either on a ladder or moving along the ground AND
// You must be moving fast enough
if ( !movingalongground )
return;
fWalking = groundspeed < RUN_SPEED_ESTIMATE_SQR;
VectorCopy( vecOrigin, knee );
VectorCopy( vecOrigin, feet );
height = GetCollideable()->OBBMaxs()[ 2 ] - GetCollideable()->OBBMins()[ 2 ];
knee[2] = vecOrigin[2] + 0.2 * height;
// find out what we're stepping in or on...
if ( enginetrace->GetPointContents( knee ) & MASK_WATER )
{
static int iSkipStep = 0;
if ( iSkipStep == 0 )
{
iSkipStep++;
return;
}
if ( iSkipStep++ == 3 )
{
iSkipStep = 0;
}
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) );
fvol = 0.65;
}
else if ( enginetrace->GetPointContents( feet ) & MASK_WATER )
{
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) );
fvol = fWalking ? 0.2 : 0.5;
}
else
{
if ( !psurface )
return;
switch ( psurface->game.material )
{
default:
case CHAR_TEX_CONCRETE:
fvol = fWalking ? 0.2 : 0.5;
break;
case CHAR_TEX_METAL:
fvol = fWalking ? 0.2 : 0.5;
break;
case CHAR_TEX_DIRT:
fvol = fWalking ? 0.25 : 0.55;
break;
case CHAR_TEX_VENT:
fvol = fWalking ? 0.4 : 0.7;
break;
case CHAR_TEX_GRATE:
fvol = fWalking ? 0.2 : 0.5;
break;
case CHAR_TEX_TILE:
fvol = fWalking ? 0.2 : 0.5;
break;
case CHAR_TEX_SLOSH:
fvol = fWalking ? 0.2 : 0.5;
break;
}
}
// play the sound
// 65% volume if ducking
if ( GetFlags() & FL_DUCKING )
{
fvol *= 0.65;
}
PlayStepSound( feet, psurface, fvol, left );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseAnimating::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool left )
{
if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() )
return;
if ( !psurface )
return;
unsigned short stepSoundName = left ? psurface->sounds.stepleft : psurface->sounds.stepright;
if ( !stepSoundName )
return;
const char *pSoundName = physprops->GetString( stepSoundName );
CSoundParameters params;
if ( !CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) )
return;
CPASFilter filter(vecOrigin);
EmitSound_t ep;
ep.m_nChannel = CHAN_BODY;
ep.m_pSoundName = params.soundname;
ep.m_flVolume = fvol;
ep.m_SoundLevel = params.soundlevel;
ep.m_nFlags = 0;
ep.m_nPitch = params.pitch;
ep.m_pOrigin = &vecOrigin;
EmitSound( filter, entindex(), ep );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
surfacedata_t *C_BaseAnimating::GetGroundSurface()
{
//
// Find the name of the material that lies beneath the player.
//
Vector start, end;
VectorCopy( GetAbsOrigin(), start );
VectorCopy( start, end );
// Straight down
end.z -= 64;
// Fill in default values, just in case.
Ray_t ray;
ray.Init( start, end, GetCollideable()->OBBMins(), GetCollideable()->OBBMaxs() );
trace_t trace;
UTIL_TraceRay( ray, MASK_NPCSOLID, this, COLLISION_GROUP_NPC, &trace );
if ( trace.fraction == 1.0f )
return NULL; // no ground
return physprops->GetSurfaceData( trace.surface.surfaceProps );
}
Left Foot
#ifndef HL2MP
char pSoundName[256];
if ( !options || !options[0] )
{
options = "NPC_CombineS";
}
Vector vel;
EstimateAbsVelocity( vel );
// If he's moving fast enough, play the run sound
if ( vel.Length2DSqr() > RUN_SPEED_ESTIMATE_SQR )
{
Q_snprintf( pSoundName, 256, "%s.RunFootstepLeft", options );
}
else
{
Q_snprintf( pSoundName, 256, "%s.FootstepLeft", options );
}
EmitSound( pSoundName );
#endif
if ( IsNPC() )
{
Vector vel;
EstimateAbsVelocity( vel );
UpdateStepSound( GetGroundSurface(), GetAbsOrigin(), vel, true );
}
Right Foot
#ifndef HL2MP
char pSoundName[256];
if ( !options || !options[0] )
{
options = "NPC_CombineS";
}
Vector vel;
EstimateAbsVelocity( vel );
// If he's moving fast enough, play the run sound
if ( vel.Length2DSqr() > RUN_SPEED_ESTIMATE_SQR )
{
Q_snprintf( pSoundName, 256, "%s.RunFootstepRight", options );
}
else
{
Q_snprintf( pSoundName, 256, "%s.FootstepRight", options );
}
EmitSound( pSoundName );
#endif
if ( IsNPC() )
{
Vector vel;
EstimateAbsVelocity( vel );
UpdateStepSound( GetGroundSurface(), GetAbsOrigin(), vel, false );
}