Team Fortress 2 Source Code as on 22/4/2020
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.

1454 lines
39 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "dod_playeranimstate.h"
  8. #include "base_playeranimstate.h"
  9. #include "tier0/vprof.h"
  10. #include "animation.h"
  11. #include "studio.h"
  12. #include "apparent_velocity_helper.h"
  13. #include "utldict.h"
  14. #include "weapon_dodbase.h"
  15. #include "dod_shareddefs.h"
  16. #ifdef CLIENT_DLL
  17. #include "c_dod_player.h"
  18. #include "engine/ivdebugoverlay.h"
  19. #include "filesystem.h"
  20. ConVar anim_showmainactivity( "anim_showmainactivity", "0", FCVAR_CHEAT, "Show the idle, walk, run, and/or sprint activities." );
  21. #else
  22. #include "dod_player.h"
  23. #endif
  24. ConVar anim_showstate( "anim_showstate", "-1", FCVAR_CHEAT | FCVAR_REPLICATED, "Show the (client) animation state for the specified entity (-1 for none)." );
  25. ConVar anim_showstatelog( "anim_showstatelog", "0", FCVAR_CHEAT | FCVAR_REPLICATED, "1 to output anim_showstate to Msg(). 2 to store in AnimState.log. 3 for both." );
  26. ConVar dod_bodyheightoffset( "dod_bodyheightoffset", "4", FCVAR_CHEAT | FCVAR_REPLICATED, "Deploy height offset." );
  27. #define ANIMPART_STAND "stand"
  28. #define ANIMPART_PRONE "prone"
  29. #define ANIMPART_CROUCH "crouch"
  30. #define ANIMPART_SPRINT "sprint"
  31. #define ANIMPART_SANDBAG "sandbag"
  32. #define ANIMPART_BIPOD "bipod"
  33. // When moving this fast, he plays run anim.
  34. #define ARBITRARY_RUN_SPEED 300.0f
  35. #define DOD_BODYYAW_RATE 720.0f
  36. #define DOD_WALK_SPEED 60.0f
  37. #define DOD_RUN_SPEED 120.0f
  38. #define DOD_SPRINT_SPEED 260.0f
  39. class CDODPlayerAnimState : public CBasePlayerAnimState, public IDODPlayerAnimState
  40. {
  41. public:
  42. DECLARE_CLASS( CDODPlayerAnimState, CBasePlayerAnimState );
  43. friend IDODPlayerAnimState* CreatePlayerAnimState( CDODPlayer *pPlayer );
  44. CDODPlayerAnimState();
  45. virtual void ShowDebugInfo( void );
  46. // This is called by both the client and the server in the same way to trigger events for
  47. // players firing, jumping, throwing grenades, etc.
  48. virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
  49. virtual void ClearAnimationState();
  50. virtual Activity CalcMainActivity();
  51. virtual void Update( float eyeYaw, float eyePitch );
  52. virtual void DebugShowAnimState( int iStartLine );
  53. virtual int CalcAimLayerSequence( float *flCyle, float *flAimSequenceWeight, bool bForceIdle ) { return 0; }
  54. virtual float GetCurrentMaxGroundSpeed();
  55. virtual void ComputeSequences( CStudioHdr *pStudioHdr );
  56. virtual void ClearAnimationLayers();
  57. virtual void RestartMainSequence();
  58. virtual float CalcMovementPlaybackRate( bool *bIsMoving );
  59. Activity TranslateActivity( Activity actDesired );
  60. void CancelGestures( void );
  61. protected:
  62. // Pose paramters.
  63. bool SetupPoseParameters( CStudioHdr *pStudioHdr );
  64. virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr );
  65. virtual void ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr );
  66. virtual void ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr );
  67. void ComputePoseParam_BodyHeight( CStudioHdr *pStudioHdr );
  68. virtual void EstimateYaw( void );
  69. void ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw );
  70. void ComputeFireSequence();
  71. void ComputeDeployedSequence();
  72. void ComputeGestureSequence( CStudioHdr *pStudioHdr );
  73. void RestartGesture( int iGestureType, Activity act, bool bAutoKill = true );
  74. void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd, float flWeight = 1.0 );
  75. void DebugShowAnimStateForPlayer( bool bIsServer );
  76. void DebugShowEyeYaw( void );
  77. // Client specific.
  78. #ifdef CLIENT_DLL
  79. // Debug.
  80. void DebugShowActivity( Activity activity );
  81. #endif
  82. private:
  83. void InitDOD( CDODPlayer *pPlayer );
  84. bool HandleJumping( Activity *idealActivity );
  85. bool HandleProne( Activity *idealActivity );
  86. bool HandleProneDown( CDODPlayer *pPlayer, Activity *idealActivity );
  87. bool HandleProneUp( CDODPlayer *pPlayer, Activity *idealActivity );
  88. bool HandleDucked( Activity *idealActivity );
  89. bool IsGettingDown( CDODPlayer *pPlayer );
  90. bool IsGettingUp( CDODPlayer *pPlayer );
  91. CDODPlayer* GetOuterDOD() const;
  92. bool IsPlayingGesture( int type )
  93. {
  94. return ( m_bPlayingGesture && m_iGestureType == type );
  95. }
  96. private:
  97. // Current state variables.
  98. bool m_bJumping; // Set on a jump event.
  99. float m_flJumpStartTime;
  100. bool m_bFirstJumpFrame;
  101. // These control the prone state _achine.
  102. bool m_bGettingDown;
  103. bool m_bGettingUp;
  104. bool m_bWasGoingProne;
  105. bool m_bWasGettingUp;
  106. // The single Gesture layer
  107. bool m_bPlayingGesture;
  108. bool m_bAutokillGesture;
  109. int m_iGestureSequence;
  110. float m_flGestureCycle;
  111. int m_iGestureType;
  112. enum
  113. {
  114. GESTURE_NONE = -1,
  115. GESTURE_ATTACK1 = 0,
  116. GESTURE_ATTACK2,
  117. GESTURE_RELOAD,
  118. GESTURE_HAND_SIGNAL,
  119. GESTURE_FIDGET,
  120. GESTURE_PLANT,
  121. GESTURE_DEFUSE,
  122. };
  123. // Pose parameters.
  124. bool m_bPoseParameterInit;
  125. float m_flEstimateYaw;
  126. float m_flEstimateVelocity;
  127. float m_flLastAimPitch;
  128. float m_flLastAimYaw;
  129. float m_flLastBodyHeight;
  130. float m_flLastAimTurnTime;
  131. Vector2D m_vecLastMoveYaw;
  132. int m_iMoveX;
  133. int m_iMoveY;
  134. int m_iAimYaw;
  135. int m_iAimPitch;
  136. int m_iBodyHeight;
  137. float m_flFireIdleTime; // Time that we drop our gun
  138. bool m_bLastDeployState; // true = last was deployed, false = last was not deployed
  139. DODWeaponID m_iLastWeaponID; // remember the weapon we were last using
  140. // Our DOD player pointer.
  141. CDODPlayer *m_pOuterDOD;
  142. };
  143. IDODPlayerAnimState* CreatePlayerAnimState( CDODPlayer *pPlayer )
  144. {
  145. CDODPlayerAnimState *pState = new CDODPlayerAnimState;
  146. pState->InitDOD( pPlayer );
  147. return pState;
  148. }
  149. // -------------------------------------------------------------------------------- //
  150. // CDODPlayerAnimState implementation.
  151. // -------------------------------------------------------------------------------- //
  152. CDODPlayerAnimState::CDODPlayerAnimState()
  153. {
  154. m_bGettingDown = false;
  155. m_bGettingUp = false;
  156. m_bWasGoingProne = false;
  157. m_bWasGettingUp = false;
  158. m_pOuterDOD = NULL;
  159. m_bPoseParameterInit = false;
  160. m_flEstimateYaw = 0.0f;
  161. m_flLastAimPitch = 0.0f;
  162. m_flLastAimYaw = 0.0f;
  163. m_flLastBodyHeight = 0.0f;
  164. m_flLastAimTurnTime = 0.0f;
  165. m_vecLastMoveYaw.Init();
  166. m_iMoveX = -1;
  167. m_iMoveY = -1;
  168. m_iAimYaw = -1;
  169. m_iAimPitch = -1;
  170. m_iBodyHeight = -1;
  171. }
  172. void CDODPlayerAnimState::InitDOD( CDODPlayer *pPlayer )
  173. {
  174. m_pOuterDOD = pPlayer;
  175. CModAnimConfig config;
  176. config.m_flMaxBodyYawDegrees = 45;
  177. config.m_LegAnimType = LEGANIM_GOLDSRC;
  178. config.m_bUseAimSequences = false;
  179. BaseClass::Init( pPlayer, config );
  180. }
  181. void CDODPlayerAnimState::ClearAnimationState()
  182. {
  183. m_bJumping = false;
  184. m_flFireIdleTime = 0;
  185. m_bLastDeployState = false;
  186. m_iLastWeaponID = WEAPON_NONE;
  187. CancelGestures();
  188. BaseClass::ClearAnimationState();
  189. }
  190. void CDODPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
  191. {
  192. if ( event == PLAYERANIMEVENT_FIRE_GUN )
  193. {
  194. RestartGesture( GESTURE_ATTACK1, ACT_RANGE_ATTACK1, false );
  195. if( GetOuterDOD()->m_Shared.IsBazookaDeployed() )
  196. {
  197. m_flFireIdleTime = gpGlobals->curtime + 0.1; // don't hold this pose after firing
  198. }
  199. else
  200. {
  201. // hold last frame of fire pose for 2 seconds ( if we are moving )
  202. m_flFireIdleTime = gpGlobals->curtime + 2;
  203. }
  204. }
  205. if ( event == PLAYERANIMEVENT_SECONDARY_ATTACK )
  206. {
  207. CancelGestures();
  208. RestartGesture( GESTURE_ATTACK2, ACT_RANGE_ATTACK2 );
  209. }
  210. else if ( event == PLAYERANIMEVENT_RELOAD )
  211. {
  212. CancelGestures();
  213. RestartGesture( GESTURE_RELOAD, ACT_RELOAD );
  214. }
  215. else if ( event == PLAYERANIMEVENT_THROW_GRENADE )
  216. {
  217. CancelGestures();
  218. RestartGesture( GESTURE_ATTACK1, ACT_RANGE_ATTACK1 );
  219. }
  220. else if ( event == PLAYERANIMEVENT_ROLL_GRENADE )
  221. {
  222. CancelGestures();
  223. RestartGesture( GESTURE_ATTACK2, ACT_RANGE_ATTACK2 );
  224. }
  225. else if ( event == PLAYERANIMEVENT_JUMP )
  226. {
  227. // Play the jump animation.
  228. m_bJumping = true;
  229. m_bFirstJumpFrame = true;
  230. RestartMainSequence();
  231. m_flJumpStartTime = gpGlobals->curtime;
  232. }
  233. else if ( event == PLAYERANIMEVENT_HANDSIGNAL )
  234. {
  235. CDODPlayer *pPlayer = GetOuterDOD();
  236. if ( pPlayer && !( pPlayer->m_Shared.IsBazookaDeployed() || pPlayer->m_Shared.IsProne() || pPlayer->m_Shared.IsProneDeployed() || pPlayer->m_Shared.IsSniperZoomed() || pPlayer->m_Shared.IsSandbagDeployed() ) )
  237. {
  238. CancelGestures();
  239. RestartGesture( GESTURE_HAND_SIGNAL, ACT_DOD_HS_IDLE );
  240. }
  241. }
  242. else if ( event == PLAYERANIMEVENT_PLANT_TNT )
  243. {
  244. CancelGestures();
  245. RestartGesture( GESTURE_PLANT, ACT_DOD_PLANT_TNT );
  246. }
  247. else if ( event == PLAYERANIMEVENT_DEFUSE_TNT )
  248. {
  249. CancelGestures();
  250. RestartGesture( GESTURE_DEFUSE, ACT_DOD_DEFUSE_TNT );
  251. }
  252. }
  253. void CDODPlayerAnimState::ShowDebugInfo( void )
  254. {
  255. if ( anim_showstate.GetInt() == m_pOuter->entindex() )
  256. {
  257. DebugShowAnimStateForPlayer( m_pOuter->IsServer() );
  258. }
  259. }
  260. void CDODPlayerAnimState::RestartMainSequence()
  261. {
  262. CancelGestures();
  263. BaseClass::RestartMainSequence();
  264. }
  265. bool CDODPlayerAnimState::HandleJumping( Activity *idealActivity )
  266. {
  267. if ( m_bJumping )
  268. {
  269. if ( m_bFirstJumpFrame )
  270. {
  271. m_bFirstJumpFrame = false;
  272. RestartMainSequence(); // Reset the animation.
  273. }
  274. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  275. // on-ground flag set right when the message comes in.
  276. if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
  277. {
  278. if ( m_pOuter->GetFlags() & FL_ONGROUND )
  279. {
  280. m_bJumping = false;
  281. RestartMainSequence();
  282. }
  283. }
  284. }
  285. if ( m_bJumping )
  286. {
  287. *idealActivity = ACT_HOP;
  288. return true;
  289. }
  290. else
  291. {
  292. return false;
  293. }
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose: Handle the prone up animation.
  297. //-----------------------------------------------------------------------------
  298. bool CDODPlayerAnimState::HandleProneDown( CDODPlayer *pPlayer, Activity *idealActivity )
  299. {
  300. if ( ( pPlayer->GetCycle() > 0.99f ) || ( pPlayer->m_Shared.IsProne() ) )
  301. {
  302. *idealActivity = ACT_PRONE_IDLE;
  303. if ( GetOuterXYSpeed() > MOVING_MINIMUM_SPEED )
  304. {
  305. *idealActivity = ACT_PRONE_FORWARD;
  306. }
  307. RestartMainSequence();
  308. m_bGettingDown = false;
  309. }
  310. else
  311. {
  312. *idealActivity = ACT_GET_DOWN_STAND;
  313. if ( pPlayer->GetFlags() & FL_DUCKING )
  314. {
  315. *idealActivity = ACT_GET_DOWN_CROUCH;
  316. }
  317. }
  318. return true;
  319. }
  320. //-----------------------------------------------------------------------------
  321. // Purpose: Handle the prone up animation.
  322. //-----------------------------------------------------------------------------
  323. bool CDODPlayerAnimState::HandleProneUp( CDODPlayer *pPlayer, Activity *idealActivity )
  324. {
  325. if ( ( m_pOuter->GetCycle() > 0.99f ) || ( !pPlayer->m_Shared.IsGettingUpFromProne() ) )
  326. {
  327. m_bGettingUp = false;
  328. RestartMainSequence();
  329. return false;
  330. }
  331. *idealActivity = ACT_GET_UP_STAND;
  332. if ( pPlayer->GetFlags() & FL_DUCKING )
  333. {
  334. *idealActivity = ACT_GET_UP_CROUCH;
  335. }
  336. return true;
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Purpose: Handle the prone animations.
  340. //-----------------------------------------------------------------------------
  341. bool CDODPlayerAnimState::HandleProne( Activity *idealActivity )
  342. {
  343. // Get the player.
  344. CDODPlayer *pPlayer = GetOuterDOD();
  345. if ( !pPlayer )
  346. return false;
  347. // Find the leading edge on going prone.
  348. bool bChange = pPlayer->m_Shared.IsGoingProne() && !m_bWasGoingProne;
  349. m_bWasGoingProne = pPlayer->m_Shared.IsGoingProne();
  350. if ( bChange )
  351. {
  352. m_bGettingDown = true;
  353. RestartMainSequence();
  354. }
  355. // Find the leading edge on getting up.
  356. bChange = pPlayer->m_Shared.IsGettingUpFromProne() && !m_bWasGettingUp;
  357. m_bWasGettingUp = pPlayer->m_Shared.IsGettingUpFromProne();
  358. if ( bChange )
  359. {
  360. m_bGettingUp = true;
  361. RestartMainSequence();
  362. }
  363. // Handle the transitions.
  364. if ( m_bGettingDown )
  365. {
  366. return HandleProneDown( pPlayer, idealActivity );
  367. }
  368. else if ( m_bGettingUp )
  369. {
  370. return HandleProneUp( pPlayer, idealActivity );
  371. }
  372. // Handle the prone state.
  373. if ( pPlayer->m_Shared.IsProne() )
  374. {
  375. *idealActivity = ACT_PRONE_IDLE;
  376. if ( GetOuterXYSpeed() > MOVING_MINIMUM_SPEED )
  377. {
  378. *idealActivity = ACT_PRONE_FORWARD;
  379. }
  380. return true;
  381. }
  382. return false;
  383. }
  384. bool CDODPlayerAnimState::HandleDucked( Activity *idealActivity )
  385. {
  386. if ( m_pOuter->GetFlags() & FL_DUCKING )
  387. {
  388. if ( GetOuterXYSpeed() > MOVING_MINIMUM_SPEED )
  389. *idealActivity = ACT_RUN_CROUCH;
  390. else
  391. *idealActivity = ACT_CROUCHIDLE;
  392. return true;
  393. }
  394. else
  395. {
  396. return false;
  397. }
  398. }
  399. Activity CDODPlayerAnimState::CalcMainActivity()
  400. {
  401. Activity idealActivity = ACT_IDLE;
  402. float flSpeed = GetOuterXYSpeed();
  403. if ( HandleJumping( &idealActivity ) ||
  404. HandleProne( &idealActivity ) ||
  405. HandleDucked( &idealActivity ) )
  406. {
  407. // intentionally blank
  408. }
  409. else
  410. {
  411. if ( flSpeed > MOVING_MINIMUM_SPEED )
  412. {
  413. if( flSpeed >= DOD_SPRINT_SPEED )
  414. {
  415. idealActivity = ACT_SPRINT;
  416. // If we sprint, cancel the fire idle time
  417. CancelGestures();
  418. }
  419. else if( flSpeed >= DOD_WALK_SPEED )
  420. idealActivity = ACT_RUN;
  421. else
  422. idealActivity = ACT_WALK;
  423. }
  424. }
  425. // Shouldn't be here but we need to ship - bazooka deployed reload/running check.
  426. if ( IsPlayingGesture( GESTURE_RELOAD ) )
  427. {
  428. if ( flSpeed >= DOD_RUN_SPEED && m_pOuterDOD->m_Shared.IsBazookaOnlyDeployed() )
  429. {
  430. CancelGestures();
  431. }
  432. }
  433. ShowDebugInfo();
  434. // Client specific.
  435. #ifdef CLIENT_DLL
  436. if ( anim_showmainactivity.GetBool() )
  437. {
  438. DebugShowActivity( idealActivity );
  439. }
  440. #endif
  441. return idealActivity;
  442. }
  443. void CDODPlayerAnimState::CancelGestures( void )
  444. {
  445. m_bPlayingGesture = false;
  446. m_iGestureType = GESTURE_NONE;
  447. #ifdef CLIENT_DLL
  448. m_iGestureSequence = -1;
  449. #else
  450. m_pOuter->RemoveAllGestures();
  451. #endif
  452. }
  453. void CDODPlayerAnimState::RestartGesture( int iGestureType, Activity act, bool bAutoKill /* = true */ )
  454. {
  455. Activity idealActivity = TranslateActivity( act );
  456. m_bPlayingGesture = true;
  457. m_iGestureType = iGestureType;
  458. #ifdef CLIENT_DLL
  459. m_iGestureSequence = m_pOuter->SelectWeightedSequence( idealActivity );
  460. if( m_iGestureSequence == -1 )
  461. {
  462. m_bPlayingGesture = false;
  463. }
  464. m_flGestureCycle = 0.0f;
  465. m_bAutokillGesture = bAutoKill;
  466. #else
  467. m_pOuterDOD->RestartGesture( idealActivity, true, bAutoKill );
  468. #endif
  469. }
  470. Activity CDODPlayerAnimState::TranslateActivity( Activity actDesired )
  471. {
  472. Activity idealActivity = actDesired;
  473. if ( m_pOuterDOD->m_Shared.IsSandbagDeployed() )
  474. {
  475. switch( idealActivity )
  476. {
  477. case ACT_IDLE:
  478. idealActivity = ACT_DOD_DEPLOYED;
  479. break;
  480. case ACT_RANGE_ATTACK1:
  481. idealActivity = ACT_DOD_PRIMARYATTACK_DEPLOYED;
  482. break;
  483. case ACT_RELOAD:
  484. idealActivity = ACT_DOD_RELOAD_DEPLOYED;
  485. break;
  486. default:
  487. break;
  488. }
  489. }
  490. else if ( m_pOuterDOD->m_Shared.IsProneDeployed() )
  491. {
  492. switch( idealActivity )
  493. {
  494. case ACT_PRONE_IDLE:
  495. idealActivity = ACT_DOD_PRONE_DEPLOYED;
  496. break;
  497. case ACT_RANGE_ATTACK1:
  498. idealActivity = ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED;
  499. break;
  500. case ACT_RELOAD:
  501. idealActivity = ACT_DOD_RELOAD_PRONE_DEPLOYED;
  502. break;
  503. default:
  504. break;
  505. }
  506. }
  507. else if ( m_pOuterDOD->m_Shared.IsSniperZoomed() || m_pOuterDOD->m_Shared.IsBazookaDeployed() )
  508. {
  509. switch( idealActivity )
  510. {
  511. case ACT_IDLE:
  512. idealActivity = ACT_DOD_IDLE_ZOOMED;
  513. break;
  514. case ACT_WALK:
  515. idealActivity = ACT_DOD_WALK_ZOOMED;
  516. break;
  517. case ACT_CROUCHIDLE:
  518. idealActivity = ACT_DOD_CROUCH_ZOOMED;
  519. break;
  520. case ACT_RUN_CROUCH:
  521. idealActivity = ACT_DOD_CROUCHWALK_ZOOMED;
  522. break;
  523. case ACT_PRONE_IDLE:
  524. idealActivity = ACT_DOD_PRONE_ZOOMED;
  525. break;
  526. case ACT_PRONE_FORWARD:
  527. idealActivity = ACT_DOD_PRONE_FORWARD_ZOOMED;
  528. break;
  529. case ACT_RANGE_ATTACK1:
  530. if ( m_pOuterDOD->m_Shared.IsSniperZoomed() )
  531. {
  532. if( m_pOuterDOD->m_Shared.IsProne() )
  533. idealActivity = ACT_DOD_PRIMARYATTACK_PRONE;
  534. }
  535. break;
  536. case ACT_RELOAD:
  537. if ( m_pOuterDOD->m_Shared.IsBazookaDeployed() )
  538. {
  539. if( m_pOuterDOD->m_Shared.IsProne() )
  540. {
  541. idealActivity = ACT_DOD_RELOAD_PRONE_DEPLOYED;
  542. }
  543. else
  544. {
  545. idealActivity = ACT_DOD_RELOAD_DEPLOYED;
  546. }
  547. }
  548. break;
  549. default:
  550. break;
  551. }
  552. }
  553. else if ( m_pOuterDOD->m_Shared.IsProne() )
  554. {
  555. // translate prone shooting, reload, handsignal
  556. switch( idealActivity )
  557. {
  558. case ACT_RANGE_ATTACK1:
  559. idealActivity = ACT_DOD_PRIMARYATTACK_PRONE;
  560. break;
  561. case ACT_RANGE_ATTACK2:
  562. idealActivity = ACT_DOD_SECONDARYATTACK_PRONE;
  563. break;
  564. case ACT_RELOAD:
  565. idealActivity = ACT_DOD_RELOAD_PRONE;
  566. break;
  567. default:
  568. break;
  569. }
  570. }
  571. else if ( m_pOuter->GetFlags() & FL_DUCKING )
  572. {
  573. switch( idealActivity )
  574. {
  575. case ACT_RANGE_ATTACK1:
  576. idealActivity = ACT_DOD_PRIMARYATTACK_CROUCH;
  577. break;
  578. case ACT_RANGE_ATTACK2:
  579. idealActivity = ACT_DOD_SECONDARYATTACK_CROUCH;
  580. break;
  581. case ACT_DOD_HS_IDLE:
  582. idealActivity = ACT_DOD_HS_CROUCH;
  583. break;
  584. }
  585. }
  586. // Are our guns at fire or rest?
  587. if ( m_flFireIdleTime > gpGlobals->curtime )
  588. {
  589. switch( idealActivity )
  590. {
  591. case ACT_IDLE: idealActivity = ACT_DOD_STAND_AIM; break;
  592. case ACT_CROUCHIDLE: idealActivity = ACT_DOD_CROUCH_AIM; break;
  593. case ACT_RUN_CROUCH: idealActivity = ACT_DOD_CROUCHWALK_AIM; break;
  594. case ACT_WALK: idealActivity = ACT_DOD_WALK_AIM; break;
  595. case ACT_RUN: idealActivity = ACT_DOD_RUN_AIM; break;
  596. default: break;
  597. }
  598. }
  599. else
  600. {
  601. switch( idealActivity )
  602. {
  603. case ACT_IDLE: idealActivity = ACT_DOD_STAND_IDLE; break;
  604. case ACT_CROUCHIDLE: idealActivity = ACT_DOD_CROUCH_IDLE; break;
  605. case ACT_RUN_CROUCH: idealActivity = ACT_DOD_CROUCHWALK_IDLE; break;
  606. case ACT_WALK: idealActivity = ACT_DOD_WALK_IDLE; break;
  607. case ACT_RUN: idealActivity = ACT_DOD_RUN_IDLE; break;
  608. default: break;
  609. }
  610. }
  611. return m_pOuterDOD->TranslateActivity( idealActivity );
  612. }
  613. CDODPlayer* CDODPlayerAnimState::GetOuterDOD() const
  614. {
  615. return m_pOuterDOD;
  616. }
  617. float CDODPlayerAnimState::GetCurrentMaxGroundSpeed()
  618. {
  619. return PLAYER_SPEED_SPRINT;
  620. }
  621. float CDODPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
  622. {
  623. if( ( GetCurrentMainSequenceActivity() == ACT_GET_UP_STAND ) || ( GetCurrentMainSequenceActivity() == ACT_GET_DOWN_STAND ) ||
  624. ( GetCurrentMainSequenceActivity() == ACT_GET_UP_CROUCH ) || ( GetCurrentMainSequenceActivity() == ACT_GET_DOWN_CROUCH ) )
  625. {
  626. // We don't want to change the playback speed of these, even if we move.
  627. *bIsMoving = false;
  628. return 1.0;
  629. }
  630. // it would be a good idea to ramp up from 0.5 to 1.0 as they go from stop to moveing, it looks more natural.
  631. *bIsMoving = true;
  632. return 1.0;
  633. }
  634. void CDODPlayerAnimState::DebugShowAnimState( int iStartLine )
  635. {
  636. #ifdef CLIENT_DLL
  637. engine->Con_NPrintf( iStartLine++, "getting down: %s\n", m_bGettingDown ? "yes" : "no" );
  638. engine->Con_NPrintf( iStartLine++, "getting up: %s\n", m_bGettingUp ? "yes" : "no" );
  639. #endif
  640. BaseClass::DebugShowAnimState( iStartLine );
  641. }
  642. void CDODPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  643. {
  644. // Reset some things if we're changed weapons
  645. // do this before ComputeSequences
  646. CWeaponDODBase *pWeapon = GetOuterDOD()->m_Shared.GetActiveDODWeapon();
  647. if ( pWeapon )
  648. {
  649. if( pWeapon->GetWeaponID() != m_iLastWeaponID )
  650. {
  651. CancelGestures();
  652. m_iLastWeaponID = pWeapon->GetWeaponID();
  653. m_flFireIdleTime = 0;
  654. }
  655. }
  656. BaseClass::ComputeSequences( pStudioHdr );
  657. if( !m_bGettingDown && !m_bGettingUp )
  658. {
  659. ComputeFireSequence();
  660. #ifdef CLIENT_DLL
  661. ComputeGestureSequence( pStudioHdr );
  662. // get the weapon's swap criteria ( reload? attack? deployed? deployed reload? )
  663. // and determine whether we should use alt model or not
  664. CWeaponDODBase *pWeapon = GetOuterDOD()->m_Shared.GetActiveDODWeapon();
  665. if ( pWeapon )
  666. {
  667. int iCurrentState = ALTWPN_CRITERIA_NONE;
  668. if( m_bPlayingGesture && m_iGestureType == GESTURE_ATTACK1 )
  669. iCurrentState |= ALTWPN_CRITERIA_FIRING;
  670. else if( m_bPlayingGesture && m_iGestureType == GESTURE_RELOAD )
  671. iCurrentState |= ALTWPN_CRITERIA_RELOADING;
  672. if( m_pOuterDOD->m_Shared.IsProne() )
  673. iCurrentState |= ALTWPN_CRITERIA_PRONE;
  674. // always use default model while proning or hand signal
  675. if( !IsPlayingGesture( GESTURE_HAND_SIGNAL ) &&
  676. !IsPlayingGesture( GESTURE_FIDGET ) &&
  677. !m_bGettingDown &&
  678. !m_bGettingUp )
  679. {
  680. pWeapon->CheckForAltWeapon( iCurrentState );
  681. }
  682. else
  683. {
  684. pWeapon->SetUseAltModel( false );
  685. }
  686. }
  687. #endif
  688. }
  689. }
  690. #define GESTURE_LAYER AIMSEQUENCE_LAYER
  691. #define NUM_LAYERS_WANTED (GESTURE_LAYER + 1)
  692. void CDODPlayerAnimState::ClearAnimationLayers()
  693. {
  694. if ( !m_pOuter )
  695. return;
  696. m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
  697. for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
  698. {
  699. m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  700. }
  701. }
  702. void CDODPlayerAnimState::ComputeFireSequence( void )
  703. {
  704. // Hold the shoot pose for a time after firing, unless we stand still
  705. if( m_flFireIdleTime < gpGlobals->curtime &&
  706. IsPlayingGesture( GESTURE_ATTACK1 ) &&
  707. GetOuterXYSpeed() > MOVING_MINIMUM_SPEED )
  708. {
  709. CancelGestures();
  710. }
  711. if( GetOuterDOD()->m_Shared.IsInMGDeploy() != m_bLastDeployState )
  712. {
  713. CancelGestures();
  714. m_bLastDeployState = GetOuterDOD()->m_Shared.IsInMGDeploy();
  715. }
  716. }
  717. void CDODPlayerAnimState::ComputeGestureSequence( CStudioHdr *pStudioHdr )
  718. {
  719. UpdateLayerSequenceGeneric( pStudioHdr, GESTURE_LAYER, m_bPlayingGesture, m_flGestureCycle, m_iGestureSequence, !m_bAutokillGesture );
  720. }
  721. void CDODPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd, float flWeight /* = 1.0 */ )
  722. {
  723. if ( !bEnabled )
  724. return;
  725. if( flCurCycle > 1.0 )
  726. flCurCycle = 1.0;
  727. // Increment the fire sequence's cycle.
  728. flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
  729. if ( flCurCycle > 1 )
  730. {
  731. if ( bWaitAtEnd )
  732. {
  733. flCurCycle = 1;
  734. }
  735. else
  736. {
  737. // Not firing anymore.
  738. bEnabled = false;
  739. iSequence = 0;
  740. return;
  741. }
  742. }
  743. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
  744. pLayer->m_flCycle = flCurCycle;
  745. pLayer->m_nSequence = iSequence;
  746. pLayer->m_flPlaybackRate = 1.0;
  747. pLayer->m_flWeight = flWeight;
  748. pLayer->m_nOrder = iLayer;
  749. }
  750. extern ConVar mp_facefronttime;
  751. extern ConVar mp_feetyawrate;
  752. //-----------------------------------------------------------------------------
  753. // Purpose:
  754. //-----------------------------------------------------------------------------
  755. void CDODPlayerAnimState::Update( float eyeYaw, float eyePitch )
  756. {
  757. // Profile the animation update.
  758. VPROF( "CDODPlayerAnimState::Update" );
  759. // Get the studio header for the player.
  760. CStudioHdr *pStudioHdr = GetOuterDOD()->GetModelPtr();
  761. if ( !pStudioHdr )
  762. return;
  763. // Check to see if we should be updating the animation state - dead, ragdolled?
  764. if ( !ShouldUpdateAnimState() )
  765. {
  766. ClearAnimationState();
  767. return;
  768. }
  769. // Store the eye angles.
  770. m_flEyeYaw = AngleNormalize( eyeYaw );
  771. m_flEyePitch = AngleNormalize( eyePitch );
  772. // Clear animation overlays because we're about to completely reconstruct them.
  773. ClearAnimationLayers();
  774. // Compute the player sequences.
  775. ComputeSequences( pStudioHdr );
  776. if ( SetupPoseParameters( pStudioHdr ) )
  777. {
  778. // Pose parameter - what direction are the player's legs running in.
  779. ComputePoseParam_MoveYaw( pStudioHdr );
  780. // Pose parameter - Torso aiming (up/down).
  781. ComputePoseParam_AimPitch( pStudioHdr );
  782. // Pose parameter - Torso aiming (rotation).
  783. ComputePoseParam_AimYaw( pStudioHdr );
  784. // Pose parameter - Body Height (torso elevation).
  785. ComputePoseParam_BodyHeight( pStudioHdr );
  786. }
  787. }
  788. //-----------------------------------------------------------------------------
  789. // Purpose:
  790. //-----------------------------------------------------------------------------
  791. bool CDODPlayerAnimState::SetupPoseParameters( CStudioHdr *pStudioHdr )
  792. {
  793. // Check to see if this has already been done.
  794. if ( m_bPoseParameterInit )
  795. return true;
  796. // Save off the pose parameter indices.
  797. if ( !pStudioHdr )
  798. return false;
  799. // Look for the movement blenders.
  800. m_iMoveX = GetOuterDOD()->LookupPoseParameter( pStudioHdr, "move_x" );
  801. m_iMoveY = GetOuterDOD()->LookupPoseParameter( pStudioHdr, "move_y" );
  802. if ( ( m_iMoveX < 0 ) || ( m_iMoveY < 0 ) )
  803. return false;
  804. // Look for the aim pitch blender.
  805. m_iAimPitch = GetOuterDOD()->LookupPoseParameter( pStudioHdr, "body_pitch" );
  806. if ( m_iAimPitch < 0 )
  807. return false;
  808. // Look for aim yaw blender.
  809. m_iAimYaw = GetOuterDOD()->LookupPoseParameter( pStudioHdr, "body_yaw" );
  810. if ( m_iAimYaw < 0 )
  811. return false;
  812. // Look for the body height blender.
  813. m_iBodyHeight = GetOuterDOD()->LookupPoseParameter( pStudioHdr, "body_height" );
  814. if ( m_iBodyHeight < 0 )
  815. return false;
  816. m_bPoseParameterInit = true;
  817. return true;
  818. }
  819. #define DOD_MOVEMENT_ERROR_LIMIT 1.0
  820. //-----------------------------------------------------------------------------
  821. // Purpose:
  822. //-----------------------------------------------------------------------------
  823. void CDODPlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
  824. {
  825. // Check to see if we are deployed or prone.
  826. if( GetOuterDOD()->m_Shared.IsInMGDeploy() || GetOuterDOD()->m_Shared.IsProne() )
  827. {
  828. // Set the 9-way blend movement pose parameters.
  829. Vector2D vecCurrentMoveYaw( 0.0f, 0.0f );
  830. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveX, vecCurrentMoveYaw.x );
  831. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveY, vecCurrentMoveYaw.y );
  832. m_vecLastMoveYaw = vecCurrentMoveYaw;
  833. #if 0
  834. // Rotate the entire body instantly.
  835. m_flGoalFeetYaw = AngleNormalize( m_flEyeYaw );
  836. m_flCurrentFeetYaw = m_flGoalFeetYaw;
  837. m_flLastTurnTime = gpGlobals->curtime;
  838. // Rotate entire body into position.
  839. m_angRender[YAW] = m_flCurrentFeetYaw;
  840. m_angRender[PITCH] = m_angRender[ROLL] = 0;
  841. SetOuterBodyYaw( m_flCurrentFeetYaw );
  842. g_flLastBodyYaw = m_flCurrentFeetYaw;
  843. #endif
  844. }
  845. else
  846. {
  847. // Get the estimated movement yaw.
  848. EstimateYaw();
  849. // Get the view yaw.
  850. float flAngle = AngleNormalize( m_flEyeYaw );
  851. // rotate movement into local reference frame
  852. float flYaw = flAngle - m_flEstimateYaw;
  853. flYaw = AngleNormalize( -flYaw );
  854. // Get the current speed the character is running.
  855. Vector vecEstVelocity;
  856. vecEstVelocity.x = cos( DEG2RAD( flYaw ) ) * m_flEstimateVelocity;
  857. vecEstVelocity.y = sin( DEG2RAD( flYaw ) ) * m_flEstimateVelocity;
  858. Vector2D vecCurrentMoveYaw( 0.0f, 0.0f );
  859. // set the pose parameters to the correct direction, but not value
  860. if ( vecEstVelocity.x != 0.0f && fabs( vecEstVelocity.x ) > fabs( vecEstVelocity.y ) )
  861. {
  862. vecCurrentMoveYaw.x = (vecEstVelocity.x < 0.0) ? -1.0 : 1.0;
  863. vecCurrentMoveYaw.y = vecEstVelocity.y / fabs( vecEstVelocity.x );
  864. }
  865. else if (vecEstVelocity.y != 0.0f)
  866. {
  867. vecCurrentMoveYaw.y = (vecEstVelocity.y < 0.0) ? -1.0 : 1.0;
  868. vecCurrentMoveYaw.x = vecEstVelocity.x / fabs( vecEstVelocity.y );
  869. }
  870. #ifndef CLIENT_DLL
  871. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveX, vecCurrentMoveYaw.x );
  872. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveY, vecCurrentMoveYaw.y );
  873. #else
  874. // refine pose parameters to be more accurate
  875. int i = 0;
  876. float dx, dy;
  877. Vector vecAnimVelocity;
  878. /*
  879. if ( m_pOuter->entindex() == 2 )
  880. {
  881. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveX, vecCurrentMoveYaw.x );
  882. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveY, vecCurrentMoveYaw.y );
  883. GetOuterDOD()->GetBlendedLinearVelocity( &vecAnimVelocity );
  884. DevMsgRT("(%.2f) %.3f : (%.2f) %.3f\n", vecAnimVelocity.x, vecCurrentMoveYaw.x, vecAnimVelocity.y, vecCurrentMoveYaw.y );
  885. }
  886. */
  887. bool retry = true;
  888. do
  889. {
  890. // Set the 9-way blend movement pose parameters.
  891. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveX, vecCurrentMoveYaw.x );
  892. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveY, vecCurrentMoveYaw.y );
  893. GetOuterDOD()->GetBlendedLinearVelocity( &vecAnimVelocity );
  894. // adjust X pose parameter based on movement error
  895. if (fabs( vecAnimVelocity.x ) > 0.001)
  896. {
  897. vecCurrentMoveYaw.x *= vecEstVelocity.x / vecAnimVelocity.x;
  898. }
  899. else
  900. {
  901. vecCurrentMoveYaw.x = 0;
  902. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveX, vecCurrentMoveYaw.x );
  903. }
  904. // adjust Y pose parameter based on movement error
  905. if (fabs( vecAnimVelocity.y ) > 0.001)
  906. {
  907. vecCurrentMoveYaw.y *= vecEstVelocity.y / vecAnimVelocity.y;
  908. }
  909. else
  910. {
  911. vecCurrentMoveYaw.y = 0;
  912. GetOuter()->SetPoseParameter( pStudioHdr, m_iMoveY, vecCurrentMoveYaw.y );
  913. }
  914. dx = vecEstVelocity.x - vecAnimVelocity.x;
  915. dy = vecEstVelocity.y - vecAnimVelocity.y;
  916. retry = (vecCurrentMoveYaw.x < 1.0 && vecCurrentMoveYaw.x > -1.0) && (dx < -DOD_MOVEMENT_ERROR_LIMIT || dx > DOD_MOVEMENT_ERROR_LIMIT);
  917. retry = retry || ((vecCurrentMoveYaw.y < 1.0 && vecCurrentMoveYaw.y > -1.0) && (dy < -DOD_MOVEMENT_ERROR_LIMIT || dy > DOD_MOVEMENT_ERROR_LIMIT));
  918. } while (i++ < 5 && retry);
  919. /*
  920. if ( m_pOuter->entindex() == 2 )
  921. {
  922. DevMsgRT("%d(%.2f : %.2f) %.3f : (%.2f : %.2f) %.3f\n",
  923. i,
  924. vecEstVelocity.x, vecAnimVelocity.x, vecCurrentMoveYaw.x,
  925. vecEstVelocity.y, vecAnimVelocity.y, vecCurrentMoveYaw.y );
  926. }
  927. */
  928. #endif
  929. m_vecLastMoveYaw = vecCurrentMoveYaw;
  930. }
  931. }
  932. //-----------------------------------------------------------------------------
  933. // Purpose:
  934. //-----------------------------------------------------------------------------
  935. void CDODPlayerAnimState::EstimateYaw( void )
  936. {
  937. // Get the frame time.
  938. float flDeltaTime = gpGlobals->frametime;
  939. if ( flDeltaTime == 0.0f )
  940. {
  941. // FIXME: why does this short circuit?
  942. m_flEstimateVelocity = 0.0;
  943. m_flEstimateYaw = 0.0;
  944. return;
  945. }
  946. // Get the player's velocity and angles.
  947. Vector vecEstVelocity;
  948. GetOuterAbsVelocity( vecEstVelocity );
  949. QAngle angles = GetOuterDOD()->GetLocalAngles();
  950. // If we are not moving, sync up the feet and eyes slowly.
  951. if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f )
  952. {
  953. float flYawDelta = angles[YAW] - m_flEstimateYaw;
  954. flYawDelta = AngleNormalize( flYawDelta );
  955. if ( flDeltaTime < 0.25f )
  956. {
  957. flYawDelta *= ( flDeltaTime * 4.0f );
  958. }
  959. else
  960. {
  961. flYawDelta *= flDeltaTime;
  962. }
  963. m_flEstimateVelocity = 0.0;
  964. m_flEstimateYaw += flYawDelta;
  965. AngleNormalize( m_flEstimateYaw );
  966. }
  967. else
  968. {
  969. m_flEstimateVelocity = vecEstVelocity.Length2D();
  970. m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI );
  971. m_flEstimateYaw = clamp( m_flEstimateYaw, -180.0f, 180.0f );
  972. }
  973. }
  974. //-----------------------------------------------------------------------------
  975. // Purpose:
  976. //-----------------------------------------------------------------------------
  977. void CDODPlayerAnimState::ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr )
  978. {
  979. // Get the view pitch.
  980. float flAimPitch = m_flEyePitch;
  981. // Lock pitch at 0 if a reload gesture is playing
  982. #ifdef CLIENT_DLL
  983. if ( IsPlayingGesture( GESTURE_RELOAD ) )
  984. flAimPitch = 0;
  985. #else
  986. Activity idealActivity = TranslateActivity( ACT_RELOAD );
  987. if ( m_pOuter->IsPlayingGesture( idealActivity ) )
  988. flAimPitch = 0;
  989. #endif
  990. // Set the aim pitch pose parameter and save.
  991. GetOuter()->SetPoseParameter( pStudioHdr, m_iAimPitch, -flAimPitch );
  992. m_flLastAimPitch = flAimPitch;
  993. }
  994. //-----------------------------------------------------------------------------
  995. // Purpose:
  996. //-----------------------------------------------------------------------------
  997. void CDODPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr )
  998. {
  999. // Get the movement velocity.
  1000. Vector vecVelocity;
  1001. GetOuterAbsVelocity( vecVelocity );
  1002. // Check to see if we are moving.
  1003. bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false;
  1004. // Check our prone and deployed state.
  1005. bool bDeployed = GetOuterDOD()->m_Shared.IsSandbagDeployed() || GetOuterDOD()->m_Shared.IsProneDeployed();
  1006. bool bProne = GetOuterDOD()->m_Shared.IsProne();
  1007. // If we are moving or are prone and undeployed.
  1008. if ( bMoving || ( bProne && !bDeployed ) )
  1009. {
  1010. // The feet match the eye direction when moving - the move yaw takes care of the rest.
  1011. m_flGoalFeetYaw = m_flEyeYaw;
  1012. }
  1013. // Else if we are not moving.
  1014. else
  1015. {
  1016. // Initialize the feet.
  1017. if ( m_flLastAimTurnTime <= 0.0f )
  1018. {
  1019. m_flGoalFeetYaw = m_flEyeYaw;
  1020. m_flCurrentFeetYaw = m_flEyeYaw;
  1021. m_flLastAimTurnTime = gpGlobals->curtime;
  1022. }
  1023. // Make sure the feet yaw isn't too far out of sync with the eye yaw.
  1024. // TODO: Do something better here!
  1025. else
  1026. {
  1027. float flYawDelta = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw );
  1028. if ( bDeployed )
  1029. {
  1030. if ( fabs( flYawDelta ) > 20.0f )
  1031. {
  1032. float flSide = ( flYawDelta > 0.0f ) ? -1.0f : 1.0f;
  1033. m_flGoalFeetYaw += ( 20.0f * flSide );
  1034. }
  1035. }
  1036. else
  1037. {
  1038. if ( fabs( flYawDelta ) > m_AnimConfig.m_flMaxBodyYawDegrees )
  1039. {
  1040. float flSide = ( flYawDelta > 0.0f ) ? -1.0f : 1.0f;
  1041. m_flGoalFeetYaw += ( m_AnimConfig.m_flMaxBodyYawDegrees * flSide );
  1042. }
  1043. }
  1044. }
  1045. }
  1046. // Fix up the feet yaw.
  1047. m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw );
  1048. if ( m_flGoalFeetYaw != m_flCurrentFeetYaw )
  1049. {
  1050. ConvergeYawAngles( m_flGoalFeetYaw, DOD_BODYYAW_RATE, gpGlobals->frametime, m_flCurrentFeetYaw );
  1051. m_flLastAimTurnTime = gpGlobals->curtime;
  1052. }
  1053. // Rotate the body into position.
  1054. m_angRender[YAW] = m_flCurrentFeetYaw;
  1055. // Find the aim(torso) yaw base on the eye and feet yaws.
  1056. float flAimYaw = m_flEyeYaw - m_flCurrentFeetYaw;
  1057. flAimYaw = AngleNormalize( flAimYaw );
  1058. // Set the aim yaw and save.
  1059. GetOuter()->SetPoseParameter( pStudioHdr, m_iAimYaw, -flAimYaw );
  1060. m_flLastAimYaw = flAimYaw;
  1061. }
  1062. //-----------------------------------------------------------------------------
  1063. // Purpose:
  1064. //-----------------------------------------------------------------------------
  1065. void CDODPlayerAnimState::ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw )
  1066. {
  1067. #define FADE_TURN_DEGREES 60.0f
  1068. // Find the yaw delta.
  1069. float flDeltaYaw = flGoalYaw - flCurrentYaw;
  1070. float flDeltaYawAbs = fabs( flDeltaYaw );
  1071. flDeltaYaw = AngleNormalize( flDeltaYaw );
  1072. // Always do at least a bit of the turn (1%).
  1073. float flScale = 1.0f;
  1074. flScale = flDeltaYawAbs / FADE_TURN_DEGREES;
  1075. flScale = clamp( flScale, 0.01f, 1.0f );
  1076. float flYaw = flYawRate * flDeltaTime * flScale;
  1077. if ( flDeltaYawAbs < flYaw )
  1078. {
  1079. flCurrentYaw = flGoalYaw;
  1080. }
  1081. else
  1082. {
  1083. float flSide = ( flDeltaYaw < 0.0f ) ? -1.0f : 1.0f;
  1084. flCurrentYaw += ( flYaw * flSide );
  1085. }
  1086. flCurrentYaw = AngleNormalize( flCurrentYaw );
  1087. #undef FADE_TURN_DEGREES
  1088. }
  1089. //-----------------------------------------------------------------------------
  1090. // Purpose:
  1091. //-----------------------------------------------------------------------------
  1092. void CDODPlayerAnimState::ComputePoseParam_BodyHeight( CStudioHdr *pStudioHdr )
  1093. {
  1094. if( m_pOuterDOD->m_Shared.IsSandbagDeployed() )
  1095. {
  1096. // float flHeight = m_pOuterDOD->m_Shared.GetDeployedHeight() - 4.0f;
  1097. float flHeight = m_pOuterDOD->m_Shared.GetDeployedHeight() - dod_bodyheightoffset.GetFloat();
  1098. GetOuter()->SetPoseParameter( pStudioHdr, m_iBodyHeight, flHeight );
  1099. m_flLastBodyHeight = flHeight;
  1100. }
  1101. }
  1102. //-----------------------------------------------------------------------------
  1103. // Purpose:
  1104. //-----------------------------------------------------------------------------
  1105. void Anim_StateLog( const char *pMsg, ... )
  1106. {
  1107. // Format the string.
  1108. char str[4096];
  1109. va_list marker;
  1110. va_start( marker, pMsg );
  1111. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  1112. va_end( marker );
  1113. // Log it?
  1114. if ( anim_showstatelog.GetInt() == 1 || anim_showstatelog.GetInt() == 3 )
  1115. {
  1116. Msg( "%s", str );
  1117. }
  1118. if ( anim_showstatelog.GetInt() > 1 )
  1119. {
  1120. // static FileHandle_t hFile = filesystem->Open( "AnimState.log", "wt" );
  1121. // filesystem->FPrintf( hFile, "%s", str );
  1122. // filesystem->Flush( hFile );
  1123. }
  1124. }
  1125. //-----------------------------------------------------------------------------
  1126. // Purpose:
  1127. //-----------------------------------------------------------------------------
  1128. void Anim_StatePrintf( int iLine, const char *pMsg, ... )
  1129. {
  1130. // Format the string.
  1131. char str[4096];
  1132. va_list marker;
  1133. va_start( marker, pMsg );
  1134. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  1135. va_end( marker );
  1136. // Show it with Con_NPrintf.
  1137. engine->Con_NPrintf( iLine, "%s", str );
  1138. // Log it.
  1139. Anim_StateLog( "%s\n", str );
  1140. }
  1141. //-----------------------------------------------------------------------------
  1142. // Purpose:
  1143. //-----------------------------------------------------------------------------
  1144. void CDODPlayerAnimState::DebugShowAnimStateForPlayer( bool bIsServer )
  1145. {
  1146. // Get the player's velocity.
  1147. Vector vecVelocity;
  1148. GetOuterAbsVelocity( vecVelocity );
  1149. // Start animation state logging.
  1150. int iLine = 5;
  1151. if ( bIsServer )
  1152. {
  1153. iLine = 12;
  1154. }
  1155. // Anim_StateLog( "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount );
  1156. Anim_StatePrintf( iLine++, "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount );
  1157. // Write out the main sequence and its data.
  1158. Anim_StatePrintf( iLine++, "Main: %s, Cycle: %.2f\n", GetSequenceName( GetOuter()->GetModelPtr(), GetOuter()->GetSequence() ), GetOuter()->GetCycle() );
  1159. // Write out the layers and their data.
  1160. for ( int iAnim = 0; iAnim < GetOuter()->GetNumAnimOverlays(); ++iAnim )
  1161. {
  1162. CAnimationLayer *pLayer = GetOuter()->GetAnimOverlay( iAnim );
  1163. if ( pLayer && ( pLayer->m_nOrder != CBaseAnimatingOverlay::MAX_OVERLAYS ) )
  1164. {
  1165. Anim_StatePrintf( iLine++, "Layer %s: Weight: %.2f, Cycle: %.2f", GetSequenceName( GetOuter()->GetModelPtr(), pLayer->m_nSequence ), (float)pLayer->m_flWeight, (float)pLayer->m_flCycle );
  1166. }
  1167. }
  1168. // Write out the speed data.
  1169. Anim_StatePrintf( iLine++, "Time: %.2f, Speed: %.2f, MaxSpeed: %.2f", gpGlobals->curtime, vecVelocity.Length2D(), GetCurrentMaxGroundSpeed() );
  1170. // Write out the 9-way blend data.
  1171. Anim_StatePrintf( iLine++, "EntityYaw: %.2f, AimYaw: %.2f, AimPitch: %.2f, MoveX: %.2f, MoveY: %.2f Body: %.2f", m_angRender[YAW], m_flLastAimYaw, m_flLastAimPitch, m_vecLastMoveYaw.x, m_vecLastMoveYaw.y, m_flLastBodyHeight );
  1172. // Anim_StateLog( "--------------------------------------------\n\n" );
  1173. Anim_StatePrintf( iLine++, "--------------------------------------------\n\n" );
  1174. DebugShowEyeYaw();
  1175. }
  1176. //-----------------------------------------------------------------------------
  1177. // Purpose:
  1178. //-----------------------------------------------------------------------------
  1179. void CDODPlayerAnimState::DebugShowEyeYaw( void )
  1180. {
  1181. #ifdef _NDEBUG
  1182. float flBaseSize = 10;
  1183. float flHeight = 80;
  1184. Vector vecPos = GetOuter()->GetAbsOrigin() + Vector( 0.0f, 0.0f, 3.0f );
  1185. QAngle angles( 0.0f, 0.0f, 0.0f );
  1186. angles[YAW] = m_flEyeYaw;
  1187. Vector vecForward, vecRight, vecUp;
  1188. AngleVectors( angles, &vecForward, &vecRight, &vecUp );
  1189. // Draw a red triangle on the ground for the eye yaw.
  1190. debugoverlay->AddTriangleOverlay( ( vecPos + vecRight * flBaseSize / 2.0f ),
  1191. ( vecPos - vecRight * flBaseSize / 2.0f ),
  1192. ( vecPos + vecForward * flHeight, 255, 0, 0, 255, false, 0.01f );
  1193. #endif
  1194. }
  1195. // Client specific debug functions.
  1196. #ifdef CLIENT_DLL
  1197. //-----------------------------------------------------------------------------
  1198. // Purpose:
  1199. //-----------------------------------------------------------------------------
  1200. void CDODPlayerAnimState::DebugShowActivity( Activity activity )
  1201. {
  1202. #ifdef _DEBUG
  1203. const char *pszActivity = "other";
  1204. switch( activity )
  1205. {
  1206. case ACT_IDLE:
  1207. {
  1208. pszActivity = "idle";
  1209. break;
  1210. }
  1211. case ACT_SPRINT:
  1212. {
  1213. pszActivity = "sprint";
  1214. break;
  1215. }
  1216. case ACT_WALK:
  1217. {
  1218. pszActivity = "walk";
  1219. break;
  1220. }
  1221. case ACT_RUN:
  1222. {
  1223. pszActivity = "run";
  1224. break;
  1225. }
  1226. }
  1227. Msg( "Activity: %s\n", pszActivity );
  1228. #endif
  1229. }
  1230. #endif