//----------------------------------------------------------------------------- // Purpose: // Input : actDesired - // Output : Activity //----------------------------------------------------------------------------- Activity CTFPlayerAnimState::TranslateActivity( Activity actDesired ) { Activity translateActivity = BaseClass::TranslateActivity( actDesired ); if ( GetTFPlayer()->m_Shared.IsLoser() ) { int actCount = ARRAYSIZE( m_acttableLoserState ); for ( int i = 0; i < actCount; i++ ) { const acttable_t& act = m_acttableLoserState[ i ]; if ( actDesired == act.baseAct ) return (Activity)act.weaponAct; } } if ( GetTFPlayer()->GetActiveWeapon() ) translateActivity = GetTFPlayer()->GetActiveWeapon()->ActivityOverride( translateActivity, false ); return translateActivity; }
//----------------------------------------------------------------------------- // Purpose: // Input : actDesired - // Output : Activity //----------------------------------------------------------------------------- Activity CTFPlayerAnimState::TranslateActivity( Activity actDesired ) { Activity translateActivity = BaseClass::TranslateActivity( actDesired ); if ( GetTFPlayer()->m_Shared.IsLoser() ) { int actCount = ARRAYSIZE( m_acttableLoserState ); for ( int i = 0; i < actCount; i++ ) { const acttable_t& act = m_acttableLoserState[i]; if ( actDesired == act.baseAct) return (Activity)act.weaponAct; } } else if ( GetTFPlayer()->m_Shared.IsCarryingObject() ) { int actCount = ARRAYSIZE( m_acttableBuildingDeployed ); for ( int i = 0; i < actCount; i++ ) { const acttable_t& act = m_acttableBuildingDeployed[i]; if ( actDesired == act.baseAct ) return (Activity)act.weaponAct; } } CBaseCombatWeapon *pWeapon = GetTFPlayer()->GetActiveWeapon(); if ( pWeapon ) { translateActivity = GetTFPlayer()->GetActiveWeapon()->ActivityOverride( translateActivity, false ); // Live TF2 does this but is doing this after the above call correct? translateActivity = pWeapon->GetItem()->GetActivityOverride( GetTFPlayer()->GetTeamNumber(), translateActivity ); } return translateActivity; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFPlayerAnimState::Update( float eyeYaw, float eyePitch ) { // Profile the animation update. VPROF( "CMultiPlayerAnimState::Update" ); // Get the TF player. CTFPlayer *pTFPlayer = GetTFPlayer(); if ( !pTFPlayer ) return; // Get the studio header for the player. CStudioHdr *pStudioHdr = pTFPlayer->GetModelPtr(); if ( !pStudioHdr ) return; // Check to see if we should be updating the animation state - dead, ragdolled? if ( !ShouldUpdateAnimState() ) { ClearAnimationState(); return; } // Store the eye angles. m_flEyeYaw = AngleNormalize( eyeYaw ); m_flEyePitch = AngleNormalize( eyePitch ); // Compute the player sequences. ComputeSequences( pStudioHdr ); if ( SetupPoseParameters( pStudioHdr ) && !pTFPlayer->m_Shared.InCond( TF_COND_TAUNTING ) ) { // Pose parameter - what direction are the player's legs running in. ComputePoseParam_MoveYaw( pStudioHdr ); // Pose parameter - Torso aiming (up/down). ComputePoseParam_AimPitch( pStudioHdr ); // Pose parameter - Torso aiming (rotation). ComputePoseParam_AimYaw( pStudioHdr ); } #ifdef CLIENT_DLL if ( C_BasePlayer::ShouldDrawLocalPlayer() ) { GetBasePlayer()->SetPlaybackRate( 1.0f ); } #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : *idealActivity - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CTFPlayerAnimState::HandleDucking( Activity &idealActivity ) { if (GetBasePlayer()->GetFlags() & FL_DUCKING) { if ( GetOuterXYSpeed() < MOVING_MINIMUM_SPEED || m_pTFPlayer->m_Shared.IsLoser() ) { idealActivity = ACT_MP_CROUCH_IDLE; if ( m_pTFPlayer->m_Shared.InCond( TF_COND_AIMING ) || m_flHoldDeployedPoseUntilTime > gpGlobals->curtime ) { idealActivity = ACT_MP_CROUCH_DEPLOYED_IDLE; } } else { idealActivity = ACT_MP_CROUCHWALK; if ( m_pTFPlayer->m_Shared.InCond( TF_COND_AIMING ) ) { // Don't do this for the heavy! we don't usually let him deployed crouch walk bool bIsMinigun = false; CTFPlayer *pPlayer = GetTFPlayer(); if ( pPlayer && pPlayer->GetActiveTFWeapon() ) { bIsMinigun = ( pPlayer->GetActiveTFWeapon()->GetWeaponID() == TF_WEAPON_MINIGUN ); } if ( !bIsMinigun ) { idealActivity = ACT_MP_CROUCH_DEPLOYED; } } } return true; } return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : event - //----------------------------------------------------------------------------- void CTFPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) { Activity iGestureActivity = ACT_INVALID; switch( event ) { case PLAYERANIMEVENT_ATTACK_PRIMARY: { CTFPlayer *pPlayer = GetTFPlayer(); if ( !pPlayer ) return; CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN ); bool bIsSniperRifle = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_SNIPERRIFLE ); // Heavy weapons primary fire. if ( bIsMinigun ) { // Play standing primary fire. iGestureActivity = ACT_MP_ATTACK_STAND_PRIMARYFIRE; if ( m_bInSwim ) { // Play swimming primary fire. iGestureActivity = ACT_MP_ATTACK_SWIM_PRIMARYFIRE; } else if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { // Play crouching primary fire. iGestureActivity = ACT_MP_ATTACK_CROUCH_PRIMARYFIRE; } if ( !IsGestureSlotPlaying( GESTURE_SLOT_ATTACK_AND_RELOAD, TranslateActivity(iGestureActivity) ) ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity ); } } else if ( bIsSniperRifle && pPlayer->m_Shared.InCond( TF_COND_ZOOMED ) ) { // Weapon primary fire, zoomed in if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED ); } else { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED ); } iGestureActivity = ACT_VM_PRIMARYATTACK; // Hold our deployed pose for a few seconds m_flHoldDeployedPoseUntilTime = gpGlobals->curtime + 2.0; } else { // Weapon primary fire. if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ); } else { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE ); } iGestureActivity = ACT_VM_PRIMARYATTACK; } break; } case PLAYERANIMEVENT_VOICE_COMMAND_GESTURE: { if ( !IsGestureSlotActive( GESTURE_SLOT_ATTACK_AND_RELOAD ) ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, (Activity)nData ); } break; } case PLAYERANIMEVENT_ATTACK_SECONDARY: { // Weapon secondary fire. if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_SECONDARYFIRE ); } else { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_SECONDARYFIRE ); } iGestureActivity = ACT_VM_PRIMARYATTACK; break; } case PLAYERANIMEVENT_ATTACK_PRE: { CTFPlayer *pPlayer = GetTFPlayer(); if ( !pPlayer ) return; CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN ); bool bAutoKillPreFire = false; if ( bIsMinigun ) { bAutoKillPreFire = true; } if ( m_bInSwim && bIsMinigun ) { // Weapon pre-fire. Used for minigun windup while swimming iGestureActivity = ACT_MP_ATTACK_SWIM_PREFIRE; } else if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc in crouch. iGestureActivity = ACT_MP_ATTACK_CROUCH_PREFIRE; } else { // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc. iGestureActivity = ACT_MP_ATTACK_STAND_PREFIRE; } RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity, bAutoKillPreFire ); break; } case PLAYERANIMEVENT_ATTACK_POST: { CTFPlayer *pPlayer = GetTFPlayer(); if ( !pPlayer ) return; CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); bool bIsMinigun = ( pWpn && pWpn->GetWeaponID() == TF_WEAPON_MINIGUN ); if ( m_bInSwim && bIsMinigun ) { // Weapon pre-fire. Used for minigun winddown while swimming iGestureActivity = ACT_MP_ATTACK_SWIM_POSTFIRE; } else if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) { // Weapon post-fire. Used for minigun winddown in crouch. iGestureActivity = ACT_MP_ATTACK_CROUCH_POSTFIRE; } else { // Weapon post-fire. Used for minigun winddown. iGestureActivity = ACT_MP_ATTACK_STAND_POSTFIRE; } RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity ); break; } case PLAYERANIMEVENT_RELOAD: { // Weapon reload. if ( m_bInAirWalk ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK ); } else { BaseClass::DoAnimationEvent( event, nData ); } break; } case PLAYERANIMEVENT_RELOAD_LOOP: { // Weapon reload. if ( m_bInAirWalk ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK_LOOP ); } else { BaseClass::DoAnimationEvent( event, nData ); } break; } case PLAYERANIMEVENT_RELOAD_END: { // Weapon reload. if ( m_bInAirWalk ) { RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_AIRWALK_END ); } else { BaseClass::DoAnimationEvent( event, nData ); } break; } case PLAYERANIMEVENT_DOUBLEJUMP: { // Check to see if we are jumping! if ( !m_bJumping ) { m_bJumping = true; m_bFirstJumpFrame = true; m_flJumpStartTime = gpGlobals->curtime; RestartMainSequence(); } // Force the air walk off. m_bInAirWalk = false; // Player the air dash gesture. if (GetBasePlayer()->GetFlags() & FL_DUCKING) { RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_DOUBLEJUMP_CROUCH ); } else { RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_DOUBLEJUMP ); } break; } default: { BaseClass::DoAnimationEvent( event, nData ); break; } } #ifdef CLIENT_DLL // Make the weapon play the animation as well if (iGestureActivity != ACT_INVALID && GetBasePlayer() != C_BasePlayer::GetLocalPlayer()) { CBaseCombatWeapon *pWeapon = GetTFPlayer()->GetActiveWeapon(); if ( pWeapon ) { pWeapon->SendWeaponAnim( iGestureActivity ); pWeapon->DoAnimationEvents(pWeapon->GetModelPtr()); } } #endif }