diff options
Diffstat (limited to 'game/server/hl2/vehicle_jetski.cpp')
| -rw-r--r-- | game/server/hl2/vehicle_jetski.cpp | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/game/server/hl2/vehicle_jetski.cpp b/game/server/hl2/vehicle_jetski.cpp new file mode 100644 index 0000000..41935d1 --- /dev/null +++ b/game/server/hl2/vehicle_jetski.cpp @@ -0,0 +1,552 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "vehicle_base.h" +#include "engine/IEngineSound.h" +#include "in_buttons.h" +#include "ammodef.h" +#include "IEffects.h" +#include "beam_shared.h" +#include "weapon_gauss.h" +#include "soundenvelope.h" +#include "decals.h" +#include "soundent.h" +#include "te_effect_dispatch.h" + +#define VEHICLE_HITBOX_DRIVER 1 + +#define JETSKI_SHOCK_LENGTH_LONG2 0.35f // +#define JETSKI_SHOCK_LENGTH_LONG 0.25f // meters (about 12 inches) +#define JETSKI_SHOCK_LENGTH_REST 0.15f // meters (about 8 inches) +#define JETSKI_SHOCK_LENGTH_SHORT 0.1f // meters (about 4 inches) + +#define JETSKI_PITCH_AND_ROLL_RATE 0.02f + +#define JETSKI_FRICTION_MIN 0.3f +#define JETSKI_FRICTION_MAX 0.8f + +#define JETSKI_SPLASH_DISTANCE 40.0f +#define JETSKI_SPLASH_SPRAY 1 +#define JETSKI_SPLASH_SPRAY_SIZE 2.0f +#define JETSKI_SPLASH_GURGLE 2 +#define JETSKI_SPLASH_GURGLE_SIZE 8.0f +#define JETSKI_SPLASH_RIPPLE 3 +#define JETSKI_SPLASH_RIPPLE_SIZE 10.0f + +#define JETSKI_DRAG_NO_THRUST_IN_WATER 10.0f +#define JETSKI_DRAG_NO_THRUST_ON_WATER 30.0f +#define JETSKI_DRAG_LEAN_ADD 10.0f +#define JETSKI_DRAG_IN_REVERSE 10.0f +#define JETSKI_DRAG_IN_THRUST 5.0f + +#define JETSKI_STEERING_EPS 0.01f +#define JETSKI_STEERING_IN_PLACE 90.0f +#define JETSKI_STEERING_NORMAL 45.0f +#define JETSKI_STEERING_LEAN 60.0f + +#define JETSKI_ROTATE_IN_PLACE_RATIO 0.35f + +class CPropJetski : public CPropVehicleDriveable +{ + DECLARE_CLASS( CPropJetski, CPropVehicleDriveable ); + DECLARE_DATADESC(); + +public: + + // CPropVehicle + virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); + virtual void DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ); + virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); + + // CBaseEntity + void Think(void); + void Precache( void ); + void Spawn( void ); + + virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); + virtual int OnTakeDamage( const CTakeDamageInfo &info ); + +private: + + void OnTurn( CUserCmd *ucmd ); + void OnSpeed( CUserCmd *ucmd ); + void UpdateTurnAndSpeed( void ); + + void CreateSplash( int nSplashType ); + + bool UpdateLean( CUserCmd *ucmd ); + float CalculateFriction( CUserCmd *ucmd ); + float CalculateDrag( CUserCmd *ucmd ); + +private: + + float m_flSpringLengthApproach[4]; // + float m_flFrictionWheels[4]; + + float m_flHandbrakeTime; // handbrake after the fact to keep vehicles from rolling + bool m_bInitialHandbrake; + + float m_springLen[4]; + IPhysicsVehicleController *m_pVehicle; +}; + +LINK_ENTITY_TO_CLASS( prop_vehicle_jetski, CPropJetski ); + +//--------------------------------------------------------- +// Save/Restore +//--------------------------------------------------------- +BEGIN_DATADESC( CPropJetski ) + + DEFINE_AUTO_ARRAY( m_flSpringLengthApproach, FIELD_FLOAT ), + DEFINE_AUTO_ARRAY( m_flFrictionWheels, FIELD_FLOAT ), + DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), + DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ), + DEFINE_AUTO_ARRAY( m_springLen, FIELD_FLOAT ), + DEFINE_PHYSPTR( m_pVehicle ), + +END_DATADESC() + + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::Precache( void ) +{ + BaseClass::Precache(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::Spawn( void ) +{ + // Setup vehicle as a ray-cast jetski. + SetVehicleType( VEHICLE_TYPE_JETSKI_RAYCAST ); + + BaseClass::Spawn(); + + // Handbrake data. + m_flHandbrakeTime = gpGlobals->curtime + 0.1; + m_bInitialHandbrake = false; + m_VehiclePhysics.SetHasBrakePedal( false ); + + // Slow reverse. + m_VehiclePhysics.SetMaxReverseThrottle( -0.3f ); + + // Setup vehicle variables. + m_pVehicle = m_VehiclePhysics.GetVehicle(); + for ( int i = 0; i < 4; i++ ) + { + m_springLen[i] = JETSKI_SHOCK_LENGTH_REST; + } + + m_takedamage = DAMAGE_EVENTS_ONLY; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) +{ + if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER ) + { + if ( m_hPlayer != NULL ) + { + m_hPlayer->TakeDamage( info ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CPropJetski::OnTakeDamage( const CTakeDamageInfo &info ) +{ + //Do scaled up physic damage to the car + CTakeDamageInfo physDmg = info; + physDmg.ScaleDamage( 25 ); + VPhysicsTakeDamage( physDmg ); + + //Check to do damage to driver + if ( m_hPlayer != NULL ) + { + //Take no damage from physics damages + if ( info.GetDamageType() & DMG_CRUSH ) + return 0; + + //Take the damage + m_hPlayer->TakeDamage( info ); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::Think(void) +{ + BaseClass::Think(); + + // set handbrake after physics sim settles down + if ( gpGlobals->curtime < m_flHandbrakeTime ) + { + SetNextThink( gpGlobals->curtime ); + } + else if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake + { + m_bInitialHandbrake = true; + m_VehiclePhysics.SetHandbrake( true ); + m_VehiclePhysics.Think(); + } + + + // play enter animation + if ( (m_bEnterAnimOn || m_bExitAnimOn) && !IsSequenceFinished() ) + { + StudioFrameAdvance(); + } + else if ( IsSequenceFinished() ) + { + if ( m_bExitAnimOn ) + { + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + if ( pPlayer ) + { + pPlayer->LeaveVehicle(); // now that sequence is finished, leave car + Vector vecEyes; + QAngle vecEyeAng; + GetAttachment( "vehicle_driver_eyes", vecEyes, vecEyeAng ); + vecEyeAng.x = 0; + vecEyeAng.z = 0; + pPlayer->SnapEyeAngles( vecEyeAng ); + } + m_bExitAnimOn = false; + } + int iSequence = SelectWeightedSequence( ACT_IDLE ); + if ( iSequence > ACTIVITY_NOT_AVAILABLE ) + { + m_flCycle = 0; + m_flAnimTime = gpGlobals->curtime; + ResetSequence( iSequence ); + ResetClientsideFrame(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::OnTurn( CUserCmd *ucmd ) +{ +#if 0 + // Check for lean and adjust the turning radius accordingly. + if ( ucmd->buttons & IN_JUMP ) + { + m_VehiclePhysics.SetSteeringDegrees( JETSKI_STEERING_LEAN ); + } + else + { + m_VehiclePhysics.SetSteeringDegrees( JETSKI_STEERING_NORMAL ); + } + +#endif + float flSteering = m_VehiclePhysics.GetSteering(); + bool bLeft = ( flSteering < -JETSKI_STEERING_EPS ); + bool bRight = ( flSteering > JETSKI_STEERING_EPS ); + + float flAbsSteering = fabsf( flSteering ); + float flInvAbsSteering = 1.0f - flAbsSteering; + + // Get the speed and ratio to max speed. + float flSpeed = m_VehiclePhysics.GetSpeed(); + float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); + float flRatio = flSpeed / flMaxSpeed; + float flScale = 1.0f - flRatio; + flScale *= 0.95f; + flScale += 0.05f; + + flAbsSteering *= flScale; + flInvAbsSteering *= flScale; + + m_flSpringLengthApproach[0] = JETSKI_SHOCK_LENGTH_SHORT; // Front-Left + m_flSpringLengthApproach[1] = JETSKI_SHOCK_LENGTH_SHORT; // Front-Right + m_flSpringLengthApproach[2] = JETSKI_SHOCK_LENGTH_SHORT; // Back-Left + m_flSpringLengthApproach[3] = JETSKI_SHOCK_LENGTH_SHORT; // Back-Right + + return; + + // Roll right. + if( bRight ) + { + float flLengthRight = JETSKI_SHOCK_LENGTH_SHORT + ( JETSKI_SHOCK_LENGTH_REST - JETSKI_SHOCK_LENGTH_SHORT ) * flInvAbsSteering; + float flLengthLeft = JETSKI_SHOCK_LENGTH_REST + ( JETSKI_SHOCK_LENGTH_LONG - JETSKI_SHOCK_LENGTH_REST ) * flAbsSteering; + + m_flSpringLengthApproach[0] = flLengthLeft; // Front-Left + m_flSpringLengthApproach[1] = flLengthRight; // Front-Right + m_flSpringLengthApproach[2] = flLengthLeft; // Back-Left + m_flSpringLengthApproach[3] = flLengthRight; // Back-Right + } + // Roll left. + else if ( bLeft ) + { + float flLengthRight = JETSKI_SHOCK_LENGTH_REST + ( JETSKI_SHOCK_LENGTH_LONG - JETSKI_SHOCK_LENGTH_REST ) * flAbsSteering; + float flLengthLeft = JETSKI_SHOCK_LENGTH_SHORT + ( JETSKI_SHOCK_LENGTH_REST - JETSKI_SHOCK_LENGTH_SHORT ) * flInvAbsSteering; + + m_flSpringLengthApproach[0] = flLengthLeft; // Front-Left + m_flSpringLengthApproach[1] = flLengthRight; // Front-Right + m_flSpringLengthApproach[2] = flLengthLeft; // Back-Left + m_flSpringLengthApproach[3] = flLengthRight; // Back-Right + } + // Return springs to their normal height + else + { + m_flSpringLengthApproach[0] = JETSKI_SHOCK_LENGTH_REST; // Front-Left + m_flSpringLengthApproach[1] = JETSKI_SHOCK_LENGTH_REST; // Front-Right + m_flSpringLengthApproach[2] = JETSKI_SHOCK_LENGTH_REST; // Back-Left + m_flSpringLengthApproach[3] = JETSKI_SHOCK_LENGTH_REST; // Back-Right + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CPropJetski::UpdateLean( CUserCmd *ucmd ) +{ + // Are we leaning back? + if ( ucmd->buttons & IN_JUMP ) + { + m_pVehicle->SetLeanBack( true ); + return true; + } + + m_pVehicle->SetLeanBack( false ); + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CPropJetski::CalculateFriction( CUserCmd *ucmd ) +{ + // Get the speed and ratio to max speed. + float flSpeed = m_VehiclePhysics.GetSpeed(); + float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); + float flRatio = flSpeed / flMaxSpeed; + + float flFriction = JETSKI_FRICTION_MAX; + + flRatio = 1.0f - ( float )pow( flRatio, 4 ); + flFriction = JETSKI_FRICTION_MIN + ( JETSKI_FRICTION_MAX - JETSKI_FRICTION_MIN ) * flRatio; + + flFriction = clamp( flFriction, JETSKI_FRICTION_MIN, JETSKI_FRICTION_MAX ); + + // Debug! + Msg( "Speed = %f, Friction = %f", flSpeed, flFriction ); + + return flFriction; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CPropJetski::CalculateDrag( CUserCmd *ucmd ) +{ + // Get the speed and ratio to max speed. + float flSpeed = m_VehiclePhysics.GetSpeed(); + float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); + float flRatio = flSpeed / flMaxSpeed; + + float flDrag = 0.0f; + + bool bLean = UpdateLean( ucmd ); + +#if 0 + if ( bLean ) + { + flDrag += JETSKI_DRAG_LEAN_ADD; + } + float flNormalizedRatio = ( flRatio - 0.4f ) * 1.667f; + float flSplineRatio = SimpleSpline( flNormalizedRatio ); + + flFriction = JETSKI_FRICTION_MAX + ( JETSKI_FRICTION_MIN - JETSKI_FRICTION_MAX ) * flSplineRatio; + flDrag = JETSKI_DRAG_IN_WATER + ( JETSKI_DRAG_ON_WATER - JETSKI_DRAG_IN_WATER ) * flNormalizedRatio; + + // Leaning backwards. + if ( bLean ) + { + flDrag += JETSKI_DRAG_LEAN_ADD; + } + } + +#define JETSKI_DRAG_NO_THRUST_IN_WATER 10.0f +#define JETSKI_DRAG_NO_THRUST_ON_WATER 30.0f +#define JETSKI_DRAG_LEAN_ADD 10.0f +#define JETSKI_DRAG_IN_REVERSE 10.0f +#define JETSKI_DRAG_IN_THRUST 5.0f +#endif + + // Debug + Msg( "Drag = %f\n", flDrag ); + + return flDrag; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::OnSpeed( CUserCmd *ucmd ) +{ + // Get the physics object so we can adjust the drag. + IPhysicsObject *pPhysJetski = VPhysicsGetObject(); + if ( !pPhysJetski ) + return; + + float flFriction = CalculateFriction( ucmd ); + float flDrag = CalculateDrag( ucmd ); + + // Update the friction of the jetski "fake wheels." + for ( int iWheel = 0; iWheel < 4; ++iWheel ) + { + m_flFrictionWheels[iWheel] = flFriction; + } + + // Update the Damp coefficient on the jetski. + float flZero = 0.0f; + pPhysJetski->SetDragCoefficient( &flDrag, &flZero ); + +#if 0 + // Splash effects. + if ( flRatio > 0.1f ) + { + CreateSplash( JETSKI_SPLASH_RIPPLE ); + } + + float flRandom = random->RandomFloat( 0.0f, 1.0f ); + if ( flRatio > 0.8f && flRandom < 0.15f ) + { + CreateSplash( JETSKI_SPLASH_SPRAY ); + } +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::UpdateTurnAndSpeed( void ) +{ +#if 1 + // Update springs. + m_springLen[0] = UTIL_Approach( m_flSpringLengthApproach[0], m_springLen[0], JETSKI_PITCH_AND_ROLL_RATE ); + m_pVehicle->SetSpringLength( 0, m_springLen[0] ); + m_springLen[1] = UTIL_Approach( m_flSpringLengthApproach[1], m_springLen[1], JETSKI_PITCH_AND_ROLL_RATE ); + m_pVehicle->SetSpringLength( 1, m_springLen[1] ); + m_springLen[2] = UTIL_Approach( m_flSpringLengthApproach[2], m_springLen[2], JETSKI_PITCH_AND_ROLL_RATE ); + m_pVehicle->SetSpringLength( 2, m_springLen[2] ); + m_springLen[3] = UTIL_Approach( m_flSpringLengthApproach[3], m_springLen[3], JETSKI_PITCH_AND_ROLL_RATE ); + m_pVehicle->SetSpringLength( 3, m_springLen[3] ); +#endif + + // Update wheel frictions. + for ( int iWheel = 0; iWheel < 4; ++iWheel ) + { + m_pVehicle->SetWheelFriction( iWheel, m_flFrictionWheels[iWheel] ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ) +{ + //Lose control when the player dies + if ( pPlayer->IsAlive() == false ) + return; + + OnTurn( ucmd ); + OnSpeed( ucmd ); + UpdateTurnAndSpeed(); + + m_VehiclePhysics.UpdateDriverControls( ucmd, ucmd->frametime ); + + // Save this data. + m_nSpeed = m_VehiclePhysics.GetSpeed(); + m_nRPM = m_VehiclePhysics.GetRPM(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pPlayer - +// *pMoveData - +//----------------------------------------------------------------------------- +void CPropJetski::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) +{ + BaseClass::ProcessMovement( pPlayer, pMoveData ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) +{ + DriveVehicle( player, ucmd ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropJetski::CreateSplash( int nSplashType ) +{ + Vector vecSplashPoint; + QAngle vecSplashAngles; + GetAttachment( "splash_pt", vecSplashPoint, vecSplashAngles ); + + Vector vecForward, vecUp; + AngleVectors( vecSplashAngles, &vecForward, &vecUp, NULL ); + + CEffectData data; + data.m_vOrigin = vecSplashPoint; + + switch ( nSplashType ) + { + case JETSKI_SPLASH_SPRAY: + { + Vector vecSplashDir; + vecSplashDir = ( vecForward + vecUp ) * 0.5f; + VectorNormalize( vecSplashDir ); + data.m_vNormal = vecSplashDir; + data.m_flScale = JETSKI_SPLASH_SPRAY_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_SPRAY_SIZE * 0.25 ); + DispatchEffect( "waterripple", data ); + DispatchEffect( "watersplash", data ); + } + case JETSKI_SPLASH_GURGLE: + { + Vector vecSplashDir; + vecSplashDir = vecUp; + data.m_vNormal = vecSplashDir; + + data.m_flScale = JETSKI_SPLASH_GURGLE_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_GURGLE_SIZE * 0.25 ); + DispatchEffect( "waterripple", data ); + DispatchEffect( "watersplash", data ); + } + case JETSKI_SPLASH_RIPPLE: + { + Vector vecSplashDir; + vecSplashDir = vecUp; + data.m_vNormal = vecSplashDir; + data.m_flScale = JETSKI_SPLASH_RIPPLE_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_RIPPLE_SIZE * 0.25 ); + DispatchEffect( "waterripple", data ); + } + default: + { + return; + } + } +}
\ No newline at end of file |