psy_commando

prop_sfr_vehicle.cpp

Apr 28th, 2012
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 18.59 KB | None | 0 0
  1. #include "cbase.h"
  2. #include "prop_sfr_vehicle.h"
  3. #include "in_buttons.h"
  4. #include "env_player_surface_trigger.h"
  5. #include "fourwheelvehiclephysics.h"
  6. #include "vehicle_viewblend_shared.h"
  7.  
  8. ConVar r_VehicleViewDampenFreq( "r_VehicleViewDampenFreq", "7.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED );
  9. ConVar r_VehicleViewDampenDamp( "r_VehicleViewDampenDamp", "1.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED);
  10. ConVar r_VehicleViewZHeight( "r_VehicleViewZHeight", "10.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED );
  11.  
  12. #define SMOOTHING_FACTOR 0.9
  13. #define SF_PROP_SFR_VEHICLE_ALWAYSTHINK 0x00000001
  14.  
  15. IMPLEMENT_SERVERCLASS_ST(CPropSFRVehicle, DT_PropSFRVehicle)
  16.     SendPropEHandle(SENDINFO(m_hPlayer)),
  17.    SendPropBool( SENDINFO( m_bIsOn ) ),
  18.  
  19. //  // We need to send a hi-res origin to avoid prediction errors sliding along walls
  20.     SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ),
  21.     // send a hi-res origin to the local player for use in prediction
  22.     SendPropVectorXY(SENDINFO(m_vecOrigin),               -1, SPROP_NOSCALE | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_OriginXY ),
  23.     SendPropFloat   (SENDINFO_VECTORELEM(m_vecOrigin, 2), -1, SPROP_NOSCALE | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_OriginZ ),
  24.  
  25.    SendPropFloat        ( SENDINFO_VECTORELEM(m_vecVelocity, 0), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
  26.     SendPropFloat       ( SENDINFO_VECTORELEM(m_vecVelocity, 1), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
  27.     SendPropFloat       ( SENDINFO_VECTORELEM(m_vecVelocity, 2), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ),
  28. // 
  29. //   SendPropExclude( "DT_BaseEntity", "m_angRotation" ),
  30. //#if PREDICTION_ERROR_CHECK_LEVEL > 1
  31. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesX ),
  32. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesY ),
  33. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesZ ),
  34. //#else
  35. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesX ),
  36. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesY ),
  37. //  SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_CHANGES_OFTEN, CBaseEntity::SendProxy_AnglesZ ),
  38. //#endif
  39.  
  40. END_SEND_TABLE();
  41.  
  42. BEGIN_DATADESC( CPropSFRVehicle )
  43.    DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ),
  44.  
  45.     // Keys
  46.     DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "VehicleScript" ),
  47.     DEFINE_FIELD( m_vecSmoothedVelocity, FIELD_VECTOR ),
  48.    DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
  49.  
  50.     // Inputs
  51.    DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ),
  52.  
  53.    // Outputs
  54.     DEFINE_OUTPUT( m_playerOn, "PlayerOn" ),
  55.     DEFINE_OUTPUT( m_playerOff, "PlayerOff" ),
  56.  
  57. END_DATADESC()
  58.  
  59. LINK_ENTITY_TO_CLASS( sfr_vehicle, CPropSFRVehicle );
  60.  
  61.  
  62.  
  63. CPropSFRVehicle::CPropSFRVehicle()
  64. {
  65.    m_flTimeLastEnterExit= 0;
  66. }
  67.  
  68. CPropSFRVehicle::~CPropSFRVehicle()
  69. {
  70. }
  71.  
  72. void CPropSFRVehicle::Precache( void )
  73. {
  74.    BaseClass::Precache();
  75. }
  76.  
  77. void CPropSFRVehicle::Spawn( void )
  78. {
  79.    SetVehicle( this ); //psy : set this here because the baseclass is retarded !
  80.     // NOTE: The model has to be set before we can spawn vehicle physics
  81.     BaseClass::Spawn();
  82.  
  83.     SetNextThink( gpGlobals->curtime );
  84.    SetCollisionGroup( COLLISION_GROUP_VEHICLE );
  85.     m_vecSmoothedVelocity.Init();
  86.     m_takedamage = DAMAGE_EVENTS_ONLY;
  87. }
  88.  
  89. void CPropSFRVehicle::Think( void )
  90. {
  91.     // Derived classes of CPropVehicle have their own code to determine how frequently to think.
  92.     // But the prop_vehicle entity native to this class will only think one time, so this flag
  93.     // was added to allow prop_vehicle to always think without affecting the derived classes.
  94.     if( HasSpawnFlags(SF_PROP_SFR_VEHICLE_ALWAYSTHINK) )
  95.     {
  96.         SetNextThink(gpGlobals->curtime);
  97.     }
  98.  
  99.     if ( ShouldThink() )
  100.     {
  101.         SetNextThink( gpGlobals->curtime );
  102.     }
  103. }
  104.  
  105. void CPropSFRVehicle::VPhysicsUpdate( IPhysicsObject *pPhysics )
  106. {
  107.     if ( IsMarkedForDeletion() )
  108.         return;
  109.  
  110.     Vector  velocity;
  111.     VPhysicsGetObject()->GetVelocity( &velocity, NULL );
  112.  
  113.     //Update our smoothed velocity
  114.     m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + velocity * ( 1 - SMOOTHING_FACTOR );
  115.    
  116.     BaseClass::VPhysicsUpdate( pPhysics );
  117. }
  118.  
  119. void CPropSFRVehicle::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info )
  120. {
  121.     CBaseEntity *pDriver = GetDriver();
  122.     if ( pDriver != NULL )
  123.     {
  124.         pDriver->Event_KilledOther( pVictim, info );
  125.     }
  126.  
  127.     BaseClass::Event_KilledOther( pVictim, info );
  128. }
  129.  
  130. Vector CPropSFRVehicle::GetSmoothedVelocity( void )
  131. {
  132.    BaseClass::GetSmoothedVelocity();
  133.     return m_vecSmoothedVelocity;
  134. }
  135.  
  136. void CPropSFRVehicle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  137. {
  138.     CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  139.     if ( !pPlayer )
  140.         return;
  141.    if( pPlayer == GetPassenger( VEHICLE_ROLE_DRIVER ) ) //psy: avoid resetting and trying to climb in the vehicle we're in please !
  142.       return;
  143.  
  144.     ResetUseKey( pPlayer );
  145.  
  146.     HandlePassengerEntry( pPlayer, (value>0) );
  147. }
  148.  
  149.  void CPropSFRVehicle::ResetUseKey( CBasePlayer *pPlayer )
  150.  {
  151.     pPlayer->m_afButtonPressed &= ~IN_USE;
  152.  }
  153.  
  154. bool CPropSFRVehicle::CanEnterVehicle( CBaseEntity *pEntity )
  155. {
  156.    return true;
  157. }
  158.  
  159. bool CPropSFRVehicle::CanExitVehicle( CBaseEntity *pEntity )
  160. {
  161.    return true;
  162. }
  163.  
  164. void CPropSFRVehicle::EnterVehicle( CBaseCombatCharacter *pPassenger )
  165. {
  166.     if ( pPassenger == NULL )
  167.         return;
  168.  
  169.     CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
  170.     if ( pPlayer != NULL )
  171.     {
  172.         // Remove any player who may be in the vehicle at the moment
  173.         if ( m_hPlayer )
  174.         {
  175.             ExitVehicle( VEHICLE_ROLE_DRIVER );
  176.         }
  177.  
  178.         m_hPlayer = pPlayer;
  179.         //m_playerOn.FireOutput( pPlayer, this, 0 );
  180.  
  181.         // Don't start the engine if the player's using an entry animation,
  182.         // because we want to start the engine once the animation is done.
  183.       StartEngine();
  184.  
  185.         // Start Thinking
  186.         SetNextThink( gpGlobals->curtime );
  187.       m_flTimeLastEnterExit = gpGlobals->curtime;
  188.       m_playerOn.FireOutput( pPlayer, this );
  189.       TurnOn();
  190.     }
  191.     else
  192.     {
  193.         // NPCs are not yet supported - jdw
  194.         Assert( 0 );
  195.     }
  196. }
  197.  
  198. void CPropSFRVehicle::ExitVehicle( int nRole )
  199. {
  200.     CBasePlayer *pPlayer = m_hPlayer;
  201.     if ( !pPlayer )
  202.         return;
  203.  
  204.     m_hPlayer = NULL;
  205.     ResetUseKey( pPlayer );
  206.    
  207.     //m_playerOff.FireOutput( pPlayer, this, 0 );
  208.    m_flTimeLastEnterExit = gpGlobals->curtime;
  209.  
  210.     StopEngine();
  211.  
  212.    m_playerOff.FireOutput( pPlayer, this );
  213.    TurnOff();
  214. }
  215.  
  216. CBaseEntity *CPropSFRVehicle::GetDriver()
  217. {
  218.    return m_hPlayer;
  219. }
  220.  
  221.  
  222. /*
  223. psy:
  224.  I had to reimplement this here and neglect the parent class because the parent class re-call
  225.  this method through the "GetDriveableVehicle" method and create an infinite recursive loop.
  226. */
  227. void CPropSFRVehicle::ItemPostFrame( CBasePlayer *pPlayer )
  228. {  
  229.    Assert( pPlayer == GetPassenger( VEHICLE_ROLE_DRIVER ) );
  230.  
  231.    if( pPlayer->m_afButtonPressed & IN_USE )
  232.    {
  233.        if ( GetDrivableVehicle()->CanExitVehicle(pPlayer) )
  234.        {
  235.            if ( !HandlePassengerExit( pPlayer ) && ( pPlayer != NULL ) )
  236.            {
  237.                pPlayer->PlayUseDenySound();
  238.          }
  239.  
  240.        }
  241.       //ResetUseKey(pPlayer);
  242.    }
  243. }
  244.  
  245. //-----------------------------------------------------------------------------
  246. // Purpose:
  247. //-----------------------------------------------------------------------------
  248. void CPropSFRVehicle::TurnOn( )
  249. {
  250.     //if ( IsEngineDisabled() )
  251.     //  return;
  252.  
  253.     if ( !m_bIsOn )
  254.     {
  255.         m_bIsOn = true;
  256.     }
  257. }
  258.  
  259. //-----------------------------------------------------------------------------
  260. // Purpose:
  261. //-----------------------------------------------------------------------------
  262. void CPropSFRVehicle::TurnOff( )
  263. {
  264.     ResetControls();
  265.  
  266.     if ( m_bIsOn )
  267.     {
  268.         m_bIsOn = false;
  269.     }
  270. }
  271.  
  272. //-----------------------------------------------------------------------------
  273. // Control initialization
  274. //-----------------------------------------------------------------------------
  275. void CPropSFRVehicle::ResetControls()
  276. {
  277. }
  278.  
  279. /*
  280. psy:
  281.  I had to reimplement this here and neglect the parent class because the parent class re-call
  282.  this method through the "GetDriveableVehicle" method and create an infinite recursive loop.
  283. */
  284. void CPropSFRVehicle::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData )
  285. {
  286.     trace_t tr;
  287.     UTIL_TraceLine( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin() - Vector( 0, 0, 256 ), MASK_PLAYERSOLID, GetVehicleEnt(), COLLISION_GROUP_NONE, &tr );
  288.  
  289.     // If our gamematerial has changed, tell any player surface triggers that are watching
  290.     IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps();
  291.     const surfacedata_t *pSurfaceProp = physprops->GetSurfaceData( tr.surface.surfaceProps );
  292.     char cCurrGameMaterial = pSurfaceProp->game.material;
  293.  
  294.     // Changed?
  295.     if ( m_chPreviousTextureType != cCurrGameMaterial )
  296.     {
  297.         CEnvPlayerSurfaceTrigger::SetPlayerSurface( pPlayer, cCurrGameMaterial );
  298.     }
  299.  
  300.     m_chPreviousTextureType = cCurrGameMaterial;
  301. }
  302.  
  303. void CPropSFRVehicle::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
  304. {
  305.     // If the engine's not active, prevent driving
  306.     if ( !IsEngineOn() )
  307.         return;
  308.  
  309.     // If the player's entering/exiting the vehicle, prevent movement
  310.     //if ( m_bEnterAnimOn || m_bExitAnimOn )
  311.     //  return;
  312.  
  313.     DriveVehicle( player, ucmd );
  314. }
  315.  
  316. void CPropSFRVehicle::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd )
  317. {
  318.     //Lose control when the player dies
  319.     if ( pPlayer->IsAlive() == false )
  320.         return;
  321.  
  322.     DriveVehicle( TICK_INTERVAL, ucmd, pPlayer->m_afButtonPressed, pPlayer->m_afButtonReleased );
  323. }
  324.  
  325. void CPropSFRVehicle::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased )
  326. {
  327.    int iButtons = ucmd->buttons;
  328.  
  329.     //
  330.     // Fire the appropriate outputs based on button pressed events.
  331.     //
  332.     // BUGBUG: m_afButtonPressed is broken - check the player.cpp code!!!
  333.  
  334.     if ( iButtonsDown & IN_ATTACK )
  335.     {
  336.     }
  337.     if ( iButtonsDown & IN_ATTACK2 )
  338.     {
  339.     }
  340.  
  341.     if ( iButtons & IN_ATTACK )
  342.     {
  343.  
  344.     }
  345.     if ( iButtons & IN_ATTACK2 )
  346.     {
  347.     }
  348.  
  349. }
  350.  
  351. void    CPropSFRVehicle::StartEngine( void )
  352. {
  353.    TurnOn();
  354. }
  355.  
  356. void    CPropSFRVehicle::StopEngine( void )
  357. {
  358.    TurnOff();
  359. }
  360.  
  361. bool CPropSFRVehicle::IsEngineOn( void )
  362. {
  363.    return IsOn();
  364. }
  365.  
  366. //-----------------------------------------------------------------------------
  367. // Purpose:
  368. // Input  : &inputdata -
  369. //-----------------------------------------------------------------------------
  370. void CPropSFRVehicle::InputEnterVehicleImmediate( inputdata_t &inputdata )
  371. {
  372.    DevMsg( "Enter vehicle Immediate !!!" );
  373.  
  374.     // Try the activator first & use them if they are a player.
  375.     CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator );
  376.     if ( pPassenger == NULL )
  377.     {
  378.         // Activator was not a player, just grab the singleplayer player.
  379.         pPassenger = UTIL_PlayerByIndex( 1 );
  380.         if ( pPassenger == NULL )
  381.             return;
  382.     }
  383.  
  384.     CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
  385.     if ( pPlayer != NULL )
  386.     {
  387.         if ( pPlayer->IsInAVehicle() )
  388.         {
  389.             // Force the player out of whatever vehicle they are in.
  390.             pPlayer->LeaveVehicle();
  391.         }
  392.        
  393.         pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER );
  394.     }
  395.     else
  396.     {
  397.         // NPCs are not currently supported - jdw
  398.         Assert( 0 );
  399.     }
  400. }
  401.  
  402. // ===========================================================
  403. // CPropSFRVehicleWithViewSmoothing
  404. // ===========================================================
  405.  
  406. BEGIN_DATADESC(CPropSFRVehicleWithViewSmoothing)
  407.    DEFINE_EMBEDDED( m_ViewSmoothing ),
  408. END_DATADESC();
  409.  
  410. const float CPropSFRVehicleWithViewSmoothing::_VEHICLE_FRAMETIME_MIN = 1e-6;
  411. const float CPropSFRVehicleWithViewSmoothing::_VEHICLE_DELTA_LENGHT_MAX = 12.0f;
  412.  
  413. CPropSFRVehicleWithViewSmoothing::CPropSFRVehicleWithViewSmoothing()
  414. {
  415.     // Setup our smoothing data
  416.     memset( &m_ViewSmoothing, 0, sizeof( m_ViewSmoothing ) );
  417.  
  418.     m_ViewSmoothing.bClampEyeAngles     = true;
  419.     m_ViewSmoothing.bDampenEyePosition  = true;
  420.     m_ViewSmoothing.flPitchCurveZero    = PITCH_CURVE_ZERO;
  421.     m_ViewSmoothing.flPitchCurveLinear  = PITCH_CURVE_LINEAR;
  422.     m_ViewSmoothing.flRollCurveZero     = ROLL_CURVE_ZERO;
  423.     m_ViewSmoothing.flRollCurveLinear   = ROLL_CURVE_LINEAR;
  424. }
  425.  
  426. void CPropSFRVehicleWithViewSmoothing::GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV )
  427. {
  428.     CBaseEntity *pDriver = GetPassenger( nRole );
  429.     if ( pDriver && pDriver->IsPlayer())
  430.     {
  431.         CBasePlayer *pPlayerDriver = ToBasePlayer( pDriver );
  432.  
  433.         SFRSharedVehicleViewSmoothing( pPlayerDriver,
  434.                                     pOrigin, pAngles,
  435.                                     false, false,
  436.                                     GetAbsOrigin(),
  437.                                     &m_ViewSmoothing,
  438.                                     pFOV );
  439.     }
  440.     else
  441.     {
  442.         // NPCs are not supported
  443.         Assert( 0 );
  444.     }
  445. }
  446.  
  447. void CPropSFRVehicleWithViewSmoothing::EnterVehicle( CBaseCombatCharacter *pPassenger )
  448. {
  449.    CBasePlayer * pPlayer = ToBasePlayer( pPassenger );
  450.  
  451.     if ( pPlayer != NULL )
  452.    {
  453.         Vector vecViewOffset = GetSavedViewOffset();
  454.  
  455.         // Clear our state
  456.         InitViewSmoothing( pPlayer->GetAbsOrigin() + vecViewOffset, pPlayer->EyeAngles() );
  457.    }
  458.  
  459.    BaseClass::EnterVehicle( pPassenger );
  460. }
  461.  
  462. void CPropSFRVehicleWithViewSmoothing::ExitVehicle( int iRole )
  463. {
  464.    BaseClass::ExitVehicle( iRole );
  465.  
  466.     // Clear our state
  467.     InitViewSmoothing( vec3_origin, vec3_angle );
  468. }
  469.  
  470. void CPropSFRVehicleWithViewSmoothing::SetVehicle( CBaseEntity *pVehicle )
  471. {
  472.     BaseClass::SetVehicle( pVehicle );
  473.    
  474.     // Save this for view smoothing
  475.     if ( pVehicle != NULL )
  476.     {
  477.         m_ViewSmoothing.pVehicle = pVehicle->GetBaseAnimating();
  478.     }
  479. }
  480.  
  481. void CPropSFRVehicleWithViewSmoothing::InitViewSmoothing( const Vector &vecStartOrigin, const QAngle &vecStartAngles )
  482. {
  483.     m_ViewSmoothing.bWasRunningAnim = false;
  484.     m_ViewSmoothing.vecOriginSaved = vecStartOrigin;
  485.     m_ViewSmoothing.vecAnglesSaved = vecStartAngles;
  486.     m_ViewSmoothing.flFOV = 75.0f;//r_FighterFOV.GetFloat();
  487. }
  488.  
  489. void CPropSFRVehicleWithViewSmoothing::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
  490. {
  491.     // Get the frametime. (Check to see if enough time has passed to warrent dampening).
  492.     float flFrameTime = gpGlobals->frametime;
  493.  
  494.     if ( flFrameTime < _VEHICLE_FRAMETIME_MIN )
  495.     {
  496.         vecVehicleEyePos = m_vecLastEyePos;
  497.         DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f );
  498.         return;
  499.     }
  500.  
  501.     // Keep static the sideways motion.
  502.     // Dampen forward/backward motion.
  503.     DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
  504.  
  505.     // Blend up/down motion.
  506.     DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
  507. }
  508.  
  509. void CPropSFRVehicleWithViewSmoothing::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
  510. {
  511.     // vecVehicleEyePos = real eye position this frame
  512.  
  513.     // m_vecLastEyePos = eye position last frame
  514.     // m_vecEyeSpeed = eye speed last frame
  515.     // vecPredEyePos = predicted eye position this frame (assuming no acceleration - it will get that from the pd controller).
  516.     // vecPredEyeSpeed = predicted eye speed
  517.     Vector vecPredEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime;
  518.     Vector vecPredEyeSpeed = m_vecEyeSpeed;
  519.  
  520.     // m_vecLastEyeTarget = real eye position last frame (used for speed calculation).
  521.     // Calculate the approximate speed based on the current vehicle eye position and the eye position last frame.
  522.     Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime;
  523.     m_vecLastEyeTarget = vecVehicleEyePos;
  524.     if (vecVehicleEyeSpeed.Length() == 0.0)
  525.         return;
  526.  
  527.     // Calculate the delta between the predicted eye position and speed and the current eye position and speed.
  528.     Vector vecDeltaSpeed = vecVehicleEyeSpeed - vecPredEyeSpeed;
  529.     Vector vecDeltaPos = vecVehicleEyePos - vecPredEyePos;
  530.  
  531.     // Forward vector.
  532.     Vector vecForward;
  533.     AngleVectors( vecVehicleEyeAngles, &vecForward );
  534.  
  535.     float flDeltaLength = vecDeltaPos.Length();
  536.     if ( flDeltaLength > _VEHICLE_DELTA_LENGHT_MAX )
  537.     {
  538.         // Clamp.
  539.         float flDelta = flDeltaLength - _VEHICLE_DELTA_LENGHT_MAX;
  540.         if ( flDelta > 40.0f )
  541.         {
  542.             // This part is a bit of a hack to get rid of large deltas (at level load, etc.).
  543.             m_vecLastEyePos = vecVehicleEyePos;
  544.             m_vecEyeSpeed = vecVehicleEyeSpeed;
  545.         }
  546.         else
  547.         {
  548.             // Position clamp.
  549.             float flRatio = _VEHICLE_DELTA_LENGHT_MAX / flDeltaLength;
  550.             vecDeltaPos *= flRatio;
  551.             Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
  552.             vecVehicleEyePos -= vecForwardOffset;
  553.             m_vecLastEyePos = vecVehicleEyePos;
  554.  
  555.             // Speed clamp.
  556.             vecDeltaSpeed *= flRatio;
  557.             float flCoefficients[2];
  558.             ComputePDControllerCoefficients( flCoefficients, r_VehicleViewDampenFreq.GetFloat(), r_VehicleViewDampenDamp.GetFloat(), flFrameTime );
  559.             m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
  560.         }
  561.     }
  562.     else
  563.     {
  564.         // Generate an updated (dampening) speed for use in next frames position prediction.
  565.         float flCoefficients[2];
  566.         ComputePDControllerCoefficients( flCoefficients, r_VehicleViewDampenFreq.GetFloat(), r_VehicleViewDampenDamp.GetFloat(), flFrameTime );
  567.         m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
  568.        
  569.         // Save off data for next frame.
  570.         m_vecLastEyePos = vecPredEyePos;
  571.        
  572.         // Move eye forward/backward.
  573.         Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
  574.         vecVehicleEyePos -= vecForwardOffset;
  575.     }
  576. }
  577.  
  578. //-----------------------------------------------------------------------------
  579. // Purpose:
  580. //-----------------------------------------------------------------------------
  581. void CPropSFRVehicleWithViewSmoothing::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
  582. {
  583.     // Get up vector.
  584.     Vector vecUp;
  585.     AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp );
  586.     vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
  587.     vecVehicleEyePos.z += r_VehicleViewZHeight.GetFloat() * vecUp.z;
  588.  
  589.     // NOTE: Should probably use some damped equation here.
  590. }
  591.  
  592. void CPropSFRVehicleWithViewSmoothing::ComputePDControllerCoefficients( float *pCoefficientsOut,
  593.                                                   float flFrequency, float flDampening,
  594.                                                   float flDeltaTime )
  595. {
  596.     float flKs = 9.0f * flFrequency * flFrequency;
  597.     float flKd = 4.5f * flFrequency * flDampening;
  598.  
  599.     float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime );
  600.  
  601.     pCoefficientsOut[0] = flKs * flScale;
  602.     pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale;
  603. }
  604.  
  605. #ifdef CLIENT_DLL
  606.    void CPropSFRVehicleWithViewSmoothing::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
  607.    {
  608.       BaseClass::UpdateViewAngles( pLocalPlayer, pCmd );
  609.    }
  610. #endif
Advertisement
Add Comment
Please, Sign In to add comment