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.
423 lines
13 KiB
423 lines
13 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "c_prop_vehicle.h"
|
||
|
#include "hud.h"
|
||
|
#include <vgui_controls/Controls.h>
|
||
|
#include <Color.h>
|
||
|
#include "view.h"
|
||
|
#include "engine/ivdebugoverlay.h"
|
||
|
#include "movevars_shared.h"
|
||
|
#include "iviewrender.h"
|
||
|
#include "vgui/ISurface.h"
|
||
|
#include "client_virtualreality.h"
|
||
|
#include "../hud_crosshair.h"
|
||
|
#include "sourcevr/isourcevirtualreality.h"
|
||
|
// NVNT haptic utils
|
||
|
#include "haptics/haptic_utils.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
int ScreenTransform( const Vector& point, Vector& screen );
|
||
|
|
||
|
extern ConVar default_fov;
|
||
|
extern ConVar joy_response_move_vehicle;
|
||
|
|
||
|
|
||
|
IMPLEMENT_CLIENTCLASS_DT(C_PropVehicleDriveable, DT_PropVehicleDriveable, CPropVehicleDriveable)
|
||
|
RecvPropEHandle( RECVINFO(m_hPlayer) ),
|
||
|
RecvPropInt( RECVINFO( m_nSpeed ) ),
|
||
|
RecvPropInt( RECVINFO( m_nRPM ) ),
|
||
|
RecvPropFloat( RECVINFO( m_flThrottle ) ),
|
||
|
RecvPropInt( RECVINFO( m_nBoostTimeLeft ) ),
|
||
|
RecvPropInt( RECVINFO( m_nHasBoost ) ),
|
||
|
RecvPropInt( RECVINFO( m_nScannerDisabledWeapons ) ),
|
||
|
RecvPropInt( RECVINFO( m_nScannerDisabledVehicle ) ),
|
||
|
RecvPropInt( RECVINFO( m_bEnterAnimOn ) ),
|
||
|
RecvPropInt( RECVINFO( m_bExitAnimOn ) ),
|
||
|
RecvPropInt( RECVINFO( m_bUnableToFire ) ),
|
||
|
RecvPropVector( RECVINFO( m_vecEyeExitEndpoint ) ),
|
||
|
RecvPropBool( RECVINFO( m_bHasGun ) ),
|
||
|
RecvPropVector( RECVINFO( m_vecGunCrosshair ) ),
|
||
|
END_RECV_TABLE()
|
||
|
|
||
|
|
||
|
BEGIN_DATADESC( C_PropVehicleDriveable )
|
||
|
DEFINE_EMBEDDED( m_ViewSmoothingData ),
|
||
|
END_DATADESC()
|
||
|
|
||
|
ConVar r_VehicleViewClamp( "r_VehicleViewClamp", "1", FCVAR_CHEAT );
|
||
|
|
||
|
#define ROLL_CURVE_ZERO 20 // roll less than this is clamped to zero
|
||
|
#define ROLL_CURVE_LINEAR 90 // roll greater than this is copied out
|
||
|
|
||
|
#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero
|
||
|
#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out
|
||
|
// spline in between
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_PropVehicleDriveable::C_PropVehicleDriveable() :
|
||
|
m_iv_vecGunCrosshair( "C_PropVehicleDriveable::m_iv_vecGunCrosshair" )
|
||
|
|
||
|
{
|
||
|
m_hPrevPlayer = NULL;
|
||
|
|
||
|
memset( &m_ViewSmoothingData, 0, sizeof( m_ViewSmoothingData ) );
|
||
|
|
||
|
m_ViewSmoothingData.pVehicle = this;
|
||
|
m_ViewSmoothingData.bClampEyeAngles = true;
|
||
|
m_ViewSmoothingData.bDampenEyePosition = true;
|
||
|
|
||
|
m_ViewSmoothingData.flPitchCurveZero = PITCH_CURVE_ZERO;
|
||
|
m_ViewSmoothingData.flPitchCurveLinear = PITCH_CURVE_LINEAR;
|
||
|
m_ViewSmoothingData.flRollCurveZero = ROLL_CURVE_ZERO;
|
||
|
m_ViewSmoothingData.flRollCurveLinear = ROLL_CURVE_LINEAR;
|
||
|
|
||
|
m_ViewSmoothingData.flFOV = m_flFOV = default_fov.GetFloat();
|
||
|
|
||
|
AddVar( &m_vecGunCrosshair, &m_iv_vecGunCrosshair, LATCH_SIMULATION_VAR );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: De-constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_PropVehicleDriveable::~C_PropVehicleDriveable()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// By default all driveable vehicles use the curve defined by the convar.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int C_PropVehicleDriveable::GetJoystickResponseCurve() const
|
||
|
{
|
||
|
return joy_response_move_vehicle.GetInt();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_BaseCombatCharacter *C_PropVehicleDriveable::GetPassenger( int nRole )
|
||
|
{
|
||
|
if ( nRole == VEHICLE_ROLE_DRIVER )
|
||
|
return m_hPlayer.Get();
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Returns the role of the passenger
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int C_PropVehicleDriveable::GetPassengerRole( C_BaseCombatCharacter *pPassenger )
|
||
|
{
|
||
|
if ( m_hPlayer.Get() == pPassenger )
|
||
|
return VEHICLE_ROLE_DRIVER;
|
||
|
|
||
|
return VEHICLE_ROLE_NONE;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : updateType -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::OnPreDataChanged( DataUpdateType_t updateType )
|
||
|
{
|
||
|
BaseClass::OnPreDataChanged( updateType );
|
||
|
|
||
|
m_hPrevPlayer = m_hPlayer;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::OnDataChanged( DataUpdateType_t updateType )
|
||
|
{
|
||
|
BaseClass::OnDataChanged( updateType );
|
||
|
|
||
|
if ( m_hPlayer && !m_hPrevPlayer )
|
||
|
{
|
||
|
OnEnteredVehicle( m_hPlayer );
|
||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||
|
g_ClientVirtualReality.AlignTorsoAndViewToWeapon();
|
||
|
}
|
||
|
else if ( !m_hPlayer && m_hPrevPlayer )
|
||
|
{
|
||
|
// NVNT notify haptics system of navigation exit
|
||
|
OnExitedVehicle( m_hPrevPlayer );
|
||
|
// They have just exited the vehicle.
|
||
|
// Sometimes we never reach the end of our exit anim, such as if the
|
||
|
// animation doesn't have fadeout 0 specified in the QC, so we fail to
|
||
|
// catch it in VehicleViewSmoothing. Catch it here instead.
|
||
|
m_ViewSmoothingData.bWasRunningAnim = false;
|
||
|
SetNextClientThink( CLIENT_THINK_NEVER );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Should this object cast render-to-texture shadows?
|
||
|
//-----------------------------------------------------------------------------
|
||
|
ShadowType_t C_PropVehicleDriveable::ShadowCastType()
|
||
|
{
|
||
|
CStudioHdr *pStudioHdr = GetModelPtr();
|
||
|
if ( !pStudioHdr )
|
||
|
return SHADOWS_NONE;
|
||
|
|
||
|
if ( IsEffectActive(EF_NODRAW | EF_NOSHADOW) )
|
||
|
return SHADOWS_NONE;
|
||
|
|
||
|
// Always use render-to-texture. We'll always the dirty bits in our think function
|
||
|
return SHADOWS_RENDER_TO_TEXTURE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Mark the shadow as dirty while the vehicle is being driven
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::ClientThink( void )
|
||
|
{
|
||
|
// The vehicle is always dirty owing to pose parameters while it's being driven.
|
||
|
g_pClientShadowMgr->MarkRenderToTextureShadowDirty( GetShadowHandle() );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Modify the player view/camera while in a vehicle
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ )
|
||
|
{
|
||
|
SharedVehicleViewSmoothing( m_hPlayer,
|
||
|
pAbsOrigin, pAbsAngles,
|
||
|
m_bEnterAnimOn, m_bExitAnimOn,
|
||
|
m_vecEyeExitEndpoint,
|
||
|
&m_ViewSmoothingData,
|
||
|
pFOV );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Futzes with the clip planes
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::GetVehicleClipPlanes( float &flZNear, float &flZFar ) const
|
||
|
{
|
||
|
// FIXME: Need something a better long-term, this fixes the buggy.
|
||
|
flZNear = 6;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Renders hud elements
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Simply used to return intensity value based upon current timer passed in
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int GetFlashColorIntensity( int LowIntensity, int HighIntensity, bool Dimming, int Increment, int Timer )
|
||
|
{
|
||
|
if ( Dimming )
|
||
|
return ( HighIntensity - Timer * Increment );
|
||
|
else
|
||
|
return ( LowIntensity + Timer * Increment );
|
||
|
}
|
||
|
|
||
|
#define TRIANGULATED_CROSSHAIR 1
|
||
|
|
||
|
void C_PropVehicleDriveable::DrawHudElements( )
|
||
|
{
|
||
|
CHudTexture *pIcon;
|
||
|
int iIconX, iIconY;
|
||
|
|
||
|
if (m_bHasGun)
|
||
|
{
|
||
|
// draw crosshairs for vehicle gun
|
||
|
pIcon = gHUD.GetIcon( "gunhair" );
|
||
|
|
||
|
if ( pIcon != NULL )
|
||
|
{
|
||
|
float x, y;
|
||
|
|
||
|
if( UseVR() )
|
||
|
{
|
||
|
C_BasePlayer *pPlayer = (C_BasePlayer *)GetPassenger( VEHICLE_ROLE_DRIVER );
|
||
|
Vector vecStart, vecDirection;
|
||
|
pPlayer->EyePositionAndVectors( &vecStart, &vecDirection, NULL, NULL );
|
||
|
Vector vecEnd = vecStart + vecDirection * MAX_TRACE_LENGTH;
|
||
|
|
||
|
trace_t tr;
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
Vector screen;
|
||
|
screen.Init();
|
||
|
ScreenTransform(tr.endpos, screen);
|
||
|
|
||
|
int vx, vy, vw, vh;
|
||
|
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh );
|
||
|
|
||
|
float screenWidth = vw;
|
||
|
float screenHeight = vh;
|
||
|
|
||
|
x = 0.5f * ( 1.0f + screen[0] ) * screenWidth + 0.5f;
|
||
|
y = 0.5f * ( 1.0f - screen[1] ) * screenHeight + 0.5f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector screen;
|
||
|
|
||
|
x = ScreenWidth()/2;
|
||
|
y = ScreenHeight()/2;
|
||
|
|
||
|
#if TRIANGULATED_CROSSHAIR
|
||
|
ScreenTransform( m_vecGunCrosshair, screen );
|
||
|
x += 0.5 * screen[0] * ScreenWidth() + 0.5;
|
||
|
y -= 0.5 * screen[1] * ScreenHeight() + 0.5;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
x -= pIcon->Width() / 2;
|
||
|
y -= pIcon->Height() / 2;
|
||
|
|
||
|
Color clr = ( m_bUnableToFire ) ? gHUD.m_clrCaution : gHUD.m_clrNormal;
|
||
|
pIcon->DrawSelf( x, y, clr );
|
||
|
}
|
||
|
|
||
|
if ( m_nScannerDisabledWeapons )
|
||
|
{
|
||
|
// Draw icons for scanners "weps disabled"
|
||
|
pIcon = gHUD.GetIcon( "dmg_bio" );
|
||
|
if ( pIcon )
|
||
|
{
|
||
|
iIconY = 467 - pIcon->Height() / 2;
|
||
|
iIconX = 385;
|
||
|
if ( !m_bScannerWepIcon )
|
||
|
{
|
||
|
pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, 255, 255 ) );
|
||
|
m_bScannerWepIcon = true;
|
||
|
m_iScannerWepFlashTimer = 0;
|
||
|
m_bScannerWepDim = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, GetFlashColorIntensity(55, 255, m_bScannerWepDim, 10, m_iScannerWepFlashTimer), 255 ) );
|
||
|
m_iScannerWepFlashTimer++;
|
||
|
m_iScannerWepFlashTimer %= 20;
|
||
|
if(!m_iScannerWepFlashTimer)
|
||
|
m_bScannerWepDim ^= 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_nScannerDisabledVehicle )
|
||
|
{
|
||
|
// Draw icons for scanners "vehicle disabled"
|
||
|
pIcon = gHUD.GetIcon( "dmg_bio" );
|
||
|
if ( pIcon )
|
||
|
{
|
||
|
iIconY = 467 - pIcon->Height() / 2;
|
||
|
iIconX = 410;
|
||
|
if ( !m_bScannerVehicleIcon )
|
||
|
{
|
||
|
pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, 255, 255 ) );
|
||
|
m_bScannerVehicleIcon = true;
|
||
|
m_iScannerVehicleFlashTimer = 0;
|
||
|
m_bScannerVehicleDim = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pIcon->DrawSelf( XRES(iIconX), YRES(iIconY), Color( 0, 0, GetFlashColorIntensity(55, 255, m_bScannerVehicleDim, 10, m_iScannerVehicleFlashTimer), 255 ) );
|
||
|
m_iScannerVehicleFlashTimer++;
|
||
|
m_iScannerVehicleFlashTimer %= 20;
|
||
|
if(!m_iScannerVehicleFlashTimer)
|
||
|
m_bScannerVehicleDim ^= 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::RestrictView( float *pYawBounds, float *pPitchBounds,
|
||
|
float *pRollBounds, QAngle &vecViewAngles )
|
||
|
{
|
||
|
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||
|
Vector vehicleEyeOrigin;
|
||
|
QAngle vehicleEyeAngles;
|
||
|
GetAttachmentLocal( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||
|
|
||
|
// Limit the yaw.
|
||
|
if ( pYawBounds )
|
||
|
{
|
||
|
float flAngleDiff = AngleDiff( vecViewAngles.y, vehicleEyeAngles.y );
|
||
|
flAngleDiff = clamp( flAngleDiff, pYawBounds[0], pYawBounds[1] );
|
||
|
vecViewAngles.y = vehicleEyeAngles.y + flAngleDiff;
|
||
|
}
|
||
|
|
||
|
// Limit the pitch.
|
||
|
if ( pPitchBounds )
|
||
|
{
|
||
|
float flAngleDiff = AngleDiff( vecViewAngles.x, vehicleEyeAngles.x );
|
||
|
flAngleDiff = clamp( flAngleDiff, pPitchBounds[0], pPitchBounds[1] );
|
||
|
vecViewAngles.x = vehicleEyeAngles.x + flAngleDiff;
|
||
|
}
|
||
|
|
||
|
// Limit the roll.
|
||
|
if ( pRollBounds )
|
||
|
{
|
||
|
float flAngleDiff = AngleDiff( vecViewAngles.z, vehicleEyeAngles.z );
|
||
|
flAngleDiff = clamp( flAngleDiff, pRollBounds[0], pRollBounds[1] );
|
||
|
vecViewAngles.z = vehicleEyeAngles.z + flAngleDiff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
|
||
|
{
|
||
|
if ( r_VehicleViewClamp.GetInt() )
|
||
|
{
|
||
|
float pitchBounds[2] = { -85.0f, 25.0f };
|
||
|
RestrictView( NULL, pitchBounds, NULL, pCmd->viewangles );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_PropVehicleDriveable::OnEnteredVehicle( C_BaseCombatCharacter *pPassenger )
|
||
|
{
|
||
|
#if defined( WIN32 ) && !defined( _X360 )
|
||
|
// NVNT notify haptics system of navigation change
|
||
|
HapticsEnteredVehicle(this,pPassenger);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// NVNT - added function
|
||
|
void C_PropVehicleDriveable::OnExitedVehicle( C_BaseCombatCharacter *pPassenger )
|
||
|
{
|
||
|
#if defined( WIN32 ) && !defined( _X360 )
|
||
|
// NVNT notify haptics system of navigation exit
|
||
|
HapticsExitedVehicle(this,pPassenger);
|
||
|
#endif
|
||
|
}
|
||
|
|