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.
1180 lines
37 KiB
1180 lines
37 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: A base vehicle class
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "basetfvehicle.h"
|
||
|
#include "tf_movedata.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "baseplayer_shared.h"
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
#include "hud_vehicle_role.h"
|
||
|
#include "hud.h"
|
||
|
#include "hud_crosshair.h"
|
||
|
#else
|
||
|
#include "tf_team.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#include "tf_func_construction_yard.h"
|
||
|
#include "ndebugoverlay.h"
|
||
|
#endif
|
||
|
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( BaseTFVehicle, DT_BaseTFVehicle );
|
||
|
|
||
|
BEGIN_NETWORK_TABLE( CBaseTFVehicle, DT_BaseTFVehicle )
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
SendPropInt( SENDINFO(m_nMaxPassengers), CBaseTFVehicle::MAX_PASSENGER_BITS, SPROP_UNSIGNED ),
|
||
|
SendPropArray( SendPropEHandle(SENDINFO_ARRAY(m_hPassengers)), m_hPassengers ),
|
||
|
SendPropEHandle( SENDINFO(m_hDriverGun) ),
|
||
|
#else
|
||
|
RecvPropInt( RECVINFO(m_nMaxPassengers) ),
|
||
|
RecvPropArray( RecvPropEHandle(RECVINFO(m_hPassengers[0])), m_hPassengers ),
|
||
|
RecvPropEHandle( RECVINFO(m_hDriverGun) ),
|
||
|
#endif
|
||
|
END_NETWORK_TABLE()
|
||
|
|
||
|
BEGIN_PREDICTION_DATA( CBaseTFVehicle )
|
||
|
|
||
|
DEFINE_PRED_ARRAY( m_hPassengers, FIELD_EHANDLE, CBaseTFVehicle::MAX_PASSENGERS, FTYPEDESC_INSENDTABLE ),
|
||
|
|
||
|
END_PREDICTION_DATA()
|
||
|
|
||
|
extern float RemapAngleRange( float startInterval, float endInterval, float value );
|
||
|
extern ConVar road_feel;
|
||
|
|
||
|
ConVar vehicle_view_offset_forward( "vehicle_view_offset_forward", "-280", FCVAR_REPLICATED );
|
||
|
ConVar vehicle_view_offset_right( "vehicle_view_offset_right", "0", FCVAR_REPLICATED );
|
||
|
ConVar vehicle_view_offset_up( "vehicle_view_offset_up", "50", FCVAR_REPLICATED );
|
||
|
ConVar vehicle_thirdperson( "vehicle_thirdperson", "1", FCVAR_REPLICATED, "Enable/disable thirdperson camera view in vehicles" );
|
||
|
|
||
|
ConVar vehicle_attach_eye_angles( "vehicle_attach_eye_angles", "0", FCVAR_REPLICATED, "Attach player eye angles to vehicle attachments" );
|
||
|
|
||
|
#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
|
||
|
|
||
|
#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero
|
||
|
#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
ConVar road_feel( "road_feel", "0.1", FCVAR_NOTIFY | FCVAR_REPLICATED );
|
||
|
#else
|
||
|
// Deterioration
|
||
|
#define DETERIORATION_THINK_CONTEXT "VehicleDeteriorationThink"
|
||
|
#define PASSENGER_THINK_CONTEXT "VehiclePassengerThink"
|
||
|
ConVar vehicle_deterioration_start_time( "vehicle_deterioration_start_time", "90", 0, "Time it takes for a vehicle to start deteriorating after being left alone." );
|
||
|
|
||
|
#define DETERIORATION_DISTANCE (600 * 600) // Never deteriorate if team mates are within this distance
|
||
|
|
||
|
#endif // CLIENT_DLL
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseTFVehicle::CBaseTFVehicle()
|
||
|
{
|
||
|
SetPredictionEligible( true );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::Spawn()
|
||
|
{
|
||
|
BaseClass::Spawn();
|
||
|
CollisionProp()->SetSurroundingBoundsType( USE_OBB_COLLISION_BOUNDS );
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||
|
m_pIconDefaultCrosshair = NULL;
|
||
|
#else
|
||
|
m_fObjectFlags |= OF_DOESNT_NEED_POWER | OF_MUST_BE_BUILT_ON_ATTACHMENT;
|
||
|
SetContextThink( VehiclePassengerThink, 2.0, PASSENGER_THINK_CONTEXT );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Vehicle overrides
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseEntity* CBaseTFVehicle::GetVehicleEnt()
|
||
|
{
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
|
||
|
{
|
||
|
// animate + update attachment points
|
||
|
#ifdef CLIENT_DLL
|
||
|
StudioFrameAdvance();
|
||
|
#else
|
||
|
StudioFrameAdvance();
|
||
|
// This calls StudioFrameAdvance, then we use the results from that to determine where to move.
|
||
|
DispatchAnimEvents( this );
|
||
|
#endif
|
||
|
|
||
|
CTFMoveData *pMoveData = (CTFMoveData*)move;
|
||
|
Assert( sizeof(VehicleBaseMoveData_t) <= pMoveData->VehicleDataMaxSize() );
|
||
|
|
||
|
VehicleBaseMoveData_t *pVehicleData = (VehicleBaseMoveData_t*)pMoveData->VehicleData();
|
||
|
pVehicleData->m_pVehicle = this;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move )
|
||
|
{
|
||
|
VehicleDriverGunThink();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns the driver as a tfplayer pointer
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseTFPlayer *CBaseTFVehicle::GetDriverPlayer()
|
||
|
{
|
||
|
return m_hPassengers[VEHICLE_DRIVER].Get();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Can we get into the vehicle?
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::CanGetInVehicle( CBaseTFPlayer *pPlayer )
|
||
|
{
|
||
|
if ( !IsPowered() )
|
||
|
return false;
|
||
|
|
||
|
if ( !InSameTeam( pPlayer ) )
|
||
|
return false;
|
||
|
|
||
|
// Player/Class-specific query.
|
||
|
return pPlayer->CanGetInVehicle();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Here's where we deal with weapons
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::OnItemPostFrame( CBaseTFPlayer *pDriver )
|
||
|
{
|
||
|
// If we have a gun for the driver, handle it
|
||
|
if ( m_hDriverGun )
|
||
|
{
|
||
|
if ( GetPassengerRole(pDriver) != VEHICLE_DRIVER )
|
||
|
return;
|
||
|
|
||
|
if ( pDriver->m_nButtons & (IN_ATTACK | IN_ATTACK2) )
|
||
|
{
|
||
|
// Time to fire?
|
||
|
if ( m_hDriverGun->CanFireNow() )
|
||
|
{
|
||
|
m_hDriverGun->Fire( pDriver );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetPassengerRole( CBasePlayer *pEnt )
|
||
|
{
|
||
|
Assert( pEnt->IsPlayer() );
|
||
|
for ( int i = m_nMaxPassengers; --i >= 0; )
|
||
|
{
|
||
|
if (m_hPassengers[i] == pEnt)
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
Vector CBaseTFVehicle::GetSoundEmissionOrigin() const
|
||
|
{
|
||
|
return WorldSpaceCenter() + Vector( 0, 0, 64 );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBasePlayer* CBaseTFVehicle::GetPassenger( int nRole )
|
||
|
{
|
||
|
return m_hPassengers[nRole].Get();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Is a particular player in the vehicle?
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::IsPlayerInVehicle( CBaseTFPlayer *pPlayer )
|
||
|
{
|
||
|
return (GetPassengerRole( pPlayer ) >= 0);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetPassengerCount() const
|
||
|
{
|
||
|
// FIXME: Cache this off!
|
||
|
int nCount = 0;
|
||
|
for (int i = m_nMaxPassengers; --i >= 0; )
|
||
|
{
|
||
|
if (m_hPassengers[i].Get())
|
||
|
{
|
||
|
++nCount;
|
||
|
}
|
||
|
}
|
||
|
return nCount;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetMaxPassengerCount() const
|
||
|
{
|
||
|
return m_nMaxPassengers;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Process input
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::ItemPostFrame( CBasePlayer *pPassenger )
|
||
|
{
|
||
|
#ifndef CLIENT_DLL
|
||
|
Assert( GetPassengerRole( pPassenger ) != -1 );
|
||
|
if (pPassenger->m_afButtonPressed & (IN_USE /*| IN_JUMP*/))
|
||
|
{
|
||
|
// Get the player out..
|
||
|
pPassenger->LeaveVehicle();
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
OnItemPostFrame( static_cast<CBaseTFPlayer*>(pPassenger) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Reset the time before this vehicle begins to deteriorate
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::ResetDeteriorationTime( void )
|
||
|
{
|
||
|
#if !defined (CLIENT_DLL)
|
||
|
SetContextThink( VehicleDeteriorationThink, gpGlobals->curtime + vehicle_deterioration_start_time.GetFloat(), DETERIORATION_THINK_CONTEXT );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Prevent driving in construction yards
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::IsReadyToDrive( void )
|
||
|
{
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
return ( PointInConstructionYard( GetAbsOrigin() ) == false );
|
||
|
#else
|
||
|
return true;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Process input
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::SetMaxPassengerCount( int nCount )
|
||
|
{
|
||
|
#if !defined( CLIENT_DLL )
|
||
|
Assert( (nCount >= 1) && (nCount <= MAX_PASSENGERS) );
|
||
|
m_nMaxPassengers = nCount;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Server-only code here
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#if !defined (CLIENT_DLL)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::FinishedBuilding( void )
|
||
|
{
|
||
|
BaseClass::FinishedBuilding();
|
||
|
|
||
|
// See if we've finished building on a vehicle that has a passenger slot assigned to my buildpoint.
|
||
|
CBaseObject *pParent = GetParentObject();
|
||
|
if ( pParent && pParent->IsAVehicle() )
|
||
|
{
|
||
|
CBaseTFVehicle *pVehicle = static_cast<CBaseTFVehicle*>(pParent);
|
||
|
int iRole = pVehicle->GetChildVehicleRole( this );
|
||
|
if ( iRole != -1 )
|
||
|
{
|
||
|
// Is there a player in the role assigned to this buildpoint?
|
||
|
CBaseTFPlayer *pExistingPlayer = static_cast<CBaseTFPlayer*>( pVehicle->GetPassenger( iRole ) );
|
||
|
if ( pExistingPlayer )
|
||
|
{
|
||
|
// Remove the player from my parent vehicle and put them in me
|
||
|
pExistingPlayer->LeaveVehicle();
|
||
|
|
||
|
// Get in the vehicle.
|
||
|
pExistingPlayer->GetInVehicle( this, VEHICLE_DRIVER );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::VehicleDeteriorationThink( void )
|
||
|
{
|
||
|
StartDeteriorating();
|
||
|
|
||
|
SetContextThink( NULL, gpGlobals->curtime + vehicle_deterioration_start_time.GetFloat(), DETERIORATION_THINK_CONTEXT );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::VehiclePassengerThink( void )
|
||
|
{
|
||
|
SetNextThink( gpGlobals->curtime + 10.0, PASSENGER_THINK_CONTEXT );
|
||
|
|
||
|
if ( IsPlacing() )
|
||
|
{
|
||
|
ResetDeteriorationTime();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If there are any passengers in the vehicle, push off deterioration time
|
||
|
if ( GetPassengerCount() )
|
||
|
{
|
||
|
ResetDeteriorationTime();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// See if there are any team members nearby
|
||
|
if ( GetTeam() )
|
||
|
{
|
||
|
int iNumPlayers = GetTFTeam()->GetNumPlayers();
|
||
|
for ( int i = 0; i < iNumPlayers; i++ )
|
||
|
{
|
||
|
if ( GetTFTeam()->GetPlayer(i) )
|
||
|
{
|
||
|
Vector vecOrigin = GetTFTeam()->GetPlayer(i)->GetAbsOrigin();
|
||
|
if ( (vecOrigin - GetAbsOrigin()).LengthSqr() < DETERIORATION_DISTANCE )
|
||
|
{
|
||
|
// Found one nearby, reset our deterioration time
|
||
|
ResetDeteriorationTime();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Figure out which role of a vehicle a child vehicle is sitting in..
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetChildVehicleRole( CBaseTFVehicle *pChild )
|
||
|
{
|
||
|
int nBuildPoints = GetNumBuildPoints();
|
||
|
for( int i = 0; i < nBuildPoints; i++ )
|
||
|
{
|
||
|
CBaseObject* pObject = GetBuildPointObject(i);
|
||
|
if (pObject == pChild)
|
||
|
{
|
||
|
return GetBuildPointPassenger(i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Vehicles are permanently oriented off angle for vphysics.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const
|
||
|
{
|
||
|
// This call is necessary to cause m_rgflCoordinateFrame to be recomputed
|
||
|
const matrix3x4_t &entityToWorld = EntityToWorldTransform();
|
||
|
|
||
|
if (pForward != NULL)
|
||
|
{
|
||
|
MatrixGetColumn( entityToWorld, 1, *pForward );
|
||
|
}
|
||
|
|
||
|
if (pRight != NULL)
|
||
|
{
|
||
|
MatrixGetColumn( entityToWorld, 0, *pRight );
|
||
|
}
|
||
|
|
||
|
if (pUp != NULL)
|
||
|
{
|
||
|
MatrixGetColumn( entityToWorld, 2, *pUp );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Get into the vehicle
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||
|
{
|
||
|
BaseClass::Use( pActivator, pCaller, useType, value );
|
||
|
|
||
|
if ( useType == USE_ON )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator);
|
||
|
if ( pPlayer && InSameTeam(pPlayer) )
|
||
|
{
|
||
|
// Check to see if we are really using nearby build points:
|
||
|
if( !UseAttachedItem( pActivator, pCaller, useType, value ) )
|
||
|
{
|
||
|
// Attempt to board the vehicle:
|
||
|
AttemptToBoardVehicle( pPlayer );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Figure out if I should be using an attached item rather than this vehicle itself.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::UseAttachedItem( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||
|
{
|
||
|
CBaseTFPlayer* pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator);
|
||
|
if ( !pPlayer || !InSameTeam(pPlayer) )
|
||
|
return false;
|
||
|
|
||
|
Vector vecPlayerOrigin = pPlayer->GetAbsOrigin();
|
||
|
int nBestBuildPoint = -1;
|
||
|
float fBestDistance = FLT_MAX;
|
||
|
|
||
|
// Get the closest regular entry point:
|
||
|
int nRole = LocateEntryPoint( pPlayer, &fBestDistance );
|
||
|
|
||
|
// Iterate through each of the build points, if any, and see which we are closest to.
|
||
|
int nBuildPoints = GetNumBuildPoints();
|
||
|
for( int i = 0; i < nBuildPoints; i++ )
|
||
|
{
|
||
|
CBaseObject* pObject = GetBuildPointObject(i);
|
||
|
|
||
|
// If there's something in the build point that isn't in the process of being built or placed:
|
||
|
if( pObject && !pObject->IsPlacing() && !pObject->IsBuilding() )
|
||
|
{
|
||
|
Vector vecOrigin;
|
||
|
QAngle vecAngles;
|
||
|
|
||
|
// If the build point is the default point for this role, just take it
|
||
|
if (GetBuildPointPassenger(i) == nRole)
|
||
|
{
|
||
|
nBestBuildPoint = i;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// And I can get the build point.
|
||
|
if( GetBuildPoint( i, vecOrigin, vecAngles ) )
|
||
|
{
|
||
|
float fLength2dSqr = (vecOrigin - vecPlayerOrigin).AsVector2D().LengthSqr();
|
||
|
if( fLength2dSqr < fBestDistance )
|
||
|
{
|
||
|
nBestBuildPoint = i;
|
||
|
fBestDistance = fLength2dSqr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( nBestBuildPoint >= 0 )
|
||
|
{
|
||
|
// They're using an item on me, so push out the deterioration time
|
||
|
ResetDeteriorationTime();
|
||
|
GetBuildPointObject(nBestBuildPoint)->Use( pActivator, pCaller, useType, value );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Object has been removed...
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::DestroyObject( void )
|
||
|
{
|
||
|
for (int i = m_nMaxPassengers; --i >= 0; )
|
||
|
{
|
||
|
if (m_hPassengers[i])
|
||
|
{
|
||
|
m_hPassengers[i]->LeaveVehicle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::DestroyObject();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetEmptyRole( void )
|
||
|
{
|
||
|
for ( int iPassenger = 0; iPassenger < m_nMaxPassengers; ++iPassenger )
|
||
|
{
|
||
|
if ( !m_hPassengers[iPassenger].Get() )
|
||
|
return iPassenger;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Try to board the vehicle
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::AttemptToBoardVehicle( CBaseTFPlayer *pPlayer )
|
||
|
{
|
||
|
if ( !CanGetInVehicle( pPlayer ) )
|
||
|
return;
|
||
|
|
||
|
// Locate the entry point.
|
||
|
int nRole = LocateEntryPoint( pPlayer );
|
||
|
if ( nRole != -1 )
|
||
|
{
|
||
|
// Set the owner flag.
|
||
|
bool bOwner = ( pPlayer == GetOwner() );
|
||
|
if ( bOwner )
|
||
|
{
|
||
|
// Check to see if a player exists at this location (role).
|
||
|
CBaseTFPlayer *pExistingPlayer = static_cast<CBaseTFPlayer*>( GetPassenger( nRole ) );
|
||
|
if ( pExistingPlayer )
|
||
|
{
|
||
|
pExistingPlayer->LeaveVehicle();
|
||
|
|
||
|
// Get in the vehicle.
|
||
|
pPlayer->GetInVehicle( this, nRole );
|
||
|
|
||
|
// Then see if we can move the other player to another slot in this vehicle
|
||
|
int nEmptyRole = GetEmptyRole();
|
||
|
if ( nEmptyRole != -1 )
|
||
|
{
|
||
|
pExistingPlayer->GetInVehicle( this, nEmptyRole );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get in the vehicle.
|
||
|
pPlayer->GetInVehicle( this, nRole );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Handle commands sent from vgui panels on the client
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::ClientCommand( CBaseTFPlayer *pPlayer, const CCommand &args )
|
||
|
{
|
||
|
ResetDeteriorationTime();
|
||
|
|
||
|
if ( FStrEq( pCmd, "toggle_use" ) )
|
||
|
{
|
||
|
AttemptToBoardVehicle( pPlayer );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return BaseClass::ClientCommand( pPlayer, args );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get a position in *world space* inside the vehicle for the player to exit at
|
||
|
// NOTE: This doesn't check for obstructions
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::GetInitialPassengerExitPoint( int nRole, Vector *pAbsPoint, QAngle *pAbsAngles )
|
||
|
{
|
||
|
char pAttachmentName[32];
|
||
|
Q_snprintf( pAttachmentName, sizeof( pAttachmentName ), "vehicle_exit_passenger%d", nRole );
|
||
|
int exitAttachmentIndex = LookupAttachment(pAttachmentName);
|
||
|
if (exitAttachmentIndex <= 0)
|
||
|
{
|
||
|
// bad attachment, just return the origin
|
||
|
*pAbsPoint = GetAbsOrigin();
|
||
|
pAbsPoint->z += WorldAlignMaxs()[2] + 50.0f;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QAngle vehicleExitAngles;
|
||
|
if( !pAbsAngles )
|
||
|
{
|
||
|
pAbsAngles = &vehicleExitAngles;
|
||
|
}
|
||
|
|
||
|
GetAttachment( exitAttachmentIndex, *pAbsPoint, *pAbsAngles );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get a point to leave the vehicle from
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::IsValidExitPoint( int nRole, Vector *pExitPoint, QAngle *pAngles )
|
||
|
{
|
||
|
GetInitialPassengerExitPoint( nRole, pExitPoint, pAngles );
|
||
|
|
||
|
// Check the exit point:
|
||
|
Vector vecStart = *pExitPoint;
|
||
|
Vector vecEnd = *pExitPoint + Vector(0,0,20);
|
||
|
trace_t tr;
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
|
||
|
if ( (tr.fraction < 1.f) )
|
||
|
return false;
|
||
|
|
||
|
vecEnd = *pExitPoint + Vector(20,20,20);
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
|
||
|
if ( (tr.fraction < 1.f) )
|
||
|
return false;
|
||
|
|
||
|
vecEnd = *pExitPoint + Vector(-20,-20,20);
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
|
||
|
if ( (tr.fraction < 1.f) )
|
||
|
return false;
|
||
|
|
||
|
vecEnd = *pExitPoint + Vector(20,-20,20);
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
|
||
|
if ( (tr.fraction < 1.f) )
|
||
|
return false;
|
||
|
|
||
|
vecEnd = *pExitPoint + Vector(-20,20,20);
|
||
|
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr);
|
||
|
if ( (tr.fraction < 1.f) )
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::GetPassengerExitPoint( CBasePlayer *pPlayer, int nRole, Vector *pAbsPosition, QAngle *pAbsAngles )
|
||
|
{
|
||
|
|
||
|
// Deal with vehicles built on other vehicles
|
||
|
CBaseTFVehicle *pParentVehicle = dynamic_cast<CBaseTFVehicle*>(GetMoveParent());
|
||
|
if (pParentVehicle)
|
||
|
{
|
||
|
int nParentVehicleRole = pParentVehicle->GetChildVehicleRole( this );
|
||
|
if (nParentVehicleRole >= 0)
|
||
|
{
|
||
|
pParentVehicle->GetPassengerExitPoint( pPlayer, nParentVehicleRole, pAbsPosition, pAbsAngles );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Deal with vehicles build on objects
|
||
|
IHasBuildPoints *pMount = dynamic_cast<IHasBuildPoints*>(GetMoveParent());
|
||
|
if (pMount)
|
||
|
{
|
||
|
int nBuildPoint = pMount->FindObjectOnBuildPoint( this );
|
||
|
if (nBuildPoint >= 0)
|
||
|
{
|
||
|
pMount->GetExitPoint( pPlayer, nBuildPoint, pAbsPosition, pAbsAngles );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Vector vNewPos;
|
||
|
GetInitialPassengerExitPoint( nRole, pAbsPosition, pAbsAngles );
|
||
|
if ( EntityPlacementTest(pPlayer, *pAbsPosition, vNewPos, true) )
|
||
|
{
|
||
|
*pAbsPosition = vNewPos;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Find the first valid exit point
|
||
|
for( int iExitPoint = 0; iExitPoint < m_nMaxPassengers; ++iExitPoint )
|
||
|
{
|
||
|
if (iExitPoint == nRole)
|
||
|
continue;
|
||
|
|
||
|
GetInitialPassengerExitPoint( iExitPoint, pAbsPosition, pAbsAngles );
|
||
|
if ( EntityPlacementTest(pPlayer, *pAbsPosition, vNewPos, true) )
|
||
|
{
|
||
|
*pAbsPosition = vNewPos;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Worst case, we will be returning the vehicle's origin + 50z here
|
||
|
*pAbsPosition = GetAbsOrigin();
|
||
|
pAbsPosition->z = WorldAlignMaxs()[2] + 150.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::GetPassengerExitPoint( int nRole, Vector *pAbsPosition, QAngle *pAbsAngles )
|
||
|
{
|
||
|
// FIXME: Clean this up
|
||
|
CBasePlayer *pPlayer = GetPassenger(nRole);
|
||
|
GetPassengerExitPoint( pPlayer, nRole, pAbsPosition, pAbsAngles );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetEntryAnimForPoint( const Vector &vecPoint )
|
||
|
{
|
||
|
return ACTIVITY_NOT_AVAILABLE;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CBaseTFVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked )
|
||
|
{
|
||
|
bAllPointsBlocked = false;
|
||
|
return ACTIVITY_NOT_AVAILABLE;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::HandleEntryExitFinish( bool bExitAnimOn, bool bResetAnim )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pPlayer -
|
||
|
// false -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::HandlePassengerEntry( CBasePlayer *pPlayer, bool bAllowEntryOutsideZone )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pPlayer -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::HandlePassengerExit( CBasePlayer *pPlayer )
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Get and set the current driver.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::SetPassenger( int nRole, CBasePlayer *pEnt )
|
||
|
{
|
||
|
Assert( !pEnt || pEnt->IsPlayer() );
|
||
|
Assert( nRole >= 0 && nRole < m_nMaxPassengers );
|
||
|
Assert( !m_hPassengers[nRole].Get() || !pEnt );
|
||
|
m_hPassengers.Set( nRole, dynamic_cast<CBaseTFPlayer*>(pEnt) );
|
||
|
|
||
|
// If the vehicle's deteriorating, I get to own it now
|
||
|
if ( IsDeteriorating() )
|
||
|
{
|
||
|
StopDeteriorating();
|
||
|
SetBuilder( (CBaseTFPlayer*)pEnt, true );
|
||
|
}
|
||
|
|
||
|
ResetDeteriorationTime();
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Get a position in *world space* inside the vehicle for the player to start at
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::GetPassengerStartPoint( int nRole, Vector *pAbsPoint, QAngle *pAbsAngles )
|
||
|
{
|
||
|
char pAttachmentName[32];
|
||
|
Q_snprintf( pAttachmentName, sizeof( pAttachmentName ), "vehicle_feet_passenger%d", nRole );
|
||
|
int nFeetAttachmentIndex = LookupAttachment(pAttachmentName);
|
||
|
GetAttachment( nFeetAttachmentIndex, *pAbsPoint, *pAbsAngles );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
#define INITIAL_MAX_DISTANCE 999999.0f
|
||
|
|
||
|
int CBaseTFVehicle::LocateEntryPoint( CBaseTFPlayer *pPlayer, float* fBest2dDistanceSqr )
|
||
|
{
|
||
|
// Get the players origin and compare it to all the entry points on the
|
||
|
// vehicle.
|
||
|
Vector vecPlayerPos = pPlayer->GetAbsOrigin();
|
||
|
Vector vecEntryPos;
|
||
|
QAngle vecEntryAngle;
|
||
|
|
||
|
int iMinEntry = -1;
|
||
|
float flMinDistance2 = INITIAL_MAX_DISTANCE;
|
||
|
|
||
|
// Is the player the owner of the vehicle?
|
||
|
bool bOwner = ( pPlayer == GetOwner() );
|
||
|
|
||
|
char szPassengerEyes[32];
|
||
|
for( int iEntryPoint = 0; iEntryPoint < m_nMaxPassengers; ++iEntryPoint )
|
||
|
{
|
||
|
// If not the owner, check to see if the entry point is available. The
|
||
|
// entry point is always available for the owner.
|
||
|
bool bOccupied = ( GetPassenger( iEntryPoint ) != NULL );
|
||
|
|
||
|
// Also check for child vehicles...
|
||
|
|
||
|
if ( bOccupied && !bOwner )
|
||
|
continue;
|
||
|
|
||
|
// FIXME: Cache off the entry point
|
||
|
Q_snprintf( szPassengerEyes, sizeof( szPassengerEyes ), "vehicle_feet_passenger%d", iEntryPoint );
|
||
|
int nAttachmentIndex = LookupAttachment( szPassengerEyes );
|
||
|
|
||
|
float flDistance2;
|
||
|
if (nAttachmentIndex > 0)
|
||
|
{
|
||
|
GetAttachment( nAttachmentIndex, vecEntryPos, vecEntryAngle );
|
||
|
Vector vecDelta = vecEntryPos - vecPlayerPos;
|
||
|
flDistance2 = vecDelta.AsVector2D().LengthSqr();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No attachment? Choose it if we must as a last resort
|
||
|
flDistance2 = INITIAL_MAX_DISTANCE - 1;
|
||
|
}
|
||
|
|
||
|
if ( flDistance2 < flMinDistance2 )
|
||
|
{
|
||
|
flMinDistance2 = flDistance2;
|
||
|
iMinEntry = iEntryPoint;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( fBest2dDistanceSqr )
|
||
|
{
|
||
|
*fBest2dDistanceSqr = flMinDistance2;
|
||
|
}
|
||
|
return iMinEntry;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Set a gun that the driver can control
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::SetDriverGun( CBaseObjectDriverGun *pGun )
|
||
|
{
|
||
|
m_hDriverGun = pGun;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Update the driver's gun
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::VehicleDriverGunThink( void )
|
||
|
{
|
||
|
if ( !m_hDriverGun )
|
||
|
return;
|
||
|
|
||
|
// No driver?
|
||
|
CBaseTFPlayer *pDriver = GetDriverPlayer();
|
||
|
if ( !pDriver )
|
||
|
return;
|
||
|
|
||
|
QAngle vecTargetAngles = m_hDriverGun->GetCurrentAngles();
|
||
|
|
||
|
// Cast a ray out of the view to see where the player is looking.
|
||
|
trace_t trace;
|
||
|
Vector vecForward;
|
||
|
Vector vecSrc;
|
||
|
QAngle angEyeAngles;
|
||
|
GetVehicleViewPosition( VEHICLE_DRIVER, &vecSrc, &angEyeAngles, NULL );
|
||
|
AngleVectors( angEyeAngles, &vecForward, NULL, NULL );
|
||
|
Vector vecEnd = vecSrc + (vecForward * 10000);
|
||
|
UTIL_TraceLine( vecSrc, vecEnd, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &trace );
|
||
|
|
||
|
//NDebugOverlay::Box( vecSrc, -Vector(10,10,10), Vector(10,10,10), 255,0,0,8, 5 );
|
||
|
//NDebugOverlay::Box( vecEnd, -Vector(10,10,10), Vector(10,10,10), 0,255,0,8, 5 );
|
||
|
//NDebugOverlay::Box( trace.endpos, -Vector(10,10,10), Vector(10,10,10), 255,255,255,8, 0.1 );
|
||
|
|
||
|
if ( trace.fraction < 1 )
|
||
|
{
|
||
|
// Figure out what angles our turret needs to be at in order to hit the target.
|
||
|
Vector vFireOrigin = m_hDriverGun->GetFireOrigin();
|
||
|
|
||
|
//NDebugOverlay::Box( vFireOrigin, -Vector(10,10,10), Vector(10,10,10), 0,255,0,8, 0.1 );
|
||
|
|
||
|
// Get a direction vector that points at the target.
|
||
|
Vector vTo = trace.endpos - vFireOrigin;
|
||
|
|
||
|
// Transform it into the tank's local space.
|
||
|
matrix3x4_t tankToWorld;
|
||
|
AngleMatrix( GetAbsAngles(), tankToWorld );
|
||
|
|
||
|
Vector vLocalTo;
|
||
|
VectorITransform( vTo, tankToWorld, vLocalTo );
|
||
|
|
||
|
// Now figure out what the angles are in local space.
|
||
|
QAngle localAngles;
|
||
|
VectorAngles( vLocalTo, localAngles );
|
||
|
|
||
|
vecTargetAngles[YAW] = localAngles[YAW] - 90;
|
||
|
vecTargetAngles[PITCH] = anglemod( localAngles[PITCH] );
|
||
|
}
|
||
|
|
||
|
// Set the gun's angles
|
||
|
m_hDriverGun->SetTargetAngles( vecTargetAngles );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::ShouldUseThirdPersonVehicleView()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Returns the unperterbed view position for a particular role
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::GetRoleViewPosition( int nRole, Vector *pVehicleEyeOrigin, QAngle *pVehicleEyeAngles )
|
||
|
{
|
||
|
// Generate the view position in world space.
|
||
|
Vector vAbsOrigin;
|
||
|
QAngle vAbsAngle;
|
||
|
bool bUsingThirdPersonCamera = GetRoleAbsViewPosition( nRole, &vAbsOrigin, &vAbsAngle );
|
||
|
|
||
|
|
||
|
// Make a matrix for it.
|
||
|
matrix3x4_t absMatrix;
|
||
|
AngleMatrix( vAbsAngle, absMatrix );
|
||
|
MatrixSetColumn( vAbsOrigin, 3, absMatrix );
|
||
|
|
||
|
|
||
|
// Transform the matrix into local space.
|
||
|
matrix3x4_t worldToEntity, local;
|
||
|
MatrixInvert( EntityToWorldTransform(), worldToEntity );
|
||
|
ConcatTransforms( worldToEntity, absMatrix, local );
|
||
|
|
||
|
|
||
|
// Suck out the origin and angles.
|
||
|
pVehicleEyeOrigin->Init( local[0][3], local[1][3], local[2][3] );
|
||
|
MatrixAngles( local, *pVehicleEyeAngles );
|
||
|
|
||
|
return bUsingThirdPersonCamera;
|
||
|
}
|
||
|
|
||
|
bool CBaseTFVehicle::GetRoleAbsViewPosition( int nRole, Vector *pAbsVehicleEyeOrigin, QAngle *pAbsVehicleEyeAngles )
|
||
|
{
|
||
|
int iAttachment = LookupAttachment( "ThirdPersonCameraOrigin" );
|
||
|
if ( ShouldUseThirdPersonVehicleView() && vehicle_thirdperson.GetInt() && nRole == VEHICLE_DRIVER && iAttachment > 0 )
|
||
|
{
|
||
|
// Ok, we're using third person. Leave their angles intact but rotate theirt view around the
|
||
|
// ThirdPersonCameraOrigin attachment.
|
||
|
Vector vAttachOrigin;
|
||
|
QAngle vAttachAngles;
|
||
|
GetAttachment( iAttachment, vAttachOrigin, vAttachAngles );
|
||
|
|
||
|
Vector vForward, vRight, vUp;
|
||
|
AngleVectors( *pAbsVehicleEyeAngles, &vForward, &vRight, &vUp );
|
||
|
|
||
|
*pAbsVehicleEyeOrigin = vAttachOrigin + vForward * vehicle_view_offset_forward.GetFloat() +
|
||
|
vRight * vehicle_view_offset_right.GetFloat() +
|
||
|
vUp * vehicle_view_offset_up.GetFloat();
|
||
|
|
||
|
// Returning true tells the caller that we're using a third-person camera origin.
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Use the vehicle_eyes_passengerX attachments.
|
||
|
Assert( nRole >= 0 );
|
||
|
char pAttachmentName[32];
|
||
|
Q_snprintf( pAttachmentName, sizeof( pAttachmentName ), "vehicle_eyes_passenger%d", nRole );
|
||
|
int eyeAttachmentIndex = LookupAttachment(pAttachmentName);
|
||
|
|
||
|
QAngle vTempAngles;
|
||
|
GetAttachment( eyeAttachmentIndex, *pAbsVehicleEyeOrigin, vTempAngles );
|
||
|
|
||
|
if ( vehicle_attach_eye_angles.GetInt() )
|
||
|
*pAbsVehicleEyeAngles = vTempAngles;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Modify the player view/camera while in a vehicle
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ )
|
||
|
{
|
||
|
// UNDONE: Use attachment point on the vehicle, not hardcoded player eyes
|
||
|
Assert( nRole >= 0 );
|
||
|
CBasePlayer *pPlayer = GetPassenger( nRole );
|
||
|
Assert( pPlayer );
|
||
|
|
||
|
Vector vehicleEyeOrigin;
|
||
|
QAngle vehicleEyeAngles = pPlayer->LocalEyeAngles();
|
||
|
|
||
|
GetRoleAbsViewPosition( nRole, &vehicleEyeOrigin, &vehicleEyeAngles );
|
||
|
|
||
|
*pAbsOrigin = vehicleEyeOrigin;
|
||
|
*pAbsAngles = vehicleEyeAngles;
|
||
|
|
||
|
/*
|
||
|
if ( bUsingThirdPersonCamera )
|
||
|
{
|
||
|
*pAbsOrigin = vehicleEyeOrigin;
|
||
|
*pAbsAngles = vehicleEyeAngles;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
matrix3x4_t vehicleEyePosToWorld;
|
||
|
|
||
|
AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld );
|
||
|
|
||
|
// Compute the relative rotation between the unperterbed eye attachment + the eye angles
|
||
|
matrix3x4_t cameraToWorld;
|
||
|
AngleMatrix( *pAbsAngles, cameraToWorld );
|
||
|
|
||
|
matrix3x4_t worldToEyePos;
|
||
|
MatrixInvert( vehicleEyePosToWorld, worldToEyePos );
|
||
|
|
||
|
matrix3x4_t vehicleCameraToEyePos;
|
||
|
ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos );
|
||
|
|
||
|
// Now perterb the attachment point
|
||
|
if( inv_demo.GetInt() )
|
||
|
{
|
||
|
vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * road_feel.GetFloat(), PITCH_CURVE_LINEAR, vehicleEyeAngles.x );
|
||
|
vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * road_feel.GetFloat(), ROLL_CURVE_LINEAR, vehicleEyeAngles.z );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO, PITCH_CURVE_LINEAR, vehicleEyeAngles.x );
|
||
|
vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO, ROLL_CURVE_LINEAR, vehicleEyeAngles.z );
|
||
|
}
|
||
|
|
||
|
AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld );
|
||
|
|
||
|
// Now treat the relative eye angles as being relative to this new, perterbed view position...
|
||
|
matrix3x4_t newCameraToWorld;
|
||
|
ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld );
|
||
|
|
||
|
// output new view abs angles
|
||
|
MatrixAngles( newCameraToWorld, *pAbsAngles );
|
||
|
|
||
|
// UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics
|
||
|
MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin );
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Client-only code here
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#if defined (CLIENT_DLL)
|
||
|
|
||
|
void CBaseTFVehicle::ClientThink()
|
||
|
{
|
||
|
BaseClass::ClientThink();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CBaseTFVehicle::ShouldPredict( void )
|
||
|
{
|
||
|
// Only predict vehicles driven by local players
|
||
|
return GetDriverPlayer() ? GetDriverPlayer()->IsLocalPlayer() : false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Get the angles that a player in the specified role should be using for visuals
|
||
|
//-----------------------------------------------------------------------------
|
||
|
QAngle CBaseTFVehicle::GetPassengerAngles( QAngle angCurrent, int nRole )
|
||
|
{
|
||
|
// Just use your current angles
|
||
|
return angCurrent;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::DrawHudElements( void )
|
||
|
{
|
||
|
// If we've got a driver gun, tell it to draw it's elements
|
||
|
if ( m_hDriverGun )
|
||
|
{
|
||
|
m_hDriverGun->DrawHudElements();
|
||
|
}
|
||
|
|
||
|
DrawHudBoostData();
|
||
|
SetupCrosshair();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::DrawHudBoostData( void )
|
||
|
{
|
||
|
#define HUD_IMAGE_LEFT XRES( 568 )
|
||
|
|
||
|
// Boostable vehicle
|
||
|
if ( IsBoostable() )
|
||
|
{
|
||
|
// Set our color
|
||
|
CHudTexture *pVehicleBoostLabel = gHUD.GetIcon( "no2" );
|
||
|
if ( pVehicleBoostLabel )
|
||
|
{
|
||
|
int nScreenY = ScreenHeight() - YRES( 12 );
|
||
|
float nOneHudHeight = ( YRES(10) + pVehicleBoostLabel->Height() );
|
||
|
nScreenY -= ( nOneHudHeight * 3 );
|
||
|
|
||
|
pVehicleBoostLabel->DrawSelf( HUD_IMAGE_LEFT, nScreenY - pVehicleBoostLabel->Height(), gHUD.m_clrNormal );
|
||
|
gHUD.DrawProgressBar( HUD_IMAGE_LEFT, nScreenY + YRES( 4 ), XRES( 70 ), YRES( 4 ), m_nBoostTimeLeft / 100.0f, gHUD.m_clrNormal, CHud::HUDPB_HORIZONTAL_INV );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef HUD_IMAGE_LEFT
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Set a crosshair when in a vehicle and we don't have a proper
|
||
|
// crosshair sprite (ie. a commando laser rifle).
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CBaseTFVehicle::SetupCrosshair( void )
|
||
|
{
|
||
|
if ( !m_pIconDefaultCrosshair )
|
||
|
{
|
||
|
// Init the default crosshair the first time.
|
||
|
CHudTexture newTexture;
|
||
|
Q_strncpy( newTexture.szTextureFile, "sprites/crosshairs", sizeof( newTexture.szTextureFile ) );
|
||
|
|
||
|
newTexture.rc.left = 0;
|
||
|
newTexture.rc.top = 48;
|
||
|
newTexture.rc.right = newTexture.rc.left + 24;
|
||
|
newTexture.rc.bottom = newTexture.rc.top + 24;
|
||
|
m_pIconDefaultCrosshair = gHUD.AddUnsearchableHudIconToList( newTexture );
|
||
|
}
|
||
|
|
||
|
CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
|
||
|
if ( crosshair )
|
||
|
{
|
||
|
if ( !crosshair->HasCrosshair() && m_pIconDefaultCrosshair )
|
||
|
{
|
||
|
crosshair->SetCrosshair( m_pIconDefaultCrosshair, gHUD.m_clrNormal );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|