Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "cbase.h"
- #include "prop_sfr_vehicle.h"
- #include "in_buttons.h"
- #include "env_player_surface_trigger.h"
- #include "fourwheelvehiclephysics.h"
- #include "vehicle_viewblend_shared.h"
- ConVar r_VehicleViewDampenFreq( "r_VehicleViewDampenFreq", "7.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED );
- ConVar r_VehicleViewDampenDamp( "r_VehicleViewDampenDamp", "1.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED);
- ConVar r_VehicleViewZHeight( "r_VehicleViewZHeight", "10.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED );
- #define SMOOTHING_FACTOR 0.9
- #define SF_PROP_SFR_VEHICLE_ALWAYSTHINK 0x00000001
- IMPLEMENT_SERVERCLASS_ST(CPropSFRVehicle, DT_PropSFRVehicle)
- SendPropEHandle(SENDINFO(m_hPlayer)),
- SendPropBool( SENDINFO( m_bIsOn ) ),
- // // We need to send a hi-res origin to avoid prediction errors sliding along walls
- SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ),
- // send a hi-res origin to the local player for use in prediction
- SendPropVectorXY(SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_OriginXY ),
- SendPropFloat (SENDINFO_VECTORELEM(m_vecOrigin, 2), -1, SPROP_NOSCALE | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_OriginZ ),
- SendPropFloat ( SENDINFO_VECTORELEM(m_vecVelocity, 0), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
- SendPropFloat ( SENDINFO_VECTORELEM(m_vecVelocity, 1), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
- SendPropFloat ( SENDINFO_VECTORELEM(m_vecVelocity, 2), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
- //
- // SendPropExclude( "DT_BaseEntity", "m_angRotation" ),
- //#if PREDICTION_ERROR_CHECK_LEVEL > 1
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesX ),
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesY ),
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesZ ),
- //#else
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesX ),
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesY ),
- // SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesZ ),
- //#endif
- END_SEND_TABLE();
- BEGIN_DATADESC( CPropSFRVehicle )
- DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ),
- // Keys
- DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "VehicleScript" ),
- DEFINE_FIELD( m_vecSmoothedVelocity, FIELD_VECTOR ),
- DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
- // Inputs
- DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ),
- // Outputs
- DEFINE_OUTPUT( m_playerOn, "PlayerOn" ),
- DEFINE_OUTPUT( m_playerOff, "PlayerOff" ),
- END_DATADESC()
- LINK_ENTITY_TO_CLASS( sfr_vehicle, CPropSFRVehicle );
- CPropSFRVehicle::CPropSFRVehicle()
- {
- m_flTimeLastEnterExit= 0;
- }
- CPropSFRVehicle::~CPropSFRVehicle()
- {
- }
- void CPropSFRVehicle::Precache( void )
- {
- BaseClass::Precache();
- }
- void CPropSFRVehicle::Spawn( void )
- {
- SetVehicle( this ); //psy : set this here because the baseclass is retarded !
- // NOTE: The model has to be set before we can spawn vehicle physics
- BaseClass::Spawn();
- SetNextThink( gpGlobals->curtime );
- SetCollisionGroup( COLLISION_GROUP_VEHICLE );
- m_vecSmoothedVelocity.Init();
- m_takedamage = DAMAGE_EVENTS_ONLY;
- }
- void CPropSFRVehicle::Think( void )
- {
- // Derived classes of CPropVehicle have their own code to determine how frequently to think.
- // But the prop_vehicle entity native to this class will only think one time, so this flag
- // was added to allow prop_vehicle to always think without affecting the derived classes.
- if( HasSpawnFlags(SF_PROP_SFR_VEHICLE_ALWAYSTHINK) )
- {
- SetNextThink(gpGlobals->curtime);
- }
- if ( ShouldThink() )
- {
- SetNextThink( gpGlobals->curtime );
- }
- }
- void CPropSFRVehicle::VPhysicsUpdate( IPhysicsObject *pPhysics )
- {
- if ( IsMarkedForDeletion() )
- return;
- Vector velocity;
- VPhysicsGetObject()->GetVelocity( &velocity, NULL );
- //Update our smoothed velocity
- m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + velocity * ( 1 - SMOOTHING_FACTOR );
- BaseClass::VPhysicsUpdate( pPhysics );
- }
- void CPropSFRVehicle::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info )
- {
- CBaseEntity *pDriver = GetDriver();
- if ( pDriver != NULL )
- {
- pDriver->Event_KilledOther( pVictim, info );
- }
- BaseClass::Event_KilledOther( pVictim, info );
- }
- Vector CPropSFRVehicle::GetSmoothedVelocity( void )
- {
- BaseClass::GetSmoothedVelocity();
- return m_vecSmoothedVelocity;
- }
- void CPropSFRVehicle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
- {
- CBasePlayer *pPlayer = ToBasePlayer( pActivator );
- if ( !pPlayer )
- return;
- if( pPlayer == GetPassenger( VEHICLE_ROLE_DRIVER ) ) //psy: avoid resetting and trying to climb in the vehicle we're in please !
- return;
- ResetUseKey( pPlayer );
- HandlePassengerEntry( pPlayer, (value>0) );
- }
- void CPropSFRVehicle::ResetUseKey( CBasePlayer *pPlayer )
- {
- pPlayer->m_afButtonPressed &= ~IN_USE;
- }
- bool CPropSFRVehicle::CanEnterVehicle( CBaseEntity *pEntity )
- {
- return true;
- }
- bool CPropSFRVehicle::CanExitVehicle( CBaseEntity *pEntity )
- {
- return true;
- }
- void CPropSFRVehicle::EnterVehicle( CBaseCombatCharacter *pPassenger )
- {
- if ( pPassenger == NULL )
- return;
- CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
- if ( pPlayer != NULL )
- {
- // Remove any player who may be in the vehicle at the moment
- if ( m_hPlayer )
- {
- ExitVehicle( VEHICLE_ROLE_DRIVER );
- }
- m_hPlayer = pPlayer;
- //m_playerOn.FireOutput( pPlayer, this, 0 );
- // Don't start the engine if the player's using an entry animation,
- // because we want to start the engine once the animation is done.
- StartEngine();
- // Start Thinking
- SetNextThink( gpGlobals->curtime );
- m_flTimeLastEnterExit = gpGlobals->curtime;
- m_playerOn.FireOutput( pPlayer, this );
- TurnOn();
- }
- else
- {
- // NPCs are not yet supported - jdw
- Assert( 0 );
- }
- }
- void CPropSFRVehicle::ExitVehicle( int nRole )
- {
- CBasePlayer *pPlayer = m_hPlayer;
- if ( !pPlayer )
- return;
- m_hPlayer = NULL;
- ResetUseKey( pPlayer );
- //m_playerOff.FireOutput( pPlayer, this, 0 );
- m_flTimeLastEnterExit = gpGlobals->curtime;
- StopEngine();
- m_playerOff.FireOutput( pPlayer, this );
- TurnOff();
- }
- CBaseEntity *CPropSFRVehicle::GetDriver()
- {
- return m_hPlayer;
- }
- /*
- psy:
- I had to reimplement this here and neglect the parent class because the parent class re-call
- this method through the "GetDriveableVehicle" method and create an infinite recursive loop.
- */
- void CPropSFRVehicle::ItemPostFrame( CBasePlayer *pPlayer )
- {
- Assert( pPlayer == GetPassenger( VEHICLE_ROLE_DRIVER ) );
- if( pPlayer->m_afButtonPressed & IN_USE )
- {
- if ( GetDrivableVehicle()->CanExitVehicle(pPlayer) )
- {
- if ( !HandlePassengerExit( pPlayer ) && ( pPlayer != NULL ) )
- {
- pPlayer->PlayUseDenySound();
- }
- }
- //ResetUseKey(pPlayer);
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void CPropSFRVehicle::TurnOn( )
- {
- //if ( IsEngineDisabled() )
- // return;
- if ( !m_bIsOn )
- {
- m_bIsOn = true;
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void CPropSFRVehicle::TurnOff( )
- {
- ResetControls();
- if ( m_bIsOn )
- {
- m_bIsOn = false;
- }
- }
- //-----------------------------------------------------------------------------
- // Control initialization
- //-----------------------------------------------------------------------------
- void CPropSFRVehicle::ResetControls()
- {
- }
- /*
- psy:
- I had to reimplement this here and neglect the parent class because the parent class re-call
- this method through the "GetDriveableVehicle" method and create an infinite recursive loop.
- */
- void CPropSFRVehicle::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData )
- {
- trace_t tr;
- UTIL_TraceLine( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin() - Vector( 0, 0, 256 ), MASK_PLAYERSOLID, GetVehicleEnt(), COLLISION_GROUP_NONE, &tr );
- // If our gamematerial has changed, tell any player surface triggers that are watching
- IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps();
- const surfacedata_t *pSurfaceProp = physprops->GetSurfaceData( tr.surface.surfaceProps );
- char cCurrGameMaterial = pSurfaceProp->game.material;
- // Changed?
- if ( m_chPreviousTextureType != cCurrGameMaterial )
- {
- CEnvPlayerSurfaceTrigger::SetPlayerSurface( pPlayer, cCurrGameMaterial );
- }
- m_chPreviousTextureType = cCurrGameMaterial;
- }
- void CPropSFRVehicle::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
- {
- // If the engine's not active, prevent driving
- if ( !IsEngineOn() )
- return;
- // If the player's entering/exiting the vehicle, prevent movement
- //if ( m_bEnterAnimOn || m_bExitAnimOn )
- // return;
- DriveVehicle( player, ucmd );
- }
- void CPropSFRVehicle::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd )
- {
- //Lose control when the player dies
- if ( pPlayer->IsAlive() == false )
- return;
- DriveVehicle( TICK_INTERVAL, ucmd, pPlayer->m_afButtonPressed, pPlayer->m_afButtonReleased );
- }
- void CPropSFRVehicle::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased )
- {
- int iButtons = ucmd->buttons;
- //
- // Fire the appropriate outputs based on button pressed events.
- //
- // BUGBUG: m_afButtonPressed is broken - check the player.cpp code!!!
- if ( iButtonsDown & IN_ATTACK )
- {
- }
- if ( iButtonsDown & IN_ATTACK2 )
- {
- }
- if ( iButtons & IN_ATTACK )
- {
- }
- if ( iButtons & IN_ATTACK2 )
- {
- }
- }
- void CPropSFRVehicle::StartEngine( void )
- {
- TurnOn();
- }
- void CPropSFRVehicle::StopEngine( void )
- {
- TurnOff();
- }
- bool CPropSFRVehicle::IsEngineOn( void )
- {
- return IsOn();
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- // Input : &inputdata -
- //-----------------------------------------------------------------------------
- void CPropSFRVehicle::InputEnterVehicleImmediate( inputdata_t &inputdata )
- {
- DevMsg( "Enter vehicle Immediate !!!" );
- // Try the activator first & use them if they are a player.
- CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator );
- if ( pPassenger == NULL )
- {
- // Activator was not a player, just grab the singleplayer player.
- pPassenger = UTIL_PlayerByIndex( 1 );
- if ( pPassenger == NULL )
- return;
- }
- CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
- if ( pPlayer != NULL )
- {
- if ( pPlayer->IsInAVehicle() )
- {
- // Force the player out of whatever vehicle they are in.
- pPlayer->LeaveVehicle();
- }
- pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER );
- }
- else
- {
- // NPCs are not currently supported - jdw
- Assert( 0 );
- }
- }
- // ===========================================================
- // CPropSFRVehicleWithViewSmoothing
- // ===========================================================
- BEGIN_DATADESC(CPropSFRVehicleWithViewSmoothing)
- DEFINE_EMBEDDED( m_ViewSmoothing ),
- END_DATADESC();
- const float CPropSFRVehicleWithViewSmoothing::_VEHICLE_FRAMETIME_MIN = 1e-6;
- const float CPropSFRVehicleWithViewSmoothing::_VEHICLE_DELTA_LENGHT_MAX = 12.0f;
- CPropSFRVehicleWithViewSmoothing::CPropSFRVehicleWithViewSmoothing()
- {
- // Setup our smoothing data
- memset( &m_ViewSmoothing, 0, sizeof( m_ViewSmoothing ) );
- m_ViewSmoothing.bClampEyeAngles = true;
- m_ViewSmoothing.bDampenEyePosition = true;
- m_ViewSmoothing.flPitchCurveZero = PITCH_CURVE_ZERO;
- m_ViewSmoothing.flPitchCurveLinear = PITCH_CURVE_LINEAR;
- m_ViewSmoothing.flRollCurveZero = ROLL_CURVE_ZERO;
- m_ViewSmoothing.flRollCurveLinear = ROLL_CURVE_LINEAR;
- }
- void CPropSFRVehicleWithViewSmoothing::GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV )
- {
- CBaseEntity *pDriver = GetPassenger( nRole );
- if ( pDriver && pDriver->IsPlayer())
- {
- CBasePlayer *pPlayerDriver = ToBasePlayer( pDriver );
- SFRSharedVehicleViewSmoothing( pPlayerDriver,
- pOrigin, pAngles,
- false, false,
- GetAbsOrigin(),
- &m_ViewSmoothing,
- pFOV );
- }
- else
- {
- // NPCs are not supported
- Assert( 0 );
- }
- }
- void CPropSFRVehicleWithViewSmoothing::EnterVehicle( CBaseCombatCharacter *pPassenger )
- {
- CBasePlayer * pPlayer = ToBasePlayer( pPassenger );
- if ( pPlayer != NULL )
- {
- Vector vecViewOffset = GetSavedViewOffset();
- // Clear our state
- InitViewSmoothing( pPlayer->GetAbsOrigin() + vecViewOffset, pPlayer->EyeAngles() );
- }
- BaseClass::EnterVehicle( pPassenger );
- }
- void CPropSFRVehicleWithViewSmoothing::ExitVehicle( int iRole )
- {
- BaseClass::ExitVehicle( iRole );
- // Clear our state
- InitViewSmoothing( vec3_origin, vec3_angle );
- }
- void CPropSFRVehicleWithViewSmoothing::SetVehicle( CBaseEntity *pVehicle )
- {
- BaseClass::SetVehicle( pVehicle );
- // Save this for view smoothing
- if ( pVehicle != NULL )
- {
- m_ViewSmoothing.pVehicle = pVehicle->GetBaseAnimating();
- }
- }
- void CPropSFRVehicleWithViewSmoothing::InitViewSmoothing( const Vector &vecStartOrigin, const QAngle &vecStartAngles )
- {
- m_ViewSmoothing.bWasRunningAnim = false;
- m_ViewSmoothing.vecOriginSaved = vecStartOrigin;
- m_ViewSmoothing.vecAnglesSaved = vecStartAngles;
- m_ViewSmoothing.flFOV = 75.0f;//r_FighterFOV.GetFloat();
- }
- void CPropSFRVehicleWithViewSmoothing::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
- {
- // Get the frametime. (Check to see if enough time has passed to warrent dampening).
- float flFrameTime = gpGlobals->frametime;
- if ( flFrameTime < _VEHICLE_FRAMETIME_MIN )
- {
- vecVehicleEyePos = m_vecLastEyePos;
- DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f );
- return;
- }
- // Keep static the sideways motion.
- // Dampen forward/backward motion.
- DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
- // Blend up/down motion.
- DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
- }
- void CPropSFRVehicleWithViewSmoothing::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
- {
- // vecVehicleEyePos = real eye position this frame
- // m_vecLastEyePos = eye position last frame
- // m_vecEyeSpeed = eye speed last frame
- // vecPredEyePos = predicted eye position this frame (assuming no acceleration - it will get that from the pd controller).
- // vecPredEyeSpeed = predicted eye speed
- Vector vecPredEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime;
- Vector vecPredEyeSpeed = m_vecEyeSpeed;
- // m_vecLastEyeTarget = real eye position last frame (used for speed calculation).
- // Calculate the approximate speed based on the current vehicle eye position and the eye position last frame.
- Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime;
- m_vecLastEyeTarget = vecVehicleEyePos;
- if (vecVehicleEyeSpeed.Length() == 0.0)
- return;
- // Calculate the delta between the predicted eye position and speed and the current eye position and speed.
- Vector vecDeltaSpeed = vecVehicleEyeSpeed - vecPredEyeSpeed;
- Vector vecDeltaPos = vecVehicleEyePos - vecPredEyePos;
- // Forward vector.
- Vector vecForward;
- AngleVectors( vecVehicleEyeAngles, &vecForward );
- float flDeltaLength = vecDeltaPos.Length();
- if ( flDeltaLength > _VEHICLE_DELTA_LENGHT_MAX )
- {
- // Clamp.
- float flDelta = flDeltaLength - _VEHICLE_DELTA_LENGHT_MAX;
- if ( flDelta > 40.0f )
- {
- // This part is a bit of a hack to get rid of large deltas (at level load, etc.).
- m_vecLastEyePos = vecVehicleEyePos;
- m_vecEyeSpeed = vecVehicleEyeSpeed;
- }
- else
- {
- // Position clamp.
- float flRatio = _VEHICLE_DELTA_LENGHT_MAX / flDeltaLength;
- vecDeltaPos *= flRatio;
- Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
- vecVehicleEyePos -= vecForwardOffset;
- m_vecLastEyePos = vecVehicleEyePos;
- // Speed clamp.
- vecDeltaSpeed *= flRatio;
- float flCoefficients[2];
- ComputePDControllerCoefficients( flCoefficients, r_VehicleViewDampenFreq.GetFloat(), r_VehicleViewDampenDamp.GetFloat(), flFrameTime );
- m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
- }
- }
- else
- {
- // Generate an updated (dampening) speed for use in next frames position prediction.
- float flCoefficients[2];
- ComputePDControllerCoefficients( flCoefficients, r_VehicleViewDampenFreq.GetFloat(), r_VehicleViewDampenDamp.GetFloat(), flFrameTime );
- m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
- // Save off data for next frame.
- m_vecLastEyePos = vecPredEyePos;
- // Move eye forward/backward.
- Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
- vecVehicleEyePos -= vecForwardOffset;
- }
- }
- //-----------------------------------------------------------------------------
- // Purpose:
- //-----------------------------------------------------------------------------
- void CPropSFRVehicleWithViewSmoothing::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
- {
- // Get up vector.
- Vector vecUp;
- AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp );
- vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
- vecVehicleEyePos.z += r_VehicleViewZHeight.GetFloat() * vecUp.z;
- // NOTE: Should probably use some damped equation here.
- }
- void CPropSFRVehicleWithViewSmoothing::ComputePDControllerCoefficients( float *pCoefficientsOut,
- float flFrequency, float flDampening,
- float flDeltaTime )
- {
- float flKs = 9.0f * flFrequency * flFrequency;
- float flKd = 4.5f * flFrequency * flDampening;
- float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime );
- pCoefficientsOut[0] = flKs * flScale;
- pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale;
- }
- #ifdef CLIENT_DLL
- void CPropSFRVehicleWithViewSmoothing::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
- {
- BaseClass::UpdateViewAngles( pLocalPlayer, pCmd );
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment