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.

621 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "base_playeranimstate.h"
  8. #include "tier0/vprof.h"
  9. #include "animation.h"
  10. #include "studio.h"
  11. #include "apparent_velocity_helper.h"
  12. #include "utldict.h"
  13. #include "sdk_playeranimstate.h"
  14. #include "weapon_sdkbase.h"
  15. #include "weapon_basesdkgrenade.h"
  16. #ifdef CLIENT_DLL
  17. #include "c_sdk_player.h"
  18. #include "bone_setup.h"
  19. #include "interpolatedvar.h"
  20. #else
  21. #include "sdk_player.h"
  22. #endif
  23. #define ANIM_TOPSPEED_WALK 100
  24. #define ANIM_TOPSPEED_RUN 250
  25. #define ANIM_TOPSPEED_RUN_CROUCH 85
  26. #define DEFAULT_IDLE_NAME "idle_upper_"
  27. #define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_"
  28. #define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_"
  29. #define DEFAULT_WALK_NAME "walk_upper_"
  30. #define DEFAULT_RUN_NAME "run_upper_"
  31. #define DEFAULT_FIRE_IDLE_NAME "idle_shoot_"
  32. #define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_"
  33. #define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_"
  34. #define DEFAULT_FIRE_WALK_NAME "walk_shoot_"
  35. #define DEFAULT_FIRE_RUN_NAME "run_shoot_"
  36. #define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
  37. #define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
  38. #define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
  39. #define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1)
  40. // ------------------------------------------------------------------------------------------------ //
  41. // CSDKPlayerAnimState declaration.
  42. // ------------------------------------------------------------------------------------------------ //
  43. class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState
  44. {
  45. public:
  46. DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState );
  47. friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  48. CSDKPlayerAnimState();
  49. virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
  50. virtual bool IsThrowingGrenade();
  51. virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
  52. virtual void ClearAnimationState();
  53. virtual bool CanThePlayerMove();
  54. virtual float GetCurrentMaxGroundSpeed();
  55. virtual Activity CalcMainActivity();
  56. virtual void DebugShowAnimState( int iStartLine );
  57. virtual void ComputeSequences( CStudioHdr *pStudioHdr );
  58. virtual void ClearAnimationLayers();
  59. void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
  60. protected:
  61. int CalcFireLayerSequence(PlayerAnimEvent_t event);
  62. void ComputeFireSequence(CStudioHdr *pStudioHdr);
  63. void ComputeReloadSequence(CStudioHdr *pStudioHdr);
  64. int CalcReloadLayerSequence();
  65. bool IsOuterGrenadePrimed();
  66. void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
  67. int CalcGrenadePrimeSequence();
  68. int CalcGrenadeThrowSequence();
  69. int GetOuterGrenadeThrowCounter();
  70. const char* GetWeaponSuffix();
  71. bool HandleJumping();
  72. void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd );
  73. private:
  74. // Current state variables.
  75. bool m_bJumping; // Set on a jump event.
  76. float m_flJumpStartTime;
  77. bool m_bFirstJumpFrame;
  78. // Aim sequence plays reload while this is on.
  79. bool m_bReloading;
  80. float m_flReloadCycle;
  81. int m_iReloadSequence;
  82. // This is set to true if ANY animation is being played in the fire layer.
  83. bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
  84. // until it completes.
  85. int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
  86. float m_flFireCycle;
  87. // These control grenade animations.
  88. bool m_bThrowingGrenade;
  89. bool m_bPrimingGrenade;
  90. float m_flGrenadeCycle;
  91. int m_iGrenadeSequence;
  92. int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.
  93. ISDKPlayerAnimStateHelpers *m_pHelpers;
  94. };
  95. ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  96. {
  97. CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState;
  98. pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences );
  99. return pRet;
  100. }
  101. // ------------------------------------------------------------------------------------------------ //
  102. // CSDKPlayerAnimState implementation.
  103. // ------------------------------------------------------------------------------------------------ //
  104. CSDKPlayerAnimState::CSDKPlayerAnimState()
  105. {
  106. m_pOuter = NULL;
  107. m_bReloading = false;
  108. }
  109. void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
  110. {
  111. CModAnimConfig config;
  112. config.m_flMaxBodyYawDegrees = 90;
  113. config.m_LegAnimType = legAnimType;
  114. config.m_bUseAimSequences = bUseAimSequences;
  115. m_pHelpers = pHelpers;
  116. BaseClass::Init( pEntity, config );
  117. }
  118. void CSDKPlayerAnimState::ClearAnimationState()
  119. {
  120. m_bJumping = false;
  121. m_bFiring = false;
  122. m_bReloading = false;
  123. m_bThrowingGrenade = m_bPrimingGrenade = false;
  124. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  125. BaseClass::ClearAnimationState();
  126. }
  127. void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
  128. {
  129. Assert( event != PLAYERANIMEVENT_THROW_GRENADE );
  130. if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY ||
  131. event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY )
  132. {
  133. // Regardless of what we're doing in the fire layer, restart it.
  134. m_flFireCycle = 0;
  135. m_iFireSequence = CalcFireLayerSequence( event );
  136. m_bFiring = m_iFireSequence != -1;
  137. }
  138. else if ( event == PLAYERANIMEVENT_JUMP )
  139. {
  140. // Play the jump animation.
  141. m_bJumping = true;
  142. m_bFirstJumpFrame = true;
  143. m_flJumpStartTime = gpGlobals->curtime;
  144. }
  145. else if ( event == PLAYERANIMEVENT_RELOAD )
  146. {
  147. m_iReloadSequence = CalcReloadLayerSequence();
  148. if ( m_iReloadSequence != -1 )
  149. {
  150. m_bReloading = true;
  151. m_flReloadCycle = 0;
  152. }
  153. }
  154. else
  155. {
  156. Assert( !"CSDKPlayerAnimState::DoAnimationEvent" );
  157. }
  158. }
  159. float g_flThrowGrenadeFraction = 0.25;
  160. bool CSDKPlayerAnimState::IsThrowingGrenade()
  161. {
  162. if ( m_bThrowingGrenade )
  163. {
  164. // An animation event would be more appropriate here.
  165. return m_flGrenadeCycle < g_flThrowGrenadeFraction;
  166. }
  167. else
  168. {
  169. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  170. return bThrowPending || IsOuterGrenadePrimed();
  171. }
  172. }
  173. int CSDKPlayerAnimState::CalcReloadLayerSequence()
  174. {
  175. const char *pSuffix = GetWeaponSuffix();
  176. if ( !pSuffix )
  177. return -1;
  178. CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
  179. if ( !pWeapon )
  180. return -1;
  181. // First, look for reload_<weapon name>.
  182. char szName[512];
  183. Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix );
  184. int iReloadSequence = m_pOuter->LookupSequence( szName );
  185. if ( iReloadSequence != -1 )
  186. return iReloadSequence;
  187. //SDKTODO
  188. /*
  189. // Ok, look for generic categories.. pistol, shotgun, rifle, etc.
  190. if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL )
  191. {
  192. Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
  193. iReloadSequence = m_pOuter->LookupSequence( szName );
  194. if ( iReloadSequence != -1 )
  195. return iReloadSequence;
  196. }
  197. */
  198. // Fall back to reload_m4.
  199. iReloadSequence = CalcSequenceIndex( "reload_m4" );
  200. if ( iReloadSequence > 0 )
  201. return iReloadSequence;
  202. return -1;
  203. }
  204. #ifdef CLIENT_DLL
  205. void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd )
  206. {
  207. if ( !bEnabled )
  208. return;
  209. // Increment the fire sequence's cycle.
  210. flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
  211. if ( flCurCycle > 1 )
  212. {
  213. if ( bWaitAtEnd )
  214. {
  215. flCurCycle = 1;
  216. }
  217. else
  218. {
  219. // Not firing anymore.
  220. bEnabled = false;
  221. iSequence = 0;
  222. return;
  223. }
  224. }
  225. // Now dump the state into its animation layer.
  226. C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
  227. pLayer->m_flCycle = flCurCycle;
  228. pLayer->m_nSequence = iSequence;
  229. pLayer->m_flPlaybackRate = 1.0;
  230. pLayer->m_flWeight = 1.0f;
  231. pLayer->m_nOrder = iLayer;
  232. }
  233. #endif
  234. bool CSDKPlayerAnimState::IsOuterGrenadePrimed()
  235. {
  236. CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
  237. if ( pChar )
  238. {
  239. CBaseSDKGrenade *pGren = dynamic_cast<CBaseSDKGrenade*>( pChar->GetActiveWeapon() );
  240. return pGren && pGren->IsPinPulled();
  241. }
  242. else
  243. {
  244. return NULL;
  245. }
  246. }
  247. void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
  248. {
  249. #ifdef CLIENT_DLL
  250. if ( m_bThrowingGrenade )
  251. {
  252. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
  253. }
  254. else
  255. {
  256. // Priming the grenade isn't an event.. we just watch the player for it.
  257. // Also play the prime animation first if he wants to throw the grenade.
  258. bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
  259. if ( IsOuterGrenadePrimed() || bThrowPending )
  260. {
  261. if ( !m_bPrimingGrenade )
  262. {
  263. // If this guy just popped into our PVS, and he's got his grenade primed, then
  264. // let's assume that it's all the way primed rather than playing the prime
  265. // animation from the start.
  266. if ( TimeSinceLastAnimationStateClear() < 0.4f )
  267. m_flGrenadeCycle = 1;
  268. else
  269. m_flGrenadeCycle = 0;
  270. m_iGrenadeSequence = CalcGrenadePrimeSequence();
  271. }
  272. m_bPrimingGrenade = true;
  273. UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );
  274. // If we're waiting to throw and we're done playing the prime animation...
  275. if ( bThrowPending && m_flGrenadeCycle == 1 )
  276. {
  277. m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
  278. // Now play the throw animation.
  279. m_iGrenadeSequence = CalcGrenadeThrowSequence();
  280. if ( m_iGrenadeSequence != -1 )
  281. {
  282. // Configure to start playing
  283. m_bThrowingGrenade = true;
  284. m_bPrimingGrenade = false;
  285. m_flGrenadeCycle = 0;
  286. }
  287. }
  288. }
  289. else
  290. {
  291. m_bPrimingGrenade = false;
  292. }
  293. }
  294. #endif
  295. }
  296. int CSDKPlayerAnimState::CalcGrenadePrimeSequence()
  297. {
  298. return CalcSequenceIndex( "idle_shoot_gren1" );
  299. }
  300. int CSDKPlayerAnimState::CalcGrenadeThrowSequence()
  301. {
  302. return CalcSequenceIndex( "idle_shoot_gren2" );
  303. }
  304. int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter()
  305. {
  306. CSDKPlayer *pPlayer = dynamic_cast<CSDKPlayer*>( m_pOuter );
  307. if ( pPlayer )
  308. return pPlayer->m_iThrowGrenadeCounter;
  309. else
  310. return 0;
  311. }
  312. void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
  313. {
  314. #ifdef CLIENT_DLL
  315. UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false );
  316. #else
  317. // Server doesn't bother with different fire sequences.
  318. #endif
  319. }
  320. int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
  321. {
  322. const char *pSuffix = GetWeaponSuffix();
  323. if ( !pSuffix )
  324. return 0;
  325. if ( bForceIdle )
  326. {
  327. switch ( GetCurrentMainSequenceActivity() )
  328. {
  329. case ACT_CROUCHIDLE:
  330. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
  331. default:
  332. return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
  333. }
  334. }
  335. else
  336. {
  337. switch ( GetCurrentMainSequenceActivity() )
  338. {
  339. case ACT_RUN:
  340. return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );
  341. case ACT_WALK:
  342. case ACT_RUNTOIDLE:
  343. case ACT_IDLETORUN:
  344. return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );
  345. case ACT_CROUCHIDLE:
  346. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
  347. case ACT_RUN_CROUCH:
  348. return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );
  349. case ACT_IDLE:
  350. default:
  351. return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
  352. }
  353. }
  354. }
  355. const char* CSDKPlayerAnimState::GetWeaponSuffix()
  356. {
  357. // Figure out the weapon suffix.
  358. CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
  359. if ( !pWeapon )
  360. return "Pistol";
  361. const char *pSuffix = pWeapon->GetSDKWpnData().m_szAnimExtension;
  362. return pSuffix;
  363. }
  364. int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event)
  365. {
  366. // Figure out the weapon suffix.
  367. CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
  368. if ( !pWeapon )
  369. return 0;
  370. const char *pSuffix = GetWeaponSuffix();
  371. if ( !pSuffix )
  372. return 0;
  373. // Don't rely on their weapon here because the player has usually switched to their
  374. // pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client.
  375. if ( event == PLAYERANIMEVENT_THROW_GRENADE )
  376. {
  377. pSuffix = "Gren";
  378. }
  379. switch ( GetCurrentMainSequenceActivity() )
  380. {
  381. case ACT_PLAYER_RUN_FIRE:
  382. case ACT_RUN:
  383. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );
  384. case ACT_PLAYER_WALK_FIRE:
  385. case ACT_WALK:
  386. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );
  387. case ACT_PLAYER_CROUCH_FIRE:
  388. case ACT_CROUCHIDLE:
  389. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );
  390. case ACT_PLAYER_CROUCH_WALK_FIRE:
  391. case ACT_RUN_CROUCH:
  392. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );
  393. default:
  394. case ACT_PLAYER_IDLE_FIRE:
  395. return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
  396. }
  397. }
  398. bool CSDKPlayerAnimState::CanThePlayerMove()
  399. {
  400. return m_pHelpers->SDKAnim_CanMove();
  401. }
  402. float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed()
  403. {
  404. Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
  405. if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE )
  406. return ANIM_TOPSPEED_WALK;
  407. else if ( currentActivity == ACT_RUN )
  408. return ANIM_TOPSPEED_RUN;
  409. else if ( currentActivity == ACT_RUN_CROUCH )
  410. return ANIM_TOPSPEED_RUN_CROUCH;
  411. else
  412. return 0;
  413. }
  414. bool CSDKPlayerAnimState::HandleJumping()
  415. {
  416. if ( m_bJumping )
  417. {
  418. if ( m_bFirstJumpFrame )
  419. {
  420. m_bFirstJumpFrame = false;
  421. RestartMainSequence(); // Reset the animation.
  422. }
  423. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  424. // on-ground flag set right when the message comes in.
  425. if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
  426. {
  427. if ( m_pOuter->GetFlags() & FL_ONGROUND )
  428. {
  429. m_bJumping = false;
  430. RestartMainSequence(); // Reset the animation.
  431. }
  432. }
  433. }
  434. // Are we still jumping? If so, keep playing the jump animation.
  435. return m_bJumping;
  436. }
  437. Activity CSDKPlayerAnimState::CalcMainActivity()
  438. {
  439. float flOuterSpeed = GetOuterXYSpeed();
  440. if ( HandleJumping() )
  441. {
  442. return ACT_HOP;
  443. }
  444. else
  445. {
  446. Activity idealActivity = ACT_IDLE;
  447. if ( m_pOuter->GetFlags() & FL_DUCKING )
  448. {
  449. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  450. idealActivity = ACT_RUN_CROUCH;
  451. else
  452. idealActivity = ACT_CROUCHIDLE;
  453. }
  454. else
  455. {
  456. if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
  457. {
  458. if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
  459. idealActivity = ACT_RUN;
  460. else
  461. idealActivity = ACT_WALK;
  462. }
  463. else
  464. {
  465. idealActivity = ACT_IDLE;
  466. }
  467. }
  468. return idealActivity;
  469. }
  470. }
  471. void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine )
  472. {
  473. #ifdef CLIENT_DLL
  474. engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
  475. engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
  476. BaseClass::DebugShowAnimState( iStartLine );
  477. #endif
  478. }
  479. void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
  480. {
  481. BaseClass::ComputeSequences( pStudioHdr );
  482. ComputeFireSequence( pStudioHdr );
  483. ComputeReloadSequence( pStudioHdr );
  484. ComputeGrenadeSequence( pStudioHdr );
  485. }
  486. void CSDKPlayerAnimState::ClearAnimationLayers()
  487. {
  488. if ( !m_pOuter )
  489. return;
  490. m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
  491. for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
  492. {
  493. m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
  494. }
  495. }
  496. void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
  497. {
  498. #ifdef CLIENT_DLL
  499. UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
  500. #else
  501. // Server doesn't bother with different fire sequences.
  502. #endif
  503. }