Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2163 lines
60 KiB

  1. //========= Copyright � 1996-2005, 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. #include "cs_shareddefs.h"
  18. #ifdef CLIENT_DLL
  19. #include "c_cs_player.h"
  20. #include "bone_setup.h"
  21. #include "tier1/interpolatedvar.h"
  22. #include "c_cs_hostage.h"
  23. #else
  24. #include "cs_player.h"
  25. #include "cs_simple_hostage.h"
  26. #include "cs_gamestats.h"
  27. #endif
  28. // NOTE: This has to be the last file included!
  29. #include "tier0/memdbgon.h"
  30. #define ANIM_TOPSPEED_WALK 100
  31. #define ANIM_TOPSPEED_RUN 250
  32. #define ANIM_TOPSPEED_RUN_CROUCH 85
  33. #define DEFAULT_IDLE_NAME "idle_upper_"
  34. #define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_"
  35. #define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_"
  36. #define DEFAULT_WALK_NAME "walk_upper_"
  37. #define DEFAULT_RUN_NAME "run_upper_"
  38. #define DEFAULT_FIRE_IDLE_NAME "idle_shoot_"
  39. #define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_"
  40. #define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_"
  41. #define DEFAULT_FIRE_WALK_NAME "walk_shoot_"
  42. #define DEFAULT_FIRE_RUN_NAME "run_shoot_"
  43. #define DEFAULT_SILENCER_ATTACH_NAME "silencer_attach_%s"
  44. #define DEFAULT_SILENCER_DETACH_NAME "silencer_detach_%s"
  45. #define ANIM_ACT_DURATION_BEFORE_RETURN_TO_IDLE 0.5f
  46. #define ANIM_ACT_DURATION_BEFORE_RETURN_TO_WALK 0.7f
  47. enum CSPlayerAnimStateLayer_t
  48. {
  49. FIRESEQUENCE_LAYER = ( AIMSEQUENCE_LAYER + NUM_AIMSEQUENCE_LAYERS ),
  50. FIRESEQUENCE2_LAYER,
  51. DEPLOYSEQUENCE_LAYER,
  52. RELOADSEQUENCE_LAYER,
  53. SILENCERSEQUENCE_LAYER,
  54. GRENADESEQUENCE_LAYER,
  55. FLASHEDSEQUENCE_LAYER,
  56. FLINCHSEQUENCE_LAYER,
  57. TAUNTSEQUENCE_LAYER,
  58. FOOTPLANTSEQUENCE_LAYER,
  59. NUM_LAYERS_WANTED
  60. };
  61. ConVar post_jump_crouch( "post_jump_crouch", "0.2f", FCVAR_REPLICATED | FCVAR_CHEAT, "This determines how long the third person player character will crouch for after landing a jump. This only affects the third person animation visuals." );
  62. ConVar hostage_feetyawrate( "hostage_feetyawrate", "720", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "How many degrees per second that hostages can turn their feet or upper body." );
  63. // ------------------------------------------------------------------------------------------------ //
  64. // CCSPlayerAnimState declaration.
  65. // ------------------------------------------------------------------------------------------------ //
  66. class CCSPlayerAnimState : public CBasePlayerAnimState
  67. {
  68. public:
  69. DECLARE_CLASS( CCSPlayerAnimState, CBasePlayerAnimState );
  70. friend IPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  71. CCSPlayerAnimState();
  72. virtual void DoAnimationEvent( PlayerAnimEvent_t animEvent, int nData );
  73. virtual bool IsThrowingGrenade();
  74. virtual bool ShouldHideGrenadeDuringThrow();
  75. virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
  76. virtual void ClearAnimationState();
  77. virtual bool CanThePlayerMove();
  78. virtual float GetCurrentMaxGroundSpeed();
  79. virtual Activity CalcMainActivity();
  80. virtual void DebugShowAnimState( int iStartLine );
  81. virtual void ComputeSequences( CStudioHdr *pStudioHdr );
  82. virtual void ClearAnimationLayers();
  83. virtual int SelectWeightedSequence( Activity activity );
  84. // Calculate the playback rate for movement layer
  85. virtual float CalcMovementPlaybackRate( bool *bIsMoving );
  86. virtual void Update( float eyeYaw, float eyePitch );
  87. virtual void ModifyTauntDuration( float flTimingChange );
  88. void InitCS( CBaseAnimatingOverlay *pPlayer, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  89. protected:
  90. int CalcFireLayerSequence(PlayerAnimEvent_t animEvent);
  91. void ComputeFireSequence( CStudioHdr *pStudioHdr );
  92. void ComputeDeploySequence( CStudioHdr *pStudioHdr );
  93. int CalcDeployLayerSequence( void );
  94. void ComputeReloadSequence( CStudioHdr *pStudioHdr );
  95. int CalcReloadLayerSequence( PlayerAnimEvent_t animEvent );
  96. void ComputeSilencerChangeSequence( CStudioHdr *pStudioHdr );
  97. int CalcSilencerChangeLayerSequence( PlayerAnimEvent_t animEvent );
  98. int CalcFlashedLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter );
  99. void ComputeFlashedSequence( CStudioHdr *pStudioHdr );
  100. int CalcFlinchLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter );
  101. void ComputeFlinchSequence( CStudioHdr *pStudioHdr );
  102. int CalcTauntLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter );
  103. void ComputeTauntSequence( CStudioHdr *pStudioHdr );
  104. void ComputeFootPlantSequence(CStudioHdr *pStudioHdr);
  105. bool IsOuterGrenadePrimed();
  106. void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
  107. int CalcGrenadePrimeSequence();
  108. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  109. int CalcGrenadeThrowSequence( bool bUnderhand = false );
  110. #else
  111. int CalcGrenadeThrowSequence();
  112. #endif
  113. int GetOuterGrenadeThrowCounter();
  114. const char* GetWeaponSuffix();
  115. bool HandleJumping();
  116. void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd, float flWeight = 1.0f );
  117. virtual int CalcSequenceIndex( PRINTF_FORMAT_STRING const char *pBaseName, ... );
  118. bool ActiveWeaponIsDeployed();
  119. float GetTimeSinceLastActChange();
  120. void UpdateTimeSinceLastActChange();
  121. private:
  122. // Current state variables.
  123. bool m_bJumping; // Set on a jump event.
  124. float m_flJumpStartTime;
  125. bool m_bFirstJumpFrame;
  126. float m_flPostLandCrouchEndTime;
  127. // Aim sequence plays reload while this is on.
  128. bool m_bReloading;
  129. float m_flReloadCycle;
  130. int m_iReloadSequence;
  131. float m_flReloadHoldEndTime; // Intermediate shotgun reloads get held a fraction of a second
  132. // Sequence for silencer changing
  133. bool m_bSilencerChanging;
  134. float m_flSilencerChangeCycle;
  135. int m_iSilencerChangeSequence;
  136. // Sequence for flashbang reaction
  137. float m_flFlashedAmountDelayed;
  138. float m_flFlashedAmount;
  139. float m_flLastFlashDuration;
  140. int m_iFlashedSequence;
  141. // Sequence for flinches
  142. float m_flFlinchStartTime;
  143. float m_flFlinchLength;
  144. int m_nFlinchSequence;
  145. // Sequence for taunts
  146. float m_flTauntStartTime;
  147. float m_flTauntLength;
  148. int m_nTauntSequence;
  149. // Deploy sequence
  150. bool m_bDeploying;
  151. int m_iDeploySequence;
  152. float m_flDeployCycle;
  153. int m_iCurrentAimSequence;
  154. float m_flTargetMaxSpeed;
  155. float m_flCurrentMaxSpeed;
  156. int m_iIdleFireSequence;
  157. // This is set to true if ANY animation is being played in the fire layer.
  158. bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
  159. // until it completes.
  160. int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
  161. float m_flFireCycle;
  162. PlayerAnimEvent_t m_delayedFire; // if we fire while reloading, delay the fire by one frame so we can cancel the reload first
  163. PlayerAnimEvent_t m_activeFireEvent;// The current or last set fire event.
  164. // These control grenade animations.
  165. bool m_bThrowingGrenade;
  166. bool m_bPrimingGrenade;
  167. float m_flGrenadeCycle;
  168. int m_iGrenadeSequence;
  169. int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.
  170. bool m_bTryingToRunAfterJump; // State information that allows us to skip the transition animations to running right after a jump.
  171. Activity m_CurrentActivity;
  172. CCSPlayer *m_pPlayer;
  173. // m_iDeployedWeaponID is the active weapon used for animations. It does not necessarily line up with what the player has active
  174. // since the animation system uses events that have higher latency than networked variables.
  175. // Having our own weapon id will make sure we play animations with the correct weapon.
  176. CSWeaponID m_iDeployedWeaponID;
  177. float m_flWeaponSwitchTime;
  178. ICSPlayerAnimStateHelpers *m_pHelpers;
  179. void CheckCachedSequenceValidity( void );
  180. void ClearAnimationLayer( int layer );
  181. int m_sequenceCache[ ACT_CROUCHIDLE+1 ]; // Cache the first N sequences, since we don't have weights.
  182. int m_cachedModelIndex; // Model index for which the sequence cache is valid.
  183. float m_flLastActChangeTime;
  184. Activity m_LastActivity;
  185. };
  186. IPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  187. {
  188. CCSPlayerAnimState *pRet = new CCSPlayerAnimState;
  189. pRet->InitCS( pEntity, pHelpers, legAnimType, bUseAimSequences );
  190. return pRet;
  191. }
  192. //----------------------------------------------------------------------------------------------
  193. /**
  194. * Hostage animation mechanism
  195. */
  196. class CCSHostageAnimState : public CCSPlayerAnimState
  197. {
  198. public:
  199. DECLARE_CLASS( CCSHostageAnimState, CCSPlayerAnimState );
  200. CCSHostageAnimState();
  201. virtual Activity CalcMainActivity();
  202. virtual float GetFeetYawRate( void )
  203. {
  204. return hostage_feetyawrate.GetFloat();
  205. }
  206. private:
  207. Activity mCurrentActivity;
  208. // No need to cache sequences, and we *do* have multiple sequences per activity
  209. //virtual int SelectWeightedSequence( Activity activity ) { return GetOuter()->SelectWeightedSequence( activity ); }
  210. };
  211. //----------------------------------------------------------------------------------------------
  212. IPlayerAnimState* CreateHostageAnimState( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  213. {
  214. CCSHostageAnimState *anim = new CCSHostageAnimState;
  215. anim->InitCS( pEntity, pHelpers, legAnimType, bUseAimSequences );
  216. return anim;
  217. }
  218. //----------------------------------------------------------------------------------------------
  219. //----------------------------------------------------------------------------------------------
  220. CCSHostageAnimState::CCSHostageAnimState()
  221. {
  222. mCurrentActivity = ACT_IDLE;
  223. }
  224. //----------------------------------------------------------------------------------------------
  225. /**
  226. * Set hostage animation state
  227. */
  228. Activity CCSHostageAnimState::CalcMainActivity()
  229. {
  230. float flOuterSpeed = GetOuterXYSpeed();
  231. if ( HandleJumping() )
  232. {
  233. return ACT_JUMP;
  234. }
  235. else
  236. {
  237. Assert( dynamic_cast<CHostage*>( m_pOuter ) );
  238. CHostage *me = (CHostage*)m_pOuter;
  239. // If we have no leader, hang out.
  240. Activity targetIdle = me->GetLeader() ? ACT_IDLE : ACT_BUSY_QUEUE;
  241. // [msmith] We don't want to jitter the activities based on subtle speed changes.
  242. // The code below only chagnes the activity if the speed has changed by at least SPEED_CHANGE_BUFFER amount.
  243. const float SPEED_CHANGE_BUFFER = (ARBITRARY_RUN_SPEED - MOVING_MINIMUM_SPEED) / 4.0f;
  244. if ( m_pOuter->GetFlags() & FL_DUCKING )
  245. {
  246. if ( flOuterSpeed > MOVING_MINIMUM_SPEED + SPEED_CHANGE_BUFFER )
  247. {
  248. mCurrentActivity = ACT_RUN_CROUCH;
  249. }
  250. else if ( flOuterSpeed < MOVING_MINIMUM_SPEED )
  251. {
  252. mCurrentActivity = ACT_COVER_LOW;
  253. }
  254. }
  255. else
  256. {
  257. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  258. {
  259. mCurrentActivity = ACT_RUN;
  260. }
  261. else if ( flOuterSpeed < ARBITRARY_RUN_SPEED - SPEED_CHANGE_BUFFER && flOuterSpeed > MOVING_MINIMUM_SPEED + SPEED_CHANGE_BUFFER )
  262. {
  263. mCurrentActivity = ACT_WALK;
  264. }
  265. else if ( flOuterSpeed < MOVING_MINIMUM_SPEED )
  266. {
  267. mCurrentActivity = targetIdle;
  268. }
  269. }
  270. return mCurrentActivity;
  271. }
  272. }
  273. // ------------------------------------------------------------------------------------------------ //
  274. // CCSPlayerAnimState implementation.
  275. // ------------------------------------------------------------------------------------------------ //
  276. CCSPlayerAnimState::CCSPlayerAnimState()
  277. {
  278. m_pOuter = NULL;
  279. m_bJumping = false;
  280. m_flJumpStartTime = 0.0f;
  281. m_bFirstJumpFrame = false;
  282. m_flPostLandCrouchEndTime = 0.0f;
  283. m_bReloading = false;
  284. m_flReloadCycle = 0.0f;
  285. m_iReloadSequence = -1;
  286. m_flReloadHoldEndTime = 0.0f;
  287. m_bSilencerChanging = false;
  288. m_flSilencerChangeCycle = 0.0f;
  289. m_iSilencerChangeSequence = -1;
  290. m_flFlashedAmountDelayed = 0;
  291. m_flFlashedAmount = 0;
  292. m_flLastFlashDuration = 0;
  293. m_iFlashedSequence = 0;
  294. m_flFlinchStartTime = -1.0f;
  295. m_flFlinchLength = 0.0f;
  296. m_nFlinchSequence = 0;
  297. m_flTauntStartTime = -1.0f;
  298. m_flTauntLength = 0.0f;
  299. m_nTauntSequence = 0;
  300. m_bDeploying = false;
  301. m_iDeploySequence = -1;
  302. m_flDeployCycle = 0.0f;
  303. m_iCurrentAimSequence = 0;
  304. m_flTargetMaxSpeed = 0.0f;
  305. m_flCurrentMaxSpeed = 0.0f;
  306. m_bFiring = false;
  307. m_iFireSequence = -1;
  308. m_flFireCycle = 0.0f;
  309. m_delayedFire = PLAYERANIMEVENT_COUNT;
  310. m_activeFireEvent = PLAYERANIMEVENT_COUNT;
  311. m_iIdleFireSequence = -1;
  312. m_bThrowingGrenade = false;
  313. m_bPrimingGrenade = false;
  314. m_flGrenadeCycle = 0.0f;
  315. m_iGrenadeSequence = -1;
  316. m_iLastThrowGrenadeCounter = 0;
  317. m_cachedModelIndex = -1;
  318. m_bTryingToRunAfterJump = false;
  319. m_CurrentActivity = ACT_IDLE;
  320. m_pPlayer = NULL;
  321. m_iDeployedWeaponID = WEAPON_NONE;
  322. m_flWeaponSwitchTime = 0.0f;
  323. m_pHelpers = NULL;
  324. m_flLastActChangeTime = gpGlobals->curtime;
  325. m_LastActivity = ACT_IDLE;
  326. }
  327. void CCSPlayerAnimState::UpdateTimeSinceLastActChange()
  328. {
  329. if ( m_CurrentActivity != m_LastActivity )
  330. {
  331. m_flLastActChangeTime = gpGlobals->curtime;
  332. m_LastActivity = m_CurrentActivity;
  333. }
  334. }
  335. float CCSPlayerAnimState::GetTimeSinceLastActChange()
  336. {
  337. return ( gpGlobals->curtime - m_flLastActChangeTime );
  338. }
  339. void CCSPlayerAnimState::InitCS( CBaseAnimatingOverlay *pEntity, ICSPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  340. {
  341. CModAnimConfig config;
  342. config.m_flMaxBodyYawDegrees = 60;
  343. //When correcting the player's yaw, m_flMaxBodyYawDegreesCorrectionAmount is applied instead of the max.
  344. //Since this value is intended to be more than m_flMaxBodyYawDegrees, it will set the new yaw PAST the midpoint.
  345. //This looks a little more lifelike when the player is rapidly turning, and if the player halts, it makes the facefront that follows more obvious.
  346. config.m_flMaxBodyYawDegreesCorrectionAmount = 90;
  347. //Disable foot plant tunring if the feet are lagging behind by more than this angle
  348. config.m_flIdleFootPlantMaxYaw = 110;
  349. //Turning less than this amount? Don't lift the feet, just shuffle them over.
  350. config.m_flIdleFootPlantFootLiftDelta = 25;
  351. config.m_LegAnimType = legAnimType;
  352. config.m_bUseAimSequences = bUseAimSequences;
  353. m_pPlayer = ToCSPlayer( pEntity );
  354. m_pHelpers = pHelpers;
  355. BaseClass::Init( pEntity, config );
  356. }
  357. void CCSPlayerAnimState::ModifyTauntDuration( float flTimingChange )
  358. {
  359. float flInterp = ( m_flTauntLength <= 0.0f ) ? ( -1.0f ) : ( ( gpGlobals->curtime - m_flTauntStartTime ) / m_flTauntLength );
  360. bool bTaunt = ( flInterp >= 0.0f && flInterp <= 1.0f );
  361. if ( bTaunt )
  362. {
  363. // Move to start time to account for how much the timing change
  364. m_flTauntStartTime -= flTimingChange;
  365. }
  366. }
  367. //--------------------------------------------------------------------------------------------------------------
  368. void CCSPlayerAnimState::CheckCachedSequenceValidity( void )
  369. {
  370. if ( m_cachedModelIndex != GetOuter()->GetModelIndex() )
  371. {
  372. m_cachedModelIndex = GetOuter()->GetModelIndex();
  373. for ( int i=0; i<=ACT_CROUCHIDLE; ++i )
  374. {
  375. m_sequenceCache[i] = -1;
  376. }
  377. // precache the sequences we'll be using for movement
  378. if ( m_cachedModelIndex > 0 )
  379. {
  380. m_sequenceCache[ACT_HOP - 1] = GetOuter()->SelectWeightedSequence( ACT_HOP );
  381. m_sequenceCache[ACT_LEAP - 1] = GetOuter()->SelectWeightedSequence( ACT_LEAP );
  382. m_sequenceCache[ACT_JUMP - 1] = GetOuter()->SelectWeightedSequence( ACT_JUMP );
  383. m_sequenceCache[ACT_IDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_IDLE );
  384. m_sequenceCache[ACT_RUN_CROUCH - 1] = GetOuter()->SelectWeightedSequence( ACT_RUN_CROUCH );
  385. m_sequenceCache[ACT_CROUCHIDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_CROUCHIDLE );
  386. m_sequenceCache[ACT_RUN - 1] = GetOuter()->SelectWeightedSequence( ACT_RUN );
  387. m_sequenceCache[ACT_WALK - 1] = GetOuter()->SelectWeightedSequence( ACT_WALK );
  388. m_sequenceCache[ACT_IDLE - 1] = GetOuter()->SelectWeightedSequence( ACT_IDLE );
  389. }
  390. }
  391. }
  392. void CCSPlayerAnimState::ClearAnimationLayer( int layer )
  393. {
  394. // Client obeys Order of CBaseAnimatingOverlay::MAX_OVERLAYS (15), but server trusts only the ANIM_LAYER_ACTIVE flag.
  395. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( layer );
  396. if ( pLayer )
  397. {
  398. pLayer->SetWeight( 0.0f );
  399. pLayer->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  400. #ifndef CLIENT_DLL
  401. pLayer->m_fFlags = 0;
  402. #endif
  403. }
  404. }
  405. //--------------------------------------------------------------------------------------------------------------
  406. /**
  407. * Cache the sequence numbers for the first ACT_HOP activities, since the CS player doesn't have multiple
  408. * sequences per activity.
  409. */
  410. int CCSPlayerAnimState::SelectWeightedSequence( Activity activity )
  411. {
  412. VPROF( "CCSPlayerAnimState::ComputeMainSequence" );
  413. if ( activity > ACT_CROUCHIDLE || activity < 1 )
  414. {
  415. return GetOuter()->SelectWeightedSequence( activity );
  416. }
  417. CheckCachedSequenceValidity();
  418. int sequence = m_sequenceCache[ activity - 1 ];
  419. if ( sequence < 0 )
  420. {
  421. // just in case, look up the sequence if we didn't precache it above
  422. sequence = m_sequenceCache[ activity - 1 ] = GetOuter()->SelectWeightedSequence( activity );
  423. }
  424. #if defined(CLIENT_DLL) && defined(_DEBUG)
  425. int realSequence = GetOuter()->SelectWeightedSequence( activity );
  426. Assert( realSequence == sequence );
  427. #endif
  428. return sequence;
  429. }
  430. //--------------------------------------------------------------------------------------------------------------
  431. // sprintf version of LookupSequence()
  432. //--------------------------------------------------------------------------------------------------------------
  433. int CCSPlayerAnimState::CalcSequenceIndex( PRINTF_FORMAT_STRING const char *pBaseName, ... )
  434. {
  435. VPROF( "CCSPlayerAnimState::CalcSequenceIndex" );
  436. CheckCachedSequenceValidity();
  437. char szFullName[512];
  438. va_list marker;
  439. va_start( marker, pBaseName );
  440. Q_vsnprintf( szFullName, sizeof( szFullName ), pBaseName, marker );
  441. va_end( marker );
  442. // FIXME: this looks up on the player, not their weapon
  443. int iSequence = GetOuter()->LookupSequence( szFullName );
  444. // Show warnings if we can't find anything here.
  445. if ( iSequence == -1 )
  446. {
  447. static CUtlDict<int,int> dict;
  448. if ( dict.Find( szFullName ) == dict.InvalidIndex() )
  449. {
  450. dict.Insert( szFullName, 0 );
  451. Warning( "CalcSequenceIndex: can't find '%s'.\n", szFullName );
  452. }
  453. iSequence = 0;
  454. }
  455. return iSequence;
  456. }
  457. void CCSPlayerAnimState::ClearAnimationState()
  458. {
  459. m_bJumping = false;
  460. m_bDeploying = false;
  461. m_bFiring = false;
  462. m_bReloading = false;
  463. m_flReloadHoldEndTime = 0.0f;
  464. m_bSilencerChanging = false;
  465. m_bThrowingGrenade = m_bPrimingGrenade = false;
  466. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  467. m_bTryingToRunAfterJump = false;
  468. BaseClass::ClearAnimationState();
  469. }
  470. void CCSPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t animEvent, int nData )
  471. {
  472. Assert( animEvent != PLAYERANIMEVENT_THROW_GRENADE );
  473. CWeaponCSBase *pActiveWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  474. bool currentWeaponIsDeployedWeapon = ActiveWeaponIsDeployed();
  475. MDLCACHE_CRITICAL_SECTION();
  476. switch ( animEvent )
  477. {
  478. case PLAYERANIMEVENT_FIRE_GUN_PRIMARY:
  479. case PLAYERANIMEVENT_FIRE_GUN_PRIMARY_OPT:
  480. case PLAYERANIMEVENT_FIRE_GUN_PRIMARY_SPECIAL1:
  481. case PLAYERANIMEVENT_FIRE_GUN_PRIMARY_OPT_SPECIAL1:
  482. case PLAYERANIMEVENT_FIRE_GUN_SECONDARY:
  483. case PLAYERANIMEVENT_FIRE_GUN_SECONDARY_SPECIAL1:
  484. if ( currentWeaponIsDeployedWeapon )
  485. {
  486. // Regardless of what we're doing in the fire layer, restart it.
  487. m_activeFireEvent = animEvent;
  488. m_iFireSequence = CalcFireLayerSequence( animEvent );
  489. m_bFiring = m_iFireSequence != -1;
  490. m_flFireCycle = 0;
  491. // If we are interrupting a (shotgun) reload, cancel the reload, and fire next frame.
  492. if ( m_bFiring && m_bReloading )
  493. {
  494. m_bReloading = false;
  495. m_iReloadSequence = -1;
  496. m_delayedFire = animEvent;
  497. m_bFiring = false;
  498. m_iFireSequence = -1;
  499. ClearAnimationLayer( RELOADSEQUENCE_LAYER );
  500. }
  501. #ifdef CLIENT_DLL
  502. if ( m_bFiring && !m_bReloading )
  503. {
  504. if ( m_pPlayer )
  505. {
  506. m_pPlayer->ProcessMuzzleFlashEvent();
  507. }
  508. }
  509. #endif
  510. }
  511. break;
  512. case PLAYERANIMEVENT_JUMP:
  513. // Play the jump animation.
  514. m_bJumping = true;
  515. m_bFirstJumpFrame = true;
  516. m_flJumpStartTime = gpGlobals->curtime;
  517. break;
  518. case PLAYERANIMEVENT_RELOAD:
  519. {
  520. // ignore normal reload events for shotguns - they get sent to trigger sounds etc only
  521. // [mlowrance] Mag7 special case: it's classified as a Shotgun, but reloads like a conventional gun with a clip.
  522. if ( pActiveWeapon && ( pActiveWeapon->GetWeaponType() != WEAPONTYPE_SHOTGUN || pActiveWeapon->GetCSWeaponID() == WEAPON_MAG7 ) )
  523. {
  524. m_iReloadSequence = CalcReloadLayerSequence( animEvent );
  525. if ( m_iReloadSequence != -1 )
  526. {
  527. m_bReloading = true;
  528. m_flReloadCycle = 0;
  529. }
  530. else
  531. {
  532. m_bReloading = false;
  533. }
  534. }
  535. }
  536. break;
  537. case PLAYERANIMEVENT_SILENCER_ATTACH:
  538. {
  539. m_iSilencerChangeSequence = CalcSilencerChangeLayerSequence( animEvent );
  540. if ( m_iSilencerChangeSequence != -1 )
  541. {
  542. m_bSilencerChanging = true;
  543. m_flSilencerChangeCycle = 0;
  544. }
  545. else
  546. {
  547. m_bSilencerChanging = false;
  548. }
  549. }
  550. break;
  551. case PLAYERANIMEVENT_SILENCER_DETACH:
  552. {
  553. m_iSilencerChangeSequence = CalcSilencerChangeLayerSequence( animEvent );
  554. if ( m_iSilencerChangeSequence != -1 )
  555. {
  556. m_bSilencerChanging = true;
  557. m_flSilencerChangeCycle = 0;
  558. }
  559. else
  560. {
  561. m_bSilencerChanging = false;
  562. }
  563. }
  564. break;
  565. case PLAYERANIMEVENT_RELOAD_START:
  566. case PLAYERANIMEVENT_RELOAD_LOOP:
  567. // Set the hold time for _start and _loop anims, then fall through to the _end case
  568. m_flReloadHoldEndTime = gpGlobals->curtime + 0.75f;
  569. case PLAYERANIMEVENT_RELOAD_END:
  570. {
  571. // ignore shotgun reload events for non-shotguns
  572. // [mlowrance] Mag7 special case: it's classified as a Shotgun, but reloads like a conventional gun with a clip.
  573. if ( pActiveWeapon && ( pActiveWeapon->GetWeaponType() != WEAPONTYPE_SHOTGUN || pActiveWeapon->GetCSWeaponID() == WEAPON_MAG7 ) )
  574. {
  575. m_flReloadHoldEndTime = 0.0f; // clear this out in case we set it in _START or _LOOP above
  576. }
  577. else
  578. {
  579. m_iReloadSequence = CalcReloadLayerSequence( animEvent );
  580. if ( m_iReloadSequence != -1 )
  581. {
  582. m_bReloading = true;
  583. m_flReloadCycle = 0;
  584. }
  585. else
  586. {
  587. m_bReloading = false;
  588. }
  589. }
  590. }
  591. break;
  592. case PLAYERANIMEVENT_CLEAR_FIRING:
  593. {
  594. m_iFireSequence = -1;
  595. m_flFireCycle = 0;
  596. m_bFiring = false;
  597. ClearAnimationLayer( FIRESEQUENCE_LAYER );
  598. ClearAnimationLayer( FIRESEQUENCE2_LAYER );
  599. }
  600. break;
  601. case PLAYERANIMEVENT_DEPLOY:
  602. {
  603. // Update the weapon to use for animations.
  604. if ( pActiveWeapon != NULL )
  605. {
  606. m_iDeployedWeaponID = pActiveWeapon->GetCSWeaponID();
  607. }
  608. else
  609. {
  610. m_iDeployedWeaponID = WEAPON_NONE;
  611. }
  612. // Start the Deploy animation if we have one.
  613. m_iDeploySequence = CalcDeployLayerSequence();
  614. if ( m_iDeploySequence != -1 )
  615. {
  616. m_bDeploying = true;
  617. m_flDeployCycle = 0.0f;
  618. }
  619. else
  620. {
  621. m_bDeploying = false;
  622. m_iDeploySequence = -1;
  623. ClearAnimationLayer( DEPLOYSEQUENCE_LAYER );
  624. }
  625. }
  626. break;
  627. case PLAYERANIMEVENT_GRENADE_PULL_PIN:
  628. break;
  629. //default:
  630. // Assert( !"CCSPlayerAnimState::DoAnimationEvent" );
  631. }
  632. }
  633. float g_flThrowGrenadeFraction = 0.25;
  634. bool CCSPlayerAnimState::IsThrowingGrenade()
  635. {
  636. if ( m_bThrowingGrenade )
  637. {
  638. // An animation event would be more appropriate here.
  639. return m_flGrenadeCycle < g_flThrowGrenadeFraction;
  640. }
  641. else
  642. {
  643. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  644. return bThrowPending || IsOuterGrenadePrimed();
  645. }
  646. }
  647. bool CCSPlayerAnimState::ShouldHideGrenadeDuringThrow()
  648. {
  649. return m_bThrowingGrenade && (m_flGrenadeCycle > 0.1f);
  650. }
  651. int CCSPlayerAnimState::CalcSilencerChangeLayerSequence( PlayerAnimEvent_t animEvent )
  652. {
  653. if ( m_delayedFire != PLAYERANIMEVENT_COUNT )
  654. return ACTIVITY_NOT_AVAILABLE;
  655. const char *weaponSuffix = GetWeaponSuffix();
  656. if ( !weaponSuffix )
  657. return ACTIVITY_NOT_AVAILABLE;
  658. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  659. if ( !pWeapon )
  660. return ACTIVITY_NOT_AVAILABLE;
  661. char szName[512];
  662. int iSilencerChangeSequence = -1;
  663. if ( animEvent == PLAYERANIMEVENT_SILENCER_ATTACH )
  664. {
  665. Q_snprintf( szName, sizeof( szName ), DEFAULT_SILENCER_ATTACH_NAME, weaponSuffix );
  666. }
  667. else if ( animEvent == PLAYERANIMEVENT_SILENCER_DETACH )
  668. {
  669. Q_snprintf( szName, sizeof( szName ), DEFAULT_SILENCER_DETACH_NAME, weaponSuffix );
  670. }
  671. else
  672. {
  673. return ACTIVITY_NOT_AVAILABLE;
  674. }
  675. iSilencerChangeSequence = m_pOuter->LookupSequence( szName );
  676. if ( iSilencerChangeSequence != -1 )
  677. return iSilencerChangeSequence;
  678. // no current fallback
  679. return ACTIVITY_NOT_AVAILABLE;
  680. }
  681. int CCSPlayerAnimState::CalcReloadLayerSequence( PlayerAnimEvent_t animEvent )
  682. {
  683. if ( m_delayedFire != PLAYERANIMEVENT_COUNT )
  684. return -1;
  685. const char *weaponSuffix = GetWeaponSuffix();
  686. if ( !weaponSuffix )
  687. return -1;
  688. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  689. if ( !pWeapon )
  690. return -1;
  691. const char *prefix = "";
  692. switch ( GetCurrentMainSequenceActivity() )
  693. {
  694. case ACT_PLAYER_RUN_FIRE:
  695. case ACT_RUN:
  696. prefix = "run";
  697. break;
  698. case ACT_PLAYER_WALK_FIRE:
  699. case ACT_WALK:
  700. prefix = "walk";
  701. break;
  702. case ACT_PLAYER_CROUCH_FIRE:
  703. case ACT_CROUCHIDLE:
  704. prefix = "crouch_idle";
  705. break;
  706. case ACT_PLAYER_CROUCH_WALK_FIRE:
  707. case ACT_RUN_CROUCH:
  708. prefix = "crouch_walk";
  709. break;
  710. default:
  711. case ACT_PLAYER_IDLE_FIRE:
  712. prefix = "idle";
  713. break;
  714. }
  715. const char *reloadSuffix = "";
  716. switch ( animEvent )
  717. {
  718. case PLAYERANIMEVENT_RELOAD_START:
  719. reloadSuffix = "_start";
  720. break;
  721. case PLAYERANIMEVENT_RELOAD_LOOP:
  722. reloadSuffix = "_loop";
  723. break;
  724. case PLAYERANIMEVENT_RELOAD_END:
  725. reloadSuffix = "_end";
  726. break;
  727. }
  728. // First, look for <prefix>_reload_<weapon name><_start|_loop|_end>.
  729. char szName[512];
  730. int iReloadSequence = -1;
  731. // Avoid doing this look up since we don't need it for CSGO
  732. #if !defined( CSTRIKE15 )
  733. Q_snprintf( szName, sizeof( szName ), "%s_reload_%s%s", prefix, weaponSuffix, reloadSuffix );
  734. iReloadSequence = m_pOuter->LookupSequence( szName );
  735. if ( iReloadSequence != -1 )
  736. return iReloadSequence;
  737. #endif
  738. // Next, look for reload_<weapon name><_start|_loop|_end>.
  739. Q_snprintf( szName, sizeof( szName ), "reload_%s%s", weaponSuffix, reloadSuffix );
  740. iReloadSequence = m_pOuter->LookupSequence( szName );
  741. if ( iReloadSequence != -1 )
  742. return iReloadSequence;
  743. // Ok, look for generic categories.. pistol, shotgun, rifle, etc.
  744. if ( pWeapon->GetWeaponType() == WEAPONTYPE_PISTOL )
  745. {
  746. Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
  747. iReloadSequence = m_pOuter->LookupSequence( szName );
  748. if ( iReloadSequence != -1 )
  749. return iReloadSequence;
  750. }
  751. // Fall back to reload_m4.
  752. iReloadSequence = CalcSequenceIndex( "reload_m4" );
  753. if ( iReloadSequence > 0 )
  754. return iReloadSequence;
  755. return -1;
  756. }
  757. void CCSPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd, float flWeight )
  758. {
  759. if ( !bEnabled || iSequence < 0 )
  760. return;
  761. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
  762. pLayer->SetSequence( iSequence );
  763. // find cycle rate for the layer
  764. float flSequenceCycleRate = m_pPlayer->GetLayerSequenceCycleRate( pLayer, iSequence );
  765. // weapon vs self
  766. flCurCycle += flSequenceCycleRate * gpGlobals->frametime;
  767. if ( flCurCycle > 1 )
  768. {
  769. if ( bWaitAtEnd )
  770. {
  771. flCurCycle = 1;
  772. }
  773. else
  774. {
  775. // Not firing anymore.
  776. bEnabled = false;
  777. iSequence = 0;
  778. return;
  779. }
  780. }
  781. // Now dump the state into its animation layer.
  782. pLayer->SetCycle( flCurCycle );
  783. pLayer->SetPlaybackRate( 1.0f );
  784. pLayer->SetWeight( flWeight );
  785. pLayer->SetOrder( iLayer );
  786. #ifndef CLIENT_DLL
  787. pLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  788. #endif
  789. }
  790. bool CCSPlayerAnimState::IsOuterGrenadePrimed()
  791. {
  792. CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
  793. if ( pChar )
  794. {
  795. CBaseCSGrenade *pGren = dynamic_cast<CBaseCSGrenade*>( pChar->GetActiveWeapon() );
  796. return pGren && pGren->IsPinPulled();
  797. }
  798. else
  799. {
  800. return NULL;
  801. }
  802. }
  803. void CCSPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
  804. {
  805. VPROF( "CCSPlayerAnimState::ComputeGrenadeSequence" );
  806. if ( m_bThrowingGrenade )
  807. {
  808. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
  809. }
  810. else
  811. {
  812. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  813. bool bThrowingUnderhand = false;
  814. #endif
  815. if ( m_pPlayer )
  816. {
  817. CBaseCombatWeapon *pWeapon = m_pPlayer->GetActiveWeapon();
  818. CBaseCSGrenade *pGren = dynamic_cast<CBaseCSGrenade*>( pWeapon );
  819. if ( !pGren )
  820. {
  821. // The player no longer has a grenade equipped. Bail.
  822. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  823. return;
  824. }
  825. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  826. else
  827. {
  828. bThrowingUnderhand = pGren->IsThrownUnderhand();
  829. }
  830. #endif
  831. }
  832. // Priming the grenade isn't an event.. we just watch the player for it.
  833. // Also play the prime animation first if he wants to throw the grenade.
  834. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  835. if ( IsOuterGrenadePrimed() || bThrowPending )
  836. {
  837. if ( !m_bPrimingGrenade )
  838. {
  839. // If this guy just popped into our PVS, and he's got his grenade primed, then
  840. // let's assume that it's all the way primed rather than playing the prime
  841. // animation from the start.
  842. if ( TimeSinceLastAnimationStateClear() < 0.4f )
  843. {
  844. m_flGrenadeCycle = 1;
  845. }
  846. else
  847. {
  848. m_flGrenadeCycle = 0;
  849. }
  850. m_bPrimingGrenade = true;
  851. }
  852. // [MLowrance] Moved this from the IF statement above. This allows the sequences to switch while maintaining the last frame of the prime anim.
  853. // So priming the grenade at Idle, then going to a Run while holding the last frame doesn't break the character.
  854. m_iGrenadeSequence = CalcGrenadePrimeSequence();
  855. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );
  856. // If we're waiting to throw and we're done playing the prime animation...
  857. // [mlowrance] due to timing and gameplay issues, if we're pending to throw... don't wait, do it
  858. if ( bThrowPending ) //&& m_flGrenadeCycle == 1 )
  859. {
  860. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  861. // Now play the throw animation.
  862. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  863. m_iGrenadeSequence = CalcGrenadeThrowSequence( bThrowingUnderhand );
  864. #else
  865. m_iGrenadeSequence = CalcGrenadeThrowSequence();
  866. #endif
  867. if ( m_iGrenadeSequence != -1 )
  868. {
  869. // Configure to start playing
  870. m_bThrowingGrenade = true;
  871. m_bPrimingGrenade = false;
  872. m_flGrenadeCycle = 0;
  873. }
  874. }
  875. }
  876. else
  877. {
  878. m_bPrimingGrenade = false;
  879. }
  880. }
  881. }
  882. int CCSPlayerAnimState::CalcGrenadePrimeSequence()
  883. {
  884. const char *prefix = "";
  885. switch ( GetCurrentMainSequenceActivity() )
  886. {
  887. case ACT_PLAYER_RUN_FIRE:
  888. case ACT_RUN:
  889. prefix = "run";
  890. break;
  891. case ACT_PLAYER_WALK_FIRE:
  892. case ACT_WALK:
  893. prefix = "walk";
  894. break;
  895. case ACT_PLAYER_CROUCH_FIRE:
  896. case ACT_CROUCHIDLE:
  897. prefix = "crouch_idle";
  898. break;
  899. case ACT_PLAYER_CROUCH_WALK_FIRE:
  900. case ACT_RUN_CROUCH:
  901. prefix = "crouch_walk";
  902. break;
  903. default:
  904. case ACT_PLAYER_IDLE_FIRE:
  905. prefix = "idle";
  906. break;
  907. }
  908. return CalcSequenceIndex( "%s_shoot_gren1", prefix );
  909. }
  910. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  911. int CCSPlayerAnimState::CalcGrenadeThrowSequence( bool bUnderhand )
  912. #else
  913. int CCSPlayerAnimState::CalcGrenadeThrowSequence( )
  914. #endif
  915. {
  916. const char *prefix = "";
  917. switch ( GetCurrentMainSequenceActivity() )
  918. {
  919. case ACT_PLAYER_RUN_FIRE:
  920. case ACT_RUN:
  921. prefix = "run";
  922. break;
  923. case ACT_PLAYER_WALK_FIRE:
  924. case ACT_WALK:
  925. prefix = "walk";
  926. break;
  927. case ACT_PLAYER_CROUCH_FIRE:
  928. case ACT_CROUCHIDLE:
  929. prefix = "crouch_idle";
  930. break;
  931. case ACT_PLAYER_CROUCH_WALK_FIRE:
  932. case ACT_RUN_CROUCH:
  933. prefix = "crouch_walk";
  934. break;
  935. default:
  936. case ACT_PLAYER_IDLE_FIRE:
  937. prefix = "idle";
  938. break;
  939. }
  940. #ifdef GRENADE_UNDERHAND_FEATURE_ENABLED
  941. if ( bUnderhand )
  942. {
  943. return CalcSequenceIndex( "%s_shoot_gren3", prefix );
  944. }
  945. else
  946. #endif
  947. {
  948. return CalcSequenceIndex( "%s_shoot_gren2", prefix );
  949. }
  950. }
  951. int CCSPlayerAnimState::GetOuterGrenadeThrowCounter()
  952. {
  953. if ( m_pPlayer )
  954. return m_pPlayer->m_iThrowGrenadeCounter;
  955. else
  956. return 0;
  957. }
  958. void CCSPlayerAnimState::ComputeSilencerChangeSequence( CStudioHdr *pStudioHdr )
  959. {
  960. VPROF( "CCSPlayerAnimState::ComputeSilencerChangeSequence" );
  961. UpdateLayerSequenceGeneric( pStudioHdr, SILENCERSEQUENCE_LAYER, m_bSilencerChanging, m_flSilencerChangeCycle, m_iSilencerChangeSequence, false );
  962. }
  963. void CCSPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
  964. {
  965. VPROF( "CCSPlayerAnimState::ComputeReloadSequence" );
  966. bool hold = m_flReloadHoldEndTime > gpGlobals->curtime;
  967. UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, hold );
  968. if ( !m_bReloading )
  969. {
  970. m_flReloadHoldEndTime = 0.0f;
  971. }
  972. }
  973. int CCSPlayerAnimState::CalcFlinchLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter )
  974. {
  975. if ( !pBaseCombatCharacter )
  976. return ACTIVITY_NOT_AVAILABLE;
  977. int nSequence = ACTIVITY_NOT_AVAILABLE;
  978. float flTimeSinceLastInjury = pBaseCombatCharacter->GetTimeSinceLastInjury();
  979. float flTimeSinceEndOfLastFlinch = gpGlobals->curtime - ( m_flFlinchStartTime + m_flFlinchLength );
  980. // If there were hurt after the end of the last flinch, time to flinch again!
  981. bool bFlinch = pBaseCombatCharacter->HasEverBeenInjured() && ( flTimeSinceLastInjury <= flTimeSinceEndOfLastFlinch );
  982. if ( bFlinch )
  983. {
  984. Activity flinchActivity;
  985. if ( m_pOuter->GetFlags() & FL_DUCKING )
  986. {
  987. // Crouching flinches
  988. if ( pBaseCombatCharacter->LastHitGroup() != HITGROUP_HEAD )
  989. {
  990. switch ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() )
  991. {
  992. case DAMAGED_DIR_BACK:
  993. flinchActivity = ACT_FLINCH_CROUCH_FRONT;
  994. break;
  995. case DAMAGED_DIR_LEFT:
  996. flinchActivity = ACT_FLINCH_CROUCH_LEFT;
  997. break;
  998. case DAMAGED_DIR_RIGHT:
  999. flinchActivity = ACT_FLINCH_CROUCH_RIGHT;
  1000. break;
  1001. case DAMAGED_DIR_FRONT:
  1002. case DAMAGED_DIR_NONE:
  1003. default:
  1004. flinchActivity = ACT_FLINCH_CROUCH_FRONT;
  1005. break;
  1006. }
  1007. }
  1008. else
  1009. {
  1010. switch ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() )
  1011. {
  1012. case DAMAGED_DIR_BACK:
  1013. flinchActivity = ACT_FLINCH_HEAD_BACK;
  1014. break;
  1015. case DAMAGED_DIR_LEFT:
  1016. flinchActivity = ACT_FLINCH_HEAD_LEFT;
  1017. break;
  1018. case DAMAGED_DIR_RIGHT:
  1019. flinchActivity = ACT_FLINCH_HEAD_RIGHT;
  1020. break;
  1021. case DAMAGED_DIR_FRONT:
  1022. case DAMAGED_DIR_NONE:
  1023. default:
  1024. flinchActivity = ACT_FLINCH_HEAD;
  1025. break;
  1026. }
  1027. }
  1028. // do we have a sequence for the ideal activity?
  1029. if ( SelectWeightedSequence( flinchActivity ) == ACTIVITY_NOT_AVAILABLE )
  1030. {
  1031. flinchActivity = ACT_FLINCH_CROUCH_FRONT;
  1032. }
  1033. }
  1034. else
  1035. {
  1036. // Standing flinches
  1037. int nLastHitGroup = pBaseCombatCharacter->LastHitGroup();
  1038. switch ( nLastHitGroup )
  1039. {
  1040. // pick a region-specific flinch
  1041. case HITGROUP_HEAD:
  1042. {
  1043. switch ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() )
  1044. {
  1045. case DAMAGED_DIR_BACK:
  1046. flinchActivity = ACT_FLINCH_HEAD_BACK;
  1047. break;
  1048. case DAMAGED_DIR_LEFT:
  1049. flinchActivity = ACT_FLINCH_HEAD_LEFT;
  1050. break;
  1051. case DAMAGED_DIR_RIGHT:
  1052. flinchActivity = ACT_FLINCH_HEAD_RIGHT;
  1053. break;
  1054. case DAMAGED_DIR_FRONT:
  1055. case DAMAGED_DIR_NONE:
  1056. default:
  1057. flinchActivity = ACT_FLINCH_HEAD;
  1058. break;
  1059. }
  1060. }
  1061. break;
  1062. case HITGROUP_STOMACH:
  1063. flinchActivity = ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() == DAMAGED_DIR_BACK ) ? ACT_FLINCH_STOMACH_BACK : ACT_FLINCH_STOMACH;
  1064. break;
  1065. case HITGROUP_LEFTARM:
  1066. flinchActivity = ACT_FLINCH_LEFTARM;
  1067. break;
  1068. case HITGROUP_RIGHTARM:
  1069. flinchActivity = ACT_FLINCH_RIGHTARM;
  1070. break;
  1071. case HITGROUP_LEFTLEG:
  1072. flinchActivity = ACT_FLINCH_LEFTLEG;
  1073. break;
  1074. case HITGROUP_RIGHTLEG:
  1075. flinchActivity = ACT_FLINCH_RIGHTLEG;
  1076. break;
  1077. case HITGROUP_CHEST:
  1078. flinchActivity = ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() == DAMAGED_DIR_BACK ) ? ACT_FLINCH_CHEST_BACK : ACT_FLINCH_CHEST;
  1079. break;
  1080. case HITGROUP_GEAR:
  1081. case HITGROUP_GENERIC:
  1082. default:
  1083. // just get a generic flinch.
  1084. flinchActivity = flinchActivity = ( pBaseCombatCharacter->GetLastInjuryRelativeDirection() == DAMAGED_DIR_BACK ) ? ACT_FLINCH_STOMACH_BACK : ACT_FLINCH_PHYSICS;
  1085. break;
  1086. }
  1087. }
  1088. // Get the sequence for this activity
  1089. nSequence = SelectWeightedSequence( flinchActivity );
  1090. // Do we have a sequence for the ideal activity?
  1091. if ( nSequence == ACTIVITY_NOT_AVAILABLE )
  1092. {
  1093. // Fall back to a basic physics flinch
  1094. nSequence = SelectWeightedSequence( ACT_FLINCH_PHYSICS );
  1095. }
  1096. }
  1097. return nSequence;
  1098. }
  1099. void CCSPlayerAnimState::ComputeFootPlantSequence( CStudioHdr *pStudioHdr )
  1100. {
  1101. if ( !m_bInFootPlantIdleTurn )
  1102. return;
  1103. VPROF("CCSPlayerAnimState::ComputeFootPlantSequence");
  1104. CBaseCombatCharacter *pBaseCombatCharacter = dynamic_cast<CBaseCombatCharacter*>(m_pOuter);
  1105. if (!pBaseCombatCharacter)
  1106. return;
  1107. int nSequence = SelectWeightedSequence( m_bFootPlantIdleNeedToLiftFeet ? ACT_TURN : ACT_STEP_FORE );
  1108. UpdateLayerSequenceGeneric( pStudioHdr, FOOTPLANTSEQUENCE_LAYER, m_bInFootPlantIdleTurn, m_flFootPlantIdleTurnCycle, nSequence, false );
  1109. }
  1110. void CCSPlayerAnimState::ComputeFlinchSequence( CStudioHdr *pStudioHdr )
  1111. {
  1112. VPROF( "CCSPlayerAnimState::ComputeFlinchSequence" );
  1113. CBaseCombatCharacter *pBaseCombatCharacter = dynamic_cast< CBaseCombatCharacter* >( m_pOuter );
  1114. if ( !pBaseCombatCharacter )
  1115. return;
  1116. float flInterp = ( m_flFlinchLength <= 0.0f ) ? ( -1.0f ) : ( ( gpGlobals->curtime - m_flFlinchStartTime ) / m_flFlinchLength );
  1117. bool bFlinch = ( flInterp >= 0.0f && flInterp <= 1.0f );
  1118. if ( bFlinch &&
  1119. ( pBaseCombatCharacter->LastHitGroup() == HITGROUP_HEAD ) &&
  1120. m_nFlinchSequence != SelectWeightedSequence( ACT_FLINCH_HEAD ) &&
  1121. m_nFlinchSequence != SelectWeightedSequence( ACT_FLINCH_HEAD_BACK ) &&
  1122. m_nFlinchSequence != SelectWeightedSequence( ACT_FLINCH_HEAD_LEFT ) &&
  1123. m_nFlinchSequence != SelectWeightedSequence( ACT_FLINCH_HEAD_RIGHT ) )
  1124. {
  1125. // They were hit in the head while doing a non-head flinch
  1126. // Override it and force a new head flinch
  1127. bFlinch = false;
  1128. m_flFlinchStartTime = -1.0f;
  1129. m_flFlinchLength = 0.0f;
  1130. }
  1131. if ( !bFlinch )
  1132. {
  1133. // Calculate a new flinch if we have one
  1134. int nSequence = CalcFlinchLayerSequence( pBaseCombatCharacter );
  1135. if ( nSequence != ACTIVITY_NOT_AVAILABLE )
  1136. {
  1137. flInterp = 0.0f;
  1138. bFlinch = true;
  1139. m_nFlinchSequence = nSequence;
  1140. m_flFlinchStartTime = gpGlobals->curtime;
  1141. m_flFlinchLength = m_pOuter->SequenceDuration( nSequence );
  1142. }
  1143. }
  1144. // Update with the current flinch state
  1145. UpdateLayerSequenceGeneric( pStudioHdr, FLINCHSEQUENCE_LAYER, bFlinch, flInterp, m_nFlinchSequence, false );
  1146. }
  1147. int CCSPlayerAnimState::CalcFlashedLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter )
  1148. {
  1149. if ( !pBaseCombatCharacter )
  1150. return ACTIVITY_NOT_AVAILABLE;
  1151. return SelectWeightedSequence( ACT_GESTURE_BIG_FLINCH );
  1152. }
  1153. void CCSPlayerAnimState::ComputeFlashedSequence( CStudioHdr *pStudioHdr )
  1154. {
  1155. VPROF( "CCSPlayerAnimState::ComputeFlashedSequence" );
  1156. CBaseCombatCharacter *pBaseCombatCharacter = dynamic_cast< CBaseCombatCharacter* >( m_pOuter );
  1157. if ( !pBaseCombatCharacter )
  1158. return;
  1159. CCSPlayer *pPlayer = ToCSPlayer( pBaseCombatCharacter );
  1160. if ( !pPlayer )
  1161. return;
  1162. float flCurrentFlashDuration = pPlayer->m_flFlashDuration.Get();
  1163. if ( flCurrentFlashDuration != m_flLastFlashDuration )
  1164. m_flFlashedAmount = MAX( 0.0f, flCurrentFlashDuration - 1.25f );
  1165. bool bFlashed = m_flFlashedAmount > 0;
  1166. if ( bFlashed )
  1167. {
  1168. int nSequence = CalcFlashedLayerSequence( pBaseCombatCharacter );
  1169. if ( nSequence != ACTIVITY_NOT_AVAILABLE )
  1170. {
  1171. m_iFlashedSequence = nSequence;
  1172. m_flFlashedAmountDelayed = Approach( m_flFlashedAmount, m_flFlashedAmountDelayed, gpGlobals->frametime * 5.0f );
  1173. CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( FLASHEDSEQUENCE_LAYER );
  1174. pLayer->SetSequence( m_iFlashedSequence );
  1175. pLayer->SetCycle( clamp( m_flFlashedAmountDelayed, 0, 1 ) );
  1176. pLayer->SetPlaybackRate( 1.0f );
  1177. pLayer->SetWeight( 1.0f );
  1178. pLayer->SetOrder( FLASHEDSEQUENCE_LAYER );
  1179. #ifndef CLIENT_DLL
  1180. pLayer->m_fFlags |= ANIM_LAYER_ACTIVE;
  1181. #endif
  1182. }
  1183. }
  1184. if ( bFlashed )
  1185. {
  1186. m_flFlashedAmount -= gpGlobals->frametime;
  1187. }
  1188. else
  1189. {
  1190. m_flFlashedAmount = 0.0f;
  1191. }
  1192. m_flLastFlashDuration = pPlayer->m_flFlashDuration.Get();
  1193. }
  1194. int CCSPlayerAnimState::CalcTauntLayerSequence( CBaseCombatCharacter *pBaseCombatCharacter )
  1195. {
  1196. return ACTIVITY_NOT_AVAILABLE;
  1197. /*
  1198. if ( !pBaseCombatCharacter )
  1199. return ACTIVITY_NOT_AVAILABLE;
  1200. if ( !m_pPlayer || !m_pPlayer->IsTaunting() )
  1201. return ACTIVITY_NOT_AVAILABLE;
  1202. CWeaponCSBase *pActiveWeapon = m_pPlayer->GetActiveCSWeapon();
  1203. if ( !pActiveWeapon )
  1204. return ACTIVITY_NOT_AVAILABLE;
  1205. CEconItemView *pItemView = pActiveWeapon->GetAttributeContainer()->GetItem();
  1206. if ( !pItemView->IsValid() )
  1207. return ACTIVITY_NOT_AVAILABLE;
  1208. const CEconTauntDefinition *pTauntDef = GetItemSchema()->GetTauntDefinition( pItemView->GetTauntID() );
  1209. const char *pchTauntSequenceName = "";
  1210. if ( pTauntDef )
  1211. {
  1212. pchTauntSequenceName = pTauntDef->GetSequenceName();
  1213. }
  1214. return m_pOuter->LookupSequence( pchTauntSequenceName );
  1215. */
  1216. }
  1217. void CCSPlayerAnimState::ComputeTauntSequence( CStudioHdr *pStudioHdr )
  1218. {
  1219. VPROF( "CCSPlayerAnimState::ComputeFlinchSequence" );
  1220. CBaseCombatCharacter *pBaseCombatCharacter = dynamic_cast< CBaseCombatCharacter* >( m_pOuter );
  1221. if ( !pBaseCombatCharacter )
  1222. return;
  1223. float flInterp = ( m_flTauntLength <= 0.0f ) ? ( -1.0f ) : ( ( gpGlobals->curtime - m_flTauntStartTime ) / m_flTauntLength );
  1224. bool bTaunt = ( flInterp >= 0.0f && flInterp <= 1.0f );
  1225. if ( !bTaunt )
  1226. {
  1227. // Calculate a new taunt if we have one
  1228. int nSequence = CalcTauntLayerSequence( pBaseCombatCharacter );
  1229. if ( nSequence != ACTIVITY_NOT_AVAILABLE )
  1230. {
  1231. flInterp = 0.0f;
  1232. bTaunt = true;
  1233. m_nTauntSequence = nSequence;
  1234. m_flTauntStartTime = gpGlobals->curtime;
  1235. m_flTauntLength = m_pOuter->SequenceDuration( nSequence );
  1236. }
  1237. }
  1238. // Update with the current taunt state
  1239. UpdateLayerSequenceGeneric( pStudioHdr, TAUNTSEQUENCE_LAYER, bTaunt, flInterp, m_nTauntSequence, false );
  1240. }
  1241. int CCSPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
  1242. {
  1243. VPROF( "CCSPlayerAnimState::CalcAimLayerSequence" );
  1244. const char *pSuffix = GetWeaponSuffix();
  1245. if ( !pSuffix )
  1246. return 0;
  1247. Activity activity = GetCurrentMainSequenceActivity();
  1248. if ( bForceIdle )
  1249. {
  1250. switch ( activity )
  1251. {
  1252. case ACT_CROUCHIDLE:
  1253. case ACT_RUN_CROUCH:
  1254. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
  1255. default:
  1256. return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
  1257. }
  1258. }
  1259. else
  1260. {
  1261. switch ( activity )
  1262. {
  1263. case ACT_RUN:
  1264. case ACT_LEAP:
  1265. m_iCurrentAimSequence = CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );
  1266. break;
  1267. case ACT_WALK:
  1268. case ACT_RUNTOIDLE:
  1269. case ACT_IDLETORUN:
  1270. case ACT_JUMP:
  1271. m_iCurrentAimSequence = CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );
  1272. break;
  1273. case ACT_RUN_CROUCH:
  1274. m_iCurrentAimSequence = CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );
  1275. break;
  1276. // Since we blend between two transitioners, we always have the lower one be idle (hence the forceIdle flag above).
  1277. // Because the lower on is always idle, we never want to have an idle sequence in the upper transitioner.
  1278. case ACT_CROUCHIDLE:
  1279. case ACT_HOP:
  1280. case ACT_IDLE:
  1281. default:
  1282. break;
  1283. }
  1284. return m_iCurrentAimSequence;
  1285. }
  1286. }
  1287. const char* CCSPlayerAnimState::GetWeaponSuffix()
  1288. {
  1289. VPROF( "CCSPlayerAnimState::GetWeaponSuffix" );
  1290. // Figure out the weapon suffix.
  1291. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  1292. if ( !pWeapon )
  1293. return NULL;
  1294. const char *pSuffix = pWeapon->GetPlayerAnimationExtension();
  1295. #ifdef CS_SHIELD_ENABLED
  1296. if ( m_pOuter->HasShield() == true )
  1297. {
  1298. if ( m_pOuter->IsShieldDrawn() == true )
  1299. pSuffix = "shield";
  1300. else
  1301. pSuffix = "shield_undeployed";
  1302. }
  1303. #endif
  1304. return pSuffix;
  1305. }
  1306. int CCSPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t animEvent)
  1307. {
  1308. // Figure out the weapon suffix.
  1309. CWeaponCSBase *pWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  1310. if ( !pWeapon )
  1311. return -1;
  1312. const char *pSuffix = GetWeaponSuffix();
  1313. if ( !pSuffix )
  1314. return -1;
  1315. char tempsuffix[256];
  1316. if ( pWeapon->GetCSWeaponID() == WEAPON_ELITE )
  1317. {
  1318. bool bPrimary = (animEvent == PLAYERANIMEVENT_FIRE_GUN_PRIMARY);
  1319. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_%c", pSuffix, bPrimary?'r':'l' );
  1320. pSuffix = tempsuffix;
  1321. }
  1322. else if ( pWeapon->GetCSWeaponID() == WEAPON_KNIFE || pWeapon->GetCSWeaponID() == WEAPON_KNIFE_GG )
  1323. {
  1324. const char* newSuffix = tempsuffix;
  1325. if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_PRIMARY )
  1326. {
  1327. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_light_r", pSuffix );
  1328. }
  1329. else if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_PRIMARY_OPT )
  1330. {
  1331. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_light_l", pSuffix );
  1332. }
  1333. else if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_PRIMARY_SPECIAL1 )
  1334. {
  1335. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_light_r_bs", pSuffix );
  1336. }
  1337. else if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_PRIMARY_OPT_SPECIAL1 )
  1338. {
  1339. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_light_l_bs", pSuffix );
  1340. }
  1341. else if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_SECONDARY )
  1342. {
  1343. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_heavy", pSuffix );
  1344. }
  1345. else if ( animEvent == PLAYERANIMEVENT_FIRE_GUN_SECONDARY_SPECIAL1 )
  1346. {
  1347. Q_snprintf( tempsuffix, sizeof(tempsuffix), "%s_heavy_bs", pSuffix );
  1348. }
  1349. else
  1350. {
  1351. newSuffix = pSuffix;
  1352. }
  1353. pSuffix = newSuffix;
  1354. }
  1355. // Grenades handle their fire events separately
  1356. if ( animEvent == PLAYERANIMEVENT_THROW_GRENADE || pWeapon->IsKindOf(WEAPONTYPE_GRENADE) )
  1357. {
  1358. return -1;
  1359. }
  1360. m_iIdleFireSequence = CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
  1361. switch ( GetCurrentMainSequenceActivity() )
  1362. {
  1363. case ACT_PLAYER_RUN_FIRE:
  1364. case ACT_RUN:
  1365. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );
  1366. case ACT_PLAYER_WALK_FIRE:
  1367. case ACT_WALK:
  1368. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );
  1369. case ACT_PLAYER_CROUCH_FIRE:
  1370. case ACT_CROUCHIDLE:
  1371. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );
  1372. case ACT_PLAYER_CROUCH_WALK_FIRE:
  1373. case ACT_RUN_CROUCH:
  1374. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );
  1375. default:
  1376. case ACT_PLAYER_IDLE_FIRE:
  1377. return m_iIdleFireSequence;
  1378. }
  1379. }
  1380. bool CCSPlayerAnimState::CanThePlayerMove()
  1381. {
  1382. return m_pHelpers->CSAnim_CanMove();
  1383. }
  1384. float CCSPlayerAnimState::GetCurrentMaxGroundSpeed()
  1385. {
  1386. Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
  1387. if ( currentActivity == ACT_WALK || currentActivity == ACT_JUMP || currentActivity == ACT_IDLE || currentActivity == ACT_HOP || currentActivity == ACT_BUSY_QUEUE || currentActivity == ACT_TURN || currentActivity == ACT_STEP_FORE )
  1388. {
  1389. m_flTargetMaxSpeed = ANIM_TOPSPEED_WALK;
  1390. }
  1391. else if ( currentActivity == ACT_RUN || currentActivity == ACT_LEAP )
  1392. {
  1393. m_flTargetMaxSpeed = ANIM_TOPSPEED_RUN;
  1394. if ( m_pPlayer )
  1395. {
  1396. CBaseCombatWeapon *activeWeapon = m_pPlayer->GetActiveWeapon();
  1397. if ( activeWeapon )
  1398. {
  1399. CWeaponCSBase *csWeapon = dynamic_cast< CWeaponCSBase * >( activeWeapon );
  1400. if ( csWeapon )
  1401. {
  1402. m_flTargetMaxSpeed = csWeapon->GetMaxSpeed();
  1403. }
  1404. }
  1405. }
  1406. }
  1407. else if ( currentActivity == ACT_RUN_CROUCH || currentActivity == ACT_CROUCHIDLE )
  1408. {
  1409. m_flTargetMaxSpeed = ANIM_TOPSPEED_RUN_CROUCH;
  1410. }
  1411. else
  1412. {
  1413. AssertMsg1( false, "Need to handle the activity %d", currentActivity);
  1414. DevMsg("Need to handle the activity %d\n", (int)currentActivity);
  1415. m_flTargetMaxSpeed = 0.0f;
  1416. }
  1417. // The current max speed smoothly moves toward the TargetMax speed to avoid pops in animation.
  1418. return m_flCurrentMaxSpeed;
  1419. }
  1420. bool CCSPlayerAnimState::HandleJumping()
  1421. {
  1422. if ( m_bJumping )
  1423. {
  1424. if ( m_bFirstJumpFrame )
  1425. {
  1426. #if !defined(CLIENT_DLL)
  1427. // [dwenger] Needed for fun-fact implementation
  1428. CCS_GameStats.IncrementStat( m_pPlayer, CSSTAT_TOTAL_JUMPS, 1 );
  1429. #endif
  1430. m_bFirstJumpFrame = false;
  1431. RestartMainSequence(); // Reset the animation.
  1432. }
  1433. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  1434. // on-ground flag set right when the message comes in.
  1435. const float GROUND_CHECK_DELAY = 0.2f;
  1436. if ( gpGlobals->curtime - m_flJumpStartTime > GROUND_CHECK_DELAY )
  1437. {
  1438. if ( m_pOuter->GetFlags() & FL_ONGROUND )
  1439. {
  1440. m_flPostLandCrouchEndTime = gpGlobals->curtime + post_jump_crouch.GetFloat();
  1441. m_bJumping = false;
  1442. RestartMainSequence(); // Reset the animation.
  1443. }
  1444. }
  1445. }
  1446. // Are we still jumping? If so, keep playing the jump animation.
  1447. return m_bJumping;
  1448. }
  1449. Activity CCSPlayerAnimState::CalcMainActivity()
  1450. {
  1451. float flOuterSpeed = GetOuterXYSpeed();
  1452. if ( HandleJumping() )
  1453. {
  1454. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  1455. {
  1456. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  1457. return ACT_LEAP;
  1458. else
  1459. return ACT_JUMP;
  1460. }
  1461. return ACT_HOP;
  1462. }
  1463. else
  1464. {
  1465. int moveState = m_pPlayer->m_iMoveState;
  1466. bool inPostJump = false;
  1467. #if defined( CLIENT_DLL )
  1468. inPostJump = ( gpGlobals->curtime < m_flPostLandCrouchEndTime );
  1469. #endif
  1470. if ( m_pOuter->GetFlags() & FL_ANIMDUCKING || inPostJump )
  1471. {
  1472. // If the player is trying to run after jumping, we transition directly to the run animation instead of going through the
  1473. // chain of animations based soley on the player's speed.
  1474. if ( inPostJump && ( moveState == MOVESTATE_RUN ) )
  1475. {
  1476. m_bTryingToRunAfterJump = true;
  1477. }
  1478. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  1479. {
  1480. return ACT_RUN_CROUCH;
  1481. }
  1482. return ACT_CROUCHIDLE;
  1483. }
  1484. else
  1485. {
  1486. if ( m_CurrentActivity == ACT_IDLE || m_CurrentActivity == ACT_TURN || m_CurrentActivity == ACT_STEP_FORE )
  1487. {
  1488. //we aren't showing any movement animation at the moment.
  1489. //but we want to walk or run
  1490. if ( moveState != MOVESTATE_IDLE )
  1491. {
  1492. //we can walk right away, pose params will blend us in nicely
  1493. m_CurrentActivity = ACT_WALK;
  1494. //but we need to be going fast enough to go all the way up to a run
  1495. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  1496. {
  1497. m_CurrentActivity = ACT_RUN;
  1498. }
  1499. }
  1500. }
  1501. else if ( m_CurrentActivity == ACT_WALK )
  1502. {
  1503. //we're showing a little movement animation
  1504. //but we want to stop
  1505. if ( moveState == MOVESTATE_IDLE )
  1506. {
  1507. //only stop if we're slow enough
  1508. if ( flOuterSpeed < MOVING_MINIMUM_SPEED && GetTimeSinceLastActChange() > ANIM_ACT_DURATION_BEFORE_RETURN_TO_IDLE )
  1509. {
  1510. m_CurrentActivity = ACT_IDLE;
  1511. }
  1512. }
  1513. //but we want to RUN we need to be moving fast enough
  1514. else if ( moveState == MOVESTATE_RUN && flOuterSpeed > ARBITRARY_RUN_SPEED )
  1515. {
  1516. m_CurrentActivity = ACT_RUN;
  1517. }
  1518. }
  1519. else if ( m_CurrentActivity == ACT_RUN )
  1520. {
  1521. //we're playing the run animation
  1522. //if we want to walk, don't do it until we drop into walk speed
  1523. if ( moveState == MOVESTATE_WALK && flOuterSpeed < ARBITRARY_RUN_SPEED && GetTimeSinceLastActChange() > ANIM_ACT_DURATION_BEFORE_RETURN_TO_WALK )
  1524. {
  1525. m_CurrentActivity = ACT_WALK;
  1526. }
  1527. //and if we want to stop, don't do it until we drop to near-stop speed
  1528. else if ( moveState == MOVESTATE_IDLE && flOuterSpeed < MOVING_MINIMUM_SPEED && GetTimeSinceLastActChange() > ANIM_ACT_DURATION_BEFORE_RETURN_TO_IDLE )
  1529. {
  1530. m_CurrentActivity = ACT_IDLE;
  1531. }
  1532. }
  1533. // As soon as they lift up on trying to run, we no longer force the post run animation after a jump.
  1534. if ( moveState != MOVESTATE_RUN )
  1535. {
  1536. m_bTryingToRunAfterJump = false;
  1537. }
  1538. if ( m_bTryingToRunAfterJump )
  1539. {
  1540. m_CurrentActivity = ACT_RUN;
  1541. }
  1542. UpdateTimeSinceLastActChange();
  1543. return m_CurrentActivity;
  1544. }
  1545. }
  1546. }
  1547. void CCSPlayerAnimState::DebugShowAnimState( int iStartLine )
  1548. {
  1549. engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
  1550. engine->Con_NPrintf( iStartLine++, "deploy : %s, cycle: %.2f\n", m_bDeploying ? GetSequenceName( m_pOuter->GetModelPtr(), m_iDeploySequence ) : "[not deploying]", m_flDeployCycle );
  1551. engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
  1552. BaseClass::DebugShowAnimState( iStartLine );
  1553. }
  1554. void CCSPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  1555. {
  1556. BaseClass::ComputeSequences( pStudioHdr );
  1557. VPROF( "CCSPlayerAnimState::ComputeSequences" );
  1558. // dispatched through weapon
  1559. ComputeDeploySequence( pStudioHdr );
  1560. ComputeFireSequence( pStudioHdr );
  1561. ComputeReloadSequence( pStudioHdr );
  1562. ComputeSilencerChangeSequence( pStudioHdr );
  1563. ComputeGrenadeSequence( pStudioHdr );
  1564. // not dispatched through weapon (normally)
  1565. ComputeFlashedSequence( pStudioHdr );
  1566. ComputeFlinchSequence( pStudioHdr );
  1567. ComputeTauntSequence( pStudioHdr );
  1568. ComputeFootPlantSequence(pStudioHdr);
  1569. }
  1570. void CCSPlayerAnimState::ClearAnimationLayers()
  1571. {
  1572. if ( !m_pOuter )
  1573. return;
  1574. m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
  1575. for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
  1576. {
  1577. ClearAnimationLayer( i );
  1578. }
  1579. }
  1580. void CCSPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
  1581. {
  1582. VPROF( "CCSPlayerAnimState::ComputeFireSequence" );
  1583. if ( m_delayedFire != PLAYERANIMEVENT_COUNT )
  1584. {
  1585. DoAnimationEvent( m_delayedFire, 0 );
  1586. m_delayedFire = PLAYERANIMEVENT_COUNT;
  1587. }
  1588. // firing anims are blended in case the player starts or stops moving during long firing animations
  1589. bool bCrouched = ( m_pOuter->GetFlags() & FL_DUCKING ) ? true : false;
  1590. if (bCrouched)
  1591. {
  1592. UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
  1593. }
  1594. else
  1595. {
  1596. float flMaxSpeed = GetCurrentMaxGroundSpeed();
  1597. float flPortionOfMaxSpeed = 0.0f;
  1598. if ( flMaxSpeed > 0 )
  1599. {
  1600. Vector vel;
  1601. GetOuterAbsVelocity( vel );
  1602. flPortionOfMaxSpeed = MIN( vel.Length2D() / flMaxSpeed, 1.0f );
  1603. }
  1604. if ( flPortionOfMaxSpeed < 1.0f && m_iIdleFireSequence != -1 )
  1605. {
  1606. //if we're at all under top speed, lay down a base layer of the idle (non-moving) firing animation, weighted by that portion of max speed
  1607. UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iIdleFireSequence, false, 1.0 - flPortionOfMaxSpeed );
  1608. }
  1609. if ( flPortionOfMaxSpeed > 0 )
  1610. {
  1611. //we are moving and firing, but playing the idle firing animation. Re-evaluate the sequence so we can swap to the walk/crouchwalk/run version.
  1612. if ( m_bFiring && m_iFireSequence == m_iIdleFireSequence )
  1613. {
  1614. m_iFireSequence = CalcFireLayerSequence( m_activeFireEvent );
  1615. }
  1616. // blend in the moving version of this firing animation
  1617. UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE2_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false, flPortionOfMaxSpeed );
  1618. }
  1619. }
  1620. }
  1621. int CCSPlayerAnimState::CalcDeployLayerSequence( void )
  1622. {
  1623. // Figure out the weapon suffix.
  1624. const char *pSuffix = GetWeaponSuffix();
  1625. if ( !pSuffix )
  1626. return -1;
  1627. //[msmith] NOTE: Once we get all the deploy animations added in, use the line below (CalcSequenceIndex) instead of querying LookupSequence directly.
  1628. //return CalcSequenceIndex( "deploy_%s", pSuffix );
  1629. char szName[512];
  1630. Q_snprintf( szName, sizeof( szName ), "deploy_%s", pSuffix );
  1631. return m_pOuter->LookupSequence( szName );
  1632. }
  1633. void CCSPlayerAnimState::ComputeDeploySequence( CStudioHdr *pStudioHdr )
  1634. {
  1635. // We need to base the deploy animation on weapon changes instead of an animation event since animation
  1636. // events are delayed and can cause base animations to be out of sync with the new weapons.
  1637. // There is a tricky bit here since the weapon gets set before the deploy event.
  1638. // To fix this, while the actively deployed weapon differs from the active weapon,
  1639. // clear out all the other layers.
  1640. if ( !ActiveWeaponIsDeployed() )
  1641. {
  1642. // Clear out the transition history so that we pop to the new weapon instead of blending to it.
  1643. m_LowAimSequenceTransitioner.RemoveAll();
  1644. m_HighAimSequenceTransitioner.RemoveAll();
  1645. // Resets and turns off any Fire anim that might be playing
  1646. m_bFiring = false;
  1647. m_iFireSequence = -1;
  1648. ClearAnimationLayer( FIRESEQUENCE_LAYER );
  1649. // Resets and turns off any Reload anim that might be playing
  1650. m_bReloading = false;
  1651. m_iReloadSequence = -1;
  1652. ClearAnimationLayer( RELOADSEQUENCE_LAYER );
  1653. // Resets and turns off any Silencer attach/detach anim that might be playing
  1654. m_bSilencerChanging = false;
  1655. m_iSilencerChangeSequence = -1;
  1656. ClearAnimationLayer( SILENCERSEQUENCE_LAYER );
  1657. // Resets and turns off any Grenade animations that might be playing.
  1658. m_bThrowingGrenade = false;
  1659. m_bPrimingGrenade = false;
  1660. m_iGrenadeSequence = -1;
  1661. ClearAnimationLayer( GRENADESEQUENCE_LAYER );
  1662. }
  1663. if ( m_bDeploying )
  1664. {
  1665. VPROF( "CCSPlayerAnimState::ComputeDeploySequence" );
  1666. UpdateLayerSequenceGeneric( pStudioHdr, DEPLOYSEQUENCE_LAYER, m_bDeploying, m_flDeployCycle, m_iDeploySequence, false );
  1667. // Not deploying anymore so clear out the layer.
  1668. if ( !m_bDeploying )
  1669. {
  1670. ClearAnimationLayer( DEPLOYSEQUENCE_LAYER );
  1671. }
  1672. }
  1673. }
  1674. float CCSPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
  1675. {
  1676. // Determine ideal playback rate
  1677. Vector vel;
  1678. GetOuterAbsVelocity( vel );
  1679. float speed = vel.Length2D();
  1680. bool isMoving = ( speed > MOVING_MINIMUM_SPEED );
  1681. *bIsMoving = false;
  1682. float flReturnValue = 1;
  1683. if ( isMoving && CanThePlayerMove() )
  1684. {
  1685. if ( m_flCurrentMaxSpeed < 0.001f )
  1686. {
  1687. flReturnValue = 0.01;
  1688. }
  1689. else
  1690. {
  1691. // [msmith]
  1692. // The playback rate is used to blend between idle and moving.
  1693. // If we're fully moving, we want it to be 1.0.
  1694. flReturnValue = speed / m_flCurrentMaxSpeed;
  1695. // We cap this to one so we are never more than fully moving.
  1696. flReturnValue = clamp( flReturnValue, 0.0f, 1.0f );
  1697. }
  1698. *bIsMoving = true;
  1699. }
  1700. return flReturnValue;
  1701. }
  1702. void CCSPlayerAnimState::Update( float eyeYaw, float eyePitch )
  1703. {
  1704. // Adjust the maxSpeed toward the targetmax speed. Doesn't need to be perfect here.
  1705. // We just need to avoid some pops from when the speed suddenly changes.
  1706. const float SPEED_BLEND_VALUE = 0.15f;
  1707. m_flCurrentMaxSpeed += ( m_flTargetMaxSpeed - m_flCurrentMaxSpeed ) * SPEED_BLEND_VALUE;
  1708. if ( m_pPlayer && m_pPlayer->IsTaunting() )
  1709. {
  1710. // Get the studio header for the player.
  1711. CStudioHdr *pStudioHdr = m_pPlayer->GetModelPtr();
  1712. if ( !pStudioHdr )
  1713. return;
  1714. Vector vPositionToFace = vec3_origin; // FIXME: orientation lock target goes here!
  1715. bool bInTaunt = m_pPlayer->IsTaunting();
  1716. bool bIsImmobilized = bInTaunt;
  1717. bool bForceAdjust = bInTaunt; // FIXME: Maybe want this at some point
  1718. bool bIsOrientationLockedOnEntity = false;
  1719. if ( !bIsImmobilized )
  1720. {
  1721. // Pose parameter - what direction are the player's legs running in.
  1722. ComputePoseParam_MoveYaw( pStudioHdr );
  1723. }
  1724. if ( bIsOrientationLockedOnEntity )
  1725. {
  1726. // snap body to align with eye angles
  1727. m_bForceAimYaw = true;
  1728. Vector toOther = vPositionToFace - m_pPlayer->GetAbsOrigin();
  1729. QAngle alignedAngles;
  1730. VectorAngles( toOther, alignedAngles );
  1731. m_flEyeYaw = alignedAngles.y;
  1732. m_flEyePitch = alignedAngles.x;
  1733. }
  1734. // else if ( bForceAdjust )
  1735. // {
  1736. // m_bForceAimYaw = true;
  1737. // m_flEyeYaw = m_pPlayer->GetTauntYaw();
  1738. // }
  1739. if ( bIsOrientationLockedOnEntity || !bIsImmobilized || bForceAdjust )
  1740. {
  1741. eyePitch = m_flEyePitch;
  1742. eyeYaw = m_flEyeYaw;
  1743. }
  1744. }
  1745. BaseClass::Update(eyeYaw, eyePitch);
  1746. }
  1747. bool CCSPlayerAnimState::ActiveWeaponIsDeployed()
  1748. {
  1749. CWeaponCSBase *pActiveWeapon = m_pHelpers->CSAnim_GetActiveWeapon();
  1750. bool currentWeaponIsDeployedWeapon = true;
  1751. if ( pActiveWeapon != NULL )
  1752. {
  1753. currentWeaponIsDeployedWeapon = ( pActiveWeapon->GetCSWeaponID() == m_iDeployedWeaponID );
  1754. if ( !currentWeaponIsDeployedWeapon )
  1755. {
  1756. // If the player is out of view we don't get animation events about deploy etc.
  1757. // Because of this we use a time out to update the active weapon.
  1758. const float MAX_DEPLOY_DELAY = 1.0f;
  1759. if ( m_flWeaponSwitchTime == 0.0f )
  1760. {
  1761. m_flWeaponSwitchTime = gpGlobals->curtime;
  1762. }
  1763. else if ( m_flWeaponSwitchTime + MAX_DEPLOY_DELAY < gpGlobals->curtime )
  1764. {
  1765. // It has been MAX_DEPLOY_DELAY since the player switched weapons.
  1766. // Go ahead and set the active weapon as the deployed weapon.
  1767. m_iDeployedWeaponID = pActiveWeapon->GetCSWeaponID();
  1768. currentWeaponIsDeployedWeapon = true;
  1769. }
  1770. }
  1771. else
  1772. {
  1773. m_flWeaponSwitchTime = 0.0f;
  1774. }
  1775. }
  1776. return currentWeaponIsDeployedWeapon;
  1777. }