text: //========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose: 
  //
  //=============================================================================//
  
  #ifndef VEHICLE_BASESERVER_H
  #define VEHICLE_BASESERVER_H
  #ifdef _WIN32
  #pragma once
  #endif
  
  #include "vehicle_sounds.h"
  #include "entityblocker.h"
  
  class CSoundPatch;
  
  struct vbs_sound_update_t
  {
  	float	flFrameTime;
  	float	flCurrentSpeedFraction;
  	float	flWorldSpaceSpeed;
  	bool	bThrottleDown;
  	bool	bReverse;
  	bool	bTurbo;
  	bool	bVehicleInWater;
  	bool	bExitVehicle;
  
  	void Defaults()
  	{
  		flFrameTime = gpGlobals->frametime;
  		flCurrentSpeedFraction = 0;
  		flWorldSpaceSpeed = 0;
  		bThrottleDown = false;
  		bReverse = false;
  		bTurbo = false;
  		bVehicleInWater = false;
  		bExitVehicle = false;
  	}
  };
  
  // -----------------------------------------
  //  Information about the passenger in the car 
  // -----------------------------------------
  class CPassengerInfo
  {
  public:
  	CPassengerInfo( void ) : m_nRole( -1 ), m_nSeat( -1 ), m_strRoleName( NULL_STRING ), m_strSeatName( NULL_STRING ) {}
  
  	DECLARE_SIMPLE_DATADESC();
  
  	int GetSeat( void ) const { return m_nSeat; }
  	int	GetRole( void ) const { return m_nRole; }
  	CBaseCombatCharacter *GetPassenger( void ) const { return m_hPassenger; }
  
  private:
  	int									m_nRole;		// Role (by index)
  	int									m_nSeat;		// Seat (by index)
  	string_t							m_strRoleName;	// Used in restoration for fix-up
  	string_t							m_strSeatName;	// Used in restoration for fix-up
  	CHandle<CBaseCombatCharacter>		m_hPassenger;	// Actual passenger
  
  	friend class CBaseServerVehicle;
  };
  
  // -----------------------------------------
  //  Seat transition information (animation and priority)
  // -----------------------------------------
  
  class CPassengerSeatTransition
  {
  public:
  	CPassengerSeatTransition( void ) : m_strAnimationName( NULL_STRING ), m_nPriority( -1 ) {};
  
  	string_t GetAnimationName( void ) const { return m_strAnimationName; }
  	int		 GetPriority( void ) const { return m_nPriority; }
  
  private:
  	string_t	m_strAnimationName;	// Name of animation to play
  	int			m_nPriority;		// Priority of the transition
  
  	friend class CBaseServerVehicle;
  };
  
  // -----------------------------------------
  //  Seat in a vehicle (attachment and a collection of animations to reach it)
  // -----------------------------------------
  class CPassengerSeat
  {
  public:
  	CPassengerSeat( void ) : m_nAttachmentID( -1 ) {};
  	int GetAttachmentID( void ) const { return m_nAttachmentID; }
  
  private:
  	string_t								m_strSeatName;			// Used for save/load fixup
  	int										m_nAttachmentID;		// Goal attachment
  	CUtlVector<CPassengerSeatTransition>	m_EntryTransitions;		// Entry information
  	CUtlVector<CPassengerSeatTransition>	m_ExitTransitions;		// Exit information
  
  	friend class CBaseServerVehicle;
  };
  
  // -----------------------------------------
  //  Passenger role information
  // -----------------------------------------
  class CPassengerRole
  {
  public:
  	CPassengerRole( void ) : m_strName( NULL_STRING ) {};
  	string_t GetName( void ) const { return m_strName; }
  
  private:
  	string_t						m_strName;			// Name of the set
  	CUtlVector<CPassengerSeat>		m_PassengerSeats;	// Passenger info
  
  	friend class CBaseServerVehicle;
  };
  
  //-----------------------------------------------------------------------------
  // Purpose: Base class for drivable vehicle handling. Contain it in your 
  //			drivable vehicle.
  //-----------------------------------------------------------------------------
  class CBaseServerVehicle : public IServerVehicle
  {
  public:
  	DECLARE_SIMPLE_DATADESC();
  	DECLARE_CLASS_NOBASE( CBaseServerVehicle );
  
  	CBaseServerVehicle( void );
  	~CBaseServerVehicle( void );
  
  	virtual void			Precache( void );
  
  // IVehicle
  public:
  	virtual CBaseCombatCharacter *GetPassenger( int nRole = VEHICLE_ROLE_DRIVER );
  
  	virtual int				GetPassengerRole( CBaseCombatCharacter *pPassenger );
  	virtual void			GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL );
  	virtual bool			IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
  	virtual void			SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move );
  	virtual void			ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData );
  	virtual void			FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move );
  	virtual void			ItemPostFrame( CBasePlayer *pPlayer );
  
  // IServerVehicle
  public:
  	virtual CBaseEntity		*GetVehicleEnt( void ) { return m_pVehicle; }
  	virtual void			SetPassenger( int nRole, CBaseCombatCharacter *pPassenger );
  	virtual bool			IsPassengerVisible( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
  	virtual bool			IsPassengerDamagable( int nRole  = VEHICLE_ROLE_DRIVER ) { return true; }
  	virtual bool			PassengerShouldReceiveDamage( CTakeDamageInfo &info );
  
  	virtual bool			IsVehicleUpright( void ) { return true; }
  	virtual bool			IsPassengerEntering( void ) { Assert( 0 ); return false; }
  	virtual bool			IsPassengerExiting( void ) { Assert( 0 ); return false; }
  	
  	virtual void			HandlePassengerEntry( CBaseCombatCharacter *pPassenger, bool bAllowEntryOutsideZone = false );
  	virtual bool			HandlePassengerExit( CBaseCombatCharacter *pPassenger );
  
  	virtual void			GetPassengerSeatPoint( int nRole, Vector *pPoint, QAngle *pAngles );
  	virtual bool			GetPassengerExitPoint( int nRole, Vector *pPoint, QAngle *pAngles );
  	virtual Class_T			ClassifyPassenger( CBaseCombatCharacter *pPassenger, Class_T defaultClassification ) { return defaultClassification; }
  	virtual float			PassengerDamageModifier( const CTakeDamageInfo &info ) { return 1.0; }
  	virtual const vehicleparams_t	*GetVehicleParams( void ) { return NULL; }
  	virtual bool			IsVehicleBodyInWater( void ) { return false; }
  	virtual IPhysicsVehicleController *GetVehicleController() { return NULL; }
  
  	// NPC Driving
  	virtual bool			NPC_CanDrive( void ) { return true; }
  	virtual void			NPC_SetDriver( CNPC_VehicleDriver *pDriver ) { return; }
  	virtual void			NPC_DriveVehicle( void ) { return; }
  	virtual void			NPC_ThrottleCenter( void );
  	virtual void			NPC_ThrottleReverse( void );
  	virtual void			NPC_ThrottleForward( void );
  	virtual void			NPC_Brake( void );
  	virtual void			NPC_TurnLeft( float flDegrees );
  	virtual void			NPC_TurnRight( float flDegrees );
  	virtual void			NPC_TurnCenter( void );
  	virtual void			NPC_PrimaryFire( void );
  	virtual void			NPC_SecondaryFire( void );
  	virtual bool			NPC_HasPrimaryWeapon( void ) { return false; }
  	virtual bool			NPC_HasSecondaryWeapon( void ) { return false; }
  	virtual void			NPC_AimPrimaryWeapon( Vector vecTarget ) { return; }
  	virtual void			NPC_AimSecondaryWeapon( Vector vecTarget ) { return; }
  
  	// Weapon handling
  	virtual void			Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange );
  	virtual void			Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange );	
  	virtual float			Weapon_PrimaryCanFireAt( void );		// Return the time at which this vehicle's primary weapon can fire again
  	virtual float			Weapon_SecondaryCanFireAt( void );		// Return the time at which this vehicle's secondary weapon can fire again
  
  	// ----------------------------------------------------------------------------
  	// NPC passenger data
  
  public:
  
  	bool			NPC_AddPassenger( CBaseCombatCharacter *pPassenger, string_t strRoleName, int nSeat );
  	bool			NPC_RemovePassenger( CBaseCombatCharacter *pPassenger );
  	virtual bool	NPC_GetPassengerSeatPosition( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngle );
  	virtual bool	NPC_GetPassengerSeatPositionLocal( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngles );
  	virtual int		NPC_GetPassengerSeatAttachment( CBaseCombatCharacter *pPassenger );
  	virtual int		NPC_GetAvailableSeat( CBaseCombatCharacter *pPassenger, string_t strRoleName, VehicleSeatQuery_e nQueryType );
  	bool			NPC_HasAvailableSeat( string_t strRoleName );
  
  
  	virtual const PassengerSeatAnims_t	*NPC_GetPassengerSeatAnims( CBaseCombatCharacter *pPassenger, PassengerSeatAnimType_t nType );
  	virtual CBaseCombatCharacter		*NPC_GetPassengerInSeat( int nRoleID, int nSeatID );
  
  	Vector	GetSavedViewOffset( void ) { return m_savedViewOffset; }
  
  private:
  
  	// Vehicle entering/exiting
  	void	ParseNPCRoles( KeyValues *pModelKeyValues );
  	void	ParseNPCPassengerSeat( KeyValues *pSetKeyValues, CPassengerSeat *pSeat );
  	void	ParseNPCSeatTransition( KeyValues *pTransitionKeyValues, CPassengerSeatTransition *pTransition );
  
  protected:
  	
  	int		FindRoleIndexByName( string_t strRoleName );
  	int		FindSeatIndexByName( int nRoleIndex, string_t strSeatName );
  	int		NPC_GetAvailableSeat_Any( CBaseCombatCharacter *pPassenger, int nRoleID );
  	int		NPC_GetAvailableSeat_Nearest( CBaseCombatCharacter *pPassenger, int nRoleID );
  
  	CPassengerRole *FindOrCreatePassengerRole( string_t strName, int *nIndex = NULL );
  
  	CUtlVector< CPassengerInfo >	m_PassengerInfo;
  	CUtlVector< CPassengerRole >	m_PassengerRoles;	// Not save/restored
  
  	// ----------------------------------------------------------------------------
  	void	ReloadScript();	// debug/tuning
  public:
  
  	void					UseLegacyExitChecks( bool bState ) { m_bUseLegacyExitChecks = bState; }
  	void					RestorePassengerInfo( void );
  
  	virtual CBaseEntity		*GetDriver( void );	// Player Driving
  	virtual void			ParseEntryExitAnims( void );
  	void					ParseExitAnim( KeyValues *pkvExitList, bool bEscapeExit );
  	virtual bool			CheckExitPoint( float yaw, int distance, Vector *pEndPoint );
  	virtual int				GetEntryAnimForPoint( const Vector &vecPoint );
  	virtual int				GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked );
  	virtual void			HandleEntryExitFinish( bool bExitAnimOn, bool bResetAnim );
  
  	virtual void			SetVehicle( CBaseEntity *pVehicle );
  	IDrivableVehicle 		*GetDrivableVehicle( void );
  
  	// Sound handling
  	bool					Initialize( const char *pScriptName );
  	virtual void			SoundStart();
  	virtual void			SoundStartDisabled();
  	virtual void			SoundShutdown( float flFadeTime = 0.0 );
  	virtual void			SoundUpdate( vbs_sound_update_t &params );
  	virtual void			PlaySound( vehiclesound iSound );
  	virtual void			StopSound( vehiclesound iSound );
  	virtual void 			RecalculateSoundGear( vbs_sound_update_t &params );
  	void					SetVehicleVolume( float flVolume ) { m_flVehicleVolume = clamp( flVolume, 0.0f, 1.0f ); }
  
  	// Rumble
  	virtual void			StartEngineRumble();
  	virtual void			StopEngineRumble();
  
  public:
  	CBaseEntity			*m_pVehicle;
  	IDrivableVehicle 	*m_pDrivableVehicle;
  
  	// NPC Driving
  	int								m_nNPCButtons;
  	int								m_nPrevNPCButtons;
  	float							m_flTurnDegrees;
  
  	// Entry / Exit anims
  	struct entryanim_t
  	{
  		int		iHitboxGroup;
  		char	szAnimName[128];
  	};
  	CUtlVector< entryanim_t >		m_EntryAnimations;
  
  	struct exitanim_t
  	{
  		bool	bUpright;
  		bool	bEscapeExit;
  		char	szAnimName[128];
  		Vector	vecExitPointLocal;		// Point the animation leaves the player at when finished
  		QAngle	vecExitAnglesLocal;
  	};
  
  	CUtlVector< exitanim_t >		m_ExitAnimations;
  	bool							m_bParsedAnimations;
  	bool							m_bUseLegacyExitChecks;	// HACK: Choreo vehicles use non-sensical setups to move the player, we need to poll their attachment point positions
  	int								m_iCurrentExitAnim;
  	Vector							m_vecCurrentExitEndPoint;
  	Vector							m_savedViewOffset;
  	CHandle<CEntityBlocker>			m_hExitBlocker;				// Entity to prevent other entities blocking the player's exit point during the exit animation
  
  	char							m_chPreviousTextureType;
  
  // sound state
  	vehiclesounds_t					m_vehicleSounds;
  private:
  	float							m_flVehicleVolume;
  	int								m_iSoundGear;			// The sound "gear" that we're currently in
  	float							m_flSpeedPercentage;
  
  	CSoundPatch						*m_pStateSound;
  	CSoundPatch						*m_pStateSoundFade;
  	sound_states					m_soundState;
  	float							m_soundStateStartTime;
  	float							m_lastSpeed;
  	
  	void	SoundState_OnNewState( sound_states lastState );
  	void	SoundState_Update( vbs_sound_update_t &params );
  	sound_states SoundState_ChooseState( vbs_sound_update_t &params );
  	void	PlaySound( const char *pSound );
  	void	StopLoopingSound( float fadeTime = 0.25f );
  	void	PlayLoopingSound( const char *pSoundName );
  	bool	PlayCrashSound( float speed );
  	bool	CheckCrash( vbs_sound_update_t &params );
  	const char *StateSoundName( sound_states state );
  	void	InitSoundParams( vbs_sound_update_t &params );
  	void	CacheEntryExitPoints( void );
  	bool	GetLocalAttachmentAtTime( int nQuerySequence, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut );
  	bool	GetLocalAttachmentAtTime( const char *lpszAnimName, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut );
  };
  
  #endif // VEHICLE_BASESERVER_H
  