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.
424 lines
12 KiB
424 lines
12 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Auto Repair
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "tf_gamemovement_commando.h"
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFGameMovementCommando::CTFGameMovementCommando()
|
||
|
{
|
||
|
m_pCommandoData = NULL;
|
||
|
|
||
|
m_vStandMins = COMMANDOCLASS_HULL_STAND_MIN;
|
||
|
m_vStandMaxs = COMMANDOCLASS_HULL_STAND_MAX;
|
||
|
m_vStandViewOffset = COMMANDOCLASS_VIEWOFFSET_STAND;
|
||
|
|
||
|
m_vDuckMins = COMMANDOCLASS_HULL_DUCK_MIN;
|
||
|
m_vDuckMaxs = COMMANDOCLASS_HULL_DUCK_MAX;
|
||
|
m_vDuckViewOffset = COMMANDOCLASS_VIEWOFFSET_DUCK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::ProcessClassMovement( CBaseTFPlayer *pPlayer, CTFMoveData *pTFMoveData )
|
||
|
{
|
||
|
// Get the class specific data from the TFMoveData structure
|
||
|
Assert( PlayerClassCommandoData_t::PLAYERCLASS_ID == pTFMoveData->m_nClassID );
|
||
|
|
||
|
// Is this how I want to handle this???
|
||
|
// m_pCommandoData = &pTFMoveData->CommandoData();
|
||
|
|
||
|
// to test pass it through!!
|
||
|
BaseClass::ProcessMovement( (CBasePlayer *)pPlayer, static_cast<CMoveData*>( pTFMoveData ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const Vector &CTFGameMovementCommando::GetPlayerMins( bool bDucked ) const
|
||
|
{
|
||
|
return bDucked ? m_vDuckMins : m_vStandMins;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const Vector &CTFGameMovementCommando::GetPlayerMaxs( bool bDucked ) const
|
||
|
{
|
||
|
return bDucked ? m_vDuckMaxs : m_vStandMaxs;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
const Vector &CTFGameMovementCommando::GetPlayerViewOffset( bool bDucked ) const
|
||
|
{
|
||
|
return bDucked ? m_vDuckViewOffset : m_vStandViewOffset;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFGameMovementCommando::CheckDoubleTapForward( void )
|
||
|
{
|
||
|
// Check for other movement keys!!!
|
||
|
if ( ( TFMove()->m_nButtons & IN_MOVELEFT ) || ( TFMove()->m_nButtons & IN_MOVERIGHT ) ||
|
||
|
( TFMove()->m_nButtons & IN_BACK ) || ( TFMove()->m_nButtons & IN_JUMP ) )
|
||
|
{
|
||
|
TFMove()->CommandoData().m_flDoubleTapForwardTime = COMMANDO_TIME_INVALID;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ( TFMove()->m_nButtons & IN_FORWARD ) && !( TFMove()->m_nOldButtons & IN_FORWARD ) )
|
||
|
{
|
||
|
// Start timer.
|
||
|
if ( TFMove()->CommandoData().m_flDoubleTapForwardTime == COMMANDO_TIME_INVALID )
|
||
|
{
|
||
|
TFMove()->CommandoData().m_flDoubleTapForwardTime = COMMANDO_DOUBLETAP_TIME;
|
||
|
}
|
||
|
// Check for a double tap.
|
||
|
else
|
||
|
{
|
||
|
if ( TFMove()->CommandoData().m_flDoubleTapForwardTime > 0.0f )
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::CheckBullRush( void )
|
||
|
{
|
||
|
// Don't check for bullrush if we are dead!
|
||
|
if ( IsDead() )
|
||
|
return;
|
||
|
|
||
|
// Don't go into bullrush if noclipping
|
||
|
if ( player->GetMoveType() == MOVETYPE_NOCLIP )
|
||
|
return;
|
||
|
|
||
|
// Cannot bullrush inside of a vehicle (manned <gun>).
|
||
|
#if !defined (CLIENT_DLL)
|
||
|
IServerVehicle *pVehicle = player->GetVehicle();
|
||
|
if ( pVehicle )
|
||
|
return;
|
||
|
#else
|
||
|
IClientVehicle *pVehicle = player->GetVehicle();
|
||
|
if ( pVehicle )
|
||
|
return;
|
||
|
#endif
|
||
|
|
||
|
if ( CheckDoubleTapForward() && !TFMove()->CommandoData().m_bBullRush &&
|
||
|
TFMove()->CommandoData().m_bCanBullRush && !( player->GetFlags() & FL_DUCKING ) )
|
||
|
{
|
||
|
// Set in a bull rush.
|
||
|
TFMove()->CommandoData().m_bBullRush = true;
|
||
|
|
||
|
// Set timers.
|
||
|
TFMove()->CommandoData().m_flBullRushTime = COMMANDO_BULLRUSH_TIME;
|
||
|
|
||
|
// Lock view/move angles
|
||
|
Vector vBullrushDir;
|
||
|
AngleVectors( TFMove()->m_vecViewAngles, &vBullrushDir, NULL, NULL );
|
||
|
TFMove()->CommandoData().m_vecBullRushDir = vBullrushDir;
|
||
|
TFMove()->CommandoData().m_vecBullRushViewDir = TFMove()->m_vecViewAngles;
|
||
|
TFMove()->CommandoData().m_vecBullRushViewGoalDir.Init();
|
||
|
TFMove()->CommandoData().m_vecBullRushViewGoalDir.SetY( TFMove()->m_vecViewAngles.y );
|
||
|
|
||
|
// Set movement type.
|
||
|
player->SetMoveType( (MoveType_t)COMMANDO_MOVETYPE_BULLRUSH );
|
||
|
player->SetMoveCollide( MOVECOLLIDE_DEFAULT );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFGameMovementCommando::PrePlayerMove( void )
|
||
|
{
|
||
|
// Assume we don't touch anything (Reset the touch list).
|
||
|
MoveHelper()->ResetTouchList();
|
||
|
|
||
|
// Check to see if we are stuck.
|
||
|
if ( CheckStuck() )
|
||
|
return false;
|
||
|
|
||
|
CheckBullRush();
|
||
|
|
||
|
// Update (reduce) movement timers.
|
||
|
UpdateTimers();
|
||
|
|
||
|
// Check to see if the player is dead and setup death data, otherwise setup
|
||
|
// the players view angles.
|
||
|
if ( !CheckDeath() )
|
||
|
{
|
||
|
SetupViewAngles();
|
||
|
}
|
||
|
|
||
|
// Handle ducking.
|
||
|
HandleDuck();
|
||
|
|
||
|
// Handle ladder.
|
||
|
HandleLadder();
|
||
|
|
||
|
// Categorize the player's position.
|
||
|
CategorizePosition();
|
||
|
|
||
|
// Calculate the player's movement speed (has to happen after categorize position)
|
||
|
SetupSpeed();
|
||
|
|
||
|
// Update our stepping sound (based on the player's location).
|
||
|
player->UpdateStepSound( m_pSurfaceData, mv->m_vecAbsOrigin, mv->m_vecVelocity );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::HandlePlayerMove( void )
|
||
|
{
|
||
|
// Handle the specific bull rush movement type.
|
||
|
if ( player->GetMoveType() == COMMANDO_MOVETYPE_BULLRUSH )
|
||
|
{
|
||
|
BullRushMove();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Let the default TF2 player movement code handle the move.
|
||
|
BaseClass::HandlePlayerMove();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::HandleDuck( void )
|
||
|
{
|
||
|
if ( player->GetMoveType() == COMMANDO_MOVETYPE_BULLRUSH )
|
||
|
return;
|
||
|
|
||
|
BaseClass::HandleDuck();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::UpdateTimers( void )
|
||
|
{
|
||
|
BaseClass::UpdateTimers();
|
||
|
|
||
|
CTFMoveData *pMoveData = TFMove();
|
||
|
if ( !pMoveData )
|
||
|
return;
|
||
|
|
||
|
float frame_msec = 1000.0f * gpGlobals->frametime;
|
||
|
|
||
|
// Decrement the bull rush time.
|
||
|
if ( pMoveData->CommandoData().m_flBullRushTime != COMMANDO_TIME_INVALID )
|
||
|
{
|
||
|
if ( pMoveData->CommandoData().m_flBullRushTime > 0.0f )
|
||
|
{
|
||
|
pMoveData->CommandoData().m_flBullRushTime -= frame_msec;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TFMove()->CommandoData().m_bBullRush = false;
|
||
|
TFMove()->CommandoData().m_flBullRushTime = COMMANDO_TIME_INVALID;
|
||
|
player->SetMoveType( MOVETYPE_WALK );
|
||
|
player->SetMoveCollide( MOVECOLLIDE_DEFAULT );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pMoveData->CommandoData().m_flDoubleTapForwardTime != COMMANDO_TIME_INVALID )
|
||
|
{
|
||
|
if ( pMoveData->CommandoData().m_flDoubleTapForwardTime > 0.0f )
|
||
|
{
|
||
|
pMoveData->CommandoData().m_flDoubleTapForwardTime -= frame_msec;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pMoveData->CommandoData().m_flDoubleTapForwardTime = COMMANDO_TIME_INVALID;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::SetupViewAngles( void )
|
||
|
{
|
||
|
|
||
|
BaseClass::SetupViewAngles();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::SetupSpeed( void )
|
||
|
{
|
||
|
BaseClass::SetupSpeed();
|
||
|
|
||
|
if ( player->GetMoveType() == COMMANDO_MOVETYPE_BULLRUSH )
|
||
|
{
|
||
|
mv->m_flMaxSpeed = sv_maxspeed.GetFloat();
|
||
|
|
||
|
// Slow down by the speed factor
|
||
|
if (m_pSurfaceData)
|
||
|
{
|
||
|
mv->m_flMaxSpeed *= m_pSurfaceData->game.maxSpeedFactor;
|
||
|
}
|
||
|
|
||
|
mv->m_flForwardMove = TFMove()->m_flClientMaxSpeed * 4.0f;
|
||
|
mv->m_flUpMove = 0.0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFGameMovementCommando::CalcWishVelocityAndPosition( Vector &vWishPos, Vector &vWishDir, float &flWishSpeed )
|
||
|
{
|
||
|
//
|
||
|
// Determine the movement angles.
|
||
|
//
|
||
|
Vector vForward, vRight, vUp;
|
||
|
if ( player->GetMoveType() == COMMANDO_MOVETYPE_BULLRUSH )
|
||
|
{
|
||
|
vForward = TFMove()->CommandoData().m_vecBullRushDir;
|
||
|
// Cross the bullrush direction with the z-axis to get the right vector.
|
||
|
CrossProduct( vForward, Vector( 0.0f, 0.0f, 1.0f ), vRight );
|
||
|
vUp.Init();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AngleVectors( mv->m_vecViewAngles, &vForward, &vRight, &vUp );
|
||
|
|
||
|
//
|
||
|
// Zero out the z component of the movement vectors and renormalize.
|
||
|
//
|
||
|
vForward.z = 0.0f;
|
||
|
VectorNormalize( vForward );
|
||
|
vRight.z = 0.0f;
|
||
|
VectorNormalize( vRight );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine the xy parts of the velocity.
|
||
|
//
|
||
|
Vector vWishVel( 0.0f, 0.0f, 0.0f );
|
||
|
for ( int axis = 0; axis < 2; axis++ )
|
||
|
{
|
||
|
vWishVel[axis] = ( vForward[axis] * mv->m_flForwardMove ) +
|
||
|
( vRight[axis] * mv->m_flSideMove );
|
||
|
}
|
||
|
vWishVel.z = 0.0f;
|
||
|
|
||
|
//
|
||
|
// Componentize the velocity into direction and speed.
|
||
|
//
|
||
|
VectorCopy( vWishVel, vWishDir );
|
||
|
flWishSpeed = VectorNormalize( vWishDir );
|
||
|
|
||
|
if ( flWishSpeed > mv->m_flMaxSpeed )
|
||
|
{
|
||
|
VectorScale( vWishVel, ( mv->m_flMaxSpeed / flWishSpeed ), vWishVel );
|
||
|
flWishSpeed = mv->m_flMaxSpeed;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Accelerate (in the plane).
|
||
|
//
|
||
|
mv->m_vecVelocity.z = 0.0f;
|
||
|
Accelerate( vWishDir, flWishSpeed, sv_accelerate.GetFloat() );
|
||
|
mv->m_vecVelocity.z = 0.0f;
|
||
|
|
||
|
// Add in any base velocity (from conveyers, etc.) to the current velocity.
|
||
|
VectorAdd( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity );
|
||
|
|
||
|
//
|
||
|
// Stop the player (zero out velocity) if the player's speed is below a
|
||
|
// given threshold.
|
||
|
//
|
||
|
float flSpeed = VectorLength( mv->m_vecVelocity );
|
||
|
if ( flSpeed < 1.0f /*SPEED_STOP_THRESHOLD*/ )
|
||
|
{
|
||
|
mv->m_vecVelocity.Init();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Calculate the wish position.
|
||
|
//
|
||
|
vWishPos.x = mv->m_vecAbsOrigin.x + ( mv->m_vecVelocity.x * gpGlobals->frametime );
|
||
|
vWishPos.y = mv->m_vecAbsOrigin.y + ( mv->m_vecVelocity.y * gpGlobals->frametime );
|
||
|
vWishPos.z = mv->m_vecAbsOrigin.z;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFGameMovementCommando::BullRushMove( void )
|
||
|
{
|
||
|
CTFMoveData *pMoveData = TFMove();
|
||
|
if ( !pMoveData )
|
||
|
return;
|
||
|
|
||
|
// Ignoring water for now!!!!
|
||
|
StartGravity();
|
||
|
|
||
|
// Fricion is handled before we add in any base velocity. That way, if we are on a conveyor,
|
||
|
// we don't slow when standing still, relative to the conveyor.
|
||
|
if (player->GetGroundEntity() != NULL)
|
||
|
{
|
||
|
mv->m_vecVelocity[2] = 0.0;
|
||
|
Friction();
|
||
|
}
|
||
|
|
||
|
// Make sure velocity is valid.
|
||
|
CheckVelocity();
|
||
|
|
||
|
if (player->GetGroundEntity() != NULL)
|
||
|
{
|
||
|
WalkMove2();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AirMove(); // Take into account movement when in air.
|
||
|
}
|
||
|
|
||
|
// Set final flags.
|
||
|
CategorizePosition();
|
||
|
|
||
|
// Now pull the base velocity back out. Base velocity is set if you are on a moving object, like
|
||
|
// a conveyor (or maybe another monster?)
|
||
|
VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity );
|
||
|
|
||
|
// Make sure velocity is valid.
|
||
|
CheckVelocity();
|
||
|
|
||
|
// Add any remaining gravitational component.
|
||
|
FinishGravity();
|
||
|
|
||
|
// If we are on ground, no downward velocity.
|
||
|
if ( player->GetGroundEntity() != NULL )
|
||
|
{
|
||
|
mv->m_vecVelocity[2] = 0;
|
||
|
}
|
||
|
|
||
|
CheckFalling();
|
||
|
}
|