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.

1444 lines
44 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "tier0/vprof.h"
  8. #include "animation.h"
  9. #include "studio.h"
  10. #include "apparent_velocity_helper.h"
  11. #include "utldict.h"
  12. #include "tf_playeranimstate.h"
  13. #include "base_playeranimstate.h"
  14. #include "datacache/imdlcache.h"
  15. #include "tf_gamerules.h"
  16. #include "in_buttons.h"
  17. #include "debugoverlay_shared.h"
  18. #include "tf_weapon_passtime_gun.h"
  19. #ifdef CLIENT_DLL
  20. #include "c_tf_player.h"
  21. #include "c_func_capture_zone.h"
  22. #include "tf_gcmessages.h"
  23. #define CCaptureZone C_CaptureZone
  24. #else
  25. #include "tf_player.h"
  26. #include "func_capture_zone.h"
  27. #endif
  28. #define TF_RUN_SPEED 320.0f
  29. #define TF_WALK_SPEED 75.0f
  30. #define TF_CROUCHWALK_SPEED 110.0f
  31. //-----------------------------------------------------------------------------
  32. // Purpose:
  33. // Input : *pPlayer -
  34. // Output : CMultiPlayerAnimState*
  35. //-----------------------------------------------------------------------------
  36. CTFPlayerAnimState* CreateTFPlayerAnimState( CTFPlayer *pPlayer )
  37. {
  38. MDLCACHE_CRITICAL_SECTION();
  39. // Setup the movement data.
  40. MultiPlayerMovementData_t movementData;
  41. movementData.m_flBodyYawRate = 720.0f;
  42. movementData.m_flRunSpeed = TF_RUN_SPEED;
  43. movementData.m_flWalkSpeed = TF_WALK_SPEED;
  44. movementData.m_flSprintSpeed = -1.0f;
  45. // Create animation state for this player.
  46. CTFPlayerAnimState *pRet = new CTFPlayerAnimState( pPlayer, movementData );
  47. // Specific TF player initialization.
  48. pRet->InitTF( pPlayer );
  49. return pRet;
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose:
  53. // Input : -
  54. //-----------------------------------------------------------------------------
  55. CTFPlayerAnimState::CTFPlayerAnimState()
  56. {
  57. m_pTFPlayer = NULL;
  58. // Don't initialize TF specific variables here. Init them in InitTF()
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose:
  62. // Input : *pPlayer -
  63. // &movementData -
  64. //-----------------------------------------------------------------------------
  65. CTFPlayerAnimState::CTFPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData )
  66. : CMultiPlayerAnimState( pPlayer, movementData )
  67. {
  68. m_pTFPlayer = NULL;
  69. // Don't initialize TF specific variables here. Init them in InitTF()
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose:
  73. // Input : -
  74. //-----------------------------------------------------------------------------
  75. CTFPlayerAnimState::~CTFPlayerAnimState()
  76. {
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Initialize Team Fortress specific animation state.
  80. // Input : *pPlayer -
  81. //-----------------------------------------------------------------------------
  82. void CTFPlayerAnimState::InitTF( CTFPlayer *pPlayer )
  83. {
  84. m_pTFPlayer = pPlayer;
  85. m_bInAirWalk = false;
  86. m_flHoldDeployedPoseUntilTime = 0.0f;
  87. m_flTauntMoveX = 0.f;
  88. m_flTauntMoveY = 0.f;
  89. m_vecSmoothedUp = Vector( 0.f, 0.f, 1.f );
  90. m_flVehicleLeanVel = 0.f;
  91. m_flVehicleLeanPos = 0.f;
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Purpose:
  95. //-----------------------------------------------------------------------------
  96. void CTFPlayerAnimState::ClearAnimationState( void )
  97. {
  98. m_bInAirWalk = false;
  99. BaseClass::ClearAnimationState();
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. // Input : actDesired -
  104. // Output : Activity
  105. //-----------------------------------------------------------------------------
  106. Activity CTFPlayerAnimState::TranslateActivity( Activity actDesired )
  107. {
  108. Activity translateActivity = BaseClass::TranslateActivity( actDesired );
  109. translateActivity = ActivityOverride( translateActivity, NULL );
  110. CBaseCombatWeapon *pWeapon = GetTFPlayer()->GetActiveWeapon();
  111. if ( pWeapon )
  112. {
  113. translateActivity = pWeapon->ActivityOverride( translateActivity, NULL );
  114. CEconItemView *pEconItemView = pWeapon->GetAttributeContainer()->GetItem();
  115. if ( pEconItemView )
  116. {
  117. translateActivity = pEconItemView->GetStaticData()->GetActivityOverride( GetTFPlayer()->GetTeamNumber(), translateActivity );
  118. }
  119. }
  120. CTFPlayer *pPlayer = GetTFPlayer();
  121. if ( pPlayer->m_Shared.InCond( TF_COND_COMPETITIVE_WINNER ) )
  122. {
  123. if ( translateActivity == ACT_MP_STAND_PRIMARY ||
  124. ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) && ( translateActivity == ACT_MP_STAND_MELEE ) ) ||
  125. ( pPlayer->IsPlayerClass( TF_CLASS_DEMOMAN ) && ( translateActivity == ACT_MP_STAND_SECONDARY ) ) )
  126. {
  127. translateActivity = ACT_MP_COMPETITIVE_WINNERSTATE;
  128. }
  129. }
  130. return translateActivity;
  131. }
  132. static acttable_t s_acttableKartState[] =
  133. {
  134. { ACT_MP_STAND_IDLE, ACT_KART_IDLE, false },
  135. { ACT_MP_RUN, ACT_KART_IDLE, false },
  136. { ACT_MP_WALK, ACT_KART_IDLE, false },
  137. { ACT_MP_AIRWALK, ACT_KART_IDLE, false },
  138. { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_KART_ACTION_SHOOT, false },
  139. { ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE, ACT_KART_ACTION_SHOOT, false },
  140. { ACT_MP_JUMP_START, ACT_KART_JUMP_START, false },
  141. { ACT_MP_JUMP_FLOAT, ACT_KART_JUMP_FLOAT, false },
  142. { ACT_MP_JUMP_LAND, ACT_KART_JUMP_LAND, false },
  143. };
  144. static acttable_t s_acttableLoserState[] =
  145. {
  146. { ACT_MP_STAND_IDLE, ACT_MP_STAND_LOSERSTATE, false },
  147. { ACT_MP_CROUCH_IDLE, ACT_MP_CROUCH_LOSERSTATE, false },
  148. { ACT_MP_RUN, ACT_MP_RUN_LOSERSTATE, false },
  149. { ACT_MP_WALK, ACT_MP_WALK_LOSERSTATE, false },
  150. { ACT_MP_AIRWALK, ACT_MP_AIRWALK_LOSERSTATE, false },
  151. { ACT_MP_CROUCHWALK, ACT_MP_CROUCHWALK_LOSERSTATE, false },
  152. { ACT_MP_JUMP, ACT_MP_JUMP_LOSERSTATE, false },
  153. { ACT_MP_JUMP_START, ACT_MP_JUMP_START_LOSERSTATE, false },
  154. { ACT_MP_JUMP_FLOAT, ACT_MP_JUMP_FLOAT_LOSERSTATE, false },
  155. { ACT_MP_JUMP_LAND, ACT_MP_JUMP_LAND_LOSERSTATE, false },
  156. { ACT_MP_SWIM, ACT_MP_SWIM_LOSERSTATE, false },
  157. { ACT_MP_DOUBLEJUMP_CROUCH, ACT_MP_DOUBLEJUMP_CROUCH_LOSERSTATE,false },
  158. };
  159. static acttable_t s_acttableCompetitiveLoserState[] =
  160. {
  161. { ACT_MP_STAND_IDLE, ACT_MP_COMPETITIVE_LOSERSTATE, false },
  162. };
  163. static acttable_t s_acttableBuildingDeployed[] =
  164. {
  165. { ACT_MP_STAND_IDLE, ACT_MP_STAND_BUILDING_DEPLOYED, false },
  166. { ACT_MP_CROUCH_IDLE, ACT_MP_CROUCH_BUILDING_DEPLOYED, false },
  167. { ACT_MP_RUN, ACT_MP_RUN_BUILDING_DEPLOYED, false },
  168. { ACT_MP_WALK, ACT_MP_WALK_BUILDING_DEPLOYED, false },
  169. { ACT_MP_AIRWALK, ACT_MP_AIRWALK_BUILDING_DEPLOYED, false },
  170. { ACT_MP_CROUCHWALK, ACT_MP_CROUCHWALK_BUILDING_DEPLOYED, false },
  171. { ACT_MP_JUMP, ACT_MP_JUMP_BUILDING_DEPLOYED, false },
  172. { ACT_MP_JUMP_START, ACT_MP_JUMP_START_BUILDING_DEPLOYED, false },
  173. { ACT_MP_JUMP_FLOAT, ACT_MP_JUMP_FLOAT_BUILDING_DEPLOYED, false },
  174. { ACT_MP_JUMP_LAND, ACT_MP_JUMP_LAND_BUILDING_DEPLOYED, false },
  175. { ACT_MP_SWIM, ACT_MP_SWIM_BUILDING_DEPLOYED, false },
  176. { ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_MP_ATTACK_STAND_BUILDING_DEPLOYED, false },
  177. { ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_MP_ATTACK_CROUCH_BUILDING_DEPLOYED, false },
  178. { ACT_MP_ATTACK_SWIM_PRIMARYFIRE, ACT_MP_ATTACK_SWIM_BUILDING_DEPLOYED, false },
  179. { ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE, ACT_MP_ATTACK_AIRWALK_BUILDING_DEPLOYED, false },
  180. { ACT_MP_ATTACK_STAND_GRENADE, ACT_MP_ATTACK_STAND_GRENADE_BUILDING_DEPLOYED, false },
  181. { ACT_MP_ATTACK_CROUCH_GRENADE, ACT_MP_ATTACK_STAND_GRENADE_BUILDING_DEPLOYED, false },
  182. { ACT_MP_ATTACK_SWIM_GRENADE, ACT_MP_ATTACK_STAND_GRENADE_BUILDING_DEPLOYED, false },
  183. { ACT_MP_ATTACK_AIRWALK_GRENADE, ACT_MP_ATTACK_STAND_GRENADE_BUILDING_DEPLOYED, false },
  184. { ACT_MP_GESTURE_VC_HANDMOUTH, ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING, false },
  185. { ACT_MP_GESTURE_VC_FINGERPOINT, ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING, false },
  186. { ACT_MP_GESTURE_VC_FISTPUMP, ACT_MP_GESTURE_VC_FISTPUMP_BUILDING, false },
  187. { ACT_MP_GESTURE_VC_THUMBSUP, ACT_MP_GESTURE_VC_THUMBSUP_BUILDING, false },
  188. { ACT_MP_GESTURE_VC_NODYES, ACT_MP_GESTURE_VC_NODYES_BUILDING, false },
  189. { ACT_MP_GESTURE_VC_NODNO, ACT_MP_GESTURE_VC_NODNO_BUILDING, false },
  190. };
  191. Activity CTFPlayerAnimState::ActivityOverride( Activity baseAct, bool *pRequired )
  192. {
  193. acttable_t *pTable = NULL;
  194. int iActivityCount = 0;
  195. CTFPlayer *pPlayer = GetTFPlayer();
  196. // Override if we're in a kart
  197. if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_KART ) )
  198. {
  199. pTable = s_acttableKartState;
  200. iActivityCount = ARRAYSIZE( s_acttableKartState );
  201. }
  202. else
  203. {
  204. if ( pPlayer->m_Shared.InCond( TF_COND_COMPETITIVE_LOSER ) )
  205. {
  206. iActivityCount = ARRAYSIZE( s_acttableCompetitiveLoserState );
  207. pTable = s_acttableCompetitiveLoserState;
  208. }
  209. else if ( pPlayer->m_Shared.IsLoser() )
  210. {
  211. iActivityCount = ARRAYSIZE( s_acttableLoserState );
  212. pTable = s_acttableLoserState;
  213. }
  214. else if ( pPlayer->m_Shared.IsCarryingObject() )
  215. {
  216. iActivityCount = ARRAYSIZE( s_acttableBuildingDeployed );
  217. pTable = s_acttableBuildingDeployed;
  218. }
  219. }
  220. for ( int i = 0; i < iActivityCount; i++ )
  221. {
  222. const acttable_t& act = pTable[i];
  223. if ( baseAct == act.baseAct )
  224. {
  225. if (pRequired)
  226. {
  227. *pRequired = act.required;
  228. }
  229. return (Activity)act.weaponAct;
  230. }
  231. }
  232. return baseAct;
  233. }
  234. //-----------------------------------------------------------------------------
  235. // Purpose:
  236. //-----------------------------------------------------------------------------
  237. bool CTFPlayerAnimState::ShouldUpdateAnimState( void )
  238. {
  239. CTFPlayer *pTFPlayer = GetTFPlayer();
  240. if ( pTFPlayer )
  241. {
  242. // Stop animating if we have a custom player model that doesn't use the normal class animations
  243. if ( pTFPlayer->GetPlayerClass()->HasCustomModel() && !pTFPlayer->GetPlayerClass()->CustomModelUsesClassAnimations() )
  244. return false;
  245. }
  246. return BaseClass::ShouldUpdateAnimState();
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose:
  250. //-----------------------------------------------------------------------------
  251. void CTFPlayerAnimState::GetOuterAbsVelocity( Vector& vel )
  252. {
  253. #ifdef CLIENT_DLL
  254. if ( IsItemTestingBot() )
  255. {
  256. switch ( TFGameRules()->ItemTesting_GetBotAnim() )
  257. {
  258. default:
  259. case TI_BOTANIM_IDLE:
  260. case TI_BOTANIM_CROUCH:
  261. case TI_BOTANIM_JUMP:
  262. break;
  263. case TI_BOTANIM_CROUCH_WALK:
  264. case TI_BOTANIM_RUN:
  265. {
  266. QAngle angles( 0, 0, 0 );
  267. angles[YAW] = m_angRender[YAW];
  268. Vector vForward, vRight, vUp;
  269. AngleVectors( angles, &vForward, &vRight, &vUp );
  270. vel = vForward * GetCurrentMaxGroundSpeed();
  271. }
  272. break;
  273. }
  274. return;
  275. }
  276. #endif
  277. BaseClass::GetOuterAbsVelocity( vel );
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose:
  281. //-----------------------------------------------------------------------------
  282. void CTFPlayerAnimState::Update( float eyeYaw, float eyePitch )
  283. {
  284. // Profile the animation update.
  285. VPROF( "CMultiPlayerAnimState::Update" );
  286. // Get the TF player.
  287. CTFPlayer *pTFPlayer = GetTFPlayer();
  288. if ( !pTFPlayer )
  289. return;
  290. // Get the studio header for the player.
  291. CStudioHdr *pStudioHdr = pTFPlayer->GetModelPtr();
  292. if ( !pStudioHdr )
  293. return;
  294. if ( pTFPlayer->GetPlayerClass()->HasCustomModel() )
  295. {
  296. if ( !pTFPlayer->GetPlayerClass()->CustomModelUsesClassAnimations() )
  297. {
  298. if ( pTFPlayer->GetPlayerClass()->CustomModelRotates() )
  299. {
  300. if ( pTFPlayer->GetPlayerClass()->CustomModelRotationSet() )
  301. {
  302. QAngle angRot = pTFPlayer->GetPlayerClass()->GetCustomModelRotation();
  303. m_angRender = angRot;
  304. }
  305. else
  306. {
  307. m_angRender = vec3_angle;
  308. m_angRender[YAW] = AngleNormalize( eyeYaw );
  309. }
  310. }
  311. // Restart our animation whenever we change models
  312. if ( pTFPlayer->GetPlayerClass()->CustomModelHasChanged() )
  313. {
  314. RestartMainSequence();
  315. }
  316. ClearAnimationState();
  317. return;
  318. }
  319. }
  320. // Check to see if we should be updating the animation state - dead, ragdolled?
  321. if ( !ShouldUpdateAnimState() )
  322. {
  323. ClearAnimationState();
  324. return;
  325. }
  326. // Store the eye angles.
  327. m_flEyeYaw = AngleNormalize( eyeYaw );
  328. m_flEyePitch = AngleNormalize( eyePitch );
  329. // Compute the player sequences.
  330. ComputeSequences( pStudioHdr );
  331. CTFPlayer *pTauntPartner = pTFPlayer->GetTauntPartner();
  332. Vector vPositionToFace = ( pTauntPartner ? pTauntPartner->GetAbsOrigin() : vec3_origin );
  333. bool bInTaunt = pTFPlayer->m_Shared.InCond( TF_COND_TAUNTING );
  334. bool bInKart = pTFPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_KART );
  335. bool bIsImmobilized = bInTaunt || pTFPlayer->m_Shared.IsControlStunned();
  336. if ( SetupPoseParameters( pStudioHdr ) )
  337. {
  338. if ( !bIsImmobilized )
  339. {
  340. // Pose parameter - what direction are the player's legs running in.
  341. ComputePoseParam_MoveYaw( pStudioHdr );
  342. }
  343. if ( bInTaunt )
  344. {
  345. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between
  346. // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window,
  347. // and the fact that m_flEyeYaw is never propogated from the server to the client.
  348. // TODO: Fix this after Halloween 2014.
  349. m_bForceAimYaw = true;
  350. m_flEyeYaw = pTFPlayer->GetTauntYaw();
  351. Taunt_ComputePoseParam_MoveX( pStudioHdr );
  352. Taunt_ComputePoseParam_MoveY( pStudioHdr );
  353. }
  354. else if ( bInKart )
  355. {
  356. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between
  357. // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window,
  358. // and the fact that m_flEyeYaw is never propogated from the server to the client.
  359. // TODO: Fix this after Halloween 2014.
  360. m_bForceAimYaw = true; // This makes it so our "legs" dont lag behind our eyes when standing still.
  361. Vehicle_ComputePoseParam_MoveYaw( pStudioHdr );
  362. Vehicle_ComputePoseParam_AccelLean( pStudioHdr );
  363. // Trace down a bit for the ground
  364. trace_t tr;
  365. //UTIL_TraceLine( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() - Vector(0,0,20), MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
  366. UTIL_TraceLine( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() - Vector(0,0,64), MASK_SOLID, pTFPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
  367. // Use the ground normal if we hit, else abs up
  368. Vector vSurfaceNormal = tr.DidHit() ? tr.plane.normal : Vector( 0.f, 0.f, 1.f );
  369. // Have smoothed up approach the surface normal
  370. m_vecSmoothedUp[ 0 ] = Approach( vSurfaceNormal[ 0 ], m_vecSmoothedUp[ 0 ], 0.2f * gpGlobals->frametime );
  371. m_vecSmoothedUp[ 1 ] = Approach( vSurfaceNormal[ 1 ], m_vecSmoothedUp[ 1 ], 0.2f * gpGlobals->frametime );
  372. m_vecSmoothedUp[ 2 ] = Approach( vSurfaceNormal[ 2 ], m_vecSmoothedUp[ 2 ], 0.2f * gpGlobals->frametime );
  373. // Get player's forward
  374. Vector vOldForward;
  375. QAngle vTauntAngles = pTFPlayer->GetAbsAngles();
  376. vTauntAngles[ YAW ] = pTFPlayer->GetTauntYaw();
  377. AngleVectors( vTauntAngles, &vOldForward, NULL, NULL );
  378. // Construct basis
  379. Vector vRight = vOldForward.Cross( m_vecSmoothedUp );
  380. Vector vForward = m_vecSmoothedUp.Cross( vRight );
  381. // Set angles
  382. VectorAngles( vForward, m_vecSmoothedUp, m_angRender );
  383. #if 0
  384. if ( tr.DidHit() )
  385. {
  386. #ifdef GAME_DLL
  387. NDebugOverlay::Line( tr.endpos, tr.endpos + tr.plane.normal * 100, 255, 0, 0, true, 1.f );
  388. NDebugOverlay::Line( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() + m_vecSmoothedUp * 100, 255, 0, 0, true, 1.f );
  389. NDebugOverlay::Line( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() + vForward * 100, 255, 0, 0, true, 1.f );
  390. #else
  391. NDebugOverlay::Line( tr.endpos, tr.endpos + tr.plane.normal * 100, 0, 0, 255, true, 1.f );
  392. NDebugOverlay::Line( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() + m_vecSmoothedUp * 100, 0, 0, 255, true, 1.f );
  393. NDebugOverlay::Line( pTFPlayer->GetAbsOrigin(), pTFPlayer->GetAbsOrigin() + vForward * 100, 0, 0, 255, true, 1.f );
  394. #endif
  395. }
  396. #endif
  397. }
  398. else if ( TFGameRules()->PlayersAreOnMatchSummaryStage() )
  399. {
  400. m_bForceAimYaw = true;
  401. m_flEyeYaw = pTFPlayer->GetTauntYaw();
  402. }
  403. if ( !bIsImmobilized || bInTaunt || bInKart )
  404. {
  405. // Pose parameter - Torso aiming (up/down).
  406. ComputePoseParam_AimPitch( pStudioHdr );
  407. // Pose parameter - Torso aiming (rotation).
  408. ComputePoseParam_AimYaw( pStudioHdr );
  409. }
  410. }
  411. #ifdef CLIENT_DLL
  412. if ( C_BasePlayer::ShouldDrawLocalPlayer() )
  413. {
  414. GetBasePlayer()->SetPlaybackRate( 1.0f );
  415. }
  416. if ( IsItemTestingBot() )
  417. {
  418. GetBasePlayer()->SetPlaybackRate( TFGameRules()->ItemTesting_GetBotAnimSpeed() );
  419. }
  420. #endif
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Updates animation state if we are throwing the passtime ball
  424. //-----------------------------------------------------------------------------
  425. void CTFPlayerAnimState::CheckPasstimeThrowAnimation()
  426. {
  427. CTFPlayer *pPlayer = GetTFPlayer();
  428. if ( !pPlayer )
  429. {
  430. return;
  431. }
  432. // FIXME: there must be a better way of doing this...
  433. CPasstimeGun *pGun = dynamic_cast< CPasstimeGun * >( pPlayer->GetEntityForLoadoutSlot( LOADOUT_POSITION_UTILITY ) );
  434. if ( !pGun )
  435. {
  436. return;
  437. }
  438. if ( pGun->GetCurrentCharge() > 0 )
  439. {
  440. if ( pPlayer->m_Shared.m_iPasstimeThrowAnimState == PASSTIME_THROW_ANIM_NONE )
  441. {
  442. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_PASSTIME_THROW_BEGIN );
  443. pPlayer->m_Shared.m_flPasstimeThrowAnimStateTime = gpGlobals->curtime + pPlayer->SequenceDuration( iSeq );
  444. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PASSTIME_THROW_BEGIN );
  445. pPlayer->m_Shared.m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_LOOP;
  446. }
  447. else if ( pPlayer->m_Shared.m_iPasstimeThrowAnimState == PASSTIME_THROW_ANIM_LOOP )
  448. {
  449. if ( gpGlobals->curtime > pPlayer->m_Shared.m_flPasstimeThrowAnimStateTime )
  450. {
  451. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_PASSTIME_THROW_MIDDLE );
  452. pPlayer->m_Shared.m_flPasstimeThrowAnimStateTime = gpGlobals->curtime + pPlayer->SequenceDuration( iSeq );
  453. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PASSTIME_THROW_MIDDLE );
  454. }
  455. }
  456. }
  457. else // not charging
  458. {
  459. if ( pPlayer->m_Shared.m_iPasstimeThrowAnimState == PASSTIME_THROW_ANIM_CANCEL )
  460. {
  461. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PASSTIME_THROW_CANCEL );
  462. pPlayer->m_Shared.m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_NONE;
  463. }
  464. else if ( pPlayer->m_Shared.m_iPasstimeThrowAnimState == PASSTIME_THROW_ANIM_LOOP )
  465. {
  466. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_PASSTIME_THROW_END );
  467. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_PASSTIME_THROW_END );
  468. pPlayer->m_Shared.m_flPasstimeThrowAnimStateTime = gpGlobals->curtime + pPlayer->SequenceDuration( iSeq );
  469. pPlayer->m_Shared.m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_END;
  470. }
  471. else if ( pPlayer->m_Shared.m_iPasstimeThrowAnimState == PASSTIME_THROW_ANIM_END )
  472. {
  473. if ( gpGlobals->curtime > pPlayer->m_Shared.m_flPasstimeThrowAnimStateTime )
  474. {
  475. pPlayer->m_Shared.m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_NONE;
  476. }
  477. }
  478. }
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: Updates animation state if we're stunned.
  482. //-----------------------------------------------------------------------------
  483. void CTFPlayerAnimState::CheckStunAnimation()
  484. {
  485. CTFPlayer *pPlayer = GetTFPlayer();
  486. if ( !pPlayer )
  487. return;
  488. // do not play stun anims if in kart
  489. if ( pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_KART ) )
  490. return;
  491. // State machine to determine the correct stun activity.
  492. if ( !pPlayer->m_Shared.IsControlStunned() &&
  493. (pPlayer->m_Shared.m_iStunAnimState == STUN_ANIM_LOOP) )
  494. {
  495. // Clean up if the condition went away before we finished.
  496. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_STUN_END );
  497. pPlayer->m_Shared.m_iStunAnimState = STUN_ANIM_NONE;
  498. }
  499. else if ( pPlayer->m_Shared.IsControlStunned() &&
  500. (pPlayer->m_Shared.m_iStunAnimState == STUN_ANIM_NONE) &&
  501. (gpGlobals->curtime < pPlayer->m_Shared.GetStunExpireTime()) )
  502. {
  503. // Play the start up animation.
  504. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_STUN_BEGIN );
  505. pPlayer->m_Shared.m_flStunMid = gpGlobals->curtime + pPlayer->SequenceDuration( iSeq );
  506. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_STUN_BEGIN );
  507. pPlayer->m_Shared.m_iStunAnimState = STUN_ANIM_LOOP;
  508. }
  509. else if ( pPlayer->m_Shared.m_iStunAnimState == STUN_ANIM_LOOP )
  510. {
  511. // We are playing the looping part of the stun animation cycle.
  512. if ( gpGlobals->curtime > pPlayer->m_Shared.m_flStunFade )
  513. {
  514. // Gameplay is telling us to fade out. Time for the end anim.
  515. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_STUN_END );
  516. pPlayer->m_Shared.SetStunExpireTime( gpGlobals->curtime + pPlayer->SequenceDuration( iSeq ) );
  517. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_STUN_END );
  518. pPlayer->m_Shared.m_iStunAnimState = STUN_ANIM_END;
  519. }
  520. else if ( gpGlobals->curtime > pPlayer->m_Shared.m_flStunMid )
  521. {
  522. // Loop again.
  523. int iSeq = pPlayer->SelectWeightedSequence( ACT_MP_STUN_MIDDLE );
  524. pPlayer->m_Shared.m_flStunMid = gpGlobals->curtime + pPlayer->SequenceDuration( iSeq );
  525. pPlayer->DoAnimationEvent( PLAYERANIMEVENT_STUN_MIDDLE );
  526. }
  527. }
  528. else if ( pPlayer->m_Shared.m_iStunAnimState == STUN_ANIM_END )
  529. {
  530. if ( gpGlobals->curtime > pPlayer->m_Shared.GetStunExpireTime() )
  531. {
  532. // The animation loop is over.
  533. pPlayer->m_Shared.m_iStunAnimState = STUN_ANIM_NONE;
  534. }
  535. }
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. //-----------------------------------------------------------------------------
  540. Activity CTFPlayerAnimState::CalcMainActivity()
  541. {
  542. CheckStunAnimation();
  543. CheckPasstimeThrowAnimation();
  544. #ifdef CLIENT_DLL
  545. bool bIsAiming = m_pTFPlayer->m_Shared.IsAiming();
  546. if ( IsItemTestingBot() )
  547. {
  548. switch ( TFGameRules()->ItemTesting_GetBotAnim() )
  549. {
  550. default:
  551. case TI_BOTANIM_JUMP:
  552. break;
  553. case TI_BOTANIM_IDLE:
  554. if ( bIsAiming )
  555. return ACT_MP_DEPLOYED_IDLE;
  556. return ACT_MP_STAND_IDLE;
  557. case TI_BOTANIM_CROUCH:
  558. if ( bIsAiming )
  559. return ACT_MP_CROUCH_DEPLOYED_IDLE;
  560. return ACT_MP_CROUCH_IDLE;
  561. case TI_BOTANIM_CROUCH_WALK:
  562. if ( bIsAiming )
  563. return ACT_MP_CROUCH_DEPLOYED;
  564. return ACT_MP_CROUCHWALK;
  565. case TI_BOTANIM_RUN:
  566. if ( bIsAiming )
  567. return ACT_MP_DEPLOYED;
  568. return ACT_MP_RUN;
  569. }
  570. }
  571. #endif
  572. return BaseClass::CalcMainActivity();
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Purpose:
  576. //-----------------------------------------------------------------------------
  577. void CTFPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr )
  578. {
  579. if ( IsItemTestingBot() )
  580. {
  581. if ( TFGameRules()->ItemTesting_GetBotViewScan() )
  582. {
  583. static float flDeltaYaw = 0.4f;
  584. static float flCurrentYaw = 0.0f;
  585. static float flDeltaPitch = 0.4f;
  586. static float flCurrentPitch = 0.0f;
  587. // Pan left & right
  588. flCurrentYaw = flCurrentYaw + ( flDeltaYaw * TFGameRules()->ItemTesting_GetBotAnimSpeed() );
  589. if ( fabs(flCurrentYaw) >= 45 )
  590. {
  591. flDeltaYaw *= -1;
  592. }
  593. flCurrentYaw = AngleNormalize( flCurrentYaw );
  594. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimYaw, -flCurrentYaw );
  595. // Pan up & down
  596. flCurrentPitch = AngleNormalize( flCurrentPitch + ( flDeltaPitch * TFGameRules()->ItemTesting_GetBotAnimSpeed() ) );
  597. if ( fabs(flCurrentPitch) >= 150 )
  598. {
  599. flDeltaPitch *= -1;
  600. }
  601. flCurrentPitch = AngleNormalize( flCurrentPitch );
  602. flCurrentPitch = clamp(flCurrentPitch, -45.f, 90.f );
  603. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimPitch, -flCurrentPitch );
  604. return;
  605. }
  606. // Rotating on the spot?
  607. if ( TFGameRules()->ItemTesting_GetBotTurntable() )
  608. {
  609. m_flGoalFeetYaw = m_flEyeYaw;
  610. m_flCurrentFeetYaw = m_flGoalFeetYaw;
  611. m_angRender[YAW] = m_flCurrentFeetYaw;
  612. float flAimYaw = m_flEyeYaw - m_flCurrentFeetYaw;
  613. flAimYaw = AngleNormalize( flAimYaw );
  614. GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimYaw, -flAimYaw );
  615. return;
  616. }
  617. }
  618. BaseClass::ComputePoseParam_AimYaw( pStudioHdr );
  619. }
  620. //-----------------------------------------------------------------------------
  621. // Purpose:
  622. //-----------------------------------------------------------------------------
  623. void CTFPlayerAnimState::Taunt_ComputePoseParam_MoveX( CStudioHdr *pStudioHdr )
  624. {
  625. CTFPlayer *pTFPlayer = GetTFPlayer();
  626. if ( pTFPlayer->IsTaunting() && pTFPlayer->CanMoveDuringTaunt() )
  627. {
  628. int iMove = 0;
  629. iMove += pTFPlayer->m_nButtons & IN_FORWARD ? 1 : 0;
  630. iMove += pTFPlayer->m_nButtons & IN_BACK ? -1 : 0;
  631. float fl_move_x = 1.f;
  632. if ( pTFPlayer->GetTauntMoveAcceleration() > 0.f )
  633. {
  634. fl_move_x = Sign( iMove ) * ( gpGlobals->frametime / pTFPlayer->GetTauntMoveAcceleration() );
  635. }
  636. // turning?
  637. if ( iMove != 0.f )
  638. {
  639. m_flTauntMoveX = clamp( m_flTauntMoveX + fl_move_x, -1.f, 1.f );
  640. }
  641. else if ( m_flTauntMoveX != 0.f )
  642. {
  643. // smooth the value back to 0
  644. if ( m_flTauntMoveX < 0.f )
  645. {
  646. m_flTauntMoveX = clamp( m_flTauntMoveX + fabs( fl_move_x ), -1.f, 0.f );
  647. }
  648. if ( m_flTauntMoveX > 0.f )
  649. {
  650. m_flTauntMoveX = clamp( m_flTauntMoveX - fabs( fl_move_x ), 0.f, 1.f );
  651. }
  652. }
  653. }
  654. else
  655. {
  656. m_flTauntMoveX = 0.f;
  657. }
  658. pTFPlayer->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, Sign( m_flTauntMoveX ) * SimpleSpline( fabs( m_flTauntMoveX ) ) );
  659. }
  660. //-----------------------------------------------------------------------------
  661. // Purpose:
  662. //-----------------------------------------------------------------------------
  663. void CTFPlayerAnimState::Taunt_ComputePoseParam_MoveY( CStudioHdr *pStudioHdr )
  664. {
  665. CTFPlayer *pTFPlayer = GetTFPlayer();
  666. if ( pTFPlayer->IsTaunting() && pTFPlayer->CanMoveDuringTaunt() )
  667. {
  668. float flTauntYawDiff = pTFPlayer->GetTauntYaw() - pTFPlayer->GetPrevTauntYaw();
  669. float fl_move_y = 1.f;
  670. if ( pTFPlayer->GetTauntTurnAccelerationTime() > 0.f )
  671. {
  672. fl_move_y = Sign( flTauntYawDiff ) * ( gpGlobals->frametime / pTFPlayer->GetTauntTurnAccelerationTime() );
  673. }
  674. // turning?
  675. if ( flTauntYawDiff != 0.f )
  676. {
  677. m_flTauntMoveY = clamp( m_flTauntMoveY + fl_move_y, -1.f, 1.f );
  678. }
  679. else if ( m_flTauntMoveY != 0.f )
  680. {
  681. // smooth the value back to 0
  682. if ( m_flTauntMoveY < 0.f )
  683. {
  684. m_flTauntMoveY = clamp( m_flTauntMoveY + fabs( fl_move_y ), -1.f, 0.f );
  685. }
  686. if ( m_flTauntMoveY > 0.f )
  687. {
  688. m_flTauntMoveY = clamp( m_flTauntMoveY - fabs( fl_move_y ), 0.f, 1.f );
  689. }
  690. }
  691. }
  692. else
  693. {
  694. m_flTauntMoveY = 0.f;
  695. }
  696. pTFPlayer->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, Sign( m_flTauntMoveY ) * SimpleSpline( fabs( m_flTauntMoveY ) ) );
  697. }
  698. extern ConVar tf_halloween_kart_slow_turn_accel_speed;
  699. void CTFPlayerAnimState::Vehicle_ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
  700. {
  701. float flValue = -m_pTFPlayer->m_Shared.GetVehicleTurnPoseAmount() / tf_halloween_kart_slow_turn_accel_speed.GetFloat();
  702. if ( m_pTFPlayer->GetTauntMoveSpeed() < 0.f )
  703. {
  704. flValue = -flValue;
  705. }
  706. flValue *= 0.5f;
  707. #ifdef DEBUG
  708. #ifdef CLIENT_DLL
  709. engine->Con_NPrintf( 10, "CLIENT Pose: %3.2f", flValue );
  710. #else
  711. engine->Con_NPrintf( 11, "SERVER Pose: %3.2f", flValue );
  712. #endif
  713. #endif
  714. m_pTFPlayer->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, flValue );
  715. }
  716. extern ConVar tf_halloween_kart_dash_speed;
  717. extern ConVar tf_halloween_kart_brake_speed;
  718. void CTFPlayerAnimState::Vehicle_ComputePoseParam_AccelLean( CStudioHdr *pStudioHdr )
  719. {
  720. m_pTFPlayer->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, m_flVehicleLeanPos );
  721. }
  722. void CTFPlayerAnimState::Vehicle_LeanAccel( float flInAccel )
  723. {
  724. // Accelerate our lean vel
  725. float flDiff = flInAccel - m_flVehicleLeanPos;
  726. float flAccel = 0.1f * flDiff - 1.5f * m_flVehicleLeanVel;
  727. m_flVehicleLeanVel += flAccel * gpGlobals->frametime;
  728. // Move our lean pos by our lean vel
  729. m_flVehicleLeanPos += m_flVehicleLeanVel * gpGlobals->frametime;
  730. // Decay it a bit
  731. m_flVehicleLeanPos -= m_flVehicleLeanPos * 0.1f;
  732. m_flVehicleLeanPos = clamp( m_flVehicleLeanPos, -1.f, 1.f );
  733. #ifdef DEBUG
  734. #ifdef CLIENT_DLL
  735. engine->Con_NPrintf( 16, "CLIENT Acc: %.2f Vel: %.2f Pose: %.2f", flAccel, m_flVehicleLeanVel, m_flVehicleLeanPos );
  736. #else
  737. engine->Con_NPrintf( 17, "SERVER Acc: %.2f Vel: %.2f Pose: %.2f", flAccel, m_flVehicleLeanVel, m_flVehicleLeanPos );
  738. #endif
  739. #endif
  740. }
  741. //-----------------------------------------------------------------------------
  742. // Purpose:
  743. //-----------------------------------------------------------------------------
  744. void CTFPlayerAnimState::RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill )
  745. {
  746. Activity translatedActivity = iGestureActivity;
  747. CTFPlayer *pPlayer = GetTFPlayer();
  748. if ( pPlayer )
  749. {
  750. // Allow the weapon to override the activity.
  751. CTFWeaponBase *pWeapon = pPlayer->GetActiveTFWeapon();
  752. if ( pWeapon )
  753. {
  754. CEconItemView *pWeaponEconItemView = pWeapon->GetAttributeContainer()->GetItem();
  755. if ( pWeaponEconItemView )
  756. {
  757. translatedActivity = pWeaponEconItemView->GetStaticData()->GetActivityOverride( pPlayer->GetTeamNumber(), translatedActivity );
  758. }
  759. }
  760. }
  761. BaseClass::RestartGesture( iGestureSlot, translatedActivity, bAutoKill );
  762. }
  763. //-----------------------------------------------------------------------------
  764. // Purpose:
  765. // Input : event -
  766. //-----------------------------------------------------------------------------
  767. void CTFPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
  768. {
  769. bool bInDuck = ( m_pTFPlayer->GetFlags() & FL_DUCKING ) ? true : false;
  770. if ( bInDuck && SelectWeightedSequence( TranslateActivity( ACT_MP_CROUCHWALK ) ) < 0 )
  771. {
  772. bInDuck = false;
  773. }
  774. Activity iGestureActivity = ACT_INVALID;
  775. switch( event )
  776. {
  777. case PLAYERANIMEVENT_ATTACK_PRIMARY:
  778. {
  779. CTFPlayer *pPlayer = GetTFPlayer();
  780. if ( !pPlayer )
  781. return;
  782. CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
  783. bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN );
  784. bool bIsSniperRifle = ( pWpn && WeaponID_IsSniperRifleOrBow( pWpn->GetWeaponID() ) );
  785. // Heavy weapons primary fire.
  786. if ( bIsMinigun )
  787. {
  788. // Play standing primary fire.
  789. iGestureActivity = ACT_MP_ATTACK_STAND_PRIMARYFIRE;
  790. if ( m_bInSwim )
  791. {
  792. // Play swimming primary fire.
  793. iGestureActivity = ACT_MP_ATTACK_SWIM_PRIMARYFIRE;
  794. }
  795. else if ( bInDuck )
  796. {
  797. // Play crouching primary fire.
  798. iGestureActivity = ACT_MP_ATTACK_CROUCH_PRIMARYFIRE;
  799. }
  800. if ( !IsGestureSlotPlaying( GESTURE_SLOT_ATTACK_AND_RELOAD, TranslateActivity(iGestureActivity) ) )
  801. {
  802. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity );
  803. }
  804. }
  805. else if ( bIsSniperRifle && pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) )
  806. {
  807. // Weapon primary fire, zoomed in
  808. if ( bInDuck )
  809. {
  810. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED );
  811. }
  812. else
  813. {
  814. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED );
  815. }
  816. iGestureActivity = ACT_VM_PRIMARYATTACK;
  817. // Hold our deployed pose for a few seconds
  818. m_flHoldDeployedPoseUntilTime = gpGlobals->curtime + 2.0;
  819. }
  820. else
  821. {
  822. Activity baseActivity = bInDuck ? ACT_MP_ATTACK_CROUCH_PRIMARYFIRE : ACT_MP_ATTACK_STAND_PRIMARYFIRE;
  823. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, baseActivity );
  824. // iGestureActivity = ACT_VM_PRIMARYATTACK;
  825. }
  826. break;
  827. }
  828. case PLAYERANIMEVENT_ATTACK_PRIMARY_SUPER:
  829. {
  830. Activity baseActivity = bInDuck ? ACT_MP_ATTACK_CROUCH_PRIMARY_SUPER : ACT_MP_ATTACK_STAND_PRIMARY_SUPER;
  831. if ( m_bInSwim )
  832. baseActivity = ACT_MP_ATTACK_SWIM_PRIMARY_SUPER;
  833. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, baseActivity );
  834. // iGestureActivity = ACT_VM_PRIMARYATTACK;
  835. }
  836. break;
  837. case PLAYERANIMEVENT_VOICE_COMMAND_GESTURE:
  838. {
  839. if ( !IsGestureSlotActive( GESTURE_SLOT_ATTACK_AND_RELOAD ) )
  840. {
  841. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, (Activity)nData );
  842. }
  843. break;
  844. }
  845. case PLAYERANIMEVENT_ATTACK_SECONDARY:
  846. {
  847. Activity baseActivity = bInDuck ? ACT_MP_ATTACK_CROUCH_SECONDARYFIRE : ACT_MP_ATTACK_STAND_SECONDARYFIRE;
  848. if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist )
  849. {
  850. baseActivity = ACT_MP_ATTACK_SWIM_SECONDARYFIRE;
  851. }
  852. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, baseActivity );
  853. iGestureActivity = ACT_VM_SECONDARYATTACK;
  854. break;
  855. }
  856. case PLAYERANIMEVENT_ATTACK_PRE:
  857. {
  858. CTFPlayer *pPlayer = GetTFPlayer();
  859. if ( !pPlayer )
  860. return;
  861. CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
  862. bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN );
  863. bool bAutoKillPreFire = false;
  864. if ( bIsMinigun )
  865. {
  866. bAutoKillPreFire = true;
  867. }
  868. if ( m_bInSwim && bIsMinigun )
  869. {
  870. // Weapon pre-fire. Used for minigun windup while swimming
  871. iGestureActivity = ACT_MP_ATTACK_SWIM_PREFIRE;
  872. }
  873. else if ( bInDuck )
  874. {
  875. // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc in crouch.
  876. iGestureActivity = ACT_MP_ATTACK_CROUCH_PREFIRE;
  877. }
  878. else
  879. {
  880. // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc.
  881. iGestureActivity = ACT_MP_ATTACK_STAND_PREFIRE;
  882. }
  883. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity, bAutoKillPreFire );
  884. break;
  885. }
  886. case PLAYERANIMEVENT_ATTACK_POST:
  887. {
  888. CTFPlayer *pPlayer = GetTFPlayer();
  889. if ( !pPlayer )
  890. return;
  891. CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
  892. bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN );
  893. if ( m_bInSwim && bIsMinigun )
  894. {
  895. // Weapon pre-fire. Used for minigun winddown while swimming
  896. iGestureActivity = ACT_MP_ATTACK_SWIM_POSTFIRE;
  897. }
  898. else if ( bInDuck )
  899. {
  900. // Weapon post-fire. Used for minigun winddown in crouch.
  901. iGestureActivity = ACT_MP_ATTACK_CROUCH_POSTFIRE;
  902. }
  903. else
  904. {
  905. // Weapon post-fire. Used for minigun winddown.
  906. iGestureActivity = ACT_MP_ATTACK_STAND_POSTFIRE;
  907. }
  908. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity );
  909. break;
  910. }
  911. case PLAYERANIMEVENT_RELOAD:
  912. {
  913. // Weapon reload.
  914. if ( m_bInAirWalk )
  915. {
  916. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK );
  917. }
  918. else
  919. {
  920. BaseClass::DoAnimationEvent( event, nData );
  921. }
  922. break;
  923. }
  924. case PLAYERANIMEVENT_RELOAD_LOOP:
  925. {
  926. // Weapon reload.
  927. if ( m_bInAirWalk )
  928. {
  929. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK_LOOP );
  930. }
  931. else
  932. {
  933. BaseClass::DoAnimationEvent( event, nData );
  934. }
  935. break;
  936. }
  937. case PLAYERANIMEVENT_RELOAD_END:
  938. {
  939. // Weapon reload.
  940. if ( m_bInAirWalk )
  941. {
  942. RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK_END );
  943. }
  944. else
  945. {
  946. BaseClass::DoAnimationEvent( event, nData );
  947. }
  948. break;
  949. }
  950. case PLAYERANIMEVENT_DOUBLEJUMP:
  951. {
  952. CTFPlayer *pPlayer = GetTFPlayer();
  953. if ( !pPlayer )
  954. return;
  955. // Check to see if we are jumping!
  956. if ( !m_bJumping )
  957. {
  958. m_bJumping = true;
  959. m_bFirstJumpFrame = true;
  960. m_flJumpStartTime = gpGlobals->curtime;
  961. RestartMainSequence();
  962. }
  963. // Force the air walk off.
  964. m_bInAirWalk = false;
  965. // Player the air dash gesture.
  966. if ( pPlayer->m_Shared.IsLoser() )
  967. {
  968. RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_DOUBLEJUMP_LOSERSTATE );
  969. }
  970. else
  971. {
  972. RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_DOUBLEJUMP );
  973. }
  974. break;
  975. }
  976. case PLAYERANIMEVENT_DOUBLEJUMP_CROUCH:
  977. // RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_DOUBLEJUMP_CROUCH );
  978. // m_aGestureSlots[GESTURE_SLOT_JUMP].m_pAnimLayer->m_flBlendIn = 0.4f;
  979. // m_aGestureSlots[GESTURE_SLOT_JUMP].m_pAnimLayer->m_flBlendOut = 0.4f;
  980. #ifdef CLIENT_DLL
  981. // m_aGestureSlots[GESTURE_SLOT_JUMP].m_pAnimLayer->m_bClientBlend = true;
  982. #endif
  983. break;
  984. case PLAYERANIMEVENT_STUN_BEGIN:
  985. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_STUN_BEGIN, false );
  986. break;
  987. case PLAYERANIMEVENT_STUN_MIDDLE:
  988. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_STUN_MIDDLE, false );
  989. break;
  990. case PLAYERANIMEVENT_STUN_END:
  991. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_STUN_END );
  992. break;
  993. case PLAYERANIMEVENT_PASSTIME_THROW_BEGIN:
  994. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_PASSTIME_THROW_BEGIN, false );
  995. break;
  996. case PLAYERANIMEVENT_PASSTIME_THROW_MIDDLE:
  997. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_PASSTIME_THROW_MIDDLE, false );
  998. break;
  999. case PLAYERANIMEVENT_PASSTIME_THROW_END:
  1000. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_PASSTIME_THROW_END );
  1001. break;
  1002. case PLAYERANIMEVENT_PASSTIME_THROW_CANCEL:
  1003. RestartGesture( GESTURE_SLOT_CUSTOM, ACT_MP_PASSTIME_THROW_CANCEL );
  1004. break;
  1005. default:
  1006. {
  1007. BaseClass::DoAnimationEvent( event, nData );
  1008. break;
  1009. }
  1010. }
  1011. #ifdef CLIENT_DLL
  1012. // Make the weapon play the animation as well
  1013. if ( iGestureActivity != ACT_INVALID )
  1014. {
  1015. CBaseCombatWeapon *pWeapon = GetTFPlayer()->GetActiveWeapon();
  1016. if ( pWeapon )
  1017. {
  1018. pWeapon->SendWeaponAnim( iGestureActivity );
  1019. }
  1020. }
  1021. #endif
  1022. }
  1023. //-----------------------------------------------------------------------------
  1024. // Purpose:
  1025. // Input : *idealActivity -
  1026. //-----------------------------------------------------------------------------
  1027. bool CTFPlayerAnimState::HandleSwimming( Activity &idealActivity )
  1028. {
  1029. bool bInWater = BaseClass::HandleSwimming( idealActivity );
  1030. if ( bInWater )
  1031. {
  1032. if ( m_pTFPlayer->m_Shared.IsAiming() )
  1033. {
  1034. CTFWeaponBase *pWpn = m_pTFPlayer->GetActiveTFWeapon();
  1035. if ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN )
  1036. {
  1037. idealActivity = ACT_MP_SWIM_DEPLOYED;
  1038. }
  1039. // Check for sniper deployed underwater - should only be when standing on something
  1040. else if ( pWpn && WeaponID_IsSniperRifle( pWpn->GetWeaponID() ) )
  1041. {
  1042. if ( m_pTFPlayer->m_Shared.InCond( TF_COND_ZOOMED ) )
  1043. {
  1044. idealActivity = ACT_MP_SWIM_DEPLOYED;
  1045. }
  1046. }
  1047. }
  1048. }
  1049. return bInWater;
  1050. }
  1051. //-----------------------------------------------------------------------------
  1052. // Purpose:
  1053. // Input : *idealActivity -
  1054. // Output : Returns true on success, false on failure.
  1055. //-----------------------------------------------------------------------------
  1056. bool CTFPlayerAnimState::HandleMoving( Activity &idealActivity )
  1057. {
  1058. float flSpeed = GetOuterXYSpeed();
  1059. // If we move, cancel the deployed anim hold
  1060. if ( flSpeed > MOVING_MINIMUM_SPEED )
  1061. {
  1062. m_flHoldDeployedPoseUntilTime = 0.0;
  1063. }
  1064. if ( m_pTFPlayer->m_Shared.IsLoser() )
  1065. {
  1066. return BaseClass::HandleMoving( idealActivity );
  1067. }
  1068. if ( m_pTFPlayer->m_Shared.IsAiming() )
  1069. {
  1070. if ( flSpeed > MOVING_MINIMUM_SPEED )
  1071. {
  1072. idealActivity = ACT_MP_DEPLOYED;
  1073. }
  1074. else
  1075. {
  1076. idealActivity = ACT_MP_DEPLOYED_IDLE;
  1077. }
  1078. }
  1079. else if ( m_flHoldDeployedPoseUntilTime > gpGlobals->curtime )
  1080. {
  1081. // Unless we move, hold the deployed pose for a number of seconds after being deployed
  1082. idealActivity = ACT_MP_DEPLOYED_IDLE;
  1083. }
  1084. else
  1085. {
  1086. return BaseClass::HandleMoving( idealActivity );
  1087. }
  1088. return true;
  1089. }
  1090. //-----------------------------------------------------------------------------
  1091. // Purpose:
  1092. // Input : *idealActivity -
  1093. // Output : Returns true on success, false on failure.
  1094. //-----------------------------------------------------------------------------
  1095. bool CTFPlayerAnimState::HandleDucking( Activity &idealActivity )
  1096. {
  1097. bool bInDuck = ( m_pTFPlayer->GetFlags() & FL_DUCKING ) ? true : false;
  1098. if ( bInDuck && SelectWeightedSequence( TranslateActivity( ACT_MP_CROUCHWALK ) ) < 0 && !m_pTFPlayer->m_Shared.IsLoser() )
  1099. {
  1100. bInDuck = false;
  1101. }
  1102. if ( bInDuck )
  1103. {
  1104. if ( GetOuterXYSpeed() < MOVING_MINIMUM_SPEED || m_pTFPlayer->m_Shared.IsLoser() )
  1105. {
  1106. idealActivity = ACT_MP_CROUCH_IDLE;
  1107. if ( m_pTFPlayer->m_Shared.IsAiming() || m_flHoldDeployedPoseUntilTime > gpGlobals->curtime )
  1108. {
  1109. idealActivity = ACT_MP_CROUCH_DEPLOYED_IDLE;
  1110. }
  1111. }
  1112. else
  1113. {
  1114. if ( m_pTFPlayer->m_Shared.GetAirDash() > 0 )
  1115. {
  1116. idealActivity = ACT_MP_DOUBLEJUMP_CROUCH;
  1117. }
  1118. else
  1119. {
  1120. idealActivity = ACT_MP_CROUCHWALK;
  1121. }
  1122. if ( m_pTFPlayer->m_Shared.IsAiming() )
  1123. {
  1124. // Don't do this for the heavy! we don't usually let him deployed crouch walk
  1125. bool bIsMinigun = false;
  1126. CTFPlayer *pPlayer = GetTFPlayer();
  1127. if ( pPlayer && pPlayer->GetActiveTFWeapon() )
  1128. {
  1129. bIsMinigun = ( pPlayer->GetActiveTFWeapon()->GetWeaponID() == TF_WEAPON_MINIGUN );
  1130. }
  1131. if ( !bIsMinigun )
  1132. {
  1133. idealActivity = ACT_MP_CROUCH_DEPLOYED;
  1134. }
  1135. }
  1136. }
  1137. return true;
  1138. }
  1139. return false;
  1140. }
  1141. //-----------------------------------------------------------------------------
  1142. // Purpose:
  1143. //-----------------------------------------------------------------------------
  1144. float CTFPlayerAnimState::GetCurrentMaxGroundSpeed()
  1145. {
  1146. float flSpeed = BaseClass::GetCurrentMaxGroundSpeed();
  1147. if ( m_pTFPlayer->m_Shared.GetAirDash() > 0 )
  1148. {
  1149. return 1.f;
  1150. }
  1151. else
  1152. {
  1153. return flSpeed;
  1154. }
  1155. }
  1156. //-----------------------------------------------------------------------------
  1157. // Purpose:
  1158. //-----------------------------------------------------------------------------
  1159. float CTFPlayerAnimState::GetGesturePlaybackRate( void )
  1160. {
  1161. if ( IsItemTestingBot() )
  1162. return TFGameRules()->ItemTesting_GetBotAnimSpeed();
  1163. float flPlaybackRate = 1.f;
  1164. CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( m_pTFPlayer, flPlaybackRate, mult_gesture_time );
  1165. return flPlaybackRate;
  1166. }
  1167. //-----------------------------------------------------------------------------
  1168. // Purpose:
  1169. //-----------------------------------------------------------------------------
  1170. bool CTFPlayerAnimState::HandleJumping( Activity &idealActivity )
  1171. {
  1172. bool bInDuck = ( m_pTFPlayer->GetFlags() & FL_DUCKING ) ? true : false;
  1173. if ( bInDuck && SelectWeightedSequence( TranslateActivity( ACT_MP_CROUCHWALK ) ) < 0 )
  1174. {
  1175. bInDuck = false;
  1176. }
  1177. Vector vecVelocity;
  1178. GetOuterAbsVelocity( vecVelocity );
  1179. // Don't allow a firing heavy to jump or air walk.
  1180. if ( m_pTFPlayer->GetPlayerClass()->IsClass( TF_CLASS_HEAVYWEAPONS ) && m_pTFPlayer->m_Shared.InCond( TF_COND_AIMING ) )
  1181. return false;
  1182. // Handle air walking before handling jumping - air walking supersedes jump
  1183. TFPlayerClassData_t *pData = m_pTFPlayer->GetPlayerClass()->GetData();
  1184. bool bValidAirWalkClass = ( pData && pData->m_bDontDoAirwalk == false );
  1185. if ( bValidAirWalkClass && ( vecVelocity.z > 300.0f || m_bInAirWalk || m_pTFPlayer->GetGrapplingHookTarget() != NULL ) && !bInDuck )
  1186. {
  1187. // Check to see if we were in an airwalk and now we are basically on the ground.
  1188. if ( ( GetBasePlayer()->GetFlags() & FL_ONGROUND ) && m_bInAirWalk )
  1189. {
  1190. m_bInAirWalk = false;
  1191. RestartMainSequence();
  1192. RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_JUMP_LAND );
  1193. }
  1194. else if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist )
  1195. {
  1196. // Turn off air walking and reset the animation.
  1197. m_bInAirWalk = false;
  1198. RestartMainSequence();
  1199. }
  1200. else if ( ( GetBasePlayer()->GetFlags() & FL_ONGROUND ) == 0 )
  1201. {
  1202. // In an air walk.
  1203. idealActivity = ACT_MP_AIRWALK;
  1204. m_bInAirWalk = true;
  1205. }
  1206. }
  1207. // Jumping.
  1208. else
  1209. {
  1210. if ( m_bJumping )
  1211. {
  1212. // Remove me once all classes are doing the new jump
  1213. TFPlayerClassData_t *pDataJump = m_pTFPlayer->GetPlayerClass()->GetData();
  1214. bool bNewJump = (pDataJump && pDataJump->m_bDontDoNewJump == false );
  1215. if ( m_bFirstJumpFrame )
  1216. {
  1217. m_bFirstJumpFrame = false;
  1218. RestartMainSequence(); // Reset the animation.
  1219. }
  1220. // Reset if we hit water and start swimming.
  1221. if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist )
  1222. {
  1223. m_bJumping = false;
  1224. RestartMainSequence();
  1225. }
  1226. // Don't check if he's on the ground for a sec.. sometimes the client still has the
  1227. // on-ground flag set right when the message comes in.
  1228. else if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
  1229. {
  1230. if ( GetBasePlayer()->GetFlags() & FL_ONGROUND )
  1231. {
  1232. m_bJumping = false;
  1233. RestartMainSequence();
  1234. if ( bNewJump )
  1235. {
  1236. RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_JUMP_LAND );
  1237. }
  1238. }
  1239. }
  1240. // if we're still jumping
  1241. if ( m_bJumping )
  1242. {
  1243. if ( bNewJump )
  1244. {
  1245. if ( gpGlobals->curtime - m_flJumpStartTime > 0.5 )
  1246. {
  1247. idealActivity = ACT_MP_JUMP_FLOAT;
  1248. }
  1249. else
  1250. {
  1251. idealActivity = ACT_MP_JUMP_START;
  1252. }
  1253. }
  1254. else
  1255. {
  1256. idealActivity = ACT_MP_JUMP;
  1257. }
  1258. }
  1259. }
  1260. }
  1261. if ( m_bJumping || m_bInAirWalk )
  1262. return true;
  1263. return false;
  1264. }
  1265. //-----------------------------------------------------------------------------
  1266. // Purpose:
  1267. //-----------------------------------------------------------------------------
  1268. bool CTFPlayerAnimState::IsItemTestingBot( void )
  1269. {
  1270. if ( TFGameRules()->IsInItemTestingMode() )
  1271. {
  1272. // Clients don't know what's a bot. Assume the first player is the non-bat.
  1273. return ( m_pTFPlayer->entindex() > 1 );
  1274. }
  1275. return false;
  1276. }