diff options
Diffstat (limited to 'game/shared/tf2/tf_gamemovement_recon.cpp')
| -rw-r--r-- | game/shared/tf2/tf_gamemovement_recon.cpp | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/game/shared/tf2/tf_gamemovement_recon.cpp b/game/shared/tf2/tf_gamemovement_recon.cpp new file mode 100644 index 0000000..c9b8987 --- /dev/null +++ b/game/shared/tf2/tf_gamemovement_recon.cpp @@ -0,0 +1,595 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Auto Repair +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "tf_gamemovement_recon.h" +#include "tf_movedata.h" +#include "in_buttons.h" + +#define TIME_WALL_SUPPRESSION_JUMP 100 +#define TIME_WALL_SUPPRESSION_IMPACT 400 +#define TIME_WALL_STICK 50 +#define TIME_STRAFE_STICK 50 +#define TIME_LEAP_STICK 300 +#define TIME_WALL_ACTIVATE_JUMP 300 +#define TIME_WALL_INVALID -99999 +#define MAX_VERTICAL_SPEED 400 + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFGameMovementRecon::CTFGameMovementRecon() +{ + m_pReconData = NULL; + + m_vStandMins = RECONCLASS_HULL_STAND_MIN; + m_vStandMaxs = RECONCLASS_HULL_STAND_MAX; + m_vStandViewOffset = RECONCLASS_VIEWOFFSET_STAND; + + m_vDuckMins = RECONCLASS_HULL_DUCK_MIN; + m_vDuckMaxs = RECONCLASS_HULL_DUCK_MAX; + m_vDuckViewOffset = RECONCLASS_VIEWOFFSET_DUCK; + + m_bPerformingAirMove = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGameMovementRecon::ProcessClassMovement( CBaseTFPlayer *pPlayer, CTFMoveData *pTFMove ) +{ + // Get the class specific data from the TFMoveData structure + Assert( PlayerClassReconData_t::PLAYERCLASS_ID == pTFMove->m_nClassID ); + m_pReconData = &pTFMove->ReconData(); + + // to test pass it through!! + BaseClass::ProcessMovement( (CBasePlayer *)pPlayer, pTFMove ); + + // Set the jump count appropriately... + // If we've hit the ground, we can double jump again... + if ((player->GetGroundEntity() != NULL) && (pTFMove->ReconData().m_flStickTime == TIME_WALL_INVALID)) + { + m_pReconData->m_nJumpCount = 0; + ResetWallImpact( (CTFMoveData*)mv ); + } +} + +void CTFGameMovementRecon::PostPlayerMove( void ) +{ + BaseClass::PostPlayerMove( ); + + if (m_pReconData->m_flStickTime != TIME_WALL_INVALID) + { + // We're stuck, so stick! + mv->m_vecVelocity.Init( 0.0f, 0.0f, 0.0f ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGameMovementRecon::UpdateTimers( void ) +{ + BaseClass::UpdateTimers(); + + CTFMoveData *pTFMove = TFMove(); + if ( !pTFMove ) + return; + + float frame_msec = 1000.0f * gpGlobals->frametime; + + // Decrement the recon timers. + if ( pTFMove->ReconData().m_flSuppressionJumpTime != TIME_WALL_INVALID ) + { + pTFMove->ReconData().m_flSuppressionJumpTime -= frame_msec; + if ( pTFMove->ReconData().m_flSuppressionJumpTime <= 0.0f ) + { + pTFMove->ReconData().m_flSuppressionJumpTime = TIME_WALL_INVALID; + } + } + + if ( pTFMove->ReconData().m_flSuppressionImpactTime != TIME_WALL_INVALID ) + { + pTFMove->ReconData().m_flSuppressionImpactTime -= frame_msec; + if ( pTFMove->ReconData().m_flSuppressionImpactTime <= 0.0f ) + { + pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_INVALID; + } + } + + if ( pTFMove->ReconData().m_flActiveJumpTime != TIME_WALL_INVALID ) + { + pTFMove->ReconData().m_flActiveJumpTime -= frame_msec; + if ( pTFMove->ReconData().m_flActiveJumpTime <= 0.0f ) + { + pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_INVALID; + } + } + + if ( pTFMove->ReconData().m_flStickTime != TIME_WALL_INVALID ) + { + pTFMove->ReconData().m_flStickTime -= frame_msec; + if ( pTFMove->ReconData().m_flStickTime <= 0.0f ) + { + pTFMove->ReconData().m_flStickTime = TIME_WALL_INVALID; + + // Restore velocity at this time + pTFMove->m_vecVelocity = pTFMove->ReconData().m_vecUnstickVelocity; + } + } +} + +//----------------------------------------------------------------------------- +// Implement this if you want to know when the player collides during OnPlayerMove +//----------------------------------------------------------------------------- +void CTFGameMovementRecon::OnTryPlayerMoveCollision( trace_t &tr ) +{ + if ( !m_bPerformingAirMove ) + return; + + // Only keep track of world collisions + if ( tr.DidHitWorld() ) + { + CTFMoveData *pTFMove = TFMove(); + if ( pTFMove ) + { + if ( ( pTFMove->ReconData().m_flSuppressionJumpTime == TIME_WALL_INVALID ) && + ( pTFMove->ReconData().m_flSuppressionImpactTime == TIME_WALL_INVALID ) ) + { + // No walljumps off of mostly horizontal surfaces... + if ( fabs( tr.plane.normal.z ) > 0.9f ) + return; + + // No walljumps off of the same plane as the last one... + if ( (pTFMove->ReconData().m_flImpactDist == tr.plane.dist) && + (VectorsAreEqual(pTFMove->ReconData().m_vecImpactNormal, tr.plane.normal, 1e-2) ) ) + { + return; + } + + // If you hit a wall, no double jumps for you + pTFMove->ReconData().m_nJumpCount = 2; + + // Play an impact sound + MoveHelper()->StartSound( pTFMove->m_vecAbsOrigin, "Recon.WallJump" ); + + pTFMove->ReconData().m_vecImpactNormal = tr.plane.normal; + pTFMove->ReconData().m_flImpactDist = tr.plane.dist; + + pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_ACTIVATE_JUMP; + pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_SUPPRESSION_IMPACT; + } + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGameMovementRecon::AirMove() +{ + m_bPerformingAirMove = true; + + // When in the air, recon travels ballistically + if ( TFMove()->ReconData().m_nJumpCount ) + { + // Add in any base velocity to the current velocity. + VectorAdd( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); + + TryPlayerMove(); + } + else + { + // But if we're falling (or coming up off ladders), treat it normally + BaseClass::AirMove(); + } + + m_bPerformingAirMove = false; +} + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckWaterJump() +{ + // See if we are waterjumping. If so, decrement count and return. + if (player->m_flWaterJumpTime) + { + player->m_flWaterJumpTime -= gpGlobals->frametime; + if (player->m_flWaterJumpTime < 0) + player->m_flWaterJumpTime = 0; + + return true; + } + + // If we are in the water most of the way... + if ( player->GetWaterLevel() >= 2 ) + { + // swimming, not jumping + SetGroundEntity( NULL ); + + if(player->GetWaterType() == CONTENTS_WATER) // We move up a certain amount + mv->m_vecVelocity[2] = 100; + else if (player->GetWaterType() == CONTENTS_SLIME) + mv->m_vecVelocity[2] = 80; + + // play swiming sound + if ( player->m_flSwimSoundTime <= 0 ) + { + // Don't play sound again for 1 second + player->m_flSwimSoundTime = 1000; + PlaySwimSound(); + } + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Resets the impact time +//----------------------------------------------------------------------------- +void CTFGameMovementRecon::ResetWallImpact( CTFMoveData *pTFMove ) +{ + if ( pTFMove->ReconData().m_flActiveJumpTime != TIME_WALL_INVALID ) + { + pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_INVALID; + pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_INVALID; + pTFMove->ReconData().m_vecImpactNormal.Init( 9999, 9999, 9999 ); + pTFMove->ReconData().m_flImpactDist = -9999.0f; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckWallJump( CTFMoveData *pTFMove ) +{ + if ( player->GetGroundEntity() != NULL ) + return false; + + if ( pTFMove->ReconData().m_flActiveJumpTime == TIME_WALL_INVALID ) + return false; + + // Play a jump sound + PlayStepSound( m_pSurfaceData, 1.0, true ); + + Vector jumpDir; + if ( ( pTFMove->m_nButtons & ( IN_MOVELEFT | IN_MOVERIGHT ) ) ) + { + AngleVectors( pTFMove->m_vecViewAngles, NULL, &jumpDir, NULL ); + + // Apply strafe jump... + jumpDir *= ( pTFMove->m_nButtons & IN_MOVELEFT ) ? -1.0f : 1.0f; + jumpDir.z = 0.0f; + + if ( pTFMove->m_nButtons & ( IN_FORWARD | IN_BACK ) ) + { + Vector forward; + AngleVectors( pTFMove->m_vecViewAngles, &forward, NULL, NULL ); + forward *= 0.5f; + forward *= ( pTFMove->m_nButtons & IN_BACK ) ? -1.0f : 1.0f; + forward.z = 0.0; + jumpDir += forward; + } + + VectorNormalize( jumpDir ); + jumpDir *= 400; + } + else + { + AngleVectors( pTFMove->m_vecViewAngles, &jumpDir, NULL, NULL ); + jumpDir *= ( pTFMove->m_nButtons & IN_BACK ) ? -1.0f : 1.0f; + jumpDir.z = 0.0; + + VectorNormalize( jumpDir ); + jumpDir *= 400; + } + + pTFMove->ReconData().m_flStickTime = TIME_WALL_STICK; + pTFMove->ReconData().m_vecUnstickVelocity.Init( jumpDir.x, jumpDir.y, + pTFMove->m_vecVelocity[2] + 1.5 * sqrt(2 * 800 * 45.0) ); + if (pTFMove->ReconData().m_vecUnstickVelocity.GetZ() > MAX_VERTICAL_SPEED) + pTFMove->ReconData().m_vecUnstickVelocity.SetZ( MAX_VERTICAL_SPEED ); + + pTFMove->m_vecVelocity.Init( 0, 0, 0 ); + + // Don't allow jump into wall + float normalComponent = DotProduct( pTFMove->ReconData().m_vecUnstickVelocity, pTFMove->ReconData().m_vecImpactNormal ); + if ( normalComponent < 0 ) + { + Vector vUnstickVel; + VectorMA( pTFMove->ReconData().m_vecUnstickVelocity, -normalComponent, + pTFMove->ReconData().m_vecImpactNormal, vUnstickVel ); + pTFMove->ReconData().m_vecUnstickVelocity = vUnstickVel; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckBackJump( bool bWasInAir ) +{ + if ((mv->m_nButtons & IN_BACK) == 0) + return false; + + Vector jumpDir, right; + AngleVectors( mv->m_vecViewAngles, &jumpDir, &right, NULL ); + jumpDir.z = 0.0f; + jumpDir *= -1.0f; + + if (mv->m_nButtons & (IN_MOVELEFT | IN_MOVERIGHT)) + { + // Apply strafe jump... + right *= (mv->m_nButtons & IN_MOVELEFT) ? -1.0f : 1.0f; + right.z = 0.0f; + + // Make us not jump quite at a 45% angle if both are selected + right *= 0.5f; + jumpDir += right; + } + + VectorNormalize( jumpDir ); + + float flGroundFactor = 1.0f; + if ((m_pSurfaceData) /*&& (!bWasInAir)*/ ) + { + flGroundFactor = m_pSurfaceData->game.jumpFactor; + } + + jumpDir *= 150 * flGroundFactor; + + // Dampen current motion + mv->m_vecVelocity[0] *= 0.5f; + mv->m_vecVelocity[1] *= 0.5f; + + float flSideFactor = (bWasInAir) ? 2.0f : 1.0f; + float flUpFactor = (bWasInAir) ? 0.5f : 1.5f; + flSideFactor *= flGroundFactor; + flUpFactor *= flGroundFactor; + + mv->m_vecVelocity[0] += flSideFactor * jumpDir.x; + mv->m_vecVelocity[1] += flSideFactor * jumpDir.y; + mv->m_vecVelocity[2] += flUpFactor * sqrt(2 * 800 * 45.0); + + mv->m_vecVelocity[0] = clamp( mv->m_vecVelocity[0], -200, 200 ); + mv->m_vecVelocity[1] = clamp( mv->m_vecVelocity[1], -200, 200 ); + if (mv->m_vecVelocity[2] > MAX_VERTICAL_SPEED) + mv->m_vecVelocity[2] = MAX_VERTICAL_SPEED; + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckStrafeJump( bool bWasInAir ) +{ + if ( (mv->m_nButtons & (IN_MOVELEFT | IN_MOVERIGHT)) == 0 ) + return false; + + if (mv->m_nButtons & IN_FORWARD) + return false; + + Vector jumpDir; + AngleVectors( mv->m_vecViewAngles, NULL, &jumpDir, NULL ); + + // Apply strafe jump... + jumpDir *= (mv->m_nButtons & IN_MOVELEFT) ? -1.0f : 1.0f; + jumpDir.z = 0.0f; + VectorNormalize( jumpDir ); + + float flGroundFactor = 1.0f; + if ((m_pSurfaceData) /*&& (!bWasInAir)*/ ) + { + flGroundFactor = m_pSurfaceData->game.jumpFactor; + } + + jumpDir *= 300 * flGroundFactor; + + // Dampen current motion + mv->m_vecVelocity[0] *= 0.5f; + mv->m_vecVelocity[1] *= 0.5f; + mv->m_vecVelocity[0] += jumpDir.x; + mv->m_vecVelocity[1] += jumpDir.y; + + if (!bWasInAir) + mv->m_vecVelocity[2] += flGroundFactor * sqrt(2 * 800 * 45.0); // 2 * gravity * height + else + mv->m_vecVelocity[2] += 0.5f * sqrt(2 * 800 * 45.0); // 2 * gravity * height + + mv->m_vecVelocity[0] = clamp( mv->m_vecVelocity[0], -400, 400 ); + mv->m_vecVelocity[1] = clamp( mv->m_vecVelocity[1], -400, 400 ); + if (mv->m_vecVelocity[2] > MAX_VERTICAL_SPEED) + mv->m_vecVelocity[2] = MAX_VERTICAL_SPEED; + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckForwardJump( bool bWasInAir ) +{ + // If we are ducking... + if ( ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) ) + { + // d = 0.5 * g * t^2 - distance traveled with linear accel + // t = sqrt(2.0 * 45 / g) - how long to fall 45 units + // v = g * t - velocity at the end (just invert it to jump up that high) + // v = g * sqrt(2.0 * 45 / g ) + // v^2 = g * g * 2.0 * 45 / g + // v = sqrt( g * 2.0 * 45 ) + mv->m_vecVelocity[2] = sqrt(2 * 800 * 45.0); // 2 * gravity * height + } + else + { + Vector forward, right; + AngleVectors( mv->m_vecViewAngles, &forward, &right, NULL ); + forward.z = 0.0; + + if ((mv->m_nButtons & IN_FORWARD) == 0) + { + forward.x = forward.y = 0.0f; + } + + if (mv->m_nButtons & (IN_MOVELEFT | IN_MOVERIGHT)) + { + // Apply strafe jump... + right *= (mv->m_nButtons & IN_MOVELEFT) ? -1.0f : 1.0f; + right.z = 0.0f; + + // Make us not jump quite at a 45% angle if both are selected + right *= 0.5f; + forward += right; + } + + VectorNormalize( forward ); + + // Slow down by the speed factor + float flGroundFactor = 1.0f; + if ((m_pSurfaceData) /* && (!bWasInAir) */ ) + { + flGroundFactor = m_pSurfaceData->game.jumpFactor; + } + + forward *= 400 * flGroundFactor; + + // Dampen current motion + mv->m_vecVelocity[0] *= 0.5f; + mv->m_vecVelocity[1] *= 0.5f; + mv->m_vecVelocity[0] += forward.x; + mv->m_vecVelocity[1] += forward.y; + + float flUpFactor = (bWasInAir) ? 0.7f : 1.0f; + flUpFactor *= flGroundFactor; + + mv->m_vecVelocity[2] += flUpFactor * MAX_VERTICAL_SPEED; + + // Limit their velocity in X and Y. We don't want to just clamp because that will change the + // direction we're moving in. + for ( int i=0; i < 2; i++ ) + { + float flAbs = fabs( mv->m_vecVelocity[i] ); + if ( flAbs > 400 ) + { + mv->m_vecVelocity[0] *= (400.0f / flAbs); + mv->m_vecVelocity[1] *= (400.0f / flAbs); + } + } + + if (mv->m_vecVelocity[2] > MAX_VERTICAL_SPEED) + mv->m_vecVelocity[2] = MAX_VERTICAL_SPEED; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Check the jump button to make various jumps +//----------------------------------------------------------------------------- +bool CTFGameMovementRecon::CheckJumpButton() +{ + // FIXME: Refactor this so we don't have this complicated duplicate + // code here + in gamemovement.cpp + + if ( player->pl.deadflag ) + { + mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released + return false; + } + + // Water jumps! + if ( CheckWaterJump() ) + return false; + + if ( mv->m_nOldButtons & IN_JUMP ) + return false; // don't pogo stick + + CTFMoveData *pTFMove = static_cast<CTFMoveData*>( mv ); + + // Check for wall jump... + if ( !CheckWallJump( pTFMove ) ) + { + // If we already did one air jump, can't do another + if ( (player->GetGroundEntity() == NULL ) && ( pTFMove->ReconData().m_nJumpCount > 1) ) + { + mv->m_nOldButtons |= IN_JUMP; + return false; // in air, so no effect + } + + pTFMove->ReconData().m_nJumpCount += 1; + + // Am I doing a double-jump? + bool bWasInAir = (player->GetGroundEntity() == NULL); + + // In the air now. + SetGroundEntity( NULL ); + + PlayStepSound( m_pSurfaceData, 1.0, true ); + + if (!CheckBackJump(bWasInAir)) + { + if (CheckStrafeJump(bWasInAir)) + { + // Can't double jump out of a roll.... + pTFMove->ReconData().m_nJumpCount += 1; + } + else + { + CheckForwardJump(bWasInAir); + } + } + } + + pTFMove->ReconData().m_flSuppressionJumpTime = TIME_WALL_SUPPRESSION_JUMP; + + FinishGravity(); + + mv->m_outWishVel = mv->m_vecVelocity; + mv->m_outStepHeight += 0.1f; + + // Flag that we jumped. + mv->m_nOldButtons |= IN_JUMP; // don't jump again until released + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector &CTFGameMovementRecon::GetPlayerMins( bool bDucked ) const +{ + return bDucked ? m_vDuckMins : m_vStandMins; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector &CTFGameMovementRecon::GetPlayerMaxs( bool bDucked ) const +{ + return bDucked ? m_vDuckMaxs : m_vStandMaxs; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const Vector &CTFGameMovementRecon::GetPlayerViewOffset( bool bDucked ) const +{ + return bDucked ? m_vDuckViewOffset : m_vStandViewOffset; +} |