diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp')
| -rw-r--r-- | mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp | 577 |
1 files changed, 577 insertions, 0 deletions
diff --git a/mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp b/mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp new file mode 100644 index 00000000..ff8d28f2 --- /dev/null +++ b/mp/src/game/shared/hl2mp/hl2mp_player_shared.cpp @@ -0,0 +1,577 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include "cbase.h"
+
+#ifdef CLIENT_DLL
+#include "c_hl2mp_player.h"
+#include "prediction.h"
+#define CRecipientFilter C_RecipientFilter
+#else
+#include "hl2mp_player.h"
+#endif
+
+#include "engine/IEngineSound.h"
+#include "SoundEmitterSystem/isoundemittersystembase.h"
+
+extern ConVar sv_footsteps;
+
+const char *g_ppszPlayerSoundPrefixNames[PLAYER_SOUNDS_MAX] =
+{
+ "NPC_Citizen",
+ "NPC_CombineS",
+ "NPC_MetroPolice",
+};
+
+const char *CHL2MP_Player::GetPlayerModelSoundPrefix( void )
+{
+ return g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType];
+}
+
+void CHL2MP_Player::PrecacheFootStepSounds( void )
+{
+ int iFootstepSounds = ARRAYSIZE( g_ppszPlayerSoundPrefixNames );
+ int i;
+
+ for ( i = 0; i < iFootstepSounds; ++i )
+ {
+ char szFootStepName[128];
+
+ Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[i] );
+ PrecacheScriptSound( szFootStepName );
+
+ Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[i] );
+ PrecacheScriptSound( szFootStepName );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Consider the weapon's built-in accuracy, this character's proficiency with
+// the weapon, and the status of the target. Use this information to determine
+// how accurately to shoot at the target.
+//-----------------------------------------------------------------------------
+Vector CHL2MP_Player::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget )
+{
+ if ( pWeapon )
+ return pWeapon->GetBulletSpread( WEAPON_PROFICIENCY_PERFECT );
+
+ return VECTOR_CONE_15DEGREES;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : step -
+// fvol -
+// force - force sound to play
+//-----------------------------------------------------------------------------
+void CHL2MP_Player::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force )
+{
+ if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() )
+ return;
+
+#if defined( CLIENT_DLL )
+ // during prediction play footstep sounds only once
+ if ( !prediction->IsFirstTimePredicted() )
+ return;
+#endif
+
+ if ( GetFlags() & FL_DUCKING )
+ return;
+
+ m_Local.m_nStepside = !m_Local.m_nStepside;
+
+ char szStepSound[128];
+
+ if ( m_Local.m_nStepside )
+ {
+ Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] );
+ }
+ else
+ {
+ Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] );
+ }
+
+ CSoundParameters params;
+ if ( GetParametersForSound( szStepSound, params, NULL ) == false )
+ return;
+
+ CRecipientFilter filter;
+ filter.AddRecipientsByPAS( vecOrigin );
+
+#ifndef CLIENT_DLL
+ // im MP, server removed all players in origins PVS, these players
+ // generate the footsteps clientside
+ if ( gpGlobals->maxClients > 1 )
+ filter.RemoveRecipientsByPVS( vecOrigin );
+#endif
+
+ 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 );
+}
+
+
+//==========================
+// ANIMATION CODE
+//==========================
+
+
+// Below this many degrees, slow down turning rate linearly
+#define FADE_TURN_DEGREES 45.0f
+// After this, need to start turning feet
+#define MAX_TORSO_ANGLE 90.0f
+// Below this amount, don't play a turning animation/perform IK
+#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
+
+static ConVar tf2_feetyawrunscale( "tf2_feetyawrunscale", "2", FCVAR_REPLICATED, "Multiplier on tf2_feetyawrate to allow turning faster when running." );
+extern ConVar sv_backspeed;
+extern ConVar mp_feetyawrate;
+extern ConVar mp_facefronttime;
+extern ConVar mp_ik;
+
+CPlayerAnimState::CPlayerAnimState( CHL2MP_Player *outer )
+ : m_pOuter( outer )
+{
+ m_flGaitYaw = 0.0f;
+ m_flGoalFeetYaw = 0.0f;
+ m_flCurrentFeetYaw = 0.0f;
+ m_flCurrentTorsoYaw = 0.0f;
+ m_flLastYaw = 0.0f;
+ m_flLastTurnTime = 0.0f;
+ m_flTurnCorrectionTime = 0.0f;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::Update()
+{
+ m_angRender = GetOuter()->GetLocalAngles();
+ m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f;
+
+ ComputePoseParam_BodyYaw();
+ ComputePoseParam_BodyPitch(GetOuter()->GetModelPtr());
+ ComputePoseParam_BodyLookYaw();
+
+ ComputePlaybackRate();
+
+#ifdef CLIENT_DLL
+ GetOuter()->UpdateLookAt();
+#endif
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::ComputePlaybackRate()
+{
+ // Determine ideal playback rate
+ Vector vel;
+ GetOuterAbsVelocity( vel );
+
+ float speed = vel.Length2D();
+
+ bool isMoving = ( speed > 0.5f ) ? true : false;
+
+ float maxspeed = GetOuter()->GetSequenceGroundSpeed( GetOuter()->GetSequence() );
+
+ if ( isMoving && ( maxspeed > 0.0f ) )
+ {
+ float flFactor = 1.0f;
+
+ // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below
+ GetOuter()->SetPlaybackRate( ( speed * flFactor ) / maxspeed );
+
+ // BUG BUG:
+ // This stuff really should be m_flPlaybackRate = speed / m_flGroundSpeed
+ }
+ else
+ {
+ GetOuter()->SetPlaybackRate( 1.0f );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : CBasePlayer
+//-----------------------------------------------------------------------------
+CHL2MP_Player *CPlayerAnimState::GetOuter()
+{
+ return m_pOuter;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : dt -
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::EstimateYaw( void )
+{
+ float dt = gpGlobals->frametime;
+
+ if ( !dt )
+ {
+ return;
+ }
+
+ Vector est_velocity;
+ QAngle angles;
+
+ GetOuterAbsVelocity( est_velocity );
+
+ angles = GetOuter()->GetLocalAngles();
+
+ if ( est_velocity[1] == 0 && est_velocity[0] == 0 )
+ {
+ float flYawDiff = angles[YAW] - m_flGaitYaw;
+ flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360;
+ if (flYawDiff > 180)
+ flYawDiff -= 360;
+ if (flYawDiff < -180)
+ flYawDiff += 360;
+
+ if (dt < 0.25)
+ flYawDiff *= dt * 4;
+ else
+ flYawDiff *= dt;
+
+ m_flGaitYaw += flYawDiff;
+ m_flGaitYaw = m_flGaitYaw - (int)(m_flGaitYaw / 360) * 360;
+ }
+ else
+ {
+ m_flGaitYaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI);
+
+ if (m_flGaitYaw > 180)
+ m_flGaitYaw = 180;
+ else if (m_flGaitYaw < -180)
+ m_flGaitYaw = -180;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Override for backpeddling
+// Input : dt -
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::ComputePoseParam_BodyYaw( void )
+{
+ int iYaw = GetOuter()->LookupPoseParameter( "move_yaw" );
+ if ( iYaw < 0 )
+ return;
+
+ // view direction relative to movement
+ float flYaw;
+
+ EstimateYaw();
+
+ QAngle angles = GetOuter()->GetLocalAngles();
+ float ang = angles[ YAW ];
+ if ( ang > 180.0f )
+ {
+ ang -= 360.0f;
+ }
+ else if ( ang < -180.0f )
+ {
+ ang += 360.0f;
+ }
+
+ // calc side to side turning
+ flYaw = ang - m_flGaitYaw;
+ // Invert for mapping into 8way blend
+ flYaw = -flYaw;
+ flYaw = flYaw - (int)(flYaw / 360) * 360;
+
+ if (flYaw < -180)
+ {
+ flYaw = flYaw + 360;
+ }
+ else if (flYaw > 180)
+ {
+ flYaw = flYaw - 360;
+ }
+
+ GetOuter()->SetPoseParameter( iYaw, flYaw );
+
+#ifndef CLIENT_DLL
+ //Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
+ GetOuter()->SetLocalAngles( QAngle( GetOuter()->GetAnimEyeAngles().x, m_flCurrentFeetYaw, 0 ) );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
+{
+ // Get pitch from v_angle
+ float flPitch = GetOuter()->GetLocalAngles()[ PITCH ];
+
+ if ( flPitch > 180.0f )
+ {
+ flPitch -= 360.0f;
+ }
+ flPitch = clamp( flPitch, -90, 90 );
+
+ QAngle absangles = GetOuter()->GetAbsAngles();
+ absangles.x = 0.0f;
+ m_angRender = absangles;
+ m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f;
+
+ // See if we have a blender for pitch
+ GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : goal -
+// maxrate -
+// dt -
+// current -
+// Output : int
+//-----------------------------------------------------------------------------
+int CPlayerAnimState::ConvergeAngles( float goal,float maxrate, float dt, float& current )
+{
+ int direction = TURN_NONE;
+
+ float anglediff = goal - current;
+ float anglediffabs = fabs( anglediff );
+
+ anglediff = AngleNormalize( anglediff );
+
+ float scale = 1.0f;
+ if ( anglediffabs <= FADE_TURN_DEGREES )
+ {
+ scale = anglediffabs / FADE_TURN_DEGREES;
+ // Always do at least a bit of the turn ( 1% )
+ scale = clamp( scale, 0.01f, 1.0f );
+ }
+
+ float maxmove = maxrate * dt * scale;
+
+ if ( fabs( anglediff ) < maxmove )
+ {
+ current = goal;
+ }
+ else
+ {
+ if ( anglediff > 0 )
+ {
+ current += maxmove;
+ direction = TURN_LEFT;
+ }
+ else
+ {
+ current -= maxmove;
+ direction = TURN_RIGHT;
+ }
+ }
+
+ current = AngleNormalize( current );
+
+ return direction;
+}
+
+void CPlayerAnimState::ComputePoseParam_BodyLookYaw( void )
+{
+ QAngle absangles = GetOuter()->GetAbsAngles();
+ absangles.y = AngleNormalize( absangles.y );
+ m_angRender = absangles;
+ m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f;
+
+ // See if we even have a blender for pitch
+ int upper_body_yaw = GetOuter()->LookupPoseParameter( "aim_yaw" );
+ if ( upper_body_yaw < 0 )
+ {
+ return;
+ }
+
+ // Assume upper and lower bodies are aligned and that we're not turning
+ float flGoalTorsoYaw = 0.0f;
+ int turning = TURN_NONE;
+ float turnrate = 360.0f;
+
+ Vector vel;
+
+ GetOuterAbsVelocity( vel );
+
+ bool isMoving = ( vel.Length() > 1.0f ) ? true : false;
+
+ if ( !isMoving )
+ {
+ // Just stopped moving, try and clamp feet
+ if ( m_flLastTurnTime <= 0.0f )
+ {
+ m_flLastTurnTime = gpGlobals->curtime;
+ m_flLastYaw = GetOuter()->GetAnimEyeAngles().y;
+ // Snap feet to be perfectly aligned with torso/eyes
+ m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y;
+ m_flCurrentFeetYaw = m_flGoalFeetYaw;
+ m_nTurningInPlace = TURN_NONE;
+ }
+
+ // If rotating in place, update stasis timer
+ if ( m_flLastYaw != GetOuter()->GetAnimEyeAngles().y )
+ {
+ m_flLastTurnTime = gpGlobals->curtime;
+ m_flLastYaw = GetOuter()->GetAnimEyeAngles().y;
+ }
+
+ if ( m_flGoalFeetYaw != m_flCurrentFeetYaw )
+ {
+ m_flLastTurnTime = gpGlobals->curtime;
+ }
+
+ turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw );
+
+ QAngle eyeAngles = GetOuter()->GetAnimEyeAngles();
+ QAngle vAngle = GetOuter()->GetLocalAngles();
+
+ // See how far off current feetyaw is from true yaw
+ float yawdelta = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw;
+ yawdelta = AngleNormalize( yawdelta );
+
+ bool rotated_too_far = false;
+
+ float yawmagnitude = fabs( yawdelta );
+
+ // If too far, then need to turn in place
+ if ( yawmagnitude > 45 )
+ {
+ rotated_too_far = true;
+ }
+
+ // Standing still for a while, rotate feet around to face forward
+ // Or rotated too far
+ // FIXME: Play an in place turning animation
+ if ( rotated_too_far ||
+ ( gpGlobals->curtime > m_flLastTurnTime + mp_facefronttime.GetFloat() ) )
+ {
+ m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y;
+ m_flLastTurnTime = gpGlobals->curtime;
+
+ /* float yd = m_flCurrentFeetYaw - m_flGoalFeetYaw;
+ if ( yd > 0 )
+ {
+ m_nTurningInPlace = TURN_RIGHT;
+ }
+ else if ( yd < 0 )
+ {
+ m_nTurningInPlace = TURN_LEFT;
+ }
+ else
+ {
+ m_nTurningInPlace = TURN_NONE;
+ }
+
+ turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw );
+ yawdelta = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw;*/
+
+ }
+
+ // Snap upper body into position since the delta is already smoothed for the feet
+ flGoalTorsoYaw = yawdelta;
+ m_flCurrentTorsoYaw = flGoalTorsoYaw;
+ }
+ else
+ {
+ m_flLastTurnTime = 0.0f;
+ m_nTurningInPlace = TURN_NONE;
+ m_flCurrentFeetYaw = m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y;
+ flGoalTorsoYaw = 0.0f;
+ m_flCurrentTorsoYaw = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw;
+ }
+
+
+ if ( turning == TURN_NONE )
+ {
+ m_nTurningInPlace = turning;
+ }
+
+ if ( m_nTurningInPlace != TURN_NONE )
+ {
+ // If we're close to finishing the turn, then turn off the turning animation
+ if ( fabs( m_flCurrentFeetYaw - m_flGoalFeetYaw ) < MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION )
+ {
+ m_nTurningInPlace = TURN_NONE;
+ }
+ }
+
+ // Rotate entire body into position
+ absangles = GetOuter()->GetAbsAngles();
+ absangles.y = m_flCurrentFeetYaw;
+ m_angRender = absangles;
+ m_angRender[ PITCH ] = m_angRender[ ROLL ] = 0.0f;
+
+ GetOuter()->SetPoseParameter( upper_body_yaw, clamp( m_flCurrentTorsoYaw, -60.0f, 60.0f ) );
+
+ /*
+ // FIXME: Adrian, what is this?
+ int body_yaw = GetOuter()->LookupPoseParameter( "body_yaw" );
+
+ if ( body_yaw >= 0 )
+ {
+ GetOuter()->SetPoseParameter( body_yaw, 30 );
+ }
+ */
+
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : activity -
+// Output : Activity
+//-----------------------------------------------------------------------------
+Activity CPlayerAnimState::BodyYawTranslateActivity( Activity activity )
+{
+ // Not even standing still, sigh
+ if ( activity != ACT_IDLE )
+ return activity;
+
+ // Not turning
+ switch ( m_nTurningInPlace )
+ {
+ default:
+ case TURN_NONE:
+ return activity;
+ /*
+ case TURN_RIGHT:
+ return ACT_TURNRIGHT45;
+ case TURN_LEFT:
+ return ACT_TURNLEFT45;
+ */
+ case TURN_RIGHT:
+ case TURN_LEFT:
+ return mp_ik.GetBool() ? ACT_TURN : activity;
+ }
+
+ Assert( 0 );
+ return activity;
+}
+
+const QAngle& CPlayerAnimState::GetRenderAngles()
+{
+ return m_angRender;
+}
+
+
+void CPlayerAnimState::GetOuterAbsVelocity( Vector& vel )
+{
+#if defined( CLIENT_DLL )
+ GetOuter()->EstimateAbsVelocity( vel );
+#else
+ vel = GetOuter()->GetAbsVelocity();
+#endif
+}
\ No newline at end of file |