|
|
//========= Copyright 1996-2005, 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"
// 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 ); } 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 = HudIcons().GetIcon( "gunhair" );
if ( pIcon != NULL ) { float x, y; 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 ) ? GetHud().m_clrCaution : GetHud().m_clrNormal; pIcon->DrawSelf( x, y, clr ); }
if ( m_nScannerDisabledWeapons ) { // Draw icons for scanners "weps disabled"
pIcon = HudIcons().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 = HudIcons().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 ) { }
// NVNT - added function
void C_PropVehicleDriveable::OnExitedVehicle( C_BaseCombatCharacter *pPassenger ) { }
|