//========= Copyright © 1996-2005, 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 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 m_EntryTransitions; // Entry information CUtlVector 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 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 ¶ms ); virtual void PlaySound( vehiclesound iSound ); virtual void StopSound( vehiclesound iSound ); virtual void RecalculateSoundGear( vbs_sound_update_t ¶ms ); void SetVehicleVolume( float flVolume ) { m_flVehicleVolume = clamp( flVolume, 0.0, 1.0 ); } // 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 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 ¶ms ); sound_states SoundState_ChooseState( vbs_sound_update_t ¶ms ); 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 ¶ms ); const char *StateSoundName( sound_states state ); void InitSoundParams( vbs_sound_update_t ¶ms ); 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