source-engine/game/server/tf2/tf_basefourwheelvehicle.cpp

763 lines
24 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A moving vehicle that is used as a battering ram
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tf_basefourwheelvehicle.h"
#include "engine/IEngineSound.h"
#include "soundenvelope.h"
#include "vcollide_parse.h"
#include "in_buttons.h"
#include "tf_movedata.h"
#define BASEFOURWHEELEDVEHICLE_THINK_CONTEXT "BaseFourWheeledThink"
#define BASEFOURWHEELEDVEHICLE_DEPLOYTHINK_CONTEXT "BaseFourWheeledDeployThink"
// HACK HAC
#define BASEFOURWHEELEDVEHICLE_STOPTHERODEO_CONTEXT "BaseFourWheeledVehicleStopTheRodeoMadnessThink"
ConVar road_feel( "road_feel", "0.1", FCVAR_NOTIFY | FCVAR_REPLICATED );
extern ConVar tf_fastbuild;
BEGIN_DATADESC( CBaseTFFourWheelVehicle )
DEFINE_EMBEDDED( m_VehiclePhysics ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "Throttle", InputThrottle ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "Steer", InputSteering ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "Action", InputAction ),
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ),
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
END_DATADESC()
// Used for debugging to make vehicle deploying go really fast.
ConVar tf_fastdeploy( "tf_fastdeploy", "0", FCVAR_CHEAT );
IMPLEMENT_SERVERCLASS_ST(CBaseTFFourWheelVehicle, DT_BaseTFFourWheelVehicle)
SendPropFloat( SENDINFO( m_flDeployFinishTime ), 0, SPROP_NOSCALE ),
SendPropInt( SENDINFO( m_eDeployMode ), NUM_VEHICLE_DEPLOYMODE_BITS, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_bBoostUpgrade ), 1, SPROP_UNSIGNED ),
SendPropInt( SENDINFO( m_nBoostTimeLeft ), 8, SPROP_UNSIGNED ),
END_SEND_TABLE()
ConVar fourwheelvehicle_hit_damage( "fourwheelvehicle_hit_damage","40", FCVAR_NONE, "Four-wheel vehicle hit damage" );
ConVar fourwheelvehicle_hit_damage_boostmod( "fourwheelvehicle_hit_damage_boostmod", "1.5", FCVAR_NONE, "Four-wheel vehicle boosted hit damage modifier" );
ConVar fourwheelvehicle_hit_mindamagevel( "fourwheelvehicle_hit_mindamagevel","100", FCVAR_NONE, "Four-wheel vehciel hit velocity for min damage" );
ConVar fourwheelvehicle_hit_maxdamagevel( "fourwheelvehicle_hit_maxdamagevel","230", FCVAR_NONE, "Four-wheel vehicle hit velocity for max damage" );
ConVar fourwheelvehicle_impact_time( "fourwheelvehicle_impact_time", "1.0", FCVAR_NONE, "Four-wheel vehicle impact wait time." );
ConVar fourwheelvehicle_hit_damage_player( "fourwheelvehicle_hit_damage_player", "30.0f", FCVAR_NONE, "Four-wheel vehicle hit player damage." );
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
#pragma warning( disable: 4355 )
CBaseTFFourWheelVehicle::CBaseTFFourWheelVehicle() : m_VehiclePhysics(this)
{
m_flDeployFinishTime = -1;
}
#pragma warning( default: 4355 )
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CBaseTFFourWheelVehicle::~CBaseTFFourWheelVehicle ()
{
}
//-----------------------------------------------------------------------------
// Purpose: Put a vehicle in a deploy state. Turn off the engine and run a
// deploy animation.
//-----------------------------------------------------------------------------
bool CBaseTFFourWheelVehicle::Deploy( void )
{
// Make sure we're allowed to deploy here
if ( !IsReadyToDrive() )
return false;
// Check to see if we are already in a deploy mode.
if ( m_eDeployMode != VEHICLE_MODE_NORMAL )
return false;
// Disable the vehicle's motion.
DisableMotion();
// Save pre-deploy activity.
m_PreDeployActivity = GetActivity();
// Set the deploying activity - ACT_DEPLOY
SetActivity( ACT_DEPLOY );
// Get the deployment time.
float flDeployTime = SequenceDuration();
if ( tf_fastdeploy.GetBool() )
flDeployTime = 1;
m_flDeployFinishTime = gpGlobals->curtime + flDeployTime;
SetContextThink( BaseFourWheeledVehicleDeployThink, gpGlobals->curtime + flDeployTime,
BASEFOURWHEELEDVEHICLE_DEPLOYTHINK_CONTEXT );
// Set the deploy mode.
m_eDeployMode = VEHICLE_MODE_DEPLOYING;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Release a vehicle from a deployed state. Run a de-coupling
// animation and turn on the vehicle.
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::UnDeploy( void )
{
// Make sure we are deployed.
if ( !IsDeployed() )
return;
// Enable motion and turn on the vehicle.
EnableMotion();
// Set the undeploying activity - ACT_UNDEPLOY
SetActivity( ACT_UNDEPLOY );
// Get the undeployment time.
float flUnDeployTime = SequenceDuration();
if ( tf_fastdeploy.GetBool() )
flUnDeployTime = 1;
m_flDeployFinishTime = gpGlobals->curtime + flUnDeployTime;
SetContextThink( BaseFourWheeledVehicleDeployThink, gpGlobals->curtime + flUnDeployTime,
BASEFOURWHEELEDVEHICLE_DEPLOYTHINK_CONTEXT );
// Set the deploy mode.
m_eDeployMode = VEHICLE_MODE_UNDEPLOYING;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::CancelDeploy( void )
{
// Check for the deploying state.
if ( !IsDeploying() )
return;
// Re-enable the motion.
EnableMotion();
// Reset the activity to the previous activity.
SetActivity( m_PreDeployActivity );
// Reset the deploy mode.
m_eDeployMode = VEHICLE_MODE_NORMAL;
m_flDeployFinishTime = -1;
// Turn off the context think.
SetContextThink( NULL, 0, BASEFOURWHEELEDVEHICLE_DEPLOYTHINK_CONTEXT );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::BaseFourWheeledVehicleDeployThink( void )
{
// Called from deploy.
if ( IsDeploying() )
{
OnFinishedDeploy();
m_flDeployFinishTime = -1;
}
// Called from undeploy.
else if ( IsUndeploying() )
{
OnFinishedUnDeploy();
m_flDeployFinishTime = -1;
}
// Turn off the context think.
SetContextThink( NULL, 0, BASEFOURWHEELEDVEHICLE_DEPLOYTHINK_CONTEXT );
}
void CBaseTFFourWheelVehicle::BaseFourWheeledVehicleStopTheRodeoMadnessThink( void )
{
// HACK HACK: See note above at FinishBuilding call
// This resets the handbrake, so the newly placed object doesn't roll down any hills.
m_VehiclePhysics.ResetControls();
// Turn off the context think.
SetContextThink( NULL, 0, BASEFOURWHEELEDVEHICLE_STOPTHERODEO_CONTEXT );
// Start our base think
SetContextThink( BaseFourWheeledVehicleThink, gpGlobals->curtime + 0.1, BASEFOURWHEELEDVEHICLE_THINK_CONTEXT );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::OnFinishedDeploy( void )
{
SetActivity( ACT_DEPLOY_IDLE );
m_eDeployMode = VEHICLE_MODE_DEPLOYED;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::OnFinishedUnDeploy( void )
{
m_eDeployMode = VEHICLE_MODE_NORMAL;
}
//-----------------------------------------------------------------------------
// Purpose: Allow the vehicle to move.
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::EnableMotion( void )
{
// Enable vehicle chasis motion.
IPhysicsObject *pVehicleObject = VPhysicsGetObject();
if ( pVehicleObject )
{
pVehicleObject->EnableMotion( true );
}
// Enable motion on the tires.
m_VehiclePhysics.EnableMotion();
}
//-----------------------------------------------------------------------------
// Purpose: Dis-allow the vehicle to move.
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::DisableMotion( void )
{
// Disable vehicle chasis motion.
IPhysicsObject *pVehicleObject = VPhysicsGetObject();
if ( pVehicleObject )
{
pVehicleObject->EnableMotion( false );
}
// Disable motion on the tires.
m_VehiclePhysics.DisableMotion();
}
//-----------------------------------------------------------------------------
// Precache
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::Precache()
{
BaseClass::Precache();
PrecacheScriptSound( "BaseTFFourWheelVehicle.EMP" );
PrecacheScriptSound( "BaseTFFourWheelVehicle.RamSound" );
}
//-----------------------------------------------------------------------------
// Spawn
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::Spawn( )
{
SetModel( STRING( GetModelName() ) );
// CFourWheelServerVehicle *pServerVehicle = dynamic_cast<CFourWheelServerVehicle*>(GetServerVehicle());
// m_VehiclePhysics.SetOuter( this, pServerVehicle );
m_VehiclePhysics.Spawn();
BaseClass::Spawn();
// The base class spawn sets a default collision group, so this needs to
// be called post.
SetCollisionGroup( COLLISION_GROUP_VEHICLE );
m_eDeployMode = VEHICLE_MODE_NORMAL;
SetBoostUpgrade( false );
m_flNextHitTime = 0.0f;
}
//-----------------------------------------------------------------------------
// Teleport
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity )
{
// We basically just have to make sure the wheels are in the right place
// after teleportation occurs
matrix3x4_t startMatrixInv;
MatrixInvert( EntityToWorldTransform(), startMatrixInv );
BaseClass::Teleport( newPosition, newAngles, newVelocity );
// Teleport the vehicle physics from the starting position to the ending one
matrix3x4_t relativeTransform;
ConcatTransforms( EntityToWorldTransform(), startMatrixInv, relativeTransform );
m_VehiclePhysics.Teleport( relativeTransform );
}
//-----------------------------------------------------------------------------
// Debugging methods
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::DrawDebugGeometryOverlays()
{
if (m_debugOverlays & OVERLAY_BBOX_BIT)
{
m_VehiclePhysics.DrawDebugGeometryOverlays();
}
BaseClass::DrawDebugGeometryOverlays();
}
int CBaseTFFourWheelVehicle::DrawDebugTextOverlays()
{
int nOffset = BaseClass::DrawDebugTextOverlays();
if (m_debugOverlays & OVERLAY_TEXT_BIT)
{
nOffset = m_VehiclePhysics.DrawDebugTextOverlays( nOffset );
}
return nOffset;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseTFFourWheelVehicle::StartBuilding( CBaseEntity *pPlayer )
{
if (!BaseClass::StartBuilding(pPlayer))
return false;
// Until we're finished building, turn off vphysics-based motion
SetSolid( SOLID_VPHYSICS );
VPhysicsInitStatic();
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::FinishedBuilding( void )
{
BaseClass::FinishedBuilding();
char pScriptName[128];
Q_snprintf( pScriptName, sizeof( pScriptName ), "scripts/vehicles/%s.txt", GetClassname() );
m_VehiclePhysics.Initialize( pScriptName, true );
// HACK HACK: This is a hack to avoid physics spazzing out on a newly created vehicle with the handbrake
// set. We create and activate it, but then release the handbrake for a single Think function call and
// then zero out the controls right then. This seems to stabilize something in the physics simulator.
m_VehiclePhysics.ReleaseHandbrake();
SetContextThink( BaseFourWheeledVehicleStopTheRodeoMadnessThink, gpGlobals->curtime, BASEFOURWHEELEDVEHICLE_STOPTHERODEO_CONTEXT );
ResetDeteriorationTime();
}
//-----------------------------------------------------------------------------
// Input methods
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::InputThrottle( inputdata_t &inputdata )
{
m_VehiclePhysics.SetThrottle( inputdata.value.Float() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::InputSteering( inputdata_t &inputdata )
{
m_VehiclePhysics.SetSteering( inputdata.value.Float(), 2*gpGlobals->frametime );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::InputAction( inputdata_t &inputdata )
{
m_VehiclePhysics.SetAction( inputdata.value.Float() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::InputTurnOn( inputdata_t &inputdata )
{
if (!m_VehiclePhysics.IsOn())
{
SetContextThink( BaseFourWheeledVehicleThink, gpGlobals->curtime + 0.1, BASEFOURWHEELEDVEHICLE_THINK_CONTEXT );
m_VehiclePhysics.TurnOn( );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::InputTurnOff( inputdata_t &inputdata )
{
if ( m_VehiclePhysics.IsOn() )
{
m_VehiclePhysics.TurnOff( );
}
}
//-----------------------------------------------------------------------------
// Input methods
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::BaseFourWheeledVehicleThink()
{
if (m_VehiclePhysics.Think())
{
SetNextThink( gpGlobals->curtime, BASEFOURWHEELEDVEHICLE_THINK_CONTEXT );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::VPhysicsUpdate( IPhysicsObject *pPhysics )
{
// must be a wheel
if (!m_VehiclePhysics.VPhysicsUpdate(pPhysics))
return;
BaseClass::VPhysicsUpdate( pPhysics );
}
//-----------------------------------------------------------------------------
// Methods related to getting in and out of the vehicle
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::SetPassenger( int nRole, CBasePlayer *pEnt )
{
if ( nRole == VEHICLE_ROLE_DRIVER )
{
if (pEnt)
{
PlayerControlInit( ToBasePlayer(pEnt) );
}
else
{
PlayerControlShutdown( );
}
}
BaseClass::SetPassenger( nRole, pEnt );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::PlayerControlInit( CBasePlayer *pPlayer )
{
// Blat out the view offset
m_savedViewOffset = pPlayer->GetViewOffset();
pPlayer->SetViewOffset( vec3_origin );
m_playerOn.FireOutput( pPlayer, this, 0 );
InputTurnOn( inputdata_t() );
// Release the handbrake.
if ( !IsDeployed() )
{
m_VehiclePhysics.ReleaseHandbrake();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::ResetUseKey( CBasePlayer *pPlayer )
{
pPlayer->m_afButtonPressed &= ~IN_USE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::PlayerControlShutdown()
{
CBasePlayer *pPlayer = GetDriverPlayer();
if ( !pPlayer )
return;
ResetUseKey( pPlayer );
pPlayer->SetViewOffset( m_savedViewOffset );
m_playerOff.FireOutput( pPlayer, this, 0 );
// clear out the fire buttons
m_attackaxis.Set( 0, pPlayer, this );
m_attack2axis.Set( 0, pPlayer, this );
InputTurnOff( inputdata_t() );
}
//-----------------------------------------------------------------------------
// Purpose: Powerup has just started
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::PowerupStart( int iPowerup, float flAmount, CBaseEntity *pAttacker, CDamageModifier *pDamageModifier )
{
switch( iPowerup )
{
case POWERUP_EMP:
m_VehiclePhysics.SetMaxThrottle( 0.1 );
break;
default:
break;
}
BaseClass::PowerupStart( iPowerup, flAmount, pAttacker, pDamageModifier );
}
//-----------------------------------------------------------------------------
// Purpose: Powerup has just started
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::PowerupEnd( int iPowerup )
{
switch ( iPowerup )
{
case POWERUP_EMP:
m_VehiclePhysics.SetMaxThrottle( 1.0 );
break;
default:
break;
}
BaseClass::PowerupEnd( iPowerup );
}
//-----------------------------------------------------------------------------
// Methods related to actually driving the vehicle
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd )
{
// Lose control when the player dies
if ( pPlayer->IsAlive() == false )
return;
// Only the driver gets to drive.
int nRole = GetPassengerRole( pPlayer );
if ( nRole != VEHICLE_ROLE_DRIVER )
return;
// No driving in the mothership, kids
if ( !tf_fastbuild.GetInt() && !IsReadyToDrive() )
{
m_VehiclePhysics.SetHandbrake( true );
m_VehiclePhysics.SetThrottle( 0 );
m_VehiclePhysics.SetSteering( 0, 0 );
m_attackaxis.Set( 0, pPlayer, this );
m_attack2axis.Set( 0, pPlayer, this );
return;
}
// Update the boost time.
m_nBoostTimeLeft = m_VehiclePhysics.BoostTimeLeft();
// If the vehicle's emped, it can't drive
if ( HasPowerup( POWERUP_EMP ) )
{
// Play sounds if they're trying to drive
if ( ucmd->buttons & (IN_MOVELEFT | IN_MOVERIGHT | IN_FORWARD | IN_BACK) )
{
if ( m_flNextEmpSound < gpGlobals->curtime )
{
EmitSound( "BaseTFFourWheelVehicle.EMP" );
m_flNextEmpSound = gpGlobals->curtime + 2.0;
}
}
}
ResetDeteriorationTime();
m_VehiclePhysics.UpdateDriverControls( ucmd, TICK_INTERVAL );
float attack = 0, attack2 = 0;
if ( pPlayer->m_afButtonPressed & IN_ATTACK )
{
m_pressedAttack.FireOutput( pPlayer, this, 0 );
}
if ( pPlayer->m_afButtonPressed & IN_ATTACK2 )
{
m_pressedAttack2.FireOutput( pPlayer, this, 0 );
}
if ( ucmd->buttons & IN_ATTACK )
{
attack = 1;
}
if ( ucmd->buttons & IN_ATTACK2 )
{
attack2 = 1;
}
m_attackaxis.Set( attack, pPlayer, this );
m_attack2axis.Set( attack2, pPlayer, this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::SetupMove( CBasePlayer *pPlayer, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
{
BaseClass::SetupMove( pPlayer, ucmd, pHelper, move );
if ( IsDeployed() )
return;
DriveVehicle( pPlayer, ucmd );
m_nMovementRole = GetPassengerRole( pPlayer );
Assert( m_nMovementRole >= 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::SetBoostUpgrade( bool bBoostUpgrade )
{
m_bBoostUpgrade = bBoostUpgrade;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseTFFourWheelVehicle::IsBoostable( void )
{
return m_bBoostUpgrade;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::StartBoost( void )
{
if ( IsBoostable() )
{
m_VehiclePhysics.SetBoost( 1.0f );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseTFFourWheelVehicle::IsBoosting( void )
{
return m_VehiclePhysics.IsBoosting();
}
//-----------------------------------------------------------------------------
// Purpose: Vehicle damage!
//-----------------------------------------------------------------------------
void CBaseTFFourWheelVehicle::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent )
{
BaseClass::VPhysicsCollision( index, pEvent );
int otherIndex = !index;
CBaseEntity *pEntity = pEvent->pEntities[otherIndex];
// We only damage objects...
// And only if we're travelling fast enough...
Assert( pEntity );
if ( !pEntity->IsSolid() )
return;
// Ignore shields..
if ( pEntity->GetCollisionGroup() == TFCOLLISION_GROUP_SHIELD )
return;
// Ignore anything that's not an object
if ( pEntity->Classify() != CLASS_MILITARY && !pEntity->IsPlayer() )
return;
// Ignore teammates
if ( InSameTeam( pEntity ))
return;
// Ignore invulnerable stuff
if ( pEntity->m_takedamage == DAMAGE_NO )
return;
// See if we can damage again? (Time-based)
if ( m_flNextHitTime > gpGlobals->curtime )
return;
// Do damage based on velocity.
Vector vecVelocity = pEvent->preVelocity[index];
CTakeDamageInfo info;
info.SetInflictor( this );
info.SetAttacker( GetDriverPlayer() );
info.SetDamageType( DMG_CLUB );
float flMaxDamage = fourwheelvehicle_hit_damage.GetFloat();
float flMaxDamageVel = fourwheelvehicle_hit_maxdamagevel.GetFloat();
float flMinDamageVel = fourwheelvehicle_hit_mindamagevel.GetFloat();
float flVel = vecVelocity.Length();
if ( flVel < flMinDamageVel )
return;
EmitSound( "BaseTFFourWheelVehicle.RamSound" );
float flDamageFactor = flMaxDamage;
// Special damage for players.
if ( pEntity->IsPlayer() )
{
flDamageFactor = fourwheelvehicle_hit_damage_player.GetFloat();
if ( IsBoosting() )
{
flDamageFactor *= 4.0f;
}
// Knock the player up into the air
float flForceScale = (flVel*0.5) * 75 * 4;
Vector vecForce = vecVelocity;
VectorNormalize( vecForce );
vecForce.z += 0.7;
vecForce *= flForceScale;
info.SetDamageForce( vecForce );
}
// Damage to objects.
else
{
if ( IsBoosting() )
{
flDamageFactor *= fourwheelvehicle_hit_damage_boostmod.GetFloat();
}
if ( ( flMaxDamageVel > flMinDamageVel ) && ( flVel < flMaxDamageVel ) )
{
// Use less damage when we're not moving fast enough
float flVelocityFactor = ( flVel - flMinDamageVel ) / ( flMaxDamageVel - flMinDamageVel );
flVelocityFactor *= flVelocityFactor;
flDamageFactor *= flVelocityFactor;
}
}
info.SetDamage( flDamageFactor );
Vector damagePos;
pEvent->pInternalData->GetContactPoint( damagePos );
Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass();
info.SetDamageForce( damageForce );
info.SetDamagePosition( damagePos );
PhysCallbackDamage( pEntity, info, *pEvent, index );
// Set next time hit time
m_flNextHitTime = gpGlobals->curtime + fourwheelvehicle_impact_time.GetFloat();
}