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.

2101 lines
65 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "tier0/vprof.h"
  8. #include "animation.h"
  9. #include "studio.h"
  10. #include "apparent_velocity_helper.h"
  11. #include "utldict.h"
  12. #include "multiplayer_animstate.h"
  13. #include "activitylist.h"
  14. #ifdef CLIENT_DLL
  15. #include "c_baseplayer.h"
  16. #include "engine/ivdebugoverlay.h"
  17. #include "filesystem.h"
  18. #include "eventlist.h"
  19. ConVar anim_showmainactivity( "anim_showmainactivity", "0", FCVAR_CHEAT, "Show the idle, walk, run, and/or sprint activities." );
  20. #else
  21. #include "player.h"
  22. #endif
  23. #if defined(TF_CLIENT_DLL) || defined(TF_DLL)
  24. #include "tf_gamerules.h"
  25. #endif
  26. #ifndef CALL_ATTRIB_HOOK_FLOAT_ON_OTHER
  27. #define CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( o, r, n )
  28. #endif
  29. #define MOVING_MINIMUM_SPEED 0.5f
  30. ConVar anim_showstate( "anim_showstate", "-1", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." );
  31. ConVar anim_showstatelog( "anim_showstatelog", "0", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "1 to output anim_showstate to Msg(). 2 to store in AnimState.log. 3 for both." );
  32. ConVar mp_showgestureslots( "mp_showgestureslots", "-1", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Show multiplayer client/server gesture slot information for the specified player index (-1 for no one)." );
  33. ConVar mp_slammoveyaw( "mp_slammoveyaw", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Force movement yaw along an animation path." );
  34. //-----------------------------------------------------------------------------
  35. // Purpose:
  36. // Input : *pPlayer -
  37. // &movementData -
  38. //-----------------------------------------------------------------------------
  39. CMultiPlayerAnimState::CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData )
  40. #ifdef CLIENT_DLL
  41. : m_iv_flMaxGroundSpeed( "CMultiPlayerAnimState::m_iv_flMaxGroundSpeed" )
  42. #endif
  43. {
  44. // Pose parameters.
  45. m_bPoseParameterInit = false;
  46. m_PoseParameterData.Init();
  47. m_DebugAnimData.Init();
  48. m_pPlayer = NULL;
  49. m_angRender.Init();
  50. m_bCurrentFeetYawInitialized = false;
  51. m_flLastAnimationStateClearTime = 0.0f;
  52. m_flEyeYaw = 0.0f;
  53. m_flEyePitch = 0.0f;
  54. m_flGoalFeetYaw = 0.0f;
  55. m_flCurrentFeetYaw = 0.0f;
  56. m_flLastAimTurnTime = 0.0f;
  57. // Jumping.
  58. m_bJumping = false;
  59. m_flJumpStartTime = 0.0f;
  60. m_bFirstJumpFrame = false;
  61. // Swimming
  62. m_bInSwim = false;
  63. m_bFirstSwimFrame = true;
  64. // Dying
  65. m_bDying = false;
  66. m_bFirstDyingFrame = true;
  67. m_eCurrentMainSequenceActivity = ACT_INVALID;
  68. m_nSpecificMainSequence = -1;
  69. // Weapon data.
  70. m_hActiveWeapon = NULL;
  71. // Ground speed interpolators.
  72. #ifdef CLIENT_DLL
  73. m_iv_flMaxGroundSpeed.Setup( &m_flMaxGroundSpeed, LATCH_ANIMATION_VAR | INTERPOLATE_LINEAR_ONLY );
  74. m_flLastGroundSpeedUpdateTime = 0.0f;
  75. #endif
  76. m_flMaxGroundSpeed = 0.0f;
  77. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between
  78. // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window,
  79. // and the fact that m_flEyeYaw is never propogated from the server to the client.
  80. // TODO: Fix this after Halloween 2014.
  81. m_bForceAimYaw = false;
  82. Init( pPlayer, movementData );
  83. // movement playback options
  84. m_nMovementSequence = -1;
  85. m_LegAnimType = LEGANIM_9WAY;
  86. InitGestureSlots();
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose:
  90. // Input : -
  91. //-----------------------------------------------------------------------------
  92. CMultiPlayerAnimState::~CMultiPlayerAnimState()
  93. {
  94. ShutdownGestureSlots();
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. // Input : *pPlayer -
  99. // &movementData -
  100. //-----------------------------------------------------------------------------
  101. void CMultiPlayerAnimState::Init( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData )
  102. {
  103. // Get the player this animation data works on.
  104. m_pPlayer = pPlayer;
  105. // Copy the movement data.
  106. memcpy( &m_MovementData, &movementData, sizeof( MultiPlayerMovementData_t ) );
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Purpose:
  110. // Input : -
  111. //-----------------------------------------------------------------------------
  112. void CMultiPlayerAnimState::ClearAnimationState()
  113. {
  114. // Reset state.
  115. m_bJumping = false;
  116. m_bDying = false;
  117. m_bCurrentFeetYawInitialized = false;
  118. m_flLastAnimationStateClearTime = gpGlobals->curtime;
  119. m_nSpecificMainSequence = -1;
  120. ResetGestureSlots();
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose:
  124. // Input : event -
  125. //-----------------------------------------------------------------------------
  126. void CMultiPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
  127. {
  128. switch( event )
  129. {
  130. case PLAYERANIMEVENT_ATTACK_PRIMARY:
  131. {
  132. // Weapon primary fire.
  133. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE );
  134. break;
  135. }
  136. case PLAYERANIMEVENT_ATTACK_SECONDARY:
  137. {
  138. // Weapon secondary fire.
  139. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_SECONDARYFIRE );
  140. break;
  141. }
  142. case PLAYERANIMEVENT_ATTACK_GRENADE:
  143. {
  144. // Grenade throw.
  145. RestartGesture( GESTURE_SLOT_GRENADE, ACT_MP_ATTACK_STAND_GRENADE );
  146. break;
  147. }
  148. case PLAYERANIMEVENT_RELOAD:
  149. {
  150. // Weapon reload.
  151. if ( GetBasePlayer()->GetFlags() & FL_DUCKING )
  152. {
  153. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH );
  154. }
  155. else if ( m_bInSwim )
  156. {
  157. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM );
  158. }
  159. else
  160. {
  161. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND );
  162. }
  163. // Set the modified reload playback rate
  164. float flPlaybackRate = 1.0f;
  165. #if defined(TF_CLIENT_DLL) || defined(TF_DLL)
  166. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time );
  167. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time_hidden );
  168. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, fast_reload );
  169. #endif
  170. m_aGestureSlots[ GESTURE_SLOT_ATTACK_AND_RELOAD ].m_pAnimLayer->m_flPlaybackRate = flPlaybackRate;
  171. break;
  172. }
  173. case PLAYERANIMEVENT_RELOAD_LOOP:
  174. {
  175. // Weapon reload.
  176. if ( GetBasePlayer()->GetFlags() & FL_DUCKING )
  177. {
  178. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_LOOP );
  179. }
  180. else if ( m_bInSwim )
  181. {
  182. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM_LOOP );
  183. }
  184. else
  185. {
  186. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_LOOP );
  187. }
  188. // Set the modified reload playback rate
  189. float flPlaybackRate = 1.0f;
  190. #if defined(TF_CLIENT_DLL) || defined(TF_DLL)
  191. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time );
  192. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time_hidden );
  193. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, fast_reload );
  194. #endif
  195. m_aGestureSlots[ GESTURE_SLOT_ATTACK_AND_RELOAD ].m_pAnimLayer->m_flPlaybackRate = flPlaybackRate;
  196. break;
  197. }
  198. case PLAYERANIMEVENT_RELOAD_END:
  199. {
  200. // Weapon reload.
  201. if ( GetBasePlayer()->GetFlags() & FL_DUCKING )
  202. {
  203. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_END );
  204. }
  205. else if ( m_bInSwim )
  206. {
  207. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM_END );
  208. }
  209. else
  210. {
  211. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_END );
  212. }
  213. // Set the modified reload playback rate
  214. float flPlaybackRate = 1.0f;
  215. #if defined(TF_CLIENT_DLL) || defined(TF_DLL)
  216. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time );
  217. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, mult_reload_time_hidden );
  218. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( GetBasePlayer(), flPlaybackRate, fast_reload );
  219. #endif
  220. m_aGestureSlots[ GESTURE_SLOT_ATTACK_AND_RELOAD ].m_pAnimLayer->m_flPlaybackRate = flPlaybackRate;
  221. break;
  222. }
  223. case PLAYERANIMEVENT_JUMP:
  224. {
  225. // Jump.
  226. m_bJumping = true;
  227. m_bFirstJumpFrame = true;
  228. m_flJumpStartTime = gpGlobals->curtime;
  229. RestartMainSequence();
  230. break;
  231. }
  232. case PLAYERANIMEVENT_DIE:
  233. {
  234. // Should be here - not supporting this yet!
  235. Assert( 0 );
  236. // Start playing the death animation
  237. m_bDying = true;
  238. RestartMainSequence();
  239. break;
  240. }
  241. case PLAYERANIMEVENT_SPAWN:
  242. {
  243. // Player has respawned. Clear flags.
  244. ClearAnimationState();
  245. break;
  246. }
  247. case PLAYERANIMEVENT_SNAP_YAW:
  248. m_PoseParameterData.m_flLastAimTurnTime = 0.0f;
  249. break;
  250. case PLAYERANIMEVENT_CUSTOM:
  251. {
  252. Activity iIdealActivity = TranslateActivity( (Activity)nData );
  253. m_nSpecificMainSequence = GetBasePlayer()->SelectWeightedSequence( iIdealActivity );
  254. RestartMainSequence();
  255. }
  256. break;
  257. case PLAYERANIMEVENT_CUSTOM_GESTURE:
  258. // Weapon primary fire.
  259. RestartGesture( GESTURE_SLOT_CUSTOM, (Activity)nData );
  260. break;
  261. case PLAYERANIMEVENT_CUSTOM_SEQUENCE:
  262. m_nSpecificMainSequence = nData;
  263. RestartMainSequence();
  264. break;
  265. case PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE:
  266. // Weapon primary fire.
  267. // RestartGestureSequence( nData, false );
  268. break;
  269. case PLAYERANIMEVENT_FLINCH_CHEST:
  270. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_CHEST );
  271. break;
  272. case PLAYERANIMEVENT_FLINCH_HEAD:
  273. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_HEAD );
  274. break;
  275. case PLAYERANIMEVENT_FLINCH_LEFTARM:
  276. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_LEFTARM );
  277. break;
  278. case PLAYERANIMEVENT_FLINCH_RIGHTARM:
  279. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_RIGHTARM );
  280. break;
  281. case PLAYERANIMEVENT_FLINCH_LEFTLEG:
  282. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_LEFTLEG );
  283. break;
  284. case PLAYERANIMEVENT_FLINCH_RIGHTLEG:
  285. PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_RIGHTLEG );
  286. break;
  287. default:
  288. break;
  289. }
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Purpose:
  293. //-----------------------------------------------------------------------------
  294. void CMultiPlayerAnimState::PlayFlinchGesture( Activity iActivity )
  295. {
  296. if ( !IsGestureSlotActive( GESTURE_SLOT_FLINCH ) )
  297. {
  298. // See if we have the custom flinch. If not, revert to chest
  299. if ( iActivity != ACT_MP_GESTURE_FLINCH_CHEST && GetBasePlayer()->SelectWeightedSequence( iActivity ) == -1 )
  300. {
  301. RestartGesture( GESTURE_SLOT_FLINCH, ACT_MP_GESTURE_FLINCH_CHEST );
  302. }
  303. else
  304. {
  305. RestartGesture( GESTURE_SLOT_FLINCH, iActivity );
  306. }
  307. }
  308. }
  309. //=============================================================================
  310. //
  311. // Multiplayer gesture code.
  312. //
  313. //-----------------------------------------------------------------------------
  314. // Purpose:
  315. //-----------------------------------------------------------------------------
  316. bool CMultiPlayerAnimState::InitGestureSlots( void )
  317. {
  318. // Setup the number of gesture slots.
  319. m_aGestureSlots.AddMultipleToTail( GESTURE_SLOT_COUNT );
  320. // Assign all of the the CAnimationLayer pointers to null early in case we bail.
  321. for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture )
  322. {
  323. m_aGestureSlots[iGesture].m_pAnimLayer = NULL;
  324. }
  325. // Get the base player.
  326. CBasePlayer *pPlayer = GetBasePlayer();
  327. // Set the number of animation overlays we will use.
  328. pPlayer->SetNumAnimOverlays( GESTURE_SLOT_COUNT );
  329. for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture )
  330. {
  331. m_aGestureSlots[iGesture].m_pAnimLayer = pPlayer->GetAnimOverlay( iGesture );
  332. if ( !m_aGestureSlots[iGesture].m_pAnimLayer )
  333. return false;
  334. ResetGestureSlot( iGesture );
  335. }
  336. return true;
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Purpose:
  340. //-----------------------------------------------------------------------------
  341. void CMultiPlayerAnimState::ShutdownGestureSlots( void )
  342. {
  343. // Clean up the gesture slots.
  344. m_aGestureSlots.Purge();
  345. }
  346. //-----------------------------------------------------------------------------
  347. // Purpose:
  348. //-----------------------------------------------------------------------------
  349. void CMultiPlayerAnimState::ResetGestureSlots( void )
  350. {
  351. // Clear out all the gesture slots.
  352. for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture )
  353. {
  354. ResetGestureSlot( iGesture );
  355. }
  356. }
  357. //-----------------------------------------------------------------------------
  358. // Purpose:
  359. //-----------------------------------------------------------------------------
  360. void CMultiPlayerAnimState::ResetGestureSlot( int iGestureSlot )
  361. {
  362. // Sanity Check
  363. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  364. if ( !VerifyAnimLayerInSlot( iGestureSlot ) )
  365. return;
  366. GestureSlot_t *pGestureSlot = &m_aGestureSlots[iGestureSlot];
  367. if ( pGestureSlot )
  368. {
  369. #ifdef CLIENT_DLL
  370. // briefly set to 1.0 so we catch the events, before we reset the slot
  371. pGestureSlot->m_pAnimLayer->m_flCycle = 1.0;
  372. RunGestureSlotAnimEventsToCompletion( pGestureSlot );
  373. #endif
  374. pGestureSlot->m_iGestureSlot = GESTURE_SLOT_INVALID;
  375. pGestureSlot->m_iActivity = ACT_INVALID;
  376. pGestureSlot->m_bAutoKill = false;
  377. pGestureSlot->m_bActive = false;
  378. if ( pGestureSlot->m_pAnimLayer )
  379. {
  380. pGestureSlot->m_pAnimLayer->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  381. #ifdef CLIENT_DLL
  382. pGestureSlot->m_pAnimLayer->Reset();
  383. #endif
  384. }
  385. }
  386. }
  387. #ifdef CLIENT_DLL
  388. //-----------------------------------------------------------------------------
  389. // Purpose:
  390. //-----------------------------------------------------------------------------
  391. void CMultiPlayerAnimState::RunGestureSlotAnimEventsToCompletion( GestureSlot_t *pGesture )
  392. {
  393. CBasePlayer *pPlayer = GetBasePlayer();
  394. if( !pPlayer )
  395. return;
  396. // Get the studio header for the player.
  397. CStudioHdr *pStudioHdr = pPlayer->GetModelPtr();
  398. if ( !pStudioHdr )
  399. return;
  400. // Do all the anim events between previous cycle and 1.0, inclusive
  401. mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( pGesture->m_pAnimLayer->m_nSequence );
  402. if ( seqdesc.numevents > 0 )
  403. {
  404. mstudioevent_t *pevent = seqdesc.pEvent( 0 );
  405. for (int i = 0; i < (int)seqdesc.numevents; i++)
  406. {
  407. if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
  408. {
  409. if ( !( pevent[i].type & AE_TYPE_CLIENT ) )
  410. continue;
  411. }
  412. else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system
  413. continue;
  414. if ( pevent[i].cycle > pGesture->m_pAnimLayer->m_flPrevCycle &&
  415. pevent[i].cycle <= pGesture->m_pAnimLayer->m_flCycle )
  416. {
  417. pPlayer->FireEvent( pPlayer->GetAbsOrigin(), pPlayer->GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
  418. }
  419. }
  420. }
  421. }
  422. #endif
  423. //-----------------------------------------------------------------------------
  424. // Purpose:
  425. //-----------------------------------------------------------------------------
  426. bool CMultiPlayerAnimState::IsGestureSlotActive( int iGestureSlot )
  427. {
  428. // Sanity Check
  429. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  430. return m_aGestureSlots[iGestureSlot].m_bActive;
  431. }
  432. //-----------------------------------------------------------------------------
  433. // Purpose: Track down a crash
  434. //-----------------------------------------------------------------------------
  435. bool CMultiPlayerAnimState::VerifyAnimLayerInSlot( int iGestureSlot )
  436. {
  437. if ( iGestureSlot < 0 || iGestureSlot >= GESTURE_SLOT_COUNT )
  438. {
  439. return false;
  440. }
  441. if ( GetBasePlayer()->GetNumAnimOverlays() < iGestureSlot + 1 )
  442. {
  443. AssertMsg2( false, "Player %d doesn't have gesture slot %d any more.", GetBasePlayer()->entindex(), iGestureSlot );
  444. Msg( "Player %d doesn't have gesture slot %d any more.\n", GetBasePlayer()->entindex(), iGestureSlot );
  445. m_aGestureSlots[iGestureSlot].m_pAnimLayer = NULL;
  446. return false;
  447. }
  448. CAnimationLayer *pExpected = GetBasePlayer()->GetAnimOverlay( iGestureSlot );
  449. if ( m_aGestureSlots[iGestureSlot].m_pAnimLayer != pExpected )
  450. {
  451. AssertMsg3( false, "Gesture slot %d pointing to wrong address %p. Updating to new address %p.", iGestureSlot, m_aGestureSlots[iGestureSlot].m_pAnimLayer, pExpected );
  452. Msg( "Gesture slot %d pointing to wrong address %p. Updating to new address %p.\n", iGestureSlot, m_aGestureSlots[iGestureSlot].m_pAnimLayer, pExpected );
  453. m_aGestureSlots[iGestureSlot].m_pAnimLayer = pExpected;
  454. }
  455. return true;
  456. }
  457. //-----------------------------------------------------------------------------
  458. // Purpose:
  459. //-----------------------------------------------------------------------------
  460. bool CMultiPlayerAnimState::IsGestureSlotPlaying( int iGestureSlot, Activity iGestureActivity )
  461. {
  462. // Sanity Check
  463. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  464. // Check to see if the slot is active.
  465. if ( !IsGestureSlotActive( iGestureSlot ) )
  466. return false;
  467. return ( m_aGestureSlots[iGestureSlot].m_iActivity == iGestureActivity );
  468. }
  469. //-----------------------------------------------------------------------------
  470. // Purpose:
  471. //-----------------------------------------------------------------------------
  472. void CMultiPlayerAnimState::RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill )
  473. {
  474. // Sanity Check
  475. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  476. if ( !VerifyAnimLayerInSlot( iGestureSlot ) )
  477. return;
  478. if ( !IsGestureSlotPlaying( iGestureSlot, iGestureActivity ) )
  479. {
  480. #ifdef CLIENT_DLL
  481. if ( IsGestureSlotActive( iGestureSlot ) )
  482. {
  483. GestureSlot_t *pGesture = &m_aGestureSlots[iGestureSlot];
  484. if ( pGesture && pGesture->m_pAnimLayer )
  485. {
  486. pGesture->m_pAnimLayer->m_flCycle = 1.0; // run until the end
  487. RunGestureSlotAnimEventsToCompletion( &m_aGestureSlots[iGestureSlot] );
  488. }
  489. }
  490. #endif
  491. Activity iIdealGestureActivity = TranslateActivity( iGestureActivity );
  492. AddToGestureSlot( iGestureSlot, iIdealGestureActivity, bAutoKill );
  493. return;
  494. }
  495. // Reset the cycle = restart the gesture.
  496. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f;
  497. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f;
  498. }
  499. //-----------------------------------------------------------------------------
  500. // Purpose:
  501. //-----------------------------------------------------------------------------
  502. void CMultiPlayerAnimState::AddToGestureSlot( int iGestureSlot, Activity iGestureActivity, bool bAutoKill )
  503. {
  504. // Sanity Check
  505. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  506. CBasePlayer *pPlayer = GetBasePlayer();
  507. if ( !pPlayer )
  508. return;
  509. // Make sure we have a valid animation layer to fill out.
  510. if ( !m_aGestureSlots[iGestureSlot].m_pAnimLayer )
  511. return;
  512. if ( !VerifyAnimLayerInSlot( iGestureSlot ) )
  513. return;
  514. // Get the sequence.
  515. int iGestureSequence = pPlayer->SelectWeightedSequence( iGestureActivity );
  516. if ( iGestureSequence <= 0 )
  517. return;
  518. #ifdef CLIENT_DLL
  519. // Setup the gesture.
  520. m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot;
  521. m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity;
  522. m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill;
  523. m_aGestureSlots[iGestureSlot].m_bActive = true;
  524. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence;
  525. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot;
  526. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f;
  527. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f;
  528. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f;
  529. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f;
  530. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerAnimtime = 0.0f;
  531. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerFadeOuttime = 0.0f;
  532. pPlayer->m_flOverlayPrevEventCycle[iGestureSlot] = -1.0;
  533. #else
  534. // Setup the gesture.
  535. m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot;
  536. m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity;
  537. m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill;
  538. m_aGestureSlots[iGestureSlot].m_bActive = true;
  539. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity;
  540. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot;
  541. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nPriority = 0;
  542. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f;
  543. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f;
  544. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f;
  545. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity;
  546. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence;
  547. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f;
  548. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendIn = 0.0f;
  549. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendOut = 0.0f;
  550. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bSequenceFinished = false;
  551. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = 0.0f;
  552. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = gpGlobals->curtime;
  553. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bLooping = false;//( ( GetSequenceFlags( GetModelPtr(), iGestureSequence ) & STUDIO_LOOPING ) != 0);
  554. if ( bAutoKill )
  555. {
  556. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_AUTOKILL;
  557. }
  558. else
  559. {
  560. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags &= ~ANIM_LAYER_AUTOKILL;
  561. }
  562. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  563. #endif
  564. }
  565. //-----------------------------------------------------------------------------
  566. // Purpose:
  567. //-----------------------------------------------------------------------------
  568. void CMultiPlayerAnimState::AddVCDSequenceToGestureSlot( int iGestureSlot, int iGestureSequence, float flCycle, bool bAutoKill )
  569. {
  570. // Sanity Check
  571. Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT );
  572. CBasePlayer *pPlayer = GetBasePlayer();
  573. if ( !pPlayer )
  574. return;
  575. // Make sure we have a valid animation layer to fill out.
  576. if ( !m_aGestureSlots[iGestureSlot].m_pAnimLayer )
  577. return;
  578. if ( !VerifyAnimLayerInSlot( iGestureSlot ) )
  579. return;
  580. // Set the activity.
  581. Activity iGestureActivity = ACT_MP_VCD;
  582. #ifdef CLIENT_DLL
  583. // Setup the gesture.
  584. m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot;
  585. m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity;
  586. m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill;
  587. m_aGestureSlots[iGestureSlot].m_bActive = true;
  588. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence;
  589. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot;
  590. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f;
  591. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f;
  592. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = flCycle;
  593. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f;
  594. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerAnimtime = 0.0f;
  595. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerFadeOuttime = 0.0f;
  596. pPlayer->m_flOverlayPrevEventCycle[iGestureSlot] = flCycle == 0.f ? -1.0 : flCycle;
  597. #else
  598. // Setup the gesture.
  599. m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot;
  600. m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity;
  601. m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill;
  602. m_aGestureSlots[iGestureSlot].m_bActive = true;
  603. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity;
  604. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot;
  605. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nPriority = 0;
  606. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = flCycle;
  607. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f;
  608. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f;
  609. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity;
  610. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence;
  611. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f;
  612. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendIn = 0.0f;
  613. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendOut = 0.0f;
  614. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bSequenceFinished = false;
  615. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = 0.0f;
  616. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = gpGlobals->curtime;
  617. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bLooping = false;//( ( GetSequenceFlags( GetModelPtr(), iGestureSequence ) & STUDIO_LOOPING ) != 0);
  618. if ( bAutoKill )
  619. {
  620. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_AUTOKILL;
  621. }
  622. else
  623. {
  624. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags &= ~ANIM_LAYER_AUTOKILL;
  625. }
  626. m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  627. #endif
  628. }
  629. //-----------------------------------------------------------------------------
  630. // Purpose:
  631. //-----------------------------------------------------------------------------
  632. CAnimationLayer* CMultiPlayerAnimState::GetGestureSlotLayer( int iGestureSlot )
  633. {
  634. return m_aGestureSlots[iGestureSlot].m_pAnimLayer;
  635. }
  636. //-----------------------------------------------------------------------------
  637. // Purpose:
  638. //-----------------------------------------------------------------------------
  639. void CMultiPlayerAnimState::ShowDebugInfo( void )
  640. {
  641. if ( anim_showstate.GetInt() == GetBasePlayer()->entindex() )
  642. {
  643. DebugShowAnimStateForPlayer( GetBasePlayer()->IsServer() );
  644. }
  645. }
  646. //-----------------------------------------------------------------------------
  647. // Purpose: Cancel the current gesture and restart the main sequence.
  648. //-----------------------------------------------------------------------------
  649. void CMultiPlayerAnimState::RestartMainSequence( void )
  650. {
  651. CBaseAnimatingOverlay *pPlayer = GetBasePlayer();
  652. if ( pPlayer )
  653. {
  654. pPlayer->m_flAnimTime = gpGlobals->curtime;
  655. pPlayer->SetCycle( 0 );
  656. }
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Purpose:
  660. // Input : *idealActivity -
  661. // Output : Returns true on success, false on failure.
  662. //-----------------------------------------------------------------------------
  663. bool CMultiPlayerAnimState::HandleJumping( Activity &idealActivity )
  664. {
  665. if ( m_bJumping )
  666. {
  667. if ( m_bFirstJumpFrame )
  668. {
  669. m_bFirstJumpFrame = false;
  670. RestartMainSequence(); // Reset the animation.
  671. }
  672. // Check to see if we hit water and stop jumping animation.
  673. if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist )
  674. {
  675. m_bJumping = false;
  676. RestartMainSequence();
  677. }
  678. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  679. // on-ground flag set right when the message comes in.
  680. else if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
  681. {
  682. if ( GetBasePlayer()->GetFlags() & FL_ONGROUND )
  683. {
  684. m_bJumping = false;
  685. RestartMainSequence();
  686. }
  687. }
  688. }
  689. if ( m_bJumping )
  690. {
  691. idealActivity = ACT_MP_JUMP;
  692. return true;
  693. }
  694. else
  695. {
  696. return false;
  697. }
  698. }
  699. //-----------------------------------------------------------------------------
  700. // Purpose:
  701. // Input : *idealActivity -
  702. // Output : Returns true on success, false on failure.
  703. //-----------------------------------------------------------------------------
  704. bool CMultiPlayerAnimState::HandleDucking( Activity &idealActivity )
  705. {
  706. if ( GetBasePlayer()->GetFlags() & FL_DUCKING )
  707. {
  708. if ( GetOuterXYSpeed() > MOVING_MINIMUM_SPEED )
  709. {
  710. idealActivity = ACT_MP_CROUCHWALK;
  711. }
  712. else
  713. {
  714. idealActivity = ACT_MP_CROUCH_IDLE;
  715. }
  716. return true;
  717. }
  718. return false;
  719. }
  720. //-----------------------------------------------------------------------------
  721. // Purpose:
  722. // Input : &idealActivity -
  723. // Output : Returns true on success, false on failure.
  724. //-----------------------------------------------------------------------------
  725. bool CMultiPlayerAnimState::HandleSwimming( Activity &idealActivity )
  726. {
  727. if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist )
  728. {
  729. if ( m_bFirstSwimFrame )
  730. {
  731. // Reset the animation.
  732. RestartMainSequence();
  733. m_bFirstSwimFrame = false;
  734. }
  735. idealActivity = ACT_MP_SWIM;
  736. m_bInSwim = true;
  737. return true;
  738. }
  739. else
  740. {
  741. m_bInSwim = false;
  742. if ( !m_bFirstSwimFrame )
  743. {
  744. m_bFirstSwimFrame = true;
  745. }
  746. }
  747. return false;
  748. }
  749. //-----------------------------------------------------------------------------
  750. // Purpose:
  751. // Input : *idealActivity -
  752. // Output : Returns true on success, false on failure.
  753. //-----------------------------------------------------------------------------
  754. bool CMultiPlayerAnimState::HandleDying( Activity &idealActivity )
  755. {
  756. if ( m_bDying )
  757. {
  758. if ( m_bFirstDyingFrame )
  759. {
  760. // Reset the animation.
  761. RestartMainSequence();
  762. m_bFirstDyingFrame = false;
  763. }
  764. idealActivity = ACT_DIESIMPLE;
  765. return true;
  766. }
  767. else
  768. {
  769. if ( !m_bFirstDyingFrame )
  770. {
  771. m_bFirstDyingFrame = true;
  772. }
  773. }
  774. return false;
  775. }
  776. //-----------------------------------------------------------------------------
  777. // Purpose:
  778. // Input : *idealActivity -
  779. // Output : Returns true on success, false on failure.
  780. //-----------------------------------------------------------------------------
  781. bool CMultiPlayerAnimState::HandleMoving( Activity &idealActivity )
  782. {
  783. // In TF we run all the time now.
  784. float flSpeed = GetOuterXYSpeed();
  785. if ( flSpeed > MOVING_MINIMUM_SPEED )
  786. {
  787. // Always assume a run.
  788. idealActivity = ACT_MP_RUN;
  789. }
  790. return true;
  791. }
  792. //-----------------------------------------------------------------------------
  793. // Purpose:
  794. // Input : -
  795. // Output : Activity
  796. //-----------------------------------------------------------------------------
  797. Activity CMultiPlayerAnimState::CalcMainActivity()
  798. {
  799. Activity idealActivity = ACT_MP_STAND_IDLE;
  800. if ( HandleJumping( idealActivity ) ||
  801. HandleDucking( idealActivity ) ||
  802. HandleSwimming( idealActivity ) ||
  803. HandleDying( idealActivity ) )
  804. {
  805. // intentionally blank
  806. }
  807. else
  808. {
  809. HandleMoving( idealActivity );
  810. }
  811. ShowDebugInfo();
  812. // Client specific.
  813. #ifdef CLIENT_DLL
  814. if ( anim_showmainactivity.GetBool() )
  815. {
  816. DebugShowActivity( idealActivity );
  817. }
  818. #endif
  819. return idealActivity;
  820. }
  821. //-----------------------------------------------------------------------------
  822. // Purpose:
  823. // Input : actDesired -
  824. // Output : Activity
  825. //-----------------------------------------------------------------------------
  826. Activity CMultiPlayerAnimState::TranslateActivity( Activity actDesired )
  827. {
  828. // Translate activities for swimming.
  829. if ( m_bInSwim )
  830. {
  831. switch ( actDesired )
  832. {
  833. case ACT_MP_ATTACK_STAND_PRIMARYFIRE: { actDesired = ACT_MP_ATTACK_SWIM_PRIMARYFIRE; break; }
  834. case ACT_MP_ATTACK_STAND_SECONDARYFIRE: { actDesired = ACT_MP_ATTACK_SWIM_SECONDARYFIRE; break; }
  835. case ACT_MP_ATTACK_STAND_GRENADE: { actDesired = ACT_MP_ATTACK_SWIM_GRENADE; break; }
  836. case ACT_MP_RELOAD_STAND: { actDesired = ACT_MP_RELOAD_SWIM; break; }
  837. }
  838. }
  839. return actDesired;
  840. }
  841. //-----------------------------------------------------------------------------
  842. // Purpose:
  843. // Input : -
  844. // Output : float
  845. //-----------------------------------------------------------------------------
  846. float CMultiPlayerAnimState::GetCurrentMaxGroundSpeed()
  847. {
  848. CStudioHdr *pStudioHdr = GetBasePlayer()->GetModelPtr();
  849. if ( pStudioHdr == NULL )
  850. return 1.0f;
  851. float prevX = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveX );
  852. float prevY = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveY );
  853. float d = MAX( fabs( prevX ), fabs( prevY ) );
  854. float newX, newY;
  855. if ( d == 0.0 )
  856. {
  857. newX = 1.0;
  858. newY = 0.0;
  859. }
  860. else
  861. {
  862. newX = prevX / d;
  863. newY = prevY / d;
  864. }
  865. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, newX );
  866. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, newY );
  867. float speed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() );
  868. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, prevX );
  869. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, prevY );
  870. return speed;
  871. }
  872. //-----------------------------------------------------------------------------
  873. // Purpose:
  874. // Input : *bIsMoving -
  875. // Output : float
  876. //-----------------------------------------------------------------------------
  877. float CMultiPlayerAnimState::CalcMovementSpeed( bool *bIsMoving )
  878. {
  879. // Get the player's current velocity and speed.
  880. Vector vecVelocity;
  881. GetOuterAbsVelocity( vecVelocity );
  882. float flSpeed = vecVelocity.Length2D();
  883. if ( flSpeed > MOVING_MINIMUM_SPEED )
  884. {
  885. *bIsMoving = true;
  886. return flSpeed;
  887. }
  888. *bIsMoving = false;
  889. return 0.0f;
  890. }
  891. //-----------------------------------------------------------------------------
  892. // Purpose:
  893. // Input : *bIsMoving -
  894. // Output : float
  895. //-----------------------------------------------------------------------------
  896. float CMultiPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
  897. {
  898. float flSpeed = CalcMovementSpeed( bIsMoving );
  899. float flReturn = 1.0f;
  900. // If we are moving.
  901. if ( *bIsMoving )
  902. {
  903. // float flGroundSpeed = GetInterpolatedGroundSpeed();
  904. float flGroundSpeed = GetCurrentMaxGroundSpeed();
  905. if ( flGroundSpeed < 0.001f )
  906. {
  907. flReturn = 0.01f;
  908. }
  909. else
  910. {
  911. // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below
  912. flReturn = flSpeed / flGroundSpeed;
  913. flReturn = clamp( flReturn, 0.01f, 10.0f );
  914. }
  915. }
  916. return flReturn;
  917. }
  918. //-----------------------------------------------------------------------------
  919. // Purpose:
  920. // Output : float
  921. //-----------------------------------------------------------------------------
  922. float CMultiPlayerAnimState::GetInterpolatedGroundSpeed( void )
  923. {
  924. return m_flMaxGroundSpeed;
  925. }
  926. //-----------------------------------------------------------------------------
  927. // Purpose:
  928. // Input : *pStudioHdr -
  929. //-----------------------------------------------------------------------------
  930. void CMultiPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  931. {
  932. VPROF( "CBasePlayerAnimState::ComputeSequences" );
  933. // Lower body (walk/run/idle).
  934. ComputeMainSequence();
  935. // The groundspeed interpolator uses the main sequence info.
  936. UpdateInterpolators();
  937. ComputeGestureSequence( pStudioHdr );
  938. }
  939. //-----------------------------------------------------------------------------
  940. // Purpose:
  941. // Input : -
  942. //-----------------------------------------------------------------------------
  943. void CMultiPlayerAnimState::ComputeMainSequence()
  944. {
  945. VPROF( "CBasePlayerAnimState::ComputeMainSequence" );
  946. CBaseAnimatingOverlay *pPlayer = GetBasePlayer();
  947. // Have our class or the mod-specific class determine what the current activity is.
  948. Activity idealActivity = CalcMainActivity();
  949. #ifdef CLIENT_DLL
  950. Activity oldActivity = m_eCurrentMainSequenceActivity;
  951. #endif
  952. // Store our current activity so the aim and fire layers know what to do.
  953. m_eCurrentMainSequenceActivity = idealActivity;
  954. // Hook to force playback of a specific requested full-body sequence
  955. if ( m_nSpecificMainSequence >= 0 )
  956. {
  957. if ( pPlayer->GetSequence() != m_nSpecificMainSequence )
  958. {
  959. pPlayer->ResetSequence( m_nSpecificMainSequence );
  960. ResetGroundSpeed();
  961. return;
  962. }
  963. if ( !pPlayer->IsSequenceFinished() )
  964. return;
  965. m_nSpecificMainSequence = -1;
  966. RestartMainSequence();
  967. ResetGroundSpeed();
  968. }
  969. // Export to our outer class..
  970. int animDesired = SelectWeightedSequence( TranslateActivity( idealActivity ) );
  971. if ( pPlayer->GetSequenceActivity( pPlayer->GetSequence() ) == pPlayer->GetSequenceActivity( animDesired ) )
  972. return;
  973. if ( animDesired < 0 )
  974. {
  975. animDesired = 0;
  976. }
  977. pPlayer->ResetSequence( animDesired );
  978. #ifdef CLIENT_DLL
  979. // If we went from idle to walk, reset the interpolation history.
  980. // Kind of hacky putting this here.. it might belong outside the base class.
  981. if ( (oldActivity == ACT_MP_CROUCH_IDLE || oldActivity == ACT_MP_STAND_IDLE || oldActivity == ACT_MP_DEPLOYED_IDLE || oldActivity == ACT_MP_CROUCH_DEPLOYED_IDLE ) &&
  982. (idealActivity == ACT_MP_WALK || idealActivity == ACT_MP_CROUCHWALK ) )
  983. {
  984. ResetGroundSpeed();
  985. }
  986. #endif
  987. }
  988. //-----------------------------------------------------------------------------
  989. // Purpose:
  990. //-----------------------------------------------------------------------------
  991. void CMultiPlayerAnimState::ResetGroundSpeed( void )
  992. {
  993. #ifdef CLIENT_DLL
  994. m_flMaxGroundSpeed = GetCurrentMaxGroundSpeed();
  995. m_iv_flMaxGroundSpeed.Reset();
  996. m_iv_flMaxGroundSpeed.NoteChanged( gpGlobals->curtime, 0, false );
  997. #endif
  998. }
  999. //-----------------------------------------------------------------------------
  1000. // Purpose:
  1001. // Input : -
  1002. //-----------------------------------------------------------------------------
  1003. void CMultiPlayerAnimState::UpdateInterpolators()
  1004. {
  1005. VPROF( "CBasePlayerAnimState::UpdateInterpolators" );
  1006. // First, figure out their current max speed based on their current activity.
  1007. float flCurMaxSpeed = GetCurrentMaxGroundSpeed();
  1008. #ifdef CLIENT_DLL
  1009. float flGroundSpeedInterval = 0.1;
  1010. // Only update this 10x/sec so it has an interval to interpolate over.
  1011. if ( gpGlobals->curtime - m_flLastGroundSpeedUpdateTime >= flGroundSpeedInterval )
  1012. {
  1013. m_flLastGroundSpeedUpdateTime = gpGlobals->curtime;
  1014. m_flMaxGroundSpeed = flCurMaxSpeed;
  1015. m_iv_flMaxGroundSpeed.NoteChanged( gpGlobals->curtime, flGroundSpeedInterval, false );
  1016. }
  1017. m_iv_flMaxGroundSpeed.Interpolate( gpGlobals->curtime, flGroundSpeedInterval );
  1018. #else
  1019. m_flMaxGroundSpeed = flCurMaxSpeed;
  1020. #endif
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. // Purpose:
  1024. //-----------------------------------------------------------------------------
  1025. void CMultiPlayerAnimState::ComputeFireSequence( void )
  1026. {
  1027. }
  1028. //-----------------------------------------------------------------------------
  1029. // Purpose:
  1030. // Input : *pStudioHdr -
  1031. //-----------------------------------------------------------------------------
  1032. void CMultiPlayerAnimState::ComputeGestureSequence( CStudioHdr *pStudioHdr )
  1033. {
  1034. // Update all active gesture layers.
  1035. for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture )
  1036. {
  1037. if ( !m_aGestureSlots[iGesture].m_bActive )
  1038. continue;
  1039. if ( !VerifyAnimLayerInSlot( iGesture ) )
  1040. continue;
  1041. UpdateGestureLayer( pStudioHdr, &m_aGestureSlots[iGesture] );
  1042. }
  1043. }
  1044. //-----------------------------------------------------------------------------
  1045. // Purpose:
  1046. //-----------------------------------------------------------------------------
  1047. void CMultiPlayerAnimState::UpdateGestureLayer( CStudioHdr *pStudioHdr, GestureSlot_t *pGesture )
  1048. {
  1049. // Sanity check.
  1050. if ( !pStudioHdr || !pGesture )
  1051. return;
  1052. CBasePlayer *pPlayer = GetBasePlayer();
  1053. if( !pPlayer )
  1054. return;
  1055. #ifdef CLIENT_DLL
  1056. // Get the current cycle.
  1057. float flCycle = pGesture->m_pAnimLayer->m_flCycle;
  1058. flCycle += pPlayer->GetSequenceCycleRate( pStudioHdr, pGesture->m_pAnimLayer->m_nSequence ) * gpGlobals->frametime * GetGesturePlaybackRate() * pGesture->m_pAnimLayer->m_flPlaybackRate;
  1059. pGesture->m_pAnimLayer->m_flPrevCycle = pGesture->m_pAnimLayer->m_flCycle;
  1060. pGesture->m_pAnimLayer->m_flCycle = flCycle;
  1061. if( flCycle > 1.0f )
  1062. {
  1063. RunGestureSlotAnimEventsToCompletion( pGesture );
  1064. if ( pGesture->m_bAutoKill )
  1065. {
  1066. ResetGestureSlot( pGesture->m_iGestureSlot );
  1067. return;
  1068. }
  1069. else
  1070. {
  1071. pGesture->m_pAnimLayer->m_flCycle = 1.0f;
  1072. }
  1073. }
  1074. #else
  1075. if ( pGesture->m_iActivity != ACT_INVALID && pGesture->m_pAnimLayer->m_nActivity == ACT_INVALID )
  1076. {
  1077. ResetGestureSlot( pGesture->m_iGestureSlot );
  1078. }
  1079. #endif
  1080. }
  1081. extern ConVar mp_facefronttime;
  1082. extern ConVar mp_feetyawrate;
  1083. //-----------------------------------------------------------------------------
  1084. // Purpose:
  1085. // Input : eyeYaw -
  1086. // eyePitch -
  1087. //-----------------------------------------------------------------------------
  1088. void CMultiPlayerAnimState::Update( float eyeYaw, float eyePitch )
  1089. {
  1090. // Profile the animation update.
  1091. VPROF( "CMultiPlayerAnimState::Update" );
  1092. // Get the studio header for the player.
  1093. CStudioHdr *pStudioHdr = GetBasePlayer()->GetModelPtr();
  1094. if ( !pStudioHdr )
  1095. return;
  1096. // Check to see if we should be updating the animation state - dead, ragdolled?
  1097. if ( !ShouldUpdateAnimState() )
  1098. {
  1099. ClearAnimationState();
  1100. return;
  1101. }
  1102. // Store the eye angles.
  1103. m_flEyeYaw = AngleNormalize( eyeYaw );
  1104. m_flEyePitch = AngleNormalize( eyePitch );
  1105. // Compute the player sequences.
  1106. ComputeSequences( pStudioHdr );
  1107. if ( SetupPoseParameters( pStudioHdr ) )
  1108. {
  1109. // Pose parameter - what direction are the player's legs running in.
  1110. ComputePoseParam_MoveYaw( pStudioHdr );
  1111. // Pose parameter - Torso aiming (up/down).
  1112. ComputePoseParam_AimPitch( pStudioHdr );
  1113. // Pose parameter - Torso aiming (rotation).
  1114. ComputePoseParam_AimYaw( pStudioHdr );
  1115. }
  1116. #ifdef CLIENT_DLL
  1117. if ( C_BasePlayer::ShouldDrawLocalPlayer() )
  1118. {
  1119. GetBasePlayer()->SetPlaybackRate( 1.0f );
  1120. }
  1121. #endif
  1122. if( mp_showgestureslots.GetInt() == GetBasePlayer()->entindex() )
  1123. {
  1124. DebugGestureInfo();
  1125. }
  1126. }
  1127. //-----------------------------------------------------------------------------
  1128. // Purpose:
  1129. // Input : -
  1130. // Output : Returns true on success, false on failure.
  1131. //-----------------------------------------------------------------------------
  1132. bool CMultiPlayerAnimState::ShouldUpdateAnimState()
  1133. {
  1134. // Don't update anim state if we're not visible
  1135. if ( GetBasePlayer()->IsEffectActive( EF_NODRAW ) )
  1136. return false;
  1137. // By default, don't update their animation state when they're dead because they're
  1138. // either a ragdoll or they're not drawn.
  1139. #ifdef CLIENT_DLL
  1140. if ( GetBasePlayer()->IsDormant() )
  1141. return false;
  1142. #endif
  1143. return (GetBasePlayer()->IsAlive() || m_bDying);
  1144. }
  1145. //-----------------------------------------------------------------------------
  1146. // Purpose:
  1147. //-----------------------------------------------------------------------------
  1148. bool CMultiPlayerAnimState::SetupPoseParameters( CStudioHdr *pStudioHdr )
  1149. {
  1150. // Check to see if this has already been done.
  1151. if ( m_bPoseParameterInit )
  1152. return true;
  1153. // Save off the pose parameter indices.
  1154. if ( !pStudioHdr )
  1155. return false;
  1156. m_bPoseParameterInit = true;
  1157. // Look for the movement blenders.
  1158. m_PoseParameterData.m_iMoveX = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_x" );
  1159. m_PoseParameterData.m_iMoveY = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_y" );
  1160. /*
  1161. if ( ( m_PoseParameterData.m_iMoveX < 0 ) || ( m_PoseParameterData.m_iMoveY < 0 ) )
  1162. return false;
  1163. */
  1164. // Look for the aim pitch blender.
  1165. m_PoseParameterData.m_iAimPitch = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_pitch" );
  1166. /*
  1167. if ( m_PoseParameterData.m_iAimPitch < 0 )
  1168. return false;
  1169. */
  1170. // Look for aim yaw blender.
  1171. m_PoseParameterData.m_iAimYaw = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_yaw" );
  1172. /*
  1173. if ( m_PoseParameterData.m_iAimYaw < 0 )
  1174. return false;
  1175. */
  1176. m_PoseParameterData.m_iMoveYaw = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_yaw" );
  1177. m_PoseParameterData.m_iMoveScale = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_scale" );
  1178. /*
  1179. if ( ( m_PoseParameterData.m_iMoveYaw < 0 ) || ( m_PoseParameterData.m_iMoveScale < 0 ) )
  1180. return false;
  1181. */
  1182. return true;
  1183. }
  1184. float SnapYawTo( float flValue )
  1185. {
  1186. float flSign = 1.0f;
  1187. if ( flValue < 0.0f )
  1188. {
  1189. flSign = -1.0f;
  1190. flValue = -flValue;
  1191. }
  1192. if ( flValue < 23.0f )
  1193. {
  1194. flValue = 0.0f;
  1195. }
  1196. else if ( flValue < 67.0f )
  1197. {
  1198. flValue = 45.0f;
  1199. }
  1200. else if ( flValue < 113.0f )
  1201. {
  1202. flValue = 90.0f;
  1203. }
  1204. else if ( flValue < 157 )
  1205. {
  1206. flValue = 135.0f;
  1207. }
  1208. else
  1209. {
  1210. flValue = 180.0f;
  1211. }
  1212. return ( flValue * flSign );
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. // Purpose: double check that the movement animations actually have movement
  1216. //-----------------------------------------------------------------------------
  1217. void CMultiPlayerAnimState::DoMovementTest( CStudioHdr *pStudioHdr, float flX, float flY )
  1218. {
  1219. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, flX );
  1220. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, flY );
  1221. #ifdef STAGING_ONLY
  1222. float flTestSpeed = GetBasePlayer()->GetSequenceGroundSpeed( m_nMovementSequence );
  1223. if ( flTestSpeed < 10.0f )
  1224. {
  1225. Warning( "%s : %s (X %.0f Y %.0f) missing movement\n", pStudioHdr->pszName(), GetBasePlayer()->GetSequenceName( m_nMovementSequence ), flX, flY );
  1226. }
  1227. #endif
  1228. /*
  1229. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, flX );
  1230. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, flY );
  1231. float flDuration = GetBasePlayer()->SequenceDuration( m_nMovementSequence );
  1232. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, 1.0f );
  1233. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, 0.0f );
  1234. float flForward = GetBasePlayer()->SequenceDuration( m_nMovementSequence );
  1235. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, 0.0f );
  1236. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, 0.0f );
  1237. float flCenter = GetBasePlayer()->SequenceDuration( m_nMovementSequence );
  1238. if ( flDuration > flForward * 1.1f || flDuration < flForward * 0.9f )
  1239. {
  1240. Warning( "%s : %s (X %.0f Y %.0f) mismatched duration with forward %.1f vs %.1f\n", pStudioHdr->pszName(), GetBasePlayer()->GetSequenceName( m_nMovementSequence ), flX, flY, flDuration, flForward );
  1241. }
  1242. if ( flDuration > flCenter * 1.1f || flDuration < flCenter * 0.9f )
  1243. {
  1244. Warning( "%s : %s (X %.0f Y %.0f) mismatched duration with center %.1f vs %.1f\n", pStudioHdr->pszName(), GetBasePlayer()->GetSequenceName( m_nMovementSequence ), flX, flY, flDuration, flCenter );
  1245. }
  1246. */
  1247. }
  1248. void CMultiPlayerAnimState::DoMovementTest( CStudioHdr *pStudioHdr )
  1249. {
  1250. if ( m_LegAnimType == LEGANIM_9WAY )
  1251. {
  1252. DoMovementTest( pStudioHdr, -1.0f, -1.0f );
  1253. DoMovementTest( pStudioHdr, -1.0f, 0.0f );
  1254. DoMovementTest( pStudioHdr, -1.0f, 1.0f );
  1255. DoMovementTest( pStudioHdr, 0.0f, -1.0f );
  1256. DoMovementTest( pStudioHdr, 0.0f, 1.0f );
  1257. DoMovementTest( pStudioHdr, 1.0f, -1.0f );
  1258. DoMovementTest( pStudioHdr, 1.0f, 0.0f );
  1259. DoMovementTest( pStudioHdr, 1.0f, 1.0f );
  1260. }
  1261. }
  1262. void CMultiPlayerAnimState::GetMovementFlags( CStudioHdr *pStudioHdr )
  1263. {
  1264. if ( m_nMovementSequence == GetBasePlayer()->GetSequence() )
  1265. {
  1266. return;
  1267. }
  1268. m_nMovementSequence = GetBasePlayer()->GetSequence();
  1269. m_LegAnimType = LEGANIM_9WAY;
  1270. KeyValues *seqKeyValues = GetBasePlayer()->GetSequenceKeyValues( m_nMovementSequence );
  1271. // Msg("sequence %d : %s (%d)\n", sequence, GetOuter()->GetSequenceName( sequence ), seqKeyValues != NULL );
  1272. if (seqKeyValues)
  1273. {
  1274. KeyValues *pkvMovement = seqKeyValues->FindKey( "movement" );
  1275. if (pkvMovement)
  1276. {
  1277. const char *szStyle = pkvMovement->GetString();
  1278. if ( V_stricmp( szStyle, "robot2" ) == 0 )
  1279. {
  1280. m_LegAnimType = LEGANIM_8WAY;
  1281. }
  1282. }
  1283. seqKeyValues->deleteThis();
  1284. }
  1285. // skip tests if it's not a movement animation
  1286. if ( m_nMovementSequence < 0 || !( GetBasePlayer()->GetFlags() & FL_ONGROUND ) || pStudioHdr->pSeqdesc( m_nMovementSequence ).groupsize[0] == 1 )
  1287. {
  1288. return;
  1289. }
  1290. DoMovementTest( pStudioHdr );
  1291. }
  1292. //-----------------------------------------------------------------------------
  1293. // Purpose:
  1294. // Input : *pStudioHdr -
  1295. //-----------------------------------------------------------------------------
  1296. void CMultiPlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
  1297. {
  1298. // Get the estimated movement yaw.
  1299. EstimateYaw();
  1300. // Get the view yaw.
  1301. float flAngle = AngleNormalize( m_flEyeYaw );
  1302. // Calc side to side turning - the view vs. movement yaw.
  1303. float flYaw = flAngle - m_PoseParameterData.m_flEstimateYaw;
  1304. flYaw = AngleNormalize( -flYaw );
  1305. // Get the current speed the character is running.
  1306. bool bIsMoving;
  1307. float flSpeed = CalcMovementSpeed( &bIsMoving );
  1308. // Setup the 9-way blend parameters based on our speed and direction.
  1309. Vector2D vecCurrentMoveYaw( 0.0f, 0.0f );
  1310. if ( bIsMoving )
  1311. {
  1312. GetMovementFlags( pStudioHdr );
  1313. if ( mp_slammoveyaw.GetBool() )
  1314. {
  1315. flYaw = SnapYawTo( flYaw );
  1316. }
  1317. if ( m_LegAnimType == LEGANIM_9WAY )
  1318. {
  1319. // convert YAW back into vector
  1320. vecCurrentMoveYaw.x = cos( DEG2RAD( flYaw ) );
  1321. vecCurrentMoveYaw.y = -sin( DEG2RAD( flYaw ) );
  1322. // push edges out to -1 to 1 box
  1323. float flInvScale = MAX( fabs( vecCurrentMoveYaw.x ), fabs( vecCurrentMoveYaw.y ) );
  1324. if ( flInvScale != 0.0f )
  1325. {
  1326. vecCurrentMoveYaw.x /= flInvScale;
  1327. vecCurrentMoveYaw.y /= flInvScale;
  1328. }
  1329. // find what speed was actually authored
  1330. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, vecCurrentMoveYaw.x );
  1331. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, vecCurrentMoveYaw.y );
  1332. float flMaxSpeed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() );
  1333. // scale playback
  1334. if ( flMaxSpeed > flSpeed )
  1335. {
  1336. vecCurrentMoveYaw.x *= flSpeed / flMaxSpeed;
  1337. vecCurrentMoveYaw.y *= flSpeed / flMaxSpeed;
  1338. }
  1339. // Set the 9-way blend movement pose parameters.
  1340. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, vecCurrentMoveYaw.x );
  1341. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, vecCurrentMoveYaw.y );
  1342. }
  1343. else
  1344. {
  1345. // find what speed was actually authored
  1346. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveYaw, flYaw );
  1347. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveScale, 1.0f );
  1348. float flMaxSpeed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() );
  1349. // scale playback
  1350. if ( flMaxSpeed > flSpeed )
  1351. {
  1352. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveScale, flSpeed / flMaxSpeed );
  1353. }
  1354. }
  1355. }
  1356. else
  1357. {
  1358. // Set the 9-way blend movement pose parameters.
  1359. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, 0.0f );
  1360. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, 0.0f );
  1361. }
  1362. m_DebugAnimData.m_vecMoveYaw = vecCurrentMoveYaw;
  1363. }
  1364. //-----------------------------------------------------------------------------
  1365. // Purpose:
  1366. //-----------------------------------------------------------------------------
  1367. void CMultiPlayerAnimState::EstimateYaw( void )
  1368. {
  1369. // Get the frame time.
  1370. float flDeltaTime = gpGlobals->frametime;
  1371. if ( flDeltaTime == 0.0f )
  1372. return;
  1373. // Get the player's velocity and angles.
  1374. Vector vecEstVelocity;
  1375. GetOuterAbsVelocity( vecEstVelocity );
  1376. QAngle angles = GetBasePlayer()->GetLocalAngles();
  1377. // If we are not moving, sync up the feet and eyes slowly.
  1378. if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f )
  1379. {
  1380. float flYawDelta = angles[YAW] - m_PoseParameterData.m_flEstimateYaw;
  1381. flYawDelta = AngleNormalize( flYawDelta );
  1382. if ( flDeltaTime < 0.25f )
  1383. {
  1384. flYawDelta *= ( flDeltaTime * 4.0f );
  1385. }
  1386. else
  1387. {
  1388. flYawDelta *= flDeltaTime;
  1389. }
  1390. m_PoseParameterData.m_flEstimateYaw += flYawDelta;
  1391. AngleNormalize( m_PoseParameterData.m_flEstimateYaw );
  1392. }
  1393. else
  1394. {
  1395. m_PoseParameterData.m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI );
  1396. m_PoseParameterData.m_flEstimateYaw = clamp( m_PoseParameterData.m_flEstimateYaw, -180.0f, 180.0f );
  1397. }
  1398. }
  1399. //-----------------------------------------------------------------------------
  1400. // Purpose:
  1401. //-----------------------------------------------------------------------------
  1402. void CMultiPlayerAnimState::ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr )
  1403. {
  1404. // Get the view pitch.
  1405. float flAimPitch = m_flEyePitch;
  1406. // Set the aim pitch pose parameter and save.
  1407. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimPitch, -flAimPitch );
  1408. m_DebugAnimData.m_flAimPitch = flAimPitch;
  1409. }
  1410. //-----------------------------------------------------------------------------
  1411. // Purpose:
  1412. //-----------------------------------------------------------------------------
  1413. void CMultiPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr )
  1414. {
  1415. // Get the movement velocity.
  1416. Vector vecVelocity;
  1417. GetOuterAbsVelocity( vecVelocity );
  1418. // Check to see if we are moving.
  1419. bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false;
  1420. // If we are moving or are prone and undeployed.
  1421. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between
  1422. // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window,
  1423. // and the fact that m_flEyeYaw is never propogated from the server to the client.
  1424. // TODO: Fix this after Halloween 2014.
  1425. if ( bMoving || m_bForceAimYaw )
  1426. {
  1427. // The feet match the eye direction when moving - the move yaw takes care of the rest.
  1428. m_flGoalFeetYaw = m_flEyeYaw;
  1429. }
  1430. // Else if we are not moving.
  1431. else
  1432. {
  1433. // Initialize the feet.
  1434. if ( m_PoseParameterData.m_flLastAimTurnTime <= 0.0f )
  1435. {
  1436. m_flGoalFeetYaw = m_flEyeYaw;
  1437. m_flCurrentFeetYaw = m_flEyeYaw;
  1438. m_PoseParameterData.m_flLastAimTurnTime = gpGlobals->curtime;
  1439. }
  1440. // Make sure the feet yaw isn't too far out of sync with the eye yaw.
  1441. // TODO: Do something better here!
  1442. else
  1443. {
  1444. float flYawDelta = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw );
  1445. if ( fabs( flYawDelta ) > 45.0f/*m_AnimConfig.m_flMaxBodyYawDegrees*/ )
  1446. {
  1447. float flSide = ( flYawDelta > 0.0f ) ? -1.0f : 1.0f;
  1448. m_flGoalFeetYaw += ( 45.0f/*m_AnimConfig.m_flMaxBodyYawDegrees*/ * flSide );
  1449. }
  1450. }
  1451. }
  1452. // Fix up the feet yaw.
  1453. m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw );
  1454. if ( m_flGoalFeetYaw != m_flCurrentFeetYaw )
  1455. {
  1456. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between
  1457. // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window,
  1458. // and the fact that m_flEyeYaw is never propogated from the server to the client.
  1459. // TODO: Fix this after Halloween 2014.
  1460. if ( m_bForceAimYaw )
  1461. {
  1462. m_flCurrentFeetYaw = m_flGoalFeetYaw;
  1463. }
  1464. else
  1465. {
  1466. ConvergeYawAngles( m_flGoalFeetYaw, /*DOD_BODYYAW_RATE*/720.0f, gpGlobals->frametime, m_flCurrentFeetYaw );
  1467. m_flLastAimTurnTime = gpGlobals->curtime;
  1468. }
  1469. }
  1470. // Rotate the body into position.
  1471. m_angRender[YAW] = m_flCurrentFeetYaw;
  1472. // Find the aim(torso) yaw base on the eye and feet yaws.
  1473. float flAimYaw = m_flEyeYaw - m_flCurrentFeetYaw;
  1474. flAimYaw = AngleNormalize( flAimYaw );
  1475. // Set the aim yaw and save.
  1476. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimYaw, -flAimYaw );
  1477. m_DebugAnimData.m_flAimYaw = flAimYaw;
  1478. // Turn off a force aim yaw - either we have already updated or we don't need to.
  1479. m_bForceAimYaw = false;
  1480. #ifndef CLIENT_DLL
  1481. QAngle angle = GetBasePlayer()->GetAbsAngles();
  1482. angle[YAW] = m_flCurrentFeetYaw;
  1483. GetBasePlayer()->SetAbsAngles( angle );
  1484. #endif
  1485. }
  1486. //-----------------------------------------------------------------------------
  1487. // Purpose:
  1488. // Input : flGoalYaw -
  1489. // flYawRate -
  1490. // flDeltaTime -
  1491. // &flCurrentYaw -
  1492. //-----------------------------------------------------------------------------
  1493. void CMultiPlayerAnimState::ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw )
  1494. {
  1495. #define FADE_TURN_DEGREES 60.0f
  1496. // Find the yaw delta.
  1497. float flDeltaYaw = flGoalYaw - flCurrentYaw;
  1498. float flDeltaYawAbs = fabs( flDeltaYaw );
  1499. flDeltaYaw = AngleNormalize( flDeltaYaw );
  1500. // Always do at least a bit of the turn (1%).
  1501. float flScale = 1.0f;
  1502. flScale = flDeltaYawAbs / FADE_TURN_DEGREES;
  1503. flScale = clamp( flScale, 0.01f, 1.0f );
  1504. float flYaw = flYawRate * flDeltaTime * flScale;
  1505. if ( flDeltaYawAbs < flYaw )
  1506. {
  1507. flCurrentYaw = flGoalYaw;
  1508. }
  1509. else
  1510. {
  1511. float flSide = ( flDeltaYaw < 0.0f ) ? -1.0f : 1.0f;
  1512. flCurrentYaw += ( flYaw * flSide );
  1513. }
  1514. flCurrentYaw = AngleNormalize( flCurrentYaw );
  1515. #undef FADE_TURN_DEGREES
  1516. }
  1517. //-----------------------------------------------------------------------------
  1518. // Purpose:
  1519. // Input : -
  1520. // Output : const QAngle&
  1521. //-----------------------------------------------------------------------------
  1522. const QAngle& CMultiPlayerAnimState::GetRenderAngles()
  1523. {
  1524. return m_angRender;
  1525. }
  1526. //-----------------------------------------------------------------------------
  1527. // Purpose:
  1528. // Input : vel -
  1529. //-----------------------------------------------------------------------------
  1530. void CMultiPlayerAnimState::GetOuterAbsVelocity( Vector& vel )
  1531. {
  1532. #if defined( CLIENT_DLL )
  1533. GetBasePlayer()->EstimateAbsVelocity( vel );
  1534. #else
  1535. vel = GetBasePlayer()->GetAbsVelocity();
  1536. #endif
  1537. }
  1538. //-----------------------------------------------------------------------------
  1539. // Purpose:
  1540. //-----------------------------------------------------------------------------
  1541. void CMultiPlayerAnimState::Release( void )
  1542. {
  1543. delete this;
  1544. }
  1545. //-----------------------------------------------------------------------------
  1546. // Purpose:
  1547. // Input : -
  1548. // Output : float
  1549. //-----------------------------------------------------------------------------
  1550. float CMultiPlayerAnimState::GetOuterXYSpeed()
  1551. {
  1552. Vector vel;
  1553. GetOuterAbsVelocity( vel );
  1554. return vel.Length2D();
  1555. }
  1556. //-----------------------------------------------------------------------------
  1557. // Purpose:
  1558. //-----------------------------------------------------------------------------
  1559. void Anim_StateLog( const char *pMsg, ... )
  1560. {
  1561. // Format the string.
  1562. char str[4096];
  1563. va_list marker;
  1564. va_start( marker, pMsg );
  1565. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  1566. va_end( marker );
  1567. // Log it?
  1568. if ( anim_showstatelog.GetInt() == 1 || anim_showstatelog.GetInt() == 3 )
  1569. {
  1570. Msg( "%s", str );
  1571. }
  1572. if ( anim_showstatelog.GetInt() > 1 )
  1573. {
  1574. // static FileHandle_t hFile = filesystem->Open( "AnimState.log", "wt" );
  1575. // filesystem->FPrintf( hFile, "%s", str );
  1576. // filesystem->Flush( hFile );
  1577. }
  1578. }
  1579. //-----------------------------------------------------------------------------
  1580. // Purpose:
  1581. //-----------------------------------------------------------------------------
  1582. void Anim_StatePrintf( int iLine, const char *pMsg, ... )
  1583. {
  1584. // Format the string.
  1585. char str[4096];
  1586. va_list marker;
  1587. va_start( marker, pMsg );
  1588. Q_vsnprintf( str, sizeof( str ), pMsg, marker );
  1589. va_end( marker );
  1590. // Show it with Con_NPrintf.
  1591. engine->Con_NPrintf( iLine, "%s", str );
  1592. // Log it.
  1593. Anim_StateLog( "%s\n", str );
  1594. }
  1595. //-----------------------------------------------------------------------------
  1596. // Purpose:
  1597. //-----------------------------------------------------------------------------
  1598. void CMultiPlayerAnimState::DebugShowAnimStateForPlayer( bool bIsServer )
  1599. {
  1600. // Get the player's velocity.
  1601. Vector vecVelocity;
  1602. GetOuterAbsVelocity( vecVelocity );
  1603. // Start animation state logging.
  1604. int iLine = 5;
  1605. if ( bIsServer )
  1606. {
  1607. iLine = 12;
  1608. }
  1609. // Anim_StateLog( "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount );
  1610. Anim_StatePrintf( iLine++, "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount );
  1611. // Write out the main sequence and its data.
  1612. Anim_StatePrintf( iLine++, "Main: %s, Cycle: %.2f\n", GetSequenceName( GetBasePlayer()->GetModelPtr(), GetBasePlayer()->GetSequence() ), GetBasePlayer()->GetCycle() );
  1613. #if 0
  1614. if ( m_bPlayingGesture )
  1615. {
  1616. Anim_StatePrintf( iLine++, "Gesture: %s, Cycle: %.2f\n",
  1617. GetSequenceName( GetBasePlayer()->GetModelPtr(), m_iGestureSequence ),
  1618. m_flGestureCycle );
  1619. }
  1620. #endif
  1621. // Write out the layers and their data.
  1622. for ( int iAnim = 0; iAnim < GetBasePlayer()->GetNumAnimOverlays(); ++iAnim )
  1623. {
  1624. #ifdef CLIENT_DLL
  1625. C_AnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( iAnim );
  1626. if ( pLayer && ( pLayer->m_nOrder != CBaseAnimatingOverlay::MAX_OVERLAYS ) )
  1627. {
  1628. Anim_StatePrintf( iLine++, "Layer %s: Weight: %.2f, Cycle: %.2f", GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ), (float)pLayer->m_flWeight, (float)pLayer->m_flCycle );
  1629. }
  1630. #else
  1631. CAnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( iAnim );
  1632. if ( pLayer && ( pLayer->m_nOrder != CBaseAnimatingOverlay::MAX_OVERLAYS ) )
  1633. {
  1634. Anim_StatePrintf( iLine++, "Layer %s: Weight: %.2f, Cycle: %.2f", GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ), (float)pLayer->m_flWeight, (float)pLayer->m_flCycle );
  1635. }
  1636. #endif
  1637. }
  1638. // Write out the speed data.
  1639. Anim_StatePrintf( iLine++, "Time: %.2f, Speed: %.2f, MaxSpeed: %.2f", gpGlobals->curtime, vecVelocity.Length2D(), GetCurrentMaxGroundSpeed() );
  1640. // Write out the 9-way blend data.
  1641. Anim_StatePrintf( iLine++, "EntityYaw: %.2f, AimYaw: %.2f, AimPitch: %.2f, MoveX: %.2f, MoveY: %.2f", m_angRender[YAW], m_DebugAnimData.m_flAimYaw, m_DebugAnimData.m_flAimPitch, m_DebugAnimData.m_vecMoveYaw.x, m_DebugAnimData.m_vecMoveYaw.y );
  1642. // Anim_StateLog( "--------------------------------------------\n\n" );
  1643. Anim_StatePrintf( iLine++, "--------------------------------------------\n\n" );
  1644. DebugShowEyeYaw();
  1645. }
  1646. //-----------------------------------------------------------------------------
  1647. // Purpose:
  1648. //-----------------------------------------------------------------------------
  1649. void CMultiPlayerAnimState::DebugShowEyeYaw( void )
  1650. {
  1651. #ifdef _NDEBUG
  1652. float flBaseSize = 10;
  1653. float flHeight = 80;
  1654. Vector vecPos = GetOuter()->GetAbsOrigin() + Vector( 0.0f, 0.0f, 3.0f );
  1655. QAngle angles( 0.0f, 0.0f, 0.0f );
  1656. angles[YAW] = m_flEyeYaw;
  1657. Vector vecForward, vecRight, vecUp;
  1658. AngleVectors( angles, &vecForward, &vecRight, &vecUp );
  1659. // Draw a red triangle on the ground for the eye yaw.
  1660. if ( debugoverlay )
  1661. {
  1662. debugoverlay->AddTriangleOverlay( ( vecPos + vecRight * flBaseSize / 2.0f ),
  1663. ( vecPos - vecRight * flBaseSize / 2.0f ),
  1664. ( vecPos + vecForward * flHeight, 255, 0, 0, 255, false, 0.01f );
  1665. }
  1666. #endif
  1667. }
  1668. #if defined( CLIENT_DLL )
  1669. //-----------------------------------------------------------------------------
  1670. // Purpose:
  1671. // Input : activity -
  1672. //-----------------------------------------------------------------------------
  1673. void CMultiPlayerAnimState::DebugShowActivity( Activity activity )
  1674. {
  1675. #ifdef _DEBUG
  1676. const char *pszActivity = "other";
  1677. switch( activity )
  1678. {
  1679. case ACT_MP_STAND_IDLE:
  1680. {
  1681. pszActivity = "idle";
  1682. break;
  1683. }
  1684. case ACT_MP_SPRINT:
  1685. {
  1686. pszActivity = "sprint";
  1687. break;
  1688. }
  1689. case ACT_MP_WALK:
  1690. {
  1691. pszActivity = "walk";
  1692. break;
  1693. }
  1694. case ACT_MP_RUN:
  1695. {
  1696. pszActivity = "run";
  1697. break;
  1698. }
  1699. }
  1700. Msg( "Activity: %s\n", pszActivity );
  1701. #endif
  1702. }
  1703. #endif
  1704. //-----------------------------------------------------------------------------
  1705. // Purpose:
  1706. // Input : iStartLine -
  1707. //-----------------------------------------------------------------------------
  1708. void CMultiPlayerAnimState::DebugShowAnimState( int iStartLine )
  1709. {
  1710. Vector vOuterVel;
  1711. GetOuterAbsVelocity( vOuterVel );
  1712. Anim_StateLog( "----------------- frame %d -----------------\n", gpGlobals->framecount );
  1713. int iLine = iStartLine;
  1714. Anim_StatePrintf( iLine++, "main: %s, cycle: %.2f\n", GetSequenceName( GetBasePlayer()->GetModelPtr(), GetBasePlayer()->GetSequence() ), GetBasePlayer()->GetCycle() );
  1715. #if defined( CLIENT_DLL )
  1716. for ( int i=0; i < GetBasePlayer()->GetNumAnimOverlays()-1; i++ )
  1717. {
  1718. C_AnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( i /*i+1?*/ );
  1719. Anim_StatePrintf( iLine++, "%s, weight: %.2f, cycle: %.2f, aim (%d)",
  1720. pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? "--" : GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ),
  1721. pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? -1 :(float)pLayer->m_flWeight,
  1722. pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? -1 :(float)pLayer->m_flCycle,
  1723. i
  1724. );
  1725. }
  1726. #endif
  1727. Anim_StatePrintf( iLine++, "vel: %.2f, time: %.2f, max: %.2f",
  1728. vOuterVel.Length2D(), gpGlobals->curtime, GetInterpolatedGroundSpeed() );
  1729. // AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, body_pitch: %.2f, move_x: %.2f, move_y: %.2f",
  1730. // m_angRender[YAW], g_flLastBodyYaw, g_flLastBodyPitch, m_vLastMovePose.x, m_vLastMovePose.y );
  1731. Anim_StateLog( "--------------------------------------------\n\n" );
  1732. if ( debugoverlay )
  1733. {
  1734. // Draw a red triangle on the ground for the eye yaw.
  1735. float flBaseSize = 10;
  1736. float flHeight = 80;
  1737. Vector vBasePos = GetBasePlayer()->GetAbsOrigin() + Vector( 0, 0, 3 );
  1738. QAngle angles( 0, 0, 0 );
  1739. angles[YAW] = m_flEyeYaw;
  1740. Vector vForward, vRight, vUp;
  1741. AngleVectors( angles, &vForward, &vRight, &vUp );
  1742. debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 255, 0, 0, 255, false, 0.01 );
  1743. // Draw a blue triangle on the ground for the body yaw.
  1744. angles[YAW] = m_angRender[YAW];
  1745. AngleVectors( angles, &vForward, &vRight, &vUp );
  1746. debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 0, 255, 255, false, 0.01 );
  1747. }
  1748. }
  1749. // Debug!
  1750. const char *s_aGestureSlotNames[GESTURE_SLOT_COUNT] =
  1751. {
  1752. "Attack and Reload",
  1753. "Grenade",
  1754. "Jump",
  1755. "Swim",
  1756. "Flinch",
  1757. "VCD",
  1758. "Custom"
  1759. };
  1760. //-----------------------------------------------------------------------------
  1761. // Purpose:
  1762. //-----------------------------------------------------------------------------
  1763. void CMultiPlayerAnimState::DebugGestureInfo( void )
  1764. {
  1765. CBasePlayer *pPlayer = GetBasePlayer();
  1766. if ( !pPlayer )
  1767. return;
  1768. int iLine = ( pPlayer->IsServer() ? 12 : ( 14 + GESTURE_SLOT_COUNT ) );
  1769. Anim_StatePrintf( iLine++, "%s\n", ( pPlayer->IsServer() ? "Server" : "Client" ) );
  1770. for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture )
  1771. {
  1772. GestureSlot_t *pGesture = &m_aGestureSlots[iGesture];
  1773. if ( pGesture )
  1774. {
  1775. if( pGesture->m_bActive )
  1776. {
  1777. Anim_StatePrintf( iLine++, "Gesture Slot %d(%s): %s %s(A:%s, C:%f P:%f)\n",
  1778. iGesture,
  1779. s_aGestureSlotNames[iGesture],
  1780. ActivityList_NameForIndex( pGesture->m_iActivity ),
  1781. GetSequenceName( pPlayer->GetModelPtr(), pGesture->m_pAnimLayer->m_nSequence ),
  1782. ( pGesture->m_bAutoKill ? "true" : "false" ),
  1783. (float)pGesture->m_pAnimLayer->m_flCycle, (float)pGesture->m_pAnimLayer->m_flPlaybackRate );
  1784. }
  1785. else
  1786. {
  1787. Anim_StatePrintf( iLine++, "Gesture Slot %d(%s): NOT ACTIVE!\n", iGesture, s_aGestureSlotNames[iGesture] );
  1788. }
  1789. }
  1790. }
  1791. }
  1792. //-----------------------------------------------------------------------------
  1793. // Purpose: New Model, init the pose parameters
  1794. //-----------------------------------------------------------------------------
  1795. void CMultiPlayerAnimState::OnNewModel( void )
  1796. {
  1797. m_bPoseParameterInit = false;
  1798. m_PoseParameterData.Init();
  1799. ClearAnimationState();
  1800. }