Counter Strike : Global Offensive Source Code
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.

1227 lines
35 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "base_playeranimstate.h"
  8. #include "tier0/vprof.h"
  9. #include "animation.h"
  10. #include "studio.h"
  11. #include "apparent_velocity_helper.h"
  12. #include "utldict.h"
  13. #include "filesystem.h"
  14. #ifdef CLIENT_DLL
  15. #include "c_baseplayer.h"
  16. #include "engine/ivdebugoverlay.h"
  17. ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." );
  18. ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
  19. ConVar showanimstate_activities( "cl_showanimstate_activities", "0", FCVAR_CHEAT, "Show activities in the (client) animation state display." );
  20. #else
  21. #include "player.h"
  22. ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." );
  23. ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
  24. ConVar showanimstate_activities( "sv_showanimstate_activities", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show activities in the (server) animation state display." );
  25. #endif
  26. // NOTE: This has to be the last file included!
  27. #include "tier0/memdbgon.h"
  28. // Below this many degrees, slow down turning rate linearly
  29. #define FADE_TURN_DEGREES 15.0f
  30. // After this, need to start turning feet
  31. #define MAX_TORSO_ANGLE 70.0f
  32. // Below this amount, don't play a turning animation/perform IK
  33. #define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
  34. #define POSE_PARAM_DELTA_DAMPEN 4.0f
  35. ConVar mp_feetyawrate(
  36. "mp_feetyawrate",
  37. "400",
  38. FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY,
  39. "How many degrees per second that we can turn our feet or upper body." );
  40. ConVar mp_facefronttime(
  41. "mp_facefronttime",
  42. "2",
  43. FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY,
  44. "After this amount of time of standing in place but aiming to one side, go ahead and move feet to face upper body." );
  45. ConVar mp_ik( "mp_ik", "1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Use IK on in-place turns." );
  46. // Pose parameters stored for debugging.
  47. float g_flLastBodyPitch, g_flLastBodyYaw, m_flLastMoveYaw;
  48. // ------------------------------------------------------------------------------------------------ //
  49. // CBasePlayerAnimState implementation.
  50. // ------------------------------------------------------------------------------------------------ //
  51. CBasePlayerAnimState::CBasePlayerAnimState()
  52. {
  53. m_flEyeYaw = 0.0f;
  54. m_flEyePitch = 0.0f;
  55. m_bCurrentFeetYawInitialized = false;
  56. m_flCurrentTorsoYaw = 0.0f;
  57. m_flCurrentTorsoYaw = TURN_NONE;
  58. m_flMaxGroundSpeed = 0.0f;
  59. m_flStoredCycle = 0.0f;
  60. m_flGaitYaw = 0.0f;
  61. m_flGoalFeetYaw = 0.0f;
  62. m_flCurrentFeetYaw = 0.0f;
  63. m_bForceAimYaw = false;
  64. m_flLastYaw = 0.0f;
  65. m_flLastTurnTime = 0.0f;
  66. m_angRender.Init();
  67. m_vLastMovePose.Init();
  68. m_iCurrent8WayIdleSequence = -1;
  69. m_iCurrent8WayCrouchIdleSequence = -1;
  70. m_pOuter = NULL;
  71. m_eCurrentMainSequenceActivity = ACT_IDLE;
  72. m_flLastAnimationStateClearTime = 0.0f;
  73. m_bInFootPlantIdleTurn = false;
  74. m_flFootPlantIdleTurnCycle = 0.0f;
  75. m_bFootPlantIdleNeedToLiftFeet = false;
  76. m_flPoseParamTargetDampenedScaleIdeal = 0.0f;
  77. }
  78. CBasePlayerAnimState::~CBasePlayerAnimState()
  79. {
  80. }
  81. void CBasePlayerAnimState::Init( CBaseAnimatingOverlay *pPlayer, const CModAnimConfig &config )
  82. {
  83. m_pOuter = pPlayer;
  84. m_AnimConfig = config;
  85. ClearAnimationState();
  86. }
  87. void CBasePlayerAnimState::Release()
  88. {
  89. delete this;
  90. }
  91. void CBasePlayerAnimState::ClearAnimationState()
  92. {
  93. ClearAnimationLayers();
  94. m_bCurrentFeetYawInitialized = false;
  95. m_flLastAnimationStateClearTime = gpGlobals->curtime;
  96. }
  97. float CBasePlayerAnimState::TimeSinceLastAnimationStateClear() const
  98. {
  99. return gpGlobals->curtime - m_flLastAnimationStateClearTime;
  100. }
  101. void CBasePlayerAnimState::Update( float eyeYaw, float eyePitch )
  102. {
  103. VPROF( "CBasePlayerAnimState::Update" );
  104. // Clear animation overlays because we're about to completely reconstruct them.
  105. ClearAnimationLayers();
  106. // Some mods don't want to update the player's animation state if they're dead and ragdolled.
  107. if ( !ShouldUpdateAnimState() )
  108. {
  109. ClearAnimationState();
  110. return;
  111. }
  112. CStudioHdr *pStudioHdr = GetOuter()->GetModelPtr();
  113. // Store these. All the calculations are based on them.
  114. m_flEyeYaw = AngleNormalize( eyeYaw );
  115. m_flEyePitch = AngleNormalize( eyePitch );
  116. // Compute sequences for all the layers.
  117. ComputeSequences( pStudioHdr );
  118. // Compute all the pose params.
  119. ComputePoseParam_BodyPitch( pStudioHdr ); // Look up/down.
  120. ComputePoseParam_BodyYaw(); // Torso rotation.
  121. ComputePoseParam_MoveYaw( pStudioHdr ); // What direction his legs are running in.
  122. ComputePlaybackRate();
  123. #ifdef CLIENT_DLL
  124. if ( cl_showanimstate.GetInt() == m_pOuter->entindex() )
  125. {
  126. DebugShowAnimStateFull( 5 );
  127. }
  128. else if ( cl_showanimstate.GetInt() == -2 )
  129. {
  130. C_BasePlayer *targetPlayer = C_BasePlayer::GetLocalPlayer();
  131. if( targetPlayer && ( targetPlayer->GetObserverMode() == OBS_MODE_IN_EYE || targetPlayer->GetObserverMode() == OBS_MODE_CHASE ) )
  132. {
  133. C_BaseEntity *target = targetPlayer->GetObserverTarget();
  134. if( target && target->IsPlayer() )
  135. {
  136. targetPlayer = ToBasePlayer( target );
  137. }
  138. }
  139. if ( m_pOuter == targetPlayer )
  140. {
  141. DebugShowAnimStateFull( 6 );
  142. }
  143. }
  144. #else
  145. if ( sv_showanimstate.GetInt() == m_pOuter->entindex() )
  146. {
  147. DebugShowAnimState( 20 );
  148. }
  149. #endif
  150. }
  151. bool CBasePlayerAnimState::ShouldUpdateAnimState()
  152. {
  153. // By default, don't update their animation state when they're dead because they're
  154. // either a ragdoll or they're not drawn.
  155. return GetOuter()->IsAlive();
  156. }
  157. bool CBasePlayerAnimState::ShouldChangeSequences( void ) const
  158. {
  159. return true;
  160. }
  161. void CBasePlayerAnimState::SetOuterPoseParameter( int iParam, float flValue )
  162. {
  163. // Make sure to set all the history values too, otherwise the server can overwrite them.
  164. GetOuter()->SetPoseParameter( iParam, flValue );
  165. }
  166. void CBasePlayerAnimState::ClearAnimationLayers()
  167. {
  168. Assert( 0 ); // unused?
  169. VPROF( "CBasePlayerAnimState::ClearAnimationLayers" );
  170. if ( !m_pOuter )
  171. return;
  172. m_pOuter->SetNumAnimOverlays( AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS );
  173. for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
  174. {
  175. m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  176. #ifndef CLIENT_DLL
  177. m_pOuter->GetAnimOverlay( i )->m_fFlags = 0;
  178. #endif
  179. }
  180. }
  181. void CBasePlayerAnimState::RestartMainSequence()
  182. {
  183. CBaseAnimatingOverlay *pPlayer = GetOuter();
  184. pPlayer->m_flAnimTime = gpGlobals->curtime;
  185. pPlayer->SetCycle( 0 );
  186. }
  187. void CBasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  188. {
  189. VPROF( "CBasePlayerAnimState::ComputeSequences" );
  190. ComputeMainSequence(); // Lower body (walk/run/idle).
  191. UpdateInterpolators(); // The groundspeed interpolator uses the main sequence info.
  192. if ( m_AnimConfig.m_bUseAimSequences )
  193. {
  194. ComputeAimSequence(); // Upper body, based on weapon type.
  195. }
  196. }
  197. void CBasePlayerAnimState::ResetGroundSpeed( void )
  198. {
  199. m_flMaxGroundSpeed = GetCurrentMaxGroundSpeed();
  200. }
  201. void CBasePlayerAnimState::ComputeMainSequence()
  202. {
  203. VPROF( "CBasePlayerAnimState::ComputeMainSequence" );
  204. CBaseAnimatingOverlay *pPlayer = GetOuter();
  205. // Have our class or the mod-specific class determine what the current activity is.
  206. Activity idealActivity = CalcMainActivity();
  207. Activity oldActivity = m_eCurrentMainSequenceActivity;
  208. // Store our current activity so the aim and fire layers know what to do.
  209. m_eCurrentMainSequenceActivity = idealActivity;
  210. // Export to our outer class..
  211. int animDesired = SelectWeightedSequence( TranslateActivity(idealActivity) );
  212. #if !defined ( CSTRIKE_DLL )
  213. if ( !ShouldResetMainSequence( pPlayer->GetSequence(), animDesired ) )
  214. return;
  215. #endif
  216. ResetCycleAcrossCustomActivityChange( oldActivity, idealActivity );
  217. if ( animDesired < 0 )
  218. animDesired = 0;
  219. pPlayer->ResetSequence( animDesired );
  220. #ifdef CLIENT_DLL
  221. if ( ShouldResetGroundSpeed( oldActivity, idealActivity ) )
  222. {
  223. ResetGroundSpeed();
  224. }
  225. #endif
  226. }
  227. void CBasePlayerAnimState::ResetCycleAcrossCustomActivityChange( Activity iCurrent, Activity iNew )
  228. {
  229. if ( !GetOuter() )
  230. return;
  231. if ( iCurrent == ACT_CROUCHIDLE && iNew != ACT_CROUCHIDLE )
  232. {
  233. GetOuter()->SetCycle(0);
  234. }
  235. }
  236. bool CBasePlayerAnimState::ShouldResetMainSequence( int iCurrentSequence, int iNewSequence )
  237. {
  238. if ( !GetOuter() )
  239. return false;
  240. return GetOuter()->GetSequenceActivity( iCurrentSequence ) == GetOuter()->GetSequenceActivity( iNewSequence );
  241. }
  242. bool CBasePlayerAnimState::ShouldResetGroundSpeed( Activity oldActivity, Activity idealActivity )
  243. {
  244. // If we went from idle to walk, reset the interpolation history.
  245. return ( (oldActivity == ACT_CROUCHIDLE || oldActivity == ACT_IDLE || oldActivity == ACT_TURN || oldActivity == ACT_STEP_FORE ) &&
  246. (idealActivity == ACT_WALK || idealActivity == ACT_RUN_CROUCH || idealActivity == ACT_WALK_CROUCH || idealActivity == ACT_RUN ) );
  247. }
  248. void CBasePlayerAnimState::UpdateAimSequenceLayers(
  249. float flCycle,
  250. int iFirstLayer,
  251. bool bForceIdle,
  252. CSequenceTransitioner *pTransitioner,
  253. float flWeightScale
  254. )
  255. {
  256. float flAimSequenceWeight = 1;
  257. int iAimSequence = CalcAimLayerSequence( &flCycle, &flAimSequenceWeight, bForceIdle );
  258. if ( iAimSequence == -1 )
  259. iAimSequence = 0;
  260. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer );
  261. pLayer->SetSequence( iAimSequence );
  262. pLayer->SetCycle( flCycle );
  263. pLayer->SetWeight( clamp( flWeightScale, 0.0f, 1.0f ) );
  264. pLayer->SetOrder( iFirstLayer ); // should already be set
  265. #ifndef CLIENT_DLL
  266. pLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  267. #endif
  268. }
  269. void CBasePlayerAnimState::OptimizeLayerWeights( int iFirstLayer, int nLayers )
  270. {
  271. int i;
  272. // Find the total weight of the blended layers, not including the idle layer (iFirstLayer)
  273. float totalWeight = 0.0f;
  274. for ( i=1; i < nLayers; i++ )
  275. {
  276. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
  277. if ( pLayer->IsActive() && pLayer->GetWeight() > 0.0f )
  278. {
  279. totalWeight += pLayer->GetWeight();
  280. }
  281. }
  282. // Set the idle layer's weight to be 1 minus the sum of other layer weights
  283. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer );
  284. if ( pLayer->IsActive() && pLayer->GetWeight() > 0.0f )
  285. {
  286. float flWeight = 1.0f - totalWeight;
  287. flWeight = MAX( flWeight, 0.0f );
  288. pLayer->SetWeight( flWeight );
  289. }
  290. // This part is just an optimization. Since we have the walk/run animations weighted on top of
  291. // the idle animations, all this does is disable the idle animations if the walk/runs are at
  292. // full weighting, which is whenever a guy is at full speed.
  293. //
  294. // So it saves us blending a couple animation layers whenever a guy is walking or running full speed.
  295. int iLastOne = -1;
  296. for ( i=0; i < nLayers; i++ )
  297. {
  298. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
  299. if ( pLayer->IsActive() && pLayer->GetWeight() > 0.99 )
  300. iLastOne = i;
  301. }
  302. if ( iLastOne != -1 )
  303. {
  304. for ( int i=iLastOne-1; i >= 0; i-- )
  305. {
  306. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i );
  307. #ifdef CLIENT_DLL
  308. pLayer->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  309. #else
  310. pLayer->m_nOrder.Set( CBaseAnimatingOverlay::MAX_OVERLAYS );
  311. pLayer->m_fFlags = 0;
  312. #endif
  313. }
  314. }
  315. }
  316. bool CBasePlayerAnimState::ShouldBlendAimSequenceToIdle()
  317. {
  318. Activity act = GetCurrentMainSequenceActivity();
  319. return (act == ACT_RUN || act == ACT_LEAP || act == ACT_WALK || act == ACT_JUMP || act == ACT_RUNTOIDLE || act == ACT_RUN_CROUCH || act == ACT_WALK_CROUCH );
  320. }
  321. void CBasePlayerAnimState::ComputeAimSequence()
  322. {
  323. VPROF( "CBasePlayerAnimState::ComputeAimSequence" );
  324. // Synchronize the lower and upper body cycles.
  325. float flCycle = m_pOuter->GetCycle();
  326. //[msmith]
  327. bool bIsMoving = false;
  328. float flPlaybackRate = 0.0f;
  329. if ( ShouldBlendAimSequenceToIdle() )
  330. {
  331. // See how much the player should weigh in the motion vs. the idle layers.
  332. flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving );
  333. }
  334. // Set the idle layers to full (blend between different idle layers only and do NOT consider movement layers).
  335. UpdateAimSequenceLayers( flCycle, AIMSEQUENCE_LAYER, true, &m_HighAimSequenceTransitioner, 1.0f );
  336. if ( bIsMoving )
  337. {
  338. // Blend the run / walk layers together.
  339. UpdateAimSequenceLayers( flCycle, AIMSEQUENCE_LAYER+1, false, &m_LowAimSequenceTransitioner, flPlaybackRate );
  340. }
  341. OptimizeLayerWeights( AIMSEQUENCE_LAYER, NUM_AIMSEQUENCE_LAYERS );
  342. }
  343. int CBasePlayerAnimState::CalcSequenceIndex( PRINTF_FORMAT_STRING const char *pBaseName, ... )
  344. {
  345. char szFullName[512];
  346. va_list marker;
  347. va_start( marker, pBaseName );
  348. Q_vsnprintf( szFullName, sizeof( szFullName ), pBaseName, marker );
  349. va_end( marker );
  350. int iSequence = GetOuter()->LookupSequence( szFullName );
  351. // Show warnings if we can't find anything here.
  352. if ( iSequence == -1 )
  353. {
  354. static CUtlDict<int,int> dict;
  355. if ( dict.Find( szFullName ) == dict.InvalidIndex() )
  356. {
  357. dict.Insert( szFullName, 0 );
  358. Warning( "CalcSequenceIndex: can't find '%s'.\n", szFullName );
  359. }
  360. iSequence = 0;
  361. }
  362. return iSequence;
  363. }
  364. void CBasePlayerAnimState::UpdateInterpolators()
  365. {
  366. VPROF( "CBasePlayerAnimState::UpdateInterpolators" );
  367. // First, figure out their current max speed based on their current activity.
  368. float flCurMaxSpeed = GetCurrentMaxGroundSpeed();
  369. m_flMaxGroundSpeed = flCurMaxSpeed;
  370. }
  371. float CBasePlayerAnimState::GetInterpolatedGroundSpeed()
  372. {
  373. return m_flMaxGroundSpeed;
  374. }
  375. float CBasePlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
  376. {
  377. // Determine ideal playback rate
  378. Vector vel;
  379. GetOuterAbsVelocity( vel );
  380. float speed = vel.Length2D();
  381. bool isMoving = ( speed > MOVING_MINIMUM_SPEED );
  382. *bIsMoving = false;
  383. float flReturnValue = 1;
  384. if ( isMoving && CanThePlayerMove() )
  385. {
  386. float flGroundSpeed = GetInterpolatedGroundSpeed();
  387. if ( flGroundSpeed < 0.001f )
  388. {
  389. flReturnValue = 0.01;
  390. }
  391. else
  392. {
  393. flReturnValue = speed / flGroundSpeed;
  394. flReturnValue = clamp( flReturnValue, 0.01, 10 ); // don't go nuts here.
  395. }
  396. *bIsMoving = true;
  397. }
  398. return flReturnValue;
  399. }
  400. bool CBasePlayerAnimState::CanThePlayerMove()
  401. {
  402. return true;
  403. }
  404. void CBasePlayerAnimState::ComputePlaybackRate()
  405. {
  406. VPROF( "CBasePlayerAnimState::ComputePlaybackRate" );
  407. if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY )
  408. {
  409. // When using a 9-way blend, playback rate is always 1 and we just scale the pose params
  410. // to speed up or slow down the animation.
  411. bool bIsMoving;
  412. float flRate = CalcMovementPlaybackRate( &bIsMoving );
  413. if ( bIsMoving )
  414. GetOuter()->SetPlaybackRate( flRate );
  415. else
  416. GetOuter()->SetPlaybackRate( 1 );
  417. }
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Purpose:
  421. // Output : CBasePlayer
  422. //-----------------------------------------------------------------------------
  423. CBaseAnimatingOverlay *CBasePlayerAnimState::GetOuter() const
  424. {
  425. return m_pOuter;
  426. }
  427. //-----------------------------------------------------------------------------
  428. // Purpose:
  429. // Input : dt -
  430. //-----------------------------------------------------------------------------
  431. void CBasePlayerAnimState::EstimateYaw()
  432. {
  433. Vector est_velocity;
  434. GetOuterAbsVelocity( est_velocity );
  435. float flLength = est_velocity.Length2D();
  436. if ( flLength > MOVING_MINIMUM_SPEED )
  437. {
  438. m_flGaitYaw = atan2( est_velocity[1], est_velocity[0] );
  439. m_flGaitYaw = RAD2DEG( m_flGaitYaw );
  440. m_flGaitYaw = AngleNormalize( m_flGaitYaw );
  441. }
  442. }
  443. #define MOVEMENT_MINIMUM_ANIMATED_SPEED 10.0f
  444. #define MOVEMENT_MAXIMUM_PLAYBACK_RATE 1.3f
  445. //-----------------------------------------------------------------------------
  446. // Purpose: Override for backpeddling
  447. // Input : dt -
  448. //-----------------------------------------------------------------------------
  449. void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
  450. {
  451. VPROF( "CBasePlayerAnimState::ComputePoseParam_MoveYaw" );
  452. //Matt: Goldsrc style animations need to not rotate the model
  453. if ( m_AnimConfig.m_LegAnimType == LEGANIM_GOLDSRC )
  454. {
  455. #ifndef CLIENT_DLL
  456. //Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
  457. GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
  458. #endif
  459. }
  460. // If using goldsrc-style animations where he's moving in the direction that his feet are facing,
  461. // we don't use move yaw.
  462. if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY )
  463. return;
  464. // view direction relative to movement
  465. float flYaw;
  466. EstimateYaw();
  467. float ang = m_flEyeYaw;
  468. if ( ang > 180.0f )
  469. {
  470. ang -= 360.0f;
  471. }
  472. else if ( ang < -180.0f )
  473. {
  474. ang += 360.0f;
  475. }
  476. // calc side to side turning
  477. flYaw = ang - m_flGaitYaw;
  478. // Invert for mapping into 8way blend
  479. flYaw = -flYaw;
  480. flYaw = flYaw - (int)(flYaw / 360) * 360;
  481. if (flYaw < -180)
  482. {
  483. flYaw = flYaw + 360;
  484. }
  485. else if (flYaw > 180)
  486. {
  487. flYaw = flYaw - 360;
  488. }
  489. if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY )
  490. {
  491. //Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
  492. //[msmith]: Since bounding box code uses the entities local angle, we need the local angle to match
  493. // the render angle on both the server AND the client. The server for hit tests, the client
  494. // for proper visibility culling.
  495. GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
  496. int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" );
  497. int iMoveY = GetOuter()->LookupPoseParameter( pStudioHdr, "move_y" );
  498. if ( iMoveX < 0 || iMoveY < 0 )
  499. return;
  500. bool bIsMoving;
  501. float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving );
  502. #ifdef CLIENT_DLL
  503. Vector vel;
  504. GetOuterAbsVelocity( vel );
  505. bIsMoving = ( vel.Length2D() > 0 );
  506. #endif
  507. // Setup the 9-way blend parameters based on our speed and direction.
  508. Vector2D vCurMovePose( 0, 0 );
  509. m_flPoseParamTargetDampenedScaleIdeal = Approach( flPlaybackRate, m_flPoseParamTargetDampenedScaleIdeal, gpGlobals->frametime * POSE_PARAM_DELTA_DAMPEN );
  510. if ( bIsMoving )
  511. {
  512. vCurMovePose.x = cos( DEG2RAD( flYaw ) );
  513. vCurMovePose.y = -sin( DEG2RAD( flYaw ) );
  514. // movement pose parameters on the diagonals are encoded at 1 instead of 0.707 (cos 45)
  515. // scale to the outside of a box instead of the outside of a circle.
  516. float scale = fabs( vCurMovePose.x );
  517. float scale2 = fabs( vCurMovePose.y );
  518. if ( scale2 > scale ) scale = scale2;
  519. if ( scale > 0.01f )
  520. {
  521. scale = 1.0f / scale;
  522. vCurMovePose.x *= scale;
  523. vCurMovePose.y *= scale;
  524. }
  525. #ifdef CLIENT_DLL
  526. // find the max speed the animation will move in the current direction
  527. //If these aren't applied here, the legs stutter. Even though they're re-applied in a sec
  528. GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, vCurMovePose.x );
  529. GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, vCurMovePose.y );
  530. Vector vecAnimatedVel;
  531. GetOuter()->GetBlendedLinearVelocity( &vecAnimatedVel );
  532. float flAnimatedSpeed = vecAnimatedVel.Length2D();
  533. // find how to scale the current animation down to the desired speed
  534. Vector vel;
  535. GetOuterAbsVelocity( vel );
  536. float flMovementSpeed = vel.Length2D();
  537. if ( flAnimatedSpeed > CS_PLAYER_SPEED_RUN )
  538. flAnimatedSpeed = flMovementSpeed;
  539. if ( flAnimatedSpeed < MOVEMENT_MINIMUM_ANIMATED_SPEED )
  540. {
  541. // we're moving so slowly (either just starting or just stopping) that current playback rate is almost nothing.
  542. flPlaybackRate = flMovementSpeed / ( MOVEMENT_MINIMUM_ANIMATED_SPEED * 2.0f );
  543. }
  544. else
  545. {
  546. flPlaybackRate = flMovementSpeed / flAnimatedSpeed;
  547. }
  548. // player is moving less than what's animated, scale pose parameters back towards 0,0
  549. if ( flPlaybackRate < 1.0f )
  550. {
  551. if ( flPlaybackRate > 0.08f )
  552. {
  553. vCurMovePose.x *= flPlaybackRate;
  554. vCurMovePose.y *= flPlaybackRate;
  555. GetOuter()->SetPlaybackRate( flPlaybackRate );
  556. }
  557. else
  558. {
  559. vCurMovePose.x *= 0.08f;
  560. vCurMovePose.y *= 0.08f;
  561. GetOuter()->SetPlaybackRate( 1.0f );
  562. }
  563. }
  564. else
  565. {
  566. // speed up the animation to match the needed motion, but only so far
  567. flPlaybackRate = clamp( flPlaybackRate, 1.0f, MOVEMENT_MAXIMUM_PLAYBACK_RATE );
  568. GetOuter()->SetPlaybackRate( flPlaybackRate );
  569. }
  570. #endif
  571. vCurMovePose.x *= m_flPoseParamTargetDampenedScaleIdeal;
  572. vCurMovePose.y *= m_flPoseParamTargetDampenedScaleIdeal;
  573. }
  574. GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, vCurMovePose.x );
  575. GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, vCurMovePose.y );
  576. m_vLastMovePose = vCurMovePose;
  577. }
  578. else
  579. {
  580. int iMoveYaw = GetOuter()->LookupPoseParameter( pStudioHdr, "move_yaw" );
  581. if ( iMoveYaw >= 0 )
  582. {
  583. GetOuter()->SetPoseParameter( pStudioHdr, iMoveYaw, flYaw );
  584. m_flLastMoveYaw = flYaw;
  585. // Now blend in his idle animation.
  586. // This makes the 8-way blend act like a 9-way blend by blending to
  587. // an idle sequence as he slows down.
  588. #if defined(CLIENT_DLL)
  589. #ifndef INFESTED_DLL
  590. bool bIsMoving;
  591. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER );
  592. pLayer->SetWeight( 1 - CalcMovementPlaybackRate( &bIsMoving ) );
  593. if ( !bIsMoving )
  594. {
  595. pLayer->SetWeight( 1 );
  596. }
  597. if ( ShouldChangeSequences() )
  598. {
  599. // Whenever this layer stops blending, we can choose a new idle sequence to blend to, so he
  600. // doesn't always use the same idle.
  601. if ( pLayer->GetWeight() < 0.02f || m_iCurrent8WayIdleSequence == -1 )
  602. {
  603. m_iCurrent8WayIdleSequence = m_pOuter->SelectWeightedSequence( ACT_IDLE );
  604. m_iCurrent8WayCrouchIdleSequence = m_pOuter->SelectWeightedSequence( ACT_CROUCHIDLE );
  605. }
  606. if ( m_eCurrentMainSequenceActivity == ACT_CROUCHIDLE || m_eCurrentMainSequenceActivity == ACT_RUN_CROUCH )
  607. pLayer->SetSequence( m_iCurrent8WayCrouchIdleSequence );
  608. else
  609. pLayer->SetSequence( m_iCurrent8WayIdleSequence );
  610. }
  611. pLayer->SetPlaybackRate( 1 );
  612. pLayer->SetCycle( pLayer->GetCycle() + m_pOuter->GetSequenceCycleRate( pStudioHdr, pLayer->GetSequence() ) * gpGlobals->frametime );
  613. pLayer->SetCycle( fmod( pLayer->GetCycle(), 1 ) );
  614. pLayer->SetOrder( MAIN_IDLE_SEQUENCE_LAYER );
  615. #endif
  616. #endif
  617. }
  618. }
  619. }
  620. //-----------------------------------------------------------------------------
  621. // Purpose:
  622. //-----------------------------------------------------------------------------
  623. void CBasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
  624. {
  625. VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyPitch" );
  626. // Get pitch from v_angle
  627. float flPitch = m_flEyePitch;
  628. if ( flPitch > 180.0f )
  629. {
  630. flPitch -= 360.0f;
  631. }
  632. flPitch = clamp( flPitch, -90, 90 );
  633. // See if we have a blender for pitch
  634. int pitch = GetOuter()->LookupPoseParameter( pStudioHdr, "body_pitch" );
  635. if ( pitch < 0 )
  636. return;
  637. GetOuter()->SetPoseParameter( pStudioHdr, pitch, flPitch );
  638. g_flLastBodyPitch = flPitch;
  639. }
  640. //-----------------------------------------------------------------------------
  641. // Purpose:
  642. // Input : goal -
  643. // maxrate -
  644. // dt -
  645. // current -
  646. // Output : int
  647. //-----------------------------------------------------------------------------
  648. int CBasePlayerAnimState::ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current )
  649. {
  650. int direction = TURN_NONE;
  651. float anglediff = goal - current;
  652. anglediff = AngleNormalize( anglediff );
  653. float anglediffabs = fabs( anglediff );
  654. float scale = 1.0f;
  655. if ( anglediffabs <= FADE_TURN_DEGREES )
  656. {
  657. scale = anglediffabs / FADE_TURN_DEGREES;
  658. // Always do at least a bit of the turn ( 1% )
  659. scale = clamp( scale, 0.01f, 1.0f );
  660. }
  661. float maxmove = maxrate * dt * scale;
  662. if ( anglediffabs > maxgap )
  663. {
  664. // gap is too big, jump
  665. //maxmove = (anglediffabs - maxgap);
  666. float flTooFar = MIN( anglediffabs - maxgap, maxmove * 5 );
  667. if ( anglediff > 0 )
  668. {
  669. current += flTooFar;
  670. }
  671. else
  672. {
  673. current -= flTooFar;
  674. }
  675. current = AngleNormalize( current );
  676. anglediff = goal - current;
  677. anglediff = AngleNormalize( anglediff );
  678. anglediffabs = fabs( anglediff );
  679. }
  680. if ( anglediffabs < maxmove )
  681. {
  682. // we are close enought, just set the final value
  683. current = goal;
  684. }
  685. else
  686. {
  687. // adjust value up or down
  688. if ( anglediff > 0 )
  689. {
  690. current += maxmove;
  691. direction = TURN_LEFT;
  692. }
  693. else
  694. {
  695. current -= maxmove;
  696. direction = TURN_RIGHT;
  697. }
  698. }
  699. current = AngleNormalize( current );
  700. return direction;
  701. }
  702. void CBasePlayerAnimState::ComputePoseParam_BodyYaw()
  703. {
  704. VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyYaw" );
  705. // Find out which way he's running (m_flEyeYaw is the way he's looking).
  706. Vector vel;
  707. GetOuterAbsVelocity( vel );
  708. bool bIsMoving = vel.Length2D() > MOVING_MINIMUM_SPEED;
  709. // If we just initialized this guy (maybe he just came into the PVS), then immediately
  710. // set his feet in the right direction, otherwise they'll spin around from 0 to the
  711. // right direction every time someone switches spectator targets.
  712. if ( !m_bCurrentFeetYawInitialized )
  713. {
  714. m_bCurrentFeetYawInitialized = true;
  715. m_flGoalFeetYaw = m_flCurrentFeetYaw = m_flEyeYaw;
  716. m_flLastTurnTime = 0.0f;
  717. m_bInFootPlantIdleTurn = false;
  718. }
  719. else if ( bIsMoving || m_bForceAimYaw )
  720. {
  721. // player is moving, feet yaw = aiming yaw
  722. if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY || m_AnimConfig.m_LegAnimType == LEGANIM_8WAY )
  723. {
  724. // His feet point in the direction his eyes are, but they can run in any direction.
  725. m_flGoalFeetYaw = m_flEyeYaw;
  726. }
  727. else
  728. {
  729. m_flGoalFeetYaw = RAD2DEG( atan2( vel.y, vel.x ) );
  730. // If he's running backwards, flip his feet backwards.
  731. Vector vEyeYaw( cos( DEG2RAD( m_flEyeYaw ) ), sin( DEG2RAD( m_flEyeYaw ) ), 0 );
  732. Vector vFeetYaw( cos( DEG2RAD( m_flGoalFeetYaw ) ), sin( DEG2RAD( m_flGoalFeetYaw ) ), 0 );
  733. if ( vEyeYaw.Dot( vFeetYaw ) < -0.01 )
  734. {
  735. m_flGoalFeetYaw += 180;
  736. }
  737. }
  738. m_bInFootPlantIdleTurn = false;
  739. }
  740. else if ( (gpGlobals->curtime - m_flLastTurnTime) > mp_facefronttime.GetFloat() && m_flGoalFeetYaw != m_flEyeYaw )
  741. {
  742. // player didn't move & turn for quite some time
  743. if ( vel.Length2D() <= FOOTPLANT_MINIMUM_SPEED )
  744. {
  745. m_bInFootPlantIdleTurn = true;
  746. if ( m_flFootPlantIdleTurnCycle >= 1 )
  747. m_flFootPlantIdleTurnCycle = 0;
  748. }
  749. float flDiff = AngleNormalize(m_flGoalFeetYaw - m_flEyeYaw);
  750. m_bFootPlantIdleNeedToLiftFeet = (fabs(flDiff) > m_AnimConfig.m_flIdleFootPlantFootLiftDelta);
  751. m_flGoalFeetYaw = m_flEyeYaw;
  752. }
  753. else
  754. {
  755. // If he's rotated his view further than the model can turn, make him face forward.
  756. float flDiff = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw );
  757. if ( fabs(flDiff) > m_AnimConfig.m_flMaxBodyYawDegrees )
  758. {
  759. if ( vel.Length2D() <= FOOTPLANT_MINIMUM_SPEED )
  760. {
  761. m_bInFootPlantIdleTurn = true;
  762. if ( m_flFootPlantIdleTurnCycle >= 1 )
  763. m_flFootPlantIdleTurnCycle = 0;
  764. }
  765. m_bFootPlantIdleNeedToLiftFeet = true;
  766. if ( flDiff > 0 )
  767. m_flGoalFeetYaw -= m_AnimConfig.m_flMaxBodyYawDegreesCorrectionAmount;
  768. else
  769. m_flGoalFeetYaw += m_AnimConfig.m_flMaxBodyYawDegreesCorrectionAmount;
  770. }
  771. // If current yaw is significantly different from goal, abort idle foot ik to avoid intersecting the legs
  772. if ( m_bInFootPlantIdleTurn )
  773. {
  774. float flDiffYaw = AngleNormalize(m_flCurrentFeetYaw - m_flGoalFeetYaw);
  775. if ( fabs(flDiffYaw) > m_AnimConfig.m_flIdleFootPlantMaxYaw )
  776. {
  777. m_bInFootPlantIdleTurn = false;
  778. m_flFootPlantIdleTurnCycle = 0;
  779. }
  780. }
  781. }
  782. m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw );
  783. if ( m_flCurrentFeetYaw != m_flGoalFeetYaw )
  784. {
  785. if ( m_bForceAimYaw )
  786. {
  787. m_flCurrentFeetYaw = m_flGoalFeetYaw;
  788. }
  789. else
  790. {
  791. ConvergeAngles( m_flGoalFeetYaw, GetFeetYawRate(), m_AnimConfig.m_flMaxBodyYawDegrees, gpGlobals->frametime, m_flCurrentFeetYaw );
  792. }
  793. m_flLastTurnTime = gpGlobals->curtime;
  794. }
  795. // Turn off a force aim yaw - either we have already updated or we don't need to.
  796. m_bForceAimYaw = false;
  797. float flCurrentTorsoYaw = AngleNormalize( m_flEyeYaw - m_flCurrentFeetYaw );
  798. // Rotate entire body into position
  799. m_angRender[YAW] = m_flCurrentFeetYaw;
  800. m_angRender[PITCH] = m_angRender[ROLL] = 0;
  801. SetOuterBodyYaw( flCurrentTorsoYaw );
  802. g_flLastBodyYaw = flCurrentTorsoYaw;
  803. }
  804. float CBasePlayerAnimState::SetOuterBodyYaw( float flValue )
  805. {
  806. int body_yaw = GetOuter()->LookupPoseParameter( "body_yaw" );
  807. if ( body_yaw < 0 )
  808. {
  809. return 0;
  810. }
  811. SetOuterPoseParameter( body_yaw, flValue );
  812. return flValue;
  813. }
  814. //-----------------------------------------------------------------------------
  815. // Purpose:
  816. // Input : activity -
  817. // Output : Activity
  818. //-----------------------------------------------------------------------------
  819. Activity CBasePlayerAnimState::BodyYawTranslateActivity( Activity activity )
  820. {
  821. // Not even standing still, sigh
  822. if ( activity != ACT_IDLE )
  823. return activity;
  824. // Not turning
  825. switch ( m_nTurningInPlace )
  826. {
  827. default:
  828. case TURN_NONE:
  829. return activity;
  830. case TURN_RIGHT:
  831. case TURN_LEFT:
  832. return mp_ik.GetBool() ? ACT_TURN : activity;
  833. }
  834. Assert( 0 );
  835. return activity;
  836. }
  837. const QAngle& CBasePlayerAnimState::GetRenderAngles()
  838. {
  839. return m_angRender;
  840. }
  841. void CBasePlayerAnimState::SetForceAimYaw( bool bForce )
  842. {
  843. m_bForceAimYaw = bForce;
  844. }
  845. void CBasePlayerAnimState::GetOuterAbsVelocity( Vector& vel ) const
  846. {
  847. #if defined( CLIENT_DLL )
  848. GetOuter()->EstimateAbsVelocity( vel );
  849. #else
  850. vel = GetOuter()->GetAbsVelocity();
  851. #endif
  852. }
  853. float CBasePlayerAnimState::GetOuterXYSpeed() const
  854. {
  855. Vector vel;
  856. GetOuterAbsVelocity( vel );
  857. return vel.Length2D();
  858. }
  859. // -----------------------------------------------------------------------------
  860. void CBasePlayerAnimState::AnimStateLog( PRINTF_FORMAT_STRING const char *pMsg, ... )
  861. {
  862. // Format the string.
  863. char str[4096];
  864. va_list marker;
  865. va_start( marker, pMsg );
  866. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  867. va_end( marker );
  868. // Log it?
  869. if ( showanimstate_log.GetInt() == 1 || showanimstate_log.GetInt() == 3 )
  870. {
  871. Msg( "%s", str );
  872. }
  873. if ( showanimstate_log.GetInt() > 1 )
  874. {
  875. #ifdef CLIENT_DLL
  876. const char *fname = "AnimStateClient.log";
  877. #else
  878. const char *fname = "AnimStateServer.log";
  879. #endif
  880. static FileHandle_t hFile = filesystem->Open( fname, "wt" );
  881. filesystem->FPrintf( hFile, "%s", str );
  882. filesystem->Flush( hFile );
  883. }
  884. }
  885. // -----------------------------------------------------------------------------
  886. void CBasePlayerAnimState::AnimStatePrintf( int iLine, PRINTF_FORMAT_STRING const char *pMsg, ... )
  887. {
  888. // Format the string.
  889. char str[4096];
  890. va_list marker;
  891. va_start( marker, pMsg );
  892. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  893. va_end( marker );
  894. // Show it with Con_NPrintf.
  895. engine->Con_NPrintf( iLine, "%s", str );
  896. // Log it.
  897. AnimStateLog( "%s\n", str );
  898. }
  899. // -----------------------------------------------------------------------------
  900. void CBasePlayerAnimState::DebugShowAnimState( int iStartLine )
  901. {
  902. Vector vOuterVel;
  903. GetOuterAbsVelocity( vOuterVel );
  904. int iLine = iStartLine;
  905. AnimStatePrintf( iLine++, "main: %s(%d), cycle: %.2f cyclerate: %.2f playbackrate: %.2f\n",
  906. GetSequenceName( m_pOuter->GetModelPtr(), m_pOuter->GetSequence() ),
  907. m_pOuter->GetSequence(),
  908. m_pOuter->GetCycle(),
  909. m_pOuter->GetSequenceCycleRate(m_pOuter->GetModelPtr(), m_pOuter->GetSequence()),
  910. m_pOuter->GetPlaybackRate()
  911. );
  912. if ( m_AnimConfig.m_LegAnimType == LEGANIM_8WAY )
  913. {
  914. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER );
  915. AnimStatePrintf( iLine++, "idle: %s, weight: %.2f\n",
  916. GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ),
  917. (float)pLayer->GetWeight() );
  918. }
  919. for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ )
  920. {
  921. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i );
  922. #ifdef CLIENT_DLL
  923. AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
  924. !pLayer->IsActive() ? "-- ": (pLayer->GetSequence() == 0 ? "-- " : (showanimstate_activities.GetBool()) ? GetSequenceActivityName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) ),
  925. !pLayer->IsActive() ? 0 : (int)pLayer->GetSequence(),
  926. !pLayer->IsActive() ? 0 : (float)pLayer->GetWeight(),
  927. !pLayer->IsActive() ? 0 : (float)pLayer->GetCycle(),
  928. !pLayer->IsActive() ? 0 : (int)pLayer->GetOrder(),
  929. i
  930. );
  931. #else
  932. AnimStatePrintf( iLine++, "%s(%d), flags (%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
  933. !pLayer->IsActive() ? "-- " : ( pLayer->GetSequence() == 0 ? "-- " : (showanimstate_activities.GetBool()) ? GetSequenceActivityName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->GetSequence() ) ),
  934. !pLayer->IsActive() ? 0 : (int)pLayer->GetSequence(),
  935. !pLayer->IsActive() ? 0 : (int)pLayer->m_fFlags,// Doesn't exist on client
  936. !pLayer->IsActive() ? 0 : (float)pLayer->GetWeight(),
  937. !pLayer->IsActive() ? 0 : (float)pLayer->GetCycle(),
  938. !pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder,
  939. i
  940. );
  941. #endif
  942. }
  943. AnimStatePrintf( iLine++, "vel: %.2f, time: %.2f, max: %.2f, animspeed: %.2f",
  944. vOuterVel.Length2D(), gpGlobals->curtime, GetInterpolatedGroundSpeed(), m_pOuter->GetSequenceGroundSpeed(m_pOuter->GetSequence()) );
  945. if ( m_AnimConfig.m_LegAnimType == LEGANIM_8WAY )
  946. {
  947. AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, move_yaw: %.2f, gait_yaw: %.2f, body_pitch: %.2f",
  948. m_angRender[YAW], g_flLastBodyYaw, m_flLastMoveYaw, m_flGaitYaw, g_flLastBodyPitch );
  949. }
  950. else
  951. {
  952. AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, body_pitch: %.2f, move_x: %.2f, move_y: %.2f",
  953. m_angRender[YAW], g_flLastBodyYaw, g_flLastBodyPitch, m_vLastMovePose.x, m_vLastMovePose.y );
  954. }
  955. // Draw a red triangle on the ground for the eye yaw.
  956. float flBaseSize = 10;
  957. float flHeight = 80;
  958. Vector vBasePos = GetOuter()->GetAbsOrigin() + Vector( 0, 0, 3 );
  959. QAngle angles( 0, 0, 0 );
  960. angles[YAW] = m_flEyeYaw;
  961. Vector vForward, vRight, vUp;
  962. AngleVectors( angles, &vForward, &vRight, &vUp );
  963. debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 255, 0, 0, 255, false, gpGlobals->frametime );
  964. // Draw a blue triangle on the ground for the body yaw.
  965. angles[YAW] = m_angRender[YAW];
  966. AngleVectors( angles, &vForward, &vRight, &vUp );
  967. debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 0, 255, 255, false, gpGlobals->frametime );
  968. //left limit
  969. angles[YAW] = m_flEyeYaw - 60;
  970. AngleVectors(angles, &vForward, &vRight, &vUp);
  971. debugoverlay->AddTriangleOverlay(vBasePos + vRight*flBaseSize / 4, vBasePos - vRight*flBaseSize / 4, vBasePos + vForward*flHeight, 0, 255, 0, 100, false, gpGlobals->frametime);
  972. //right limit
  973. angles[YAW] = m_flEyeYaw + 60;
  974. AngleVectors(angles, &vForward, &vRight, &vUp);
  975. debugoverlay->AddTriangleOverlay(vBasePos + vRight*flBaseSize / 4, vBasePos - vRight*flBaseSize / 4, vBasePos + vForward*flHeight, 0, 255, 0, 100, false, gpGlobals->frametime);
  976. }
  977. // -----------------------------------------------------------------------------
  978. void CBasePlayerAnimState::DebugShowAnimStateFull( int iStartLine )
  979. {
  980. AnimStateLog( "----------------- frame %d -----------------\n", gpGlobals->framecount );
  981. DebugShowAnimState( iStartLine );
  982. AnimStateLog( "--------------------------------------------\n\n" );
  983. }
  984. // -----------------------------------------------------------------------------
  985. int CBasePlayerAnimState::SelectWeightedSequence( Activity activity )
  986. {
  987. return GetOuter()->SelectWeightedSequence( activity );
  988. }
  989. float CBasePlayerAnimState::GetFeetYawRate( void )
  990. {
  991. return mp_feetyawrate.GetFloat();
  992. }