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.

1057 lines
28 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "cs_playeranimstate.h"
  8. #include "base_playeranimstate.h"
  9. #include "tier0/vprof.h"
  10. #include "animation.h"
  11. #include "weapon_csbase.h"
  12. #include "studio.h"
  13. #include "apparent_velocity_helper.h"
  14. #include "utldict.h"
  15. #include "weapon_basecsgrenade.h"
  16. #include "datacache/imdlcache.h"
  17. #ifdef CLIENT_DLL
  18. #include "c_cs_player.h"
  19. #include "bone_setup.h"
  20. #include "interpolatedvar.h"
  21. #include "c_cs_hostage.h"
  22. #else
  23. #include "cs_player.h"
  24. #include "cs_simple_hostage.h"
  25. #include "cs_gamestats.h"
  26. #endif
  27. #define ANIM_TOPSPEED_WALK 100
  28. #define ANIM_TOPSPEED_RUN 250
  29. #define ANIM_TOPSPEED_RUN_CROUCH 85
  30. #define DEFAULT_IDLE_NAME "idle_upper_"
  31. #define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_"
  32. #define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_"
  33. #define DEFAULT_WALK_NAME "walk_upper_"
  34. #define DEFAULT_RUN_NAME "run_upper_"
  35. #define DEFAULT_FIRE_IDLE_NAME "idle_shoot_"
  36. #define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_"
  37. #define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_"
  38. #define DEFAULT_FIRE_WALK_NAME "walk_shoot_"
  39. #define DEFAULT_FIRE_RUN_NAME "run_shoot_"
  40. #define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS+1)
  41. #define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
  42. #define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
  43. #define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1)
  44. // ------------------------------------------------------------------------------------------------ //
  45. // CCSPlayerAnimState declaration.
  46. // ------------------------------------------------------------------------------------------------ //
  47. class CCSPlayerAnimState : public CBasePlayerAnimState, public ICSPlayerAnimState
  48. {
  49. public:
  50. DECLARE_CLASS( CCSPlayerAnimState, CBasePlayerAnimState );
  51. friend ICSPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  52. CCSPlayerAnimState();
  53. virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
  54. virtual bool IsThrowingGrenade();
  55. virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
  56. virtual void ClearAnimationState();
  57. virtual bool CanThePlayerMove();
  58. virtual float GetCurrentMaxGroundSpeed();
  59. virtual Activity CalcMainActivity();
  60. virtual void DebugShowAnimState( int iStartLine );
  61. virtual void ComputeSequences( CStudioHdr *pStudioHdr );
  62. virtual void ClearAnimationLayers();
  63. virtual int SelectWeightedSequence( Activity activity );
  64. void InitCS( CBaseAnimatingOverlay *pPlayer, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  65. protected:
  66. int CalcFireLayerSequence(PlayerAnimEvent_t event);
  67. void ComputeFireSequence( CStudioHdr *pStudioHdr );
  68. void ComputeReloadSequence( CStudioHdr *pStudioHdr );
  69. int CalcReloadLayerSequence( PlayerAnimEvent_t event );
  70. bool IsOuterGrenadePrimed();
  71. void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
  72. int CalcGrenadePrimeSequence();
  73. int CalcGrenadeThrowSequence();
  74. int GetOuterGrenadeThrowCounter();
  75. const char* GetWeaponSuffix();
  76. bool HandleJumping();
  77. void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd );
  78. virtual int CalcSequenceIndex( const char *pBaseName, ... );
  79. private:
  80. // Current state variables.
  81. bool m_bJumping; // Set on a jump event.
  82. float m_flJumpStartTime;
  83. bool m_bFirstJumpFrame;
  84. // Aim sequence plays reload while this is on.
  85. bool m_bReloading;
  86. float m_flReloadCycle;
  87. int m_iReloadSequence;
  88. float m_flReloadHoldEndTime; // Intermediate shotgun reloads get held a fraction of a second
  89. // This is set to true if ANY animation is being played in the fire layer.
  90. bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
  91. // until it completes.
  92. int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
  93. float m_flFireCycle;
  94. PlayerAnimEvent_t m_delayedFire; // if we fire while reloading, delay the fire by one frame so we can cancel the reload first
  95. // These control grenade animations.
  96. bool m_bThrowingGrenade;
  97. bool m_bPrimingGrenade;
  98. float m_flGrenadeCycle;
  99. int m_iGrenadeSequence;
  100. int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.
  101. CCSPlayer *m_pPlayer;
  102. ICSPlayerAnimStateHelpers *m_pHelpers;
  103. void CheckCachedSequenceValidity( void );
  104. int m_sequenceCache[ ACT_CROUCHIDLE+1 ]; // Cache the first N sequences, since we don't have weights.
  105. int m_cachedModelIndex; // Model index for which the sequence cache is valid.
  106. CUtlDict<int,int> m_namedSequence; // Dictionary of sequences computed with CalcSequenceIndex. This is because LookupSequence is a performance hit - CS:S player models have 750+ sequences!
  107. };
  108. ICSPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  109. {
  110. CCSPlayerAnimState *pRet = new CCSPlayerAnimState;
  111. pRet->InitCS( pEntity, pHelpers, legAnimType, bUseAimSequences );
  112. return pRet;
  113. }
  114. //----------------------------------------------------------------------------------------------
  115. /**
  116. * Hostage animation mechanism
  117. */
  118. class CCSHostageAnimState : public CCSPlayerAnimState
  119. {
  120. public:
  121. DECLARE_CLASS( CCSHostageAnimState, CCSPlayerAnimState );
  122. CCSHostageAnimState();
  123. virtual Activity CalcMainActivity();
  124. // No need to cache sequences, and we *do* have multiple sequences per activity
  125. virtual int SelectWeightedSequence( Activity activity ) { return GetOuter()->SelectWeightedSequence( activity ); }
  126. };
  127. //----------------------------------------------------------------------------------------------
  128. ICSPlayerAnimState* CreateHostageAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  129. {
  130. CCSHostageAnimState *anim = new CCSHostageAnimState;
  131. anim->InitCS( pEntity, pHelpers, legAnimType, bUseAimSequences );
  132. return anim;
  133. }
  134. //----------------------------------------------------------------------------------------------
  135. //----------------------------------------------------------------------------------------------
  136. CCSHostageAnimState::CCSHostageAnimState()
  137. {
  138. }
  139. //----------------------------------------------------------------------------------------------
  140. /**
  141. * Set hostage animation state
  142. */
  143. Activity CCSHostageAnimState::CalcMainActivity()
  144. {
  145. float flOuterSpeed = GetOuterXYSpeed();
  146. if ( HandleJumping() )
  147. {
  148. return ACT_HOP;
  149. }
  150. else
  151. {
  152. Assert( dynamic_cast<CHostage*>( m_pOuter ) );
  153. CHostage *me = (CHostage*)m_pOuter;
  154. // if we have no leader, hang out
  155. Activity idealActivity = me->GetLeader() ? ACT_IDLE : ACT_BUSY_QUEUE;
  156. if ( m_pOuter->GetFlags() & FL_DUCKING )
  157. {
  158. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  159. idealActivity = ACT_RUN_CROUCH;
  160. else
  161. idealActivity = ACT_COVER_LOW;
  162. }
  163. else
  164. {
  165. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  166. {
  167. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  168. idealActivity = ACT_RUN;
  169. else
  170. idealActivity = ACT_WALK;
  171. }
  172. }
  173. return idealActivity;
  174. }
  175. }
  176. // ------------------------------------------------------------------------------------------------ //
  177. // CCSPlayerAnimState implementation.
  178. // ------------------------------------------------------------------------------------------------ //
  179. CCSPlayerAnimState::CCSPlayerAnimState()
  180. {
  181. m_pOuter = NULL;
  182. m_bJumping = false;
  183. m_flJumpStartTime = 0.0f;
  184. m_bFirstJumpFrame = false;
  185. m_bReloading = false;
  186. m_flReloadCycle = 0.0f;
  187. m_iReloadSequence = -1;
  188. m_flReloadHoldEndTime = 0.0f;
  189. m_bFiring = false;
  190. m_iFireSequence = -1;
  191. m_flFireCycle = 0.0f;
  192. m_delayedFire = PLAYERANIMEVENT_COUNT;
  193. m_bThrowingGrenade = false;
  194. m_bPrimingGrenade = false;
  195. m_flGrenadeCycle = 0.0f;
  196. m_iGrenadeSequence = -1;
  197. m_iLastThrowGrenadeCounter = 0;
  198. m_cachedModelIndex = -1;
  199. m_pPlayer = NULL;
  200. m_pHelpers = NULL;
  201. }
  202. void CCSPlayerAnimState::InitCS( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  203. {
  204. CModAnimConfig config;
  205. config.m_flMaxBodyYawDegrees = 90;
  206. config.m_LegAnimType = legAnimType;
  207. config.m_bUseAimSequences = bUseAimSequences;
  208. m_pPlayer = ToCSPlayer( pEntity );
  209. m_pHelpers = pHelpers;
  210. BaseClass::Init( pEntity, config );
  211. }
  212. //--------------------------------------------------------------------------------------------------------------
  213. void CCSPlayerAnimState::CheckCachedSequenceValidity( void )
  214. {
  215. if ( m_cachedModelIndex != GetOuter()->GetModelIndex() )
  216. {
  217. m_namedSequence.RemoveAll();
  218. m_cachedModelIndex = GetOuter()->GetModelIndex();
  219. for ( int i=0; i<=ACT_CROUCHIDLE; ++i )
  220. {
  221. m_sequenceCache[i] = -1;
  222. }
  223. // precache the sequences we'll be using for movement
  224. if ( m_cachedModelIndex > 0 )
  225. {
  226. m_sequenceCache[ACT_HOP - 1] = GetOuter()->SelectWeightedSequence( ACT_HOP );
  227. m_sequenceCache[ACT_IDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_IDLE );
  228. m_sequenceCache[ACT_RUN_CROUCH - 1] = GetOuter()->SelectWeightedSequence( ACT_RUN_CROUCH );
  229. m_sequenceCache[ACT_CROUCHIDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_CROUCHIDLE );
  230. m_sequenceCache[ACT_RUN - 1] = GetOuter()->SelectWeightedSequence( ACT_RUN );
  231. m_sequenceCache[ACT_WALK - 1] = GetOuter()->SelectWeightedSequence( ACT_WALK );
  232. m_sequenceCache[ACT_IDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_IDLE );
  233. }
  234. }
  235. }
  236. //--------------------------------------------------------------------------------------------------------------
  237. /**
  238. * Cache the sequence numbers for the first ACT_HOP activities, since the CS player doesn't have multiple
  239. * sequences per activity.
  240. */
  241. int CCSPlayerAnimState::SelectWeightedSequence( Activity activity )
  242. {
  243. VPROF( "CCSPlayerAnimState::ComputeMainSequence" );
  244. if ( activity > ACT_CROUCHIDLE || activity < 1 )
  245. {
  246. return GetOuter()->SelectWeightedSequence( activity );
  247. }
  248. CheckCachedSequenceValidity();
  249. int sequence = m_sequenceCache[ activity - 1 ];
  250. if ( sequence < 0 )
  251. {
  252. // just in case, look up the sequence if we didn't precache it above
  253. sequence = m_sequenceCache[ activity - 1 ] = GetOuter()->SelectWeightedSequence( activity );
  254. }
  255. #if defined(CLIENT_DLL) && defined(_DEBUG)
  256. int realSequence = GetOuter()->SelectWeightedSequence( activity );
  257. Assert( realSequence == sequence );
  258. #endif
  259. return sequence;
  260. }
  261. //--------------------------------------------------------------------------------------------------------------
  262. /**
  263. * Try to look up named sequences in a CUtlDict cache before falling back to the normal LookupSequence. It's
  264. * best to avoid the normal LookupSequence when your models have 750+ sequences...
  265. */
  266. int CCSPlayerAnimState::CalcSequenceIndex( const char *pBaseName, ... )
  267. {
  268. VPROF( "CCSPlayerAnimState::CalcSequenceIndex" );
  269. CheckCachedSequenceValidity();
  270. char szFullName[512];
  271. va_list marker;
  272. va_start( marker, pBaseName );
  273. Q_vsnprintf( szFullName, sizeof( szFullName ), pBaseName, marker );
  274. va_end( marker );
  275. int iSequence = m_namedSequence.Find( szFullName );
  276. if ( iSequence == m_namedSequence.InvalidIndex() )
  277. {
  278. iSequence = GetOuter()->LookupSequence( szFullName );
  279. m_namedSequence.Insert( szFullName, iSequence );
  280. }
  281. else
  282. {
  283. iSequence = m_namedSequence[iSequence];
  284. }
  285. #if defined(CLIENT_DLL) && defined(_DEBUG)
  286. int realSequence = GetOuter()->LookupSequence( szFullName );
  287. Assert( realSequence == iSequence );
  288. #endif
  289. // Show warnings if we can't find anything here.
  290. if ( iSequence == -1 )
  291. {
  292. static CUtlDict<int,int> dict;
  293. if ( dict.Find( szFullName ) == -1 )
  294. {
  295. dict.Insert( szFullName, 0 );
  296. Warning( "CalcSequenceIndex: can't find '%s'.\n", szFullName );
  297. }
  298. iSequence = 0;
  299. }
  300. return iSequence;
  301. }
  302. void CCSPlayerAnimState::ClearAnimationState()
  303. {
  304. m_bJumping = false;
  305. m_bFiring = false;
  306. m_bReloading = false;
  307. m_flReloadHoldEndTime = 0.0f;
  308. m_bThrowingGrenade = m_bPrimingGrenade = false;
  309. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  310. BaseClass::ClearAnimationState();
  311. }
  312. void CCSPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
  313. {
  314. Assert( event != PLAYERANIMEVENT_THROW_GRENADE );
  315. MDLCACHE_CRITICAL_SECTION();
  316. switch ( event )
  317. {
  318. case PLAYERANIMEVENT_FIRE_GUN_PRIMARY:
  319. case PLAYERANIMEVENT_FIRE_GUN_SECONDARY:
  320. // Regardless of what we're doing in the fire layer, restart it.
  321. m_flFireCycle = 0;
  322. m_iFireSequence = CalcFireLayerSequence( event );
  323. m_bFiring = m_iFireSequence != -1;
  324. // If we are interrupting a (shotgun) reload, cancel the reload, and fire next frame.
  325. if ( m_bFiring && m_bReloading )
  326. {
  327. m_bReloading = false;
  328. m_iReloadSequence = -1;
  329. m_delayedFire = event;
  330. m_bFiring = false;
  331. m_iFireSequence = -1;
  332. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( RELOADSEQUENCE_LAYER );
  333. if ( pLayer )
  334. {
  335. pLayer->m_flWeight = 0.0f;
  336. pLayer->m_nOrder = 15;
  337. }
  338. }
  339. #ifdef CLIENT_DLL
  340. if ( m_bFiring && !m_bReloading )
  341. {
  342. if ( m_pPlayer )
  343. {
  344. m_pPlayer->ProcessMuzzleFlashEvent();
  345. }
  346. }
  347. #endif
  348. break;
  349. case PLAYERANIMEVENT_JUMP:
  350. // Play the jump animation.
  351. m_bJumping = true;
  352. m_bFirstJumpFrame = true;
  353. m_flJumpStartTime = gpGlobals->curtime;
  354. break;
  355. case PLAYERANIMEVENT_RELOAD:
  356. {
  357. // ignore normal reload events for shotguns - they get sent to trigger sounds etc only
  358. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  359. if ( pWeapon && pWeapon->GetCSWpnData().m_WeaponType != WEAPONTYPE_SHOTGUN )
  360. {
  361. m_iReloadSequence = CalcReloadLayerSequence( event );
  362. if ( m_iReloadSequence != -1 )
  363. {
  364. m_bReloading = true;
  365. m_flReloadCycle = 0;
  366. }
  367. else
  368. {
  369. m_bReloading = false;
  370. }
  371. }
  372. }
  373. break;
  374. case PLAYERANIMEVENT_RELOAD_START:
  375. case PLAYERANIMEVENT_RELOAD_LOOP:
  376. // Set the hold time for _start and _loop anims, then fall through to the _end case
  377. m_flReloadHoldEndTime = gpGlobals->curtime + 0.75f;
  378. case PLAYERANIMEVENT_RELOAD_END:
  379. {
  380. // ignore shotgun reload events for non-shotguns
  381. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  382. if ( pWeapon && pWeapon->GetCSWpnData().m_WeaponType != WEAPONTYPE_SHOTGUN )
  383. {
  384. m_flReloadHoldEndTime = 0.0f; // clear this out in case we set it in _START or _LOOP above
  385. }
  386. else
  387. {
  388. m_iReloadSequence = CalcReloadLayerSequence( event );
  389. if ( m_iReloadSequence != -1 )
  390. {
  391. m_bReloading = true;
  392. m_flReloadCycle = 0;
  393. }
  394. else
  395. {
  396. m_bReloading = false;
  397. }
  398. }
  399. }
  400. break;
  401. case PLAYERANIMEVENT_CLEAR_FIRING:
  402. {
  403. m_iFireSequence = -1;
  404. }
  405. break;
  406. default:
  407. Assert( !"CCSPlayerAnimState::DoAnimationEvent" );
  408. }
  409. }
  410. float g_flThrowGrenadeFraction = 0.25;
  411. bool CCSPlayerAnimState::IsThrowingGrenade()
  412. {
  413. if ( m_bThrowingGrenade )
  414. {
  415. // An animation event would be more appropriate here.
  416. return m_flGrenadeCycle < g_flThrowGrenadeFraction;
  417. }
  418. else
  419. {
  420. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  421. return bThrowPending || IsOuterGrenadePrimed();
  422. }
  423. }
  424. int CCSPlayerAnimState::CalcReloadLayerSequence( PlayerAnimEvent_t event )
  425. {
  426. if ( m_delayedFire != PLAYERANIMEVENT_COUNT )
  427. return -1;
  428. const char *weaponSuffix = GetWeaponSuffix();
  429. if ( !weaponSuffix )
  430. return -1;
  431. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  432. if ( !pWeapon )
  433. return -1;
  434. const char *prefix = "";
  435. switch ( GetCurrentMainSequenceActivity() )
  436. {
  437. case ACT_PLAYER_RUN_FIRE:
  438. case ACT_RUN:
  439. prefix = "run";
  440. break;
  441. case ACT_PLAYER_WALK_FIRE:
  442. case ACT_WALK:
  443. prefix = "walk";
  444. break;
  445. case ACT_PLAYER_CROUCH_FIRE:
  446. case ACT_CROUCHIDLE:
  447. prefix = "crouch_idle";
  448. break;
  449. case ACT_PLAYER_CROUCH_WALK_FIRE:
  450. case ACT_RUN_CROUCH:
  451. prefix = "crouch_walk";
  452. break;
  453. default:
  454. case ACT_PLAYER_IDLE_FIRE:
  455. prefix = "idle";
  456. break;
  457. }
  458. const char *reloadSuffix = "";
  459. switch ( event )
  460. {
  461. case PLAYERANIMEVENT_RELOAD_START:
  462. reloadSuffix = "_start";
  463. break;
  464. case PLAYERANIMEVENT_RELOAD_LOOP:
  465. reloadSuffix = "_loop";
  466. break;
  467. case PLAYERANIMEVENT_RELOAD_END:
  468. reloadSuffix = "_end";
  469. break;
  470. }
  471. // First, look for <prefix>_reload_<weapon name><_start|_loop|_end>.
  472. char szName[512];
  473. Q_snprintf( szName, sizeof( szName ), "%s_reload_%s%s", prefix, weaponSuffix, reloadSuffix );
  474. int iReloadSequence = m_pOuter->LookupSequence( szName );
  475. if ( iReloadSequence != -1 )
  476. return iReloadSequence;
  477. // Next, look for reload_<weapon name><_start|_loop|_end>.
  478. Q_snprintf( szName, sizeof( szName ), "reload_%s%s", weaponSuffix, reloadSuffix );
  479. iReloadSequence = m_pOuter->LookupSequence( szName );
  480. if ( iReloadSequence != -1 )
  481. return iReloadSequence;
  482. // Ok, look for generic categories.. pistol, shotgun, rifle, etc.
  483. if ( pWeapon->GetCSWpnData().m_WeaponType == WEAPONTYPE_PISTOL )
  484. {
  485. Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
  486. iReloadSequence = m_pOuter->LookupSequence( szName );
  487. if ( iReloadSequence != -1 )
  488. return iReloadSequence;
  489. }
  490. // Fall back to reload_m4.
  491. iReloadSequence = CalcSequenceIndex( "reload_m4" );
  492. if ( iReloadSequence > 0 )
  493. return iReloadSequence;
  494. return -1;
  495. }
  496. void CCSPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd )
  497. {
  498. if ( !bEnabled || iSequence < 0 )
  499. return;
  500. // Increment the fire sequence's cycle.
  501. flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
  502. if ( flCurCycle > 1 )
  503. {
  504. if ( bWaitAtEnd )
  505. {
  506. flCurCycle = 1;
  507. }
  508. else
  509. {
  510. // Not firing anymore.
  511. bEnabled = false;
  512. iSequence = 0;
  513. return;
  514. }
  515. }
  516. // Now dump the state into its animation layer.
  517. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
  518. pLayer->m_flCycle = flCurCycle;
  519. pLayer->m_nSequence = iSequence;
  520. pLayer->m_flPlaybackRate = 1.0f;
  521. pLayer->m_flWeight = 1.0f;
  522. pLayer->m_nOrder = iLayer;
  523. #ifndef CLIENT_DLL
  524. pLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  525. #endif
  526. }
  527. bool CCSPlayerAnimState::IsOuterGrenadePrimed()
  528. {
  529. CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
  530. if ( pChar )
  531. {
  532. CBaseCSGrenade *pGren = dynamic_cast<CBaseCSGrenade*>( pChar->GetActiveWeapon() );
  533. return pGren && pGren->IsPinPulled();
  534. }
  535. else
  536. {
  537. return NULL;
  538. }
  539. }
  540. void CCSPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
  541. {
  542. VPROF( "CCSPlayerAnimState::ComputeGrenadeSequence" );
  543. if ( m_bThrowingGrenade )
  544. {
  545. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
  546. }
  547. else
  548. {
  549. if ( m_pPlayer )
  550. {
  551. CBaseCombatWeapon *pWeapon = m_pPlayer->GetActiveWeapon();
  552. CBaseCSGrenade *pGren = dynamic_cast<CBaseCSGrenade*>( pWeapon );
  553. if ( !pGren )
  554. {
  555. // The player no longer has a grenade equipped. Bail.
  556. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  557. return;
  558. }
  559. }
  560. // Priming the grenade isn't an event.. we just watch the player for it.
  561. // Also play the prime animation first if he wants to throw the grenade.
  562. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  563. if ( IsOuterGrenadePrimed() || bThrowPending )
  564. {
  565. if ( !m_bPrimingGrenade )
  566. {
  567. // If this guy just popped into our PVS, and he's got his grenade primed, then
  568. // let's assume that it's all the way primed rather than playing the prime
  569. // animation from the start.
  570. if ( TimeSinceLastAnimationStateClear() < 0.4f )
  571. {
  572. m_flGrenadeCycle = 1;
  573. }
  574. else
  575. {
  576. m_flGrenadeCycle = 0;
  577. }
  578. m_iGrenadeSequence = CalcGrenadePrimeSequence();
  579. m_bPrimingGrenade = true;
  580. }
  581. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );
  582. // If we're waiting to throw and we're done playing the prime animation...
  583. if ( bThrowPending && m_flGrenadeCycle == 1 )
  584. {
  585. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  586. // Now play the throw animation.
  587. m_iGrenadeSequence = CalcGrenadeThrowSequence();
  588. if ( m_iGrenadeSequence != -1 )
  589. {
  590. // Configure to start playing
  591. m_bThrowingGrenade = true;
  592. m_bPrimingGrenade = false;
  593. m_flGrenadeCycle = 0;
  594. }
  595. }
  596. }
  597. else
  598. {
  599. m_bPrimingGrenade = false;
  600. }
  601. }
  602. }
  603. int CCSPlayerAnimState::CalcGrenadePrimeSequence()
  604. {
  605. return CalcSequenceIndex( "idle_shoot_gren1" );
  606. }
  607. int CCSPlayerAnimState::CalcGrenadeThrowSequence()
  608. {
  609. return CalcSequenceIndex( "idle_shoot_gren2" );
  610. }
  611. int CCSPlayerAnimState::GetOuterGrenadeThrowCounter()
  612. {
  613. if ( m_pPlayer )
  614. return m_pPlayer->m_iThrowGrenadeCounter;
  615. else
  616. return 0;
  617. }
  618. void CCSPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
  619. {
  620. VPROF( "CCSPlayerAnimState::ComputeReloadSequence" );
  621. bool hold = m_flReloadHoldEndTime > gpGlobals->curtime;
  622. UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, hold );
  623. if ( !m_bReloading )
  624. {
  625. m_flReloadHoldEndTime = 0.0f;
  626. }
  627. }
  628. int CCSPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
  629. {
  630. VPROF( "CCSPlayerAnimState::CalcAimLayerSequence" );
  631. const char *pSuffix = GetWeaponSuffix();
  632. if ( !pSuffix )
  633. return 0;
  634. if ( bForceIdle )
  635. {
  636. switch ( GetCurrentMainSequenceActivity() )
  637. {
  638. case ACT_CROUCHIDLE:
  639. case ACT_RUN_CROUCH:
  640. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
  641. default:
  642. return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
  643. }
  644. }
  645. else
  646. {
  647. switch ( GetCurrentMainSequenceActivity() )
  648. {
  649. case ACT_RUN:
  650. return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );
  651. case ACT_WALK:
  652. case ACT_RUNTOIDLE:
  653. case ACT_IDLETORUN:
  654. return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );
  655. case ACT_CROUCHIDLE:
  656. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
  657. case ACT_RUN_CROUCH:
  658. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );
  659. case ACT_IDLE:
  660. default:
  661. return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
  662. }
  663. }
  664. }
  665. const char* CCSPlayerAnimState::GetWeaponSuffix()
  666. {
  667. VPROF( "CCSPlayerAnimState::GetWeaponSuffix" );
  668. // Figure out the weapon suffix.
  669. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  670. if ( !pWeapon )
  671. return 0;
  672. const char *pSuffix = pWeapon->GetCSWpnData().m_szAnimExtension;
  673. #ifdef CS_SHIELD_ENABLED
  674. if ( m_pOuter->HasShield() == true )
  675. {
  676. if ( m_pOuter->IsShieldDrawn() == true )
  677. pSuffix = "shield";
  678. else
  679. pSuffix = "shield_undeployed";
  680. }
  681. #endif
  682. return pSuffix;
  683. }
  684. int CCSPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event)
  685. {
  686. // Figure out the weapon suffix.
  687. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  688. if ( !pWeapon )
  689. return -1;
  690. const char *pSuffix = GetWeaponSuffix();
  691. if ( !pSuffix )
  692. return -1;
  693. char tempsuffix[32];
  694. if ( pWeapon->GetWeaponID() == WEAPON_ELITE )
  695. {
  696. bool bPrimary = (event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY);
  697. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_%c", pSuffix, bPrimary?'r':'l' );
  698. pSuffix = tempsuffix;
  699. }
  700. // Grenades handle their fire events separately
  701. if ( event == PLAYERANIMEVENT_THROW_GRENADE ||
  702. pWeapon->GetWeaponID() == WEAPON_HEGRENADE ||
  703. pWeapon->GetWeaponID() == WEAPON_SMOKEGRENADE ||
  704. pWeapon->GetWeaponID() == WEAPON_FLASHBANG )
  705. {
  706. return -1;
  707. }
  708. switch ( GetCurrentMainSequenceActivity() )
  709. {
  710. case ACT_PLAYER_RUN_FIRE:
  711. case ACT_RUN:
  712. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );
  713. case ACT_PLAYER_WALK_FIRE:
  714. case ACT_WALK:
  715. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );
  716. case ACT_PLAYER_CROUCH_FIRE:
  717. case ACT_CROUCHIDLE:
  718. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );
  719. case ACT_PLAYER_CROUCH_WALK_FIRE:
  720. case ACT_RUN_CROUCH:
  721. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );
  722. default:
  723. case ACT_PLAYER_IDLE_FIRE:
  724. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
  725. }
  726. }
  727. bool CCSPlayerAnimState::CanThePlayerMove()
  728. {
  729. return m_pHelpers->CSAnim_CanMove();
  730. }
  731. float CCSPlayerAnimState::GetCurrentMaxGroundSpeed()
  732. {
  733. Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
  734. if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE )
  735. return ANIM_TOPSPEED_WALK;
  736. else if ( currentActivity == ACT_RUN )
  737. {
  738. if ( m_pPlayer )
  739. {
  740. CBaseCombatWeapon *activeWeapon = m_pPlayer->GetActiveWeapon();
  741. if ( activeWeapon )
  742. {
  743. CWeaponCSBase *csWeapon = dynamic_cast< CWeaponCSBase * >( activeWeapon );
  744. if ( csWeapon )
  745. {
  746. return csWeapon->GetMaxSpeed();
  747. }
  748. }
  749. }
  750. return ANIM_TOPSPEED_RUN;
  751. }
  752. else if ( currentActivity == ACT_RUN_CROUCH )
  753. return ANIM_TOPSPEED_RUN_CROUCH;
  754. else
  755. return 0;
  756. }
  757. bool CCSPlayerAnimState::HandleJumping()
  758. {
  759. if ( m_bJumping )
  760. {
  761. if ( m_bFirstJumpFrame )
  762. {
  763. #if !defined(CLIENT_DLL)
  764. //=============================================================================
  765. // HPE_BEGIN:
  766. // [dwenger] Needed for fun-fact implementation
  767. //=============================================================================
  768. CCS_GameStats.IncrementStat(m_pPlayer, CSSTAT_TOTAL_JUMPS, 1);
  769. //=============================================================================
  770. // HPE_END
  771. //=============================================================================
  772. #endif
  773. m_bFirstJumpFrame = false;
  774. RestartMainSequence(); // Reset the animation.
  775. }
  776. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  777. // on-ground flag set right when the message comes in.
  778. if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
  779. {
  780. if ( m_pOuter->GetFlags() & FL_ONGROUND )
  781. {
  782. m_bJumping = false;
  783. RestartMainSequence(); // Reset the animation.
  784. }
  785. }
  786. }
  787. // Are we still jumping? If so, keep playing the jump animation.
  788. return m_bJumping;
  789. }
  790. Activity CCSPlayerAnimState::CalcMainActivity()
  791. {
  792. float flOuterSpeed = GetOuterXYSpeed();
  793. if ( HandleJumping() )
  794. {
  795. return ACT_HOP;
  796. }
  797. else
  798. {
  799. Activity idealActivity = ACT_IDLE;
  800. if ( m_pOuter->GetFlags() & FL_ANIMDUCKING )
  801. {
  802. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  803. idealActivity = ACT_RUN_CROUCH;
  804. else
  805. idealActivity = ACT_CROUCHIDLE;
  806. }
  807. else
  808. {
  809. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  810. {
  811. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  812. idealActivity = ACT_RUN;
  813. else
  814. idealActivity = ACT_WALK;
  815. }
  816. else
  817. {
  818. idealActivity = ACT_IDLE;
  819. }
  820. }
  821. return idealActivity;
  822. }
  823. }
  824. void CCSPlayerAnimState::DebugShowAnimState( int iStartLine )
  825. {
  826. engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
  827. engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
  828. BaseClass::DebugShowAnimState( iStartLine );
  829. }
  830. void CCSPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  831. {
  832. BaseClass::ComputeSequences( pStudioHdr );
  833. VPROF( "CCSPlayerAnimState::ComputeSequences" );
  834. ComputeFireSequence( pStudioHdr );
  835. ComputeReloadSequence( pStudioHdr );
  836. ComputeGrenadeSequence( pStudioHdr );
  837. }
  838. void CCSPlayerAnimState::ClearAnimationLayers()
  839. {
  840. if ( !m_pOuter )
  841. return;
  842. m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
  843. for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
  844. {
  845. // Client obeys Order of CBaseAnimatingOverlay::MAX_OVERLAYS (15), but server trusts only the ANIM_LAYER_ACTIVE flag.
  846. m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  847. #ifndef CLIENT_DLL
  848. m_pOuter->GetAnimOverlay( i )->m_fFlags = 0;
  849. #endif
  850. }
  851. }
  852. void CCSPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
  853. {
  854. VPROF( "CCSPlayerAnimState::ComputeFireSequence" );
  855. if ( m_delayedFire != PLAYERANIMEVENT_COUNT )
  856. {
  857. DoAnimationEvent( m_delayedFire, 0 );
  858. m_delayedFire = PLAYERANIMEVENT_COUNT;
  859. }
  860. UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
  861. }