diff options
Diffstat (limited to 'game/server/player.h')
| -rw-r--r-- | game/server/player.h | 1564 |
1 files changed, 1564 insertions, 0 deletions
diff --git a/game/server/player.h b/game/server/player.h new file mode 100644 index 0000000..4885a2d --- /dev/null +++ b/game/server/player.h @@ -0,0 +1,1564 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef PLAYER_H +#define PLAYER_H +#ifdef _WIN32 +#pragma once +#endif + +#include "basecombatcharacter.h" +#include "usercmd.h" +#include "playerlocaldata.h" +#include "PlayerState.h" +#include "game/server/iplayerinfo.h" +#include "hintsystem.h" +#include "SoundEmitterSystem/isoundemittersystembase.h" +#include "util_shared.h" + +#if defined USES_ECON_ITEMS +#include "game_item_schema.h" +#include "econ_item_view.h" +#endif + +// For queuing and processing usercmds +class CCommandContext +{ +public: + CUtlVector< CUserCmd > cmds; + + int numcmds; + int totalcmds; + int dropped_packets; + bool paused; +}; + +// Info about last 20 or so updates to the +class CPlayerCmdInfo +{ +public: + CPlayerCmdInfo() : + m_flTime( 0.0f ), m_nNumCmds( 0 ), m_nDroppedPackets( 0 ) + { + } + + // realtime of sample + float m_flTime; + // # of CUserCmds in this update + int m_nNumCmds; + // # of dropped packets on the link + int m_nDroppedPackets; +}; + +class CPlayerSimInfo +{ +public: + CPlayerSimInfo() : + m_flTime( 0.0f ), m_nNumCmds( 0 ), m_nTicksCorrected( 0 ), m_flFinalSimulationTime( 0.0f ), m_flGameSimulationTime( 0.0f ), m_flServerFrameTime( 0.0f ), m_vecAbsOrigin( 0, 0, 0 ) + { + } + + // realtime of sample + float m_flTime; + // # of CUserCmds in this update + int m_nNumCmds; + // If clock needed correction, # of ticks added/removed + int m_nTicksCorrected; // +ve or -ve + // player's m_flSimulationTime at end of frame + float m_flFinalSimulationTime; + float m_flGameSimulationTime; + // estimate of server perf + float m_flServerFrameTime; + Vector m_vecAbsOrigin; +}; +//----------------------------------------------------------------------------- +// Forward declarations: +//----------------------------------------------------------------------------- +class CBaseCombatWeapon; +class CBaseViewModel; +class CTeam; +class IPhysicsPlayerController; +class IServerVehicle; +class CUserCmd; +class CFuncLadder; +class CNavArea; +class CHintSystem; +class CAI_Expresser; + +#if defined USES_ECON_ITEMS +class CEconWearable; +#endif // USES_ECON_ITEMS + +// for step sounds +struct surfacedata_t; + +// !!!set this bit on guns and stuff that should never respawn. +#define SF_NORESPAWN ( 1 << 30 ) + +// +// Player PHYSICS FLAGS bits +// +enum PlayerPhysFlag_e +{ + PFLAG_DIROVERRIDE = ( 1<<0 ), // override the player's directional control (trains, physics gun, etc.) + PFLAG_DUCKING = ( 1<<1 ), // In the process of ducking, but totally squatted yet + PFLAG_USING = ( 1<<2 ), // Using a continuous entity + PFLAG_OBSERVER = ( 1<<3 ), // player is locked in stationary cam mode. Spectators can move, observers can't. + PFLAG_VPHYSICS_MOTIONCONTROLLER = ( 1<<4 ), // player is physically attached to a motion controller + PFLAG_GAMEPHYSICS_ROTPUSH = (1<<5), // game physics did a rotating push that we may want to override with vphysics + + // If you add another flag here check that you aren't + // overwriting phys flags in the HL2 of TF2 player classes +}; + +// +// generic player +// +//----------------------------------------------------- +//This is Half-Life player entity +//----------------------------------------------------- +#define CSUITPLAYLIST 4 // max of 4 suit sentences queued up at any time +#define SUIT_REPEAT_OK 0 + +#define SUIT_NEXT_IN_30SEC 30 +#define SUIT_NEXT_IN_1MIN 60 +#define SUIT_NEXT_IN_5MIN 300 +#define SUIT_NEXT_IN_10MIN 600 +#define SUIT_NEXT_IN_30MIN 1800 +#define SUIT_NEXT_IN_1HOUR 3600 + +#define CSUITNOREPEAT 32 + +#define TEAM_NAME_LENGTH 16 + +// constant items +#define ITEM_HEALTHKIT 1 +#define ITEM_BATTERY 4 + +#define AUTOAIM_2DEGREES 0.0348994967025 +#define AUTOAIM_5DEGREES 0.08715574274766 +#define AUTOAIM_8DEGREES 0.1391731009601 +#define AUTOAIM_10DEGREES 0.1736481776669 +#define AUTOAIM_20DEGREES 0.3490658503989 + +// useful cosines +#define DOT_1DEGREE 0.9998476951564 +#define DOT_2DEGREE 0.9993908270191 +#define DOT_3DEGREE 0.9986295347546 +#define DOT_4DEGREE 0.9975640502598 +#define DOT_5DEGREE 0.9961946980917 +#define DOT_6DEGREE 0.9945218953683 +#define DOT_7DEGREE 0.9925461516413 +#define DOT_8DEGREE 0.9902680687416 +#define DOT_9DEGREE 0.9876883405951 +#define DOT_10DEGREE 0.9848077530122 +#define DOT_15DEGREE 0.9659258262891 +#define DOT_20DEGREE 0.9396926207859 +#define DOT_25DEGREE 0.9063077870367 +#define DOT_30DEGREE 0.866025403784 +#define DOT_45DEGREE 0.707106781187 +enum +{ + VPHYS_WALK = 0, + VPHYS_CROUCH, + VPHYS_NOCLIP, +}; + + +enum PlayerConnectedState +{ + PlayerConnected, + PlayerDisconnecting, + PlayerDisconnected, +}; + +extern bool gInitHUD; +extern ConVar *sv_cheats; + +class CBasePlayer; +class CPlayerInfo : public IBotController, public IPlayerInfo +{ +public: + CPlayerInfo () { m_pParent = NULL; } + ~CPlayerInfo () {} + void SetParent( CBasePlayer *parent ) { m_pParent = parent; } + + // IPlayerInfo interface + virtual const char *GetName(); + virtual int GetUserID(); + virtual const char *GetNetworkIDString(); + virtual int GetTeamIndex(); + virtual void ChangeTeam( int iTeamNum ); + virtual int GetFragCount(); + virtual int GetDeathCount(); + virtual bool IsConnected(); + virtual int GetArmorValue(); + + virtual bool IsHLTV(); + virtual bool IsReplay(); + virtual bool IsPlayer(); + virtual bool IsFakeClient(); + virtual bool IsDead(); + virtual bool IsInAVehicle(); + virtual bool IsObserver(); + virtual const Vector GetAbsOrigin(); + virtual const QAngle GetAbsAngles(); + virtual const Vector GetPlayerMins(); + virtual const Vector GetPlayerMaxs(); + virtual const char *GetWeaponName(); + virtual const char *GetModelName(); + virtual const int GetHealth(); + virtual const int GetMaxHealth(); + + // bot specific functions + virtual void SetAbsOrigin( Vector & vec ); + virtual void SetAbsAngles( QAngle & ang ); + virtual void RemoveAllItems( bool removeSuit ); + virtual void SetActiveWeapon( const char *WeaponName ); + virtual void SetLocalOrigin( const Vector& origin ); + virtual const Vector GetLocalOrigin( void ); + virtual void SetLocalAngles( const QAngle& angles ); + virtual const QAngle GetLocalAngles( void ); + virtual bool IsEFlagSet( int nEFlagMask ); + + virtual void RunPlayerMove( CBotCmd *ucmd ); + virtual void SetLastUserCommand( const CBotCmd &cmd ); + + virtual CBotCmd GetLastUserCommand(); + +private: + CBasePlayer *m_pParent; +}; + + +class CBasePlayer : public CBaseCombatCharacter +{ +public: + DECLARE_CLASS( CBasePlayer, CBaseCombatCharacter ); +protected: + // HACK FOR BOTS + friend class CBotManager; + static edict_t *s_PlayerEdict; // must be set before calling constructor +public: + DECLARE_DATADESC(); + DECLARE_SERVERCLASS(); + + CBasePlayer(); + ~CBasePlayer(); + + // IPlayerInfo passthrough (because we can't do multiple inheritance) + IPlayerInfo *GetPlayerInfo() { return &m_PlayerInfo; } + IBotController *GetBotController() { return &m_PlayerInfo; } + + virtual void SetModel( const char *szModelName ); + void SetBodyPitch( float flPitch ); + + virtual void UpdateOnRemove( void ); + + static CBasePlayer *CreatePlayer( const char *className, edict_t *ed ); + + virtual void CreateViewModel( int viewmodelindex = 0 ); + CBaseViewModel *GetViewModel( int viewmodelindex = 0, bool bObserverOK = true ); + void HideViewModels( void ); + void DestroyViewModels( void ); + + CPlayerState *PlayerData( void ) { return &pl; } + + int RequiredEdictIndex( void ) { return ENTINDEX(edict()); } + + void LockPlayerInPlace( void ); + void UnlockPlayer( void ); + + virtual void DrawDebugGeometryOverlays(void); + + // Networking is about to update this entity, let it override and specify it's own pvs + virtual void SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize ); + virtual int UpdateTransmitState(); + virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); + + // Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds. + // Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate + // (like team members, entities out of our PVS, etc). + virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits ) const; + + virtual void Spawn( void ); + virtual void Activate( void ); + virtual void SharedSpawn(); // Shared between client and server. + virtual void ForceRespawn( void ); + + virtual void InitialSpawn( void ); + virtual void InitHUD( void ) {} + virtual void ShowViewPortPanel( const char * name, bool bShow = true, KeyValues *data = NULL ); + + virtual void PlayerDeathThink( void ); + + virtual void Jump( void ); + virtual void Duck( void ); + + const char *GetTracerType( void ); + void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); + void DoImpactEffect( trace_t &tr, int nDamageType ); + +#if !defined( NO_ENTITY_PREDICTION ) + void AddToPlayerSimulationList( CBaseEntity *other ); + void RemoveFromPlayerSimulationList( CBaseEntity *other ); + void SimulatePlayerSimulatedEntities( void ); + void ClearPlayerSimulationList( void ); +#endif + + // Physics simulation (player executes it's usercmd's here) + virtual void PhysicsSimulate( void ); + + // Forces processing of usercmds (e.g., even if game is paused, etc.) + void ForceSimulation(); + + virtual unsigned int PhysicsSolidMaskForEntity( void ) const; + + virtual void PreThink( void ); + virtual void PostThink( void ); + virtual int TakeHealth( float flHealth, int bitsDamageType ); + virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ); + bool ShouldTakeDamageInCommentaryMode( const CTakeDamageInfo &inputInfo ); + virtual int OnTakeDamage( const CTakeDamageInfo &info ); + virtual void DamageEffect(float flDamage, int fDamageType); + + virtual void OnDamagedByExplosion( const CTakeDamageInfo &info ); + + void PauseBonusProgress( bool bPause = true ); + void SetBonusProgress( int iBonusProgress ); + void SetBonusChallenge( int iBonusChallenge ); + + int GetBonusProgress() const { return m_iBonusProgress; } + int GetBonusChallenge() const { return m_iBonusChallenge; } + + virtual Vector EyePosition( ); // position of eyes + const QAngle &EyeAngles( ); + void EyePositionAndVectors( Vector *pPosition, Vector *pForward, Vector *pRight, Vector *pUp ); + virtual const QAngle &LocalEyeAngles(); // Direction of eyes + void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ); + void CacheVehicleView( void ); // Calculate and cache the position of the player in the vehicle + + // Sets the view angles + void SnapEyeAngles( const QAngle &viewAngles ); + + virtual QAngle BodyAngles(); + virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy); + virtual bool ShouldFadeOnDeath( void ) { return FALSE; } + + virtual const impactdamagetable_t &GetPhysicsImpactDamageTable(); + virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); + virtual void Event_Killed( const CTakeDamageInfo &info ); + // Notifier that I've killed some other entity. (called from Victim's Event_Killed). + virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); + + virtual void Event_Dying( const CTakeDamageInfo &info ); + + bool IsHLTV( void ) const { return pl.hltv; } + bool IsReplay( void ) const { return pl.replay; } + virtual bool IsPlayer( void ) const { return true; } // Spectators return TRUE for this, use IsObserver to separate cases + virtual bool IsNetClient( void ) const { return true; } // Bots should return FALSE for this, they can't receive NET messages + // Spectators should return TRUE for this + + virtual bool IsFakeClient( void ) const; + + // Get the client index (entindex-1). + int GetClientIndex() { return ENTINDEX( edict() ) - 1; } + + // returns the player name + const char * GetPlayerName() { return m_szNetname; } + void SetPlayerName( const char *name ); + + int GetUserID() const { return engine->GetPlayerUserId( edict() ); } + const char * GetNetworkIDString(); + virtual const Vector GetPlayerMins( void ) const; // uses local player + virtual const Vector GetPlayerMaxs( void ) const; // uses local player + + + void VelocityPunch( const Vector &vecForce ); + void ViewPunch( const QAngle &angleOffset ); + void ViewPunchReset( float tolerance = 0 ); + void ShowViewModel( bool bShow ); + void ShowCrosshair( bool bShow ); + + // View model prediction setup + void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ); + + // Handle view smoothing when going up stairs + void SmoothViewOnStairs( Vector& eyeOrigin ); + virtual float CalcRoll (const QAngle& angles, const Vector& velocity, float rollangle, float rollspeed); + void CalcViewRoll( QAngle& eyeAngles ); + + virtual int Save( ISave &save ); + virtual int Restore( IRestore &restore ); + virtual bool ShouldSavePhysics(); + virtual void OnRestore( void ); + + virtual void PackDeadPlayerItems( void ); + virtual void RemoveAllItems( bool removeSuit ); + bool IsDead() const; +#ifdef CSTRIKE_DLL + virtual bool IsRunning( void ) const { return false; } // bot support under cstrike (AR) +#endif + + bool HasPhysicsFlag( unsigned int flag ) { return (m_afPhysicsFlags & flag) != 0; } + + // Weapon stuff + virtual Vector Weapon_ShootPosition( ); + virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); + virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); + virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget /* = NULL */, const Vector *pVelocity /* = NULL */ ); + virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed) + virtual void Weapon_SetLast( CBaseCombatWeapon *pWeapon ); + virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) { return true; } + virtual bool Weapon_ShouldSelectItem( CBaseCombatWeapon *pWeapon ); + void Weapon_DropSlot( int weaponSlot ); + CBaseCombatWeapon *GetLastWeapon( void ) { return m_hLastWeapon.Get(); } + + virtual void OnMyWeaponFired( CBaseCombatWeapon *weapon ); // call this when this player fires a weapon to allow other systems to react + virtual float GetTimeSinceWeaponFired( void ) const; // returns the time, in seconds, since this player fired a weapon + virtual bool IsFiringWeapon( void ) const; // return true if this player is currently firing their weapon + + bool HasAnyAmmoOfType( int nAmmoIndex ); + + // JOHN: sends custom messages if player HUD data has changed (eg health, ammo) + virtual void UpdateClientData( void ); + void RumbleEffect( unsigned char index, unsigned char rumbleData, unsigned char rumbleFlags ); + + // Player is moved across the transition by other means + virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } + virtual void Precache( void ); + bool IsOnLadder( void ); + virtual void ExitLadder() {} + virtual surfacedata_t *GetLadderSurface( const Vector &origin ); + + virtual void SetFlashlightEnabled( bool bState ) { }; + virtual int FlashlightIsOn( void ) { return false; } + virtual void FlashlightTurnOn( void ) { }; + virtual void FlashlightTurnOff( void ) { }; + virtual bool IsIlluminatedByFlashlight( CBaseEntity *pEntity, float *flReturnDot ) {return false; } + + void UpdatePlayerSound ( void ); + virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ); + virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ); + virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName ) { return pszBaseStepSoundName; } + virtual void GetStepSoundVelocities( float *velwalk, float *velrun ); + virtual void SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking ); + virtual void DeathSound( const CTakeDamageInfo &info ); + virtual const char* GetSceneSoundToken( void ) { return ""; } + + virtual void OnEmitFootstepSound( const CSoundParameters& params, const Vector& vecOrigin, float fVolume ) {} + + Class_T Classify ( void ); + virtual void SetAnimation( PLAYER_ANIM playerAnim ); + void SetWeaponAnimType( const char *szExtention ); + + // custom player functions + virtual void ImpulseCommands( void ); + virtual void CheatImpulseCommands( int iImpulse ); + virtual bool ClientCommand( const CCommand &args ); + + void NotifySinglePlayerGameEnding() { m_bSinglePlayerGameEnding = true; } + bool IsSinglePlayerGameEnding() { return m_bSinglePlayerGameEnding == true; } + + bool HandleVoteCommands( const CCommand &args ); + + // Observer functions + virtual bool StartObserverMode(int mode); // true, if successful + virtual void StopObserverMode( void ); // stop spectator mode + virtual bool ModeWantsSpectatorGUI( int iMode ) { return true; } + virtual bool SetObserverMode(int mode); // sets new observer mode, returns true if successful + virtual int GetObserverMode( void ); // returns observer mode or OBS_NONE + virtual bool SetObserverTarget(CBaseEntity * target); + virtual void ObserverUse( bool bIsPressed ); // observer pressed use + virtual CBaseEntity *GetObserverTarget( void ); // returns players targer or NULL + virtual CBaseEntity *FindNextObserverTarget( bool bReverse ); // returns next/prev player to follow or NULL + virtual int GetNextObserverSearchStartPoint( bool bReverse ); // Where we should start looping the player list in a FindNextObserverTarget call + virtual bool IsValidObserverTarget(CBaseEntity * target); // true, if player is allowed to see this target + virtual void CheckObserverSettings(); // checks, if target still valid (didn't die etc) + virtual void JumptoPosition(const Vector &origin, const QAngle &angles); + virtual void ForceObserverMode(int mode); // sets a temporary mode, force because of invalid targets + virtual void ResetObserverMode(); // resets all observer related settings + virtual void ValidateCurrentObserverTarget( void ); // Checks the current observer target, and moves on if it's not valid anymore + virtual void AttemptToExitFreezeCam( void ); + + virtual bool StartReplayMode( float fDelay, float fDuration, int iEntity ); + virtual void StopReplayMode(); + virtual int GetDelayTicks(); + virtual int GetReplayEntity(); + + virtual void CreateCorpse( void ) { } + virtual CBaseEntity *EntSelectSpawnPoint( void ); + + // Vehicles + virtual bool IsInAVehicle( void ) const; + bool CanEnterVehicle( IServerVehicle *pVehicle, int nRole ); + virtual bool GetInVehicle( IServerVehicle *pVehicle, int nRole ); + virtual void LeaveVehicle( const Vector &vecExitPoint = vec3_origin, const QAngle &vecExitAngles = vec3_angle ); + int GetVehicleAnalogControlBias() { return m_iVehicleAnalogBias; } + void SetVehicleAnalogControlBias( int bias ) { m_iVehicleAnalogBias = bias; } + + // override these for + virtual void OnVehicleStart() {} + virtual void OnVehicleEnd( Vector &playerDestPosition ) {} + IServerVehicle *GetVehicle(); + CBaseEntity *GetVehicleEntity( void ); + bool UsingStandardWeaponsInVehicle( void ); + + void AddPoints( int score, bool bAllowNegativeScore ); + void AddPointsToTeam( int score, bool bAllowNegativeScore ); + virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); + bool RemovePlayerItem( CBaseCombatWeapon *pItem ); + CBaseEntity *HasNamedPlayerItem( const char *pszItemName ); + bool HasWeapons( void );// do I have ANY weapons? + virtual void SelectLastItem(void); + virtual void SelectItem( const char *pstr, int iSubType = 0 ); + void ItemPreFrame( void ); + virtual void ItemPostFrame( void ); + virtual CBaseEntity *GiveNamedItem( const char *szName, int iSubType = 0 ); + void EnableControl(bool fControl); + virtual void CheckTrainUpdate( void ); + void AbortReload( void ); + + void SendAmmoUpdate(void); + + void WaterMove( void ); + float GetWaterJumpTime() const; + void SetWaterJumpTime( float flWaterJumpTime ); + float GetSwimSoundTime( void ) const; + void SetSwimSoundTime( float flSwimSoundTime ); + + virtual void SetPlayerUnderwater( bool state ); + void UpdateUnderwaterState( void ); + bool IsPlayerUnderwater( void ) { return m_bPlayerUnderwater; } + + virtual bool CanBreatheUnderwater() const { return false; } + virtual void PlayerUse( void ); + virtual void PlayUseDenySound() {} + + virtual CBaseEntity *FindUseEntity( void ); + virtual bool IsUseableEntity( CBaseEntity *pEntity, unsigned int requiredCaps ); + bool ClearUseEntity(); + CBaseEntity *DoubleCheckUseNPC( CBaseEntity *pNPC, const Vector &vecSrc, const Vector &vecDir ); + + + // physics interactions + // mass/size limit set to zero for none + static bool CanPickupObject( CBaseEntity *pObject, float massLimit, float sizeLimit ); + virtual void PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize = true ) {} + virtual void ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldindThis = NULL ) {} + virtual float GetHeldObjectMass( IPhysicsObject *pHeldObject ); + + void CheckSuitUpdate(); + void SetSuitUpdate(const char *name, int fgroup, int iNoRepeat); + virtual void UpdateGeigerCounter( void ); + void CheckTimeBasedDamage( void ); + + void ResetAutoaim( void ); + + virtual Vector GetAutoaimVector( float flScale ); + virtual Vector GetAutoaimVector( float flScale, float flMaxDist ); + virtual void GetAutoaimVector( autoaim_params_t ¶ms ); + + float GetAutoaimScore( const Vector &eyePosition, const Vector &viewDir, const Vector &vecTarget, CBaseEntity *pTarget, float fScale, CBaseCombatWeapon *pActiveWeapon ); + QAngle AutoaimDeflection( Vector &vecSrc, autoaim_params_t ¶ms ); + virtual bool ShouldAutoaim( void ); + void SetTargetInfo( Vector &vecSrc, float flDist ); + + void SetViewEntity( CBaseEntity *pEntity ); + CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; } + + virtual void ForceClientDllUpdate( void ); // Forces all client .dll specific data to be resent to client. + + void DeathMessage( CBaseEntity *pKiller ); + + virtual void ProcessUsercmds( CUserCmd *cmds, int numcmds, int totalcmds, + int dropped_packets, bool paused ); + bool IsUserCmdDataValid( CUserCmd *pCmd ); + + void AvoidPhysicsProps( CUserCmd *pCmd ); + + // Run a user command. The default implementation calls ::PlayerRunCommand. In TF, this controls a vehicle if + // the player is in one. + virtual void PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper); + void RunNullCommand(); + CUserCmd * GetCurrentCommand( void ) { return m_pCurrentCommand; } + float GetTimeSinceLastUserCommand( void ) { return ( !IsConnected() || IsFakeClient() || IsBot() ) ? 0.f : gpGlobals->curtime - m_flLastUserCommandTime; } + + // Team Handling + virtual void ChangeTeam( int iTeamNum ) OVERRIDE { ChangeTeam( iTeamNum, false, false ); } + virtual void ChangeTeam( int iTeamNum, bool bAutoTeam, bool bSilent, bool bAutoBalance = false ); + + // say/sayteam allowed? + virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ) { return true; } + virtual bool CanSpeak( void ) { return true; } + + audioparams_t &GetAudioParams() { return m_Local.m_audio; } + + virtual void ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ); + + const QAngle& GetPunchAngle(); + void SetPunchAngle( const QAngle &punchAngle ); + + virtual void DoMuzzleFlash(); + + const char *GetLastKnownPlaceName( void ) const { return m_szLastPlaceName; } // return the last nav place name the player occupied + + virtual void CheckChatText( char *p, int bufsize ) {} + + virtual void CreateRagdollEntity( void ) { return; } + + virtual void HandleAnimEvent( animevent_t *pEvent ); + + virtual bool ShouldAnnounceAchievement( void ); + +#if defined USES_ECON_ITEMS + // Wearables + virtual void EquipWearable( CEconWearable *pItem ); + virtual void RemoveWearable( CEconWearable *pItem ); + void PlayWearableAnimsForPlaybackEvent( wearableanimplayback_t iPlayback ); +#endif + +public: + // Player Physics Shadow + void SetupVPhysicsShadow( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, CPhysCollide *pStandModel, const char *pStandHullName, CPhysCollide *pCrouchModel, const char *pCrouchHullName ); + IPhysicsPlayerController* GetPhysicsController() { return m_pPhysicsController; } + virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); + void VPhysicsUpdate( IPhysicsObject *pPhysics ); + virtual void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ); + virtual bool IsFollowingPhysics( void ) { return false; } + bool IsRideablePhysics( IPhysicsObject *pPhysics ); + IPhysicsObject *GetGroundVPhysics(); + + virtual void Touch( CBaseEntity *pOther ); + void SetTouchedPhysics( bool bTouch ); + bool TouchedPhysics( void ); + Vector GetSmoothedVelocity( void ); + + virtual void RefreshCollisionBounds( void ); + virtual void InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity ); + virtual void VPhysicsDestroyObject(); + void SetVCollisionState( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, int collisionState ); + void PostThinkVPhysics( void ); + virtual void UpdatePhysicsShadowToCurrentPosition(); + void UpdatePhysicsShadowToPosition( const Vector &vecAbsOrigin ); + void UpdateVPhysicsPosition( const Vector &position, const Vector &velocity, float secondsToArrival ); + + // Hint system + virtual CHintSystem *Hints( void ) { return NULL; } + bool ShouldShowHints( void ) { return Hints() ? Hints()->ShouldShowHints() : false; } + void SetShowHints( bool bShowHints ) { if (Hints()) Hints()->SetShowHints( bShowHints ); } + bool HintMessage( int hint, bool bForce = false ) { return Hints() ? Hints()->HintMessage( hint, bForce ) : false; } + void HintMessage( const char *pMessage ) { if (Hints()) Hints()->HintMessage( pMessage ); } + void StartHintTimer( int iHintID ) { if (Hints()) Hints()->StartHintTimer( iHintID ); } + void StopHintTimer( int iHintID ) { if (Hints()) Hints()->StopHintTimer( iHintID ); } + void RemoveHintTimer( int iHintID ) { if (Hints()) Hints()->RemoveHintTimer( iHintID ); } + + // Accessor methods + int FragCount() const { return m_iFrags; } + int DeathCount() const { return m_iDeaths;} + bool IsConnected() const { return m_iConnected != PlayerDisconnected; } + bool IsDisconnecting() const { return m_iConnected == PlayerDisconnecting; } + bool IsSuitEquipped() const { return m_Local.m_bWearingSuit; } + int ArmorValue() const { return m_ArmorValue; } + bool HUDNeedsRestart() const { return m_fInitHUD; } + float MaxSpeed() const { return m_flMaxspeed; } + Activity GetActivity( ) const { return m_Activity; } + inline void SetActivity( Activity eActivity ) { m_Activity = eActivity; } + bool IsPlayerLockedInPlace() const { return m_iPlayerLocked != 0; } + bool IsObserver() const { return (m_afPhysicsFlags & PFLAG_OBSERVER) != 0; } + bool IsOnTarget() const { return m_fOnTarget; } + float MuzzleFlashTime() const { return m_flFlashTime; } + float PlayerDrownTime() const { return m_AirFinished; } + + int GetObserverMode() const { return m_iObserverMode; } + CBaseEntity *GetObserverTarget() const { return m_hObserverTarget; } + + // Round gamerules + virtual bool IsReadyToPlay( void ) { return true; } + virtual bool IsReadyToSpawn( void ) { return true; } + virtual bool ShouldGainInstantSpawn( void ) { return false; } + virtual void ResetPerRoundStats( void ) { return; } + void AllowInstantSpawn( void ) { m_bAllowInstantSpawn = true; } + + virtual void ResetScores( void ) { ResetFragCount(); ResetDeathCount(); } + void ResetFragCount(); + void IncrementFragCount( int nCount ); + + void ResetDeathCount(); + void IncrementDeathCount( int nCount ); + + void SetArmorValue( int value ); + void IncrementArmorValue( int nCount, int nMaxValue = -1 ); + + void SetConnected( PlayerConnectedState iConnected ) { m_iConnected = iConnected; } + virtual void EquipSuit( bool bPlayEffects = true ); + virtual void RemoveSuit( void ); + void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; } + + void NotifyNearbyRadiationSource( float flRange ); + + void SetAnimationExtension( const char *pExtension ); + + void SetAdditionalPVSOrigin( const Vector &vecOrigin ); + void SetCameraPVSOrigin( const Vector &vecOrigin ); + void SetMuzzleFlashTime( float flTime ); + void SetUseEntity( CBaseEntity *pUseEntity ); + CBaseEntity *GetUseEntity(); + + virtual float GetPlayerMaxSpeed(); + + // Used to set private physics flags PFLAG_* + void SetPhysicsFlag( int nFlag, bool bSet ); + + void AllowImmediateDecalPainting(); + + // Suicide... + virtual void CommitSuicide( bool bExplode = false, bool bForce = false ); + virtual void CommitSuicide( const Vector &vecForce, bool bExplode = false, bool bForce = false ); + + // For debugging... + void ForceOrigin( const Vector &vecOrigin ); + + // Bot accessors... + void SetTimeBase( float flTimeBase ); + float GetTimeBase() const; + void SetLastUserCommand( const CUserCmd &cmd ); + const CUserCmd *GetLastUserCommand( void ); + + virtual bool IsBot() const; // IMPORTANT: This returns true for ANY type of bot. If your game uses different, incompatible types of bots check your specific bot type before casting + virtual bool IsBotOfType( int botType ) const; // return true if this player is a bot of the specific type (zero is invalid) + virtual int GetBotType( void ) const; // return a unique int representing the type of bot instance this is + + bool IsPredictingWeapons( void ) const; + int CurrentCommandNumber() const; + const CUserCmd *GetCurrentUserCommand() const; + int GetLockViewanglesTickNumber() const { return m_iLockViewanglesTickNumber; } + QAngle GetLockViewanglesData() const { return m_qangLockViewangles; } + + bool IsLerpingFOV( void ) const; + int GetFOV( void ); // Get the current FOV value + int GetDefaultFOV( void ) const; // Default FOV if not specified otherwise + int GetFOVForNetworking( void ); // Get the current FOV used for network computations + bool SetFOV( CBaseEntity *pRequester, int FOV, float zoomRate = 0.0f, int iZoomStart = 0 ); // Alters the base FOV of the player (must have a valid requester) + void SetDefaultFOV( int FOV ); // Sets the base FOV if nothing else is affecting it by zooming + CBaseEntity *GetFOVOwner( void ) { return m_hZoomOwner; } + float GetFOVDistanceAdjustFactor(); // shared between client and server + float GetFOVDistanceAdjustFactorForNetworking(); + + int GetImpulse( void ) const { return m_nImpulse; } + + // Movement constraints + void ActivateMovementConstraint( CBaseEntity *pEntity, const Vector &vecCenter, float flRadius, float flConstraintWidth, float flSpeedFactor ); + void DeactivateMovementConstraint( ); + + // talk control + void NotePlayerTalked() { m_fLastPlayerTalkTime = gpGlobals->curtime; } + float LastTimePlayerTalked() { return m_fLastPlayerTalkTime; } + + void DisableButtons( int nButtons ); + void EnableButtons( int nButtons ); + void ForceButtons( int nButtons ); + void UnforceButtons( int nButtons ); + + //--------------------------------- + // Inputs + //--------------------------------- + void InputSetHealth( inputdata_t &inputdata ); + void InputSetHUDVisibility( inputdata_t &inputdata ); + void InputHandleMapEvent( inputdata_t &inputdata ); + + surfacedata_t *GetSurfaceData( void ) { return m_pSurfaceData; } + void SetLadderNormal( Vector vecLadderNormal ) { m_vecLadderNormal = vecLadderNormal; } + + // Here so that derived classes can use the expresser + virtual CAI_Expresser *GetExpresser() { return NULL; }; + +#if !defined(NO_STEAM) + //---------------------------- + // Steam handling + bool GetSteamID( CSteamID *pID ); + uint64 GetSteamIDAsUInt64( void ); +#endif + + float GetRemainingMovementTimeForUserCmdProcessing() const { return m_flMovementTimeForUserCmdProcessingRemaining; } + float ConsumeMovementTimeForUserCmdProcessing( float flTimeNeeded ) + { + if ( m_flMovementTimeForUserCmdProcessingRemaining <= 0.0f ) + { + return 0.0f; + } + else if ( flTimeNeeded > m_flMovementTimeForUserCmdProcessingRemaining + FLT_EPSILON ) + { + float flResult = m_flMovementTimeForUserCmdProcessingRemaining; + m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + return flResult; + } + else + { + m_flMovementTimeForUserCmdProcessingRemaining -= flTimeNeeded; + if ( m_flMovementTimeForUserCmdProcessingRemaining < 0.0f ) + m_flMovementTimeForUserCmdProcessingRemaining = 0.0f; + return flTimeNeeded; + } + } + +private: + // How much of a movement time buffer can we process from this user? + float m_flMovementTimeForUserCmdProcessingRemaining; + + // For queueing up CUserCmds and running them from PhysicsSimulate + int GetCommandContextCount( void ) const; + CCommandContext *GetCommandContext( int index ); + CCommandContext *AllocCommandContext( void ); + void RemoveCommandContext( int index ); + void RemoveAllCommandContexts( void ); + CCommandContext *RemoveAllCommandContextsExceptNewest( void ); + void ReplaceContextCommands( CCommandContext *ctx, CUserCmd *pCommands, int nCommands ); + + int DetermineSimulationTicks( void ); + void AdjustPlayerTimeBase( int simulation_ticks ); + +public: + + // How long since this player last interacted with something the game considers an objective/target/goal + float GetTimeSinceLastObjective( void ) const { return ( m_flLastObjectiveTime == -1.f ) ? 999.f : gpGlobals->curtime - m_flLastObjectiveTime; } + void SetLastObjectiveTime( float flTime ) { m_flLastObjectiveTime = flTime; } + + // Used by gamemovement to check if the entity is stuck. + int m_StuckLast; + + // FIXME: Make these protected or private! + + // This player's data that should only be replicated to + // the player and not to other players. + CNetworkVarEmbedded( CPlayerLocalData, m_Local ); + +#if defined USES_ECON_ITEMS + CNetworkVarEmbedded( CAttributeList, m_AttributeList ); +#endif + + void InitFogController( void ); + void InputSetFogController( inputdata_t &inputdata ); + + // Used by env_soundscape_triggerable to manage when the player is touching multiple + // soundscape triggers simultaneously. + // The one at the HEAD of the list is always the current soundscape for the player. + CUtlVector<EHANDLE> m_hTriggerSoundscapeList; + + // Player data that's sometimes needed by the engine + CNetworkVarEmbedded( CPlayerState, pl ); + + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_fFlags ); + + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecViewOffset ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_flFriction ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_iAmmo ); + + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_hGroundEntity ); + + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_iHealth ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecBaseVelocity ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nNextThinkTick ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecVelocity ); + IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nWaterLevel ); + + int m_nButtons; + int m_afButtonPressed; + int m_afButtonReleased; + int m_afButtonLast; + int m_afButtonDisabled; // A mask of input flags that are cleared automatically + int m_afButtonForced; // These are forced onto the player's inputs + + CNetworkVar( bool, m_fOnTarget ); //Is the crosshair on a target? + + char m_szAnimExtension[32]; + + int m_nUpdateRate; // user snapshot rate cl_updaterate + float m_fLerpTime; // users cl_interp + bool m_bLagCompensation; // user wants lag compenstation + bool m_bPredictWeapons; // user has client side predicted weapons + + float GetDeathTime( void ) { return m_flDeathTime; } + + void ClearZoomOwner( void ); + + void SetPreviouslyPredictedOrigin( const Vector &vecAbsOrigin ); + const Vector &GetPreviouslyPredictedOrigin() const; + float GetFOVTime( void ){ return m_flFOVTime; } + + void AdjustDrownDmg( int nAmount ); + +#if defined USES_ECON_ITEMS + CEconWearable *GetWearable( int i ) { return m_hMyWearables[i]; } + const CEconWearable *GetWearable( int i ) const { return m_hMyWearables[i]; } + int GetNumWearables( void ) const { return m_hMyWearables.Count(); } +#endif + +private: + + Activity m_Activity; + float m_flLastObjectiveTime; // Last curtime player touched/killed something the gamemode considers an objective + +protected: + + void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ); + void CalcVehicleView( IServerVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles, + float& zNear, float& zFar, float& fov ); + void CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ); + void CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles); + + virtual void Internal_HandleMapEvent( inputdata_t &inputdata ){} + + // FIXME: Make these private! (tf_player uses them) + + // Secondary point to derive PVS from when zoomed in with binoculars/sniper rifle. The PVS is + // a merge of the standing origin and this additional origin + Vector m_vecAdditionalPVSOrigin; + // Extra PVS origin if we are using a camera object + Vector m_vecCameraPVSOrigin; + + CNetworkHandle( CBaseEntity, m_hUseEntity ); // the player is currently controlling this entity because of +USE latched, NULL if no entity + + int m_iTrain; // Train control position + + float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn + unsigned int m_afPhysicsFlags; // physics flags - set when 'normal' physics should be revisited or overriden + + // Vehicles + CNetworkHandle( CBaseEntity, m_hVehicle ); + + int m_iVehicleAnalogBias; + + void UpdateButtonState( int nUserCmdButtonMask ); + + bool m_bPauseBonusProgress; + CNetworkVar( int, m_iBonusProgress ); + CNetworkVar( int, m_iBonusChallenge ); + + int m_lastDamageAmount; // Last damage taken + + Vector m_DmgOrigin; + float m_DmgTake; + float m_DmgSave; + int m_bitsDamageType; // what types of damage has player taken + int m_bitsHUDDamage; // Damage bits for the current fame. These get sent to the hud via gmsgDamage + + CNetworkVar( float, m_flDeathTime ); // the time at which the player died (used in PlayerDeathThink()) + float m_flDeathAnimTime; // the time at which the player finished their death anim (used in PlayerDeathThink() and ShouldTransmit()) + + CNetworkVar( int, m_iObserverMode ); // if in spectator mode != 0 + CNetworkVar( int, m_iFOV ); // field of view + CNetworkVar( int, m_iDefaultFOV ); // default field of view + CNetworkVar( int, m_iFOVStart ); // What our FOV started at + CNetworkVar( float, m_flFOVTime ); // Time our FOV change started + + int m_iObserverLastMode; // last used observer mode + CNetworkHandle( CBaseEntity, m_hObserverTarget ); // entity handle to m_iObserverTarget + bool m_bForcedObserverMode; // true, player was forced by invalid targets to switch mode + + CNetworkHandle( CBaseEntity, m_hZoomOwner ); //This is a pointer to the entity currently controlling the player's zoom + //Only this entity can change the zoom state once it has ownership + + float m_tbdPrev; // Time-based damage timer + int m_idrowndmg; // track drowning damage taken + int m_idrownrestored; // track drowning damage restored + int m_nPoisonDmg; // track recoverable poison damage taken + int m_nPoisonRestored; // track poison damage restored + // NOTE: bits damage type appears to only be used for time-based damage + BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED]; + + // Player Physics Shadow + int m_vphysicsCollisionState; + + virtual int SpawnArmorValue( void ) const { return 0; } + + float m_fNextSuicideTime; // the time after which the player can next use the suicide command + int m_iSuicideCustomKillFlags; + + // Replay mode + float m_fDelay; // replay delay in seconds + float m_fReplayEnd; // time to stop replay mode + int m_iReplayEntity; // follow this entity in replay + +private: + void HandleFuncTrain(); + +// DATA +private: + CUtlVector< CCommandContext > m_CommandContext; + // Player Physics Shadow + +protected: //used to be private, but need access for portal mod (Dave Kircher) + IPhysicsPlayerController *m_pPhysicsController; + IPhysicsObject *m_pShadowStand; + IPhysicsObject *m_pShadowCrouch; + Vector m_oldOrigin; + Vector m_vecSmoothedVelocity; + bool m_touchedPhysObject; + bool m_bPhysicsWasFrozen; + +private: + + int m_iPlayerSound;// the index of the sound list slot reserved for this player + int m_iTargetVolume;// ideal sound volume. + + int m_rgItems[MAX_ITEMS]; + + // these are time-sensitive things that we keep track of + float m_flSwimTime; // how long player has been underwater + float m_flDuckTime; // how long we've been ducking + float m_flDuckJumpTime; + + float m_flSuitUpdate; // when to play next suit update + int m_rgSuitPlayList[CSUITPLAYLIST];// next sentencenum to play for suit update + int m_iSuitPlayNext; // next sentence slot for queue storage; + int m_rgiSuitNoRepeat[CSUITNOREPEAT]; // suit sentence no repeat list + float m_rgflSuitNoRepeatTime[CSUITNOREPEAT]; // how long to wait before allowing repeat + + float m_flgeigerRange; // range to nearest radiation source + float m_flgeigerDelay; // delay per update of range msg to client + int m_igeigerRangePrev; + + bool m_fInitHUD; // True when deferred HUD restart msg needs to be sent + bool m_fGameHUDInitialized; + bool m_fWeapon; // Set this to FALSE to force a reset of the current weapon HUD info + + int m_iUpdateTime; // stores the number of frame ticks before sending HUD update messages + int m_iClientBattery; // the Battery currently known by the client. If this changes, send a new + + // Autoaim data + QAngle m_vecAutoAim; + int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE + + int m_iFrags; + int m_iDeaths; + + float m_flNextDecalTime;// next time this player can spray a decal + + // Team Handling + // char m_szTeamName[TEAM_NAME_LENGTH]; + + // Multiplayer handling + PlayerConnectedState m_iConnected; + + // from edict_t + // CBasePlayer doesn't send this but CCSPlayer does. + CNetworkVarForDerived( int, m_ArmorValue ); + float m_AirFinished; + float m_PainFinished; + + // player locking + int m_iPlayerLocked; + +protected: + // the player's personal view model + typedef CHandle<CBaseViewModel> CBaseViewModelHandle; + CNetworkArray( CBaseViewModelHandle, m_hViewModel, MAX_VIEWMODELS ); + + // Last received usercmd (in case we drop a lot of packets ) + CUserCmd m_LastCmd; + CUserCmd *m_pCurrentCommand; + int m_iLockViewanglesTickNumber; + QAngle m_qangLockViewangles; + + float m_flStepSoundTime; // time to check for next footstep sound + + bool m_bAllowInstantSpawn; + +#if defined USES_ECON_ITEMS + // Wearables + CUtlVector<CHandle<CEconWearable > > m_hMyWearables; +#endif + +private: + +// Replicated to all clients + CNetworkVar( float, m_flMaxspeed ); + +// Not transmitted + float m_flWaterJumpTime; // used to be called teleport_time + Vector m_vecWaterJumpVel; + int m_nImpulse; + float m_flSwimSoundTime; + Vector m_vecLadderNormal; + + float m_flFlashTime; + int m_nDrownDmgRate; // Drowning damage in points per second without air. + + int m_nNumCrouches; // Number of times we've crouched (for hinting) + bool m_bDuckToggled; // If true, the player is crouching via a toggle + +public: + bool GetToggledDuckState( void ) { return m_bDuckToggled; } + void ToggleDuck( void ); + float GetStickDist( void ); + + float m_flForwardMove; + float m_flSideMove; + int m_nNumCrateHudHints; + +private: + + // Used in test code to teleport the player to random locations in the map. + Vector m_vForcedOrigin; + bool m_bForceOrigin; + + // Clients try to run on their own realtime clock, this is this client's clock + CNetworkVar( int, m_nTickBase ); + + bool m_bGamePaused; + float m_fLastPlayerTalkTime; + + CNetworkVar( CBaseCombatWeaponHandle, m_hLastWeapon ); + +#if !defined( NO_ENTITY_PREDICTION ) + CUtlVector< CHandle< CBaseEntity > > m_SimulatedByThisPlayer; +#endif + + float m_flOldPlayerZ; + float m_flOldPlayerViewOffsetZ; + + bool m_bPlayerUnderwater; + + EHANDLE m_hViewEntity; + + // Movement constraints + CNetworkHandle( CBaseEntity, m_hConstraintEntity ); + CNetworkVector( m_vecConstraintCenter ); + CNetworkVar( float, m_flConstraintRadius ); + CNetworkVar( float, m_flConstraintWidth ); + CNetworkVar( float, m_flConstraintSpeedFactor ); + + friend class CPlayerMove; + friend class CPlayerClass; + + // Player name + char m_szNetname[MAX_PLAYER_NAME_LENGTH]; + +protected: + // HACK FOR TF2 Prediction + friend class CTFGameMovementRecon; + friend class CGameMovement; + friend class CTFGameMovement; + friend class CHL1GameMovement; + friend class CCSGameMovement; + friend class CHL2GameMovement; + friend class CDODGameMovement; + friend class CPortalGameMovement; + + // Accessors for gamemovement + bool IsDucked( void ) const { return m_Local.m_bDucked; } + bool IsDucking( void ) const { return m_Local.m_bDucking; } + float GetStepSize( void ) const { return m_Local.m_flStepSize; } + + CNetworkVar( float, m_flLaggedMovementValue ); + + // These are generated while running usercmds, then given to UpdateVPhysicsPosition after running all queued commands. + Vector m_vNewVPhysicsPosition; + Vector m_vNewVPhysicsVelocity; + + Vector m_vecVehicleViewOrigin; // Used to store the calculated view of the player while riding in a vehicle + QAngle m_vecVehicleViewAngles; // Vehicle angles + float m_flVehicleViewFOV; // FOV of the vehicle driver + int m_nVehicleViewSavedFrame; // Used to mark which frame was the last one the view was calculated for + + Vector m_vecPreviouslyPredictedOrigin; // Used to determine if non-gamemovement game code has teleported, or tweaked the player's origin + int m_nBodyPitchPoseParam; + + CNetworkString( m_szLastPlaceName, MAX_PLACE_NAME_LENGTH ); + + char m_szNetworkIDString[MAX_NETWORKID_LENGTH]; + CPlayerInfo m_PlayerInfo; + + // Texture names and surface data, used by CGameMovement + int m_surfaceProps; + surfacedata_t* m_pSurfaceData; + float m_surfaceFriction; + char m_chTextureType; + char m_chPreviousTextureType; // Separate from m_chTextureType. This is cleared if the player's not on the ground. + + bool m_bSinglePlayerGameEnding; + +public: + + float GetLaggedMovementValue( void ){ return m_flLaggedMovementValue; } + void SetLaggedMovementValue( float flValue ) { m_flLaggedMovementValue = flValue; } + + inline bool IsAutoKickDisabled( void ) const; + inline void DisableAutoKick( bool disabled ); + + void DumpPerfToRecipient( CBasePlayer *pRecipient, int nMaxRecords ); + // NVNT returns true if user has a haptic device + virtual bool HasHaptics(){return m_bhasHaptics;} + // NVNT sets weather a user should receive haptic device messages. + virtual void SetHaptics(bool has) { m_bhasHaptics = has;} +private: + // NVNT member variable holding if this user is using a haptic device. + bool m_bhasHaptics; + + bool m_autoKickDisabled; + + struct StepSoundCache_t + { + StepSoundCache_t() : m_usSoundNameIndex( 0 ) {} + CSoundParameters m_SoundParameters; + unsigned short m_usSoundNameIndex; + }; + // One for left and one for right side of step + StepSoundCache_t m_StepSoundCache[ 2 ]; + + CUtlLinkedList< CPlayerSimInfo > m_vecPlayerSimInfo; + CUtlLinkedList< CPlayerCmdInfo > m_vecPlayerCmdInfo; + + IntervalTimer m_weaponFiredTimer; + + // Store the last time we successfully processed a usercommand + float m_flLastUserCommandTime; + + // used to prevent achievement announcement spam + CUtlVector< float > m_flAchievementTimes; + +public: + virtual unsigned int PlayerSolidMask( bool brushOnly = false ) const; // returns the solid mask for the given player, so bots can have a more-restrictive set + +}; + +typedef CHandle<CBasePlayer> CBasePlayerHandle; + +EXTERN_SEND_TABLE(DT_BasePlayer) + + + +//----------------------------------------------------------------------------- +// Inline methods +//----------------------------------------------------------------------------- +inline bool CBasePlayer::IsBotOfType( int botType ) const +{ + // bot type of zero is invalid + return ( GetBotType() != 0 ) && ( GetBotType() == botType ); +} + +inline int CBasePlayer::GetBotType( void ) const +{ + return 0; +} + +inline bool CBasePlayer::IsAutoKickDisabled( void ) const +{ + return m_autoKickDisabled; +} + +inline void CBasePlayer::DisableAutoKick( bool disabled ) +{ + m_autoKickDisabled = disabled; +} + +inline void CBasePlayer::SetAdditionalPVSOrigin( const Vector &vecOrigin ) +{ + m_vecAdditionalPVSOrigin = vecOrigin; +} + +inline void CBasePlayer::SetCameraPVSOrigin( const Vector &vecOrigin ) +{ + m_vecCameraPVSOrigin = vecOrigin; +} + +inline void CBasePlayer::SetMuzzleFlashTime( float flTime ) +{ + m_flFlashTime = flTime; +} + +inline void CBasePlayer::SetUseEntity( CBaseEntity *pUseEntity ) +{ + m_hUseEntity = pUseEntity; +} + +inline CBaseEntity *CBasePlayer::GetUseEntity() +{ + return m_hUseEntity; +} + +// Bot accessors... +inline void CBasePlayer::SetTimeBase( float flTimeBase ) +{ + m_nTickBase = TIME_TO_TICKS( flTimeBase ); +} + +inline void CBasePlayer::SetLastUserCommand( const CUserCmd &cmd ) +{ + m_LastCmd = cmd; +} + +inline CUserCmd const *CBasePlayer::GetLastUserCommand( void ) +{ + return &m_LastCmd; +} + +inline bool CBasePlayer::IsPredictingWeapons( void ) const +{ + return m_bPredictWeapons; +} + +inline int CBasePlayer::CurrentCommandNumber() const +{ + Assert( m_pCurrentCommand ); + return m_pCurrentCommand->command_number; +} + +inline const CUserCmd *CBasePlayer::GetCurrentUserCommand() const +{ + Assert( m_pCurrentCommand ); + return m_pCurrentCommand; +} + +inline IServerVehicle *CBasePlayer::GetVehicle() +{ + CBaseEntity *pVehicleEnt = m_hVehicle.Get(); + return pVehicleEnt ? pVehicleEnt->GetServerVehicle() : NULL; +} + +inline CBaseEntity *CBasePlayer::GetVehicleEntity() +{ + return m_hVehicle.Get(); +} + +inline bool CBasePlayer::IsInAVehicle( void ) const +{ + return ( NULL != m_hVehicle.Get() ) ? true : false; +} + +inline void CBasePlayer::SetTouchedPhysics( bool bTouch ) +{ + m_touchedPhysObject = bTouch; +} + +inline bool CBasePlayer::TouchedPhysics( void ) +{ + return m_touchedPhysObject; +} + +inline void CBasePlayer::OnMyWeaponFired( CBaseCombatWeapon *weapon ) +{ + m_weaponFiredTimer.Start(); +} + +inline float CBasePlayer::GetTimeSinceWeaponFired( void ) const +{ + return m_weaponFiredTimer.GetElapsedTime(); +} + +inline bool CBasePlayer::IsFiringWeapon( void ) const +{ + return m_weaponFiredTimer.HasStarted() && m_weaponFiredTimer.IsLessThen( 1.0f ); +} + + + +//----------------------------------------------------------------------------- +// Converts an entity to a player +//----------------------------------------------------------------------------- +inline CBasePlayer *ToBasePlayer( CBaseEntity *pEntity ) +{ + if ( !pEntity || !pEntity->IsPlayer() ) + return NULL; +#if _DEBUG + return dynamic_cast<CBasePlayer *>( pEntity ); +#else + return static_cast<CBasePlayer *>( pEntity ); +#endif +} + +inline const CBasePlayer *ToBasePlayer( const CBaseEntity *pEntity ) +{ + if ( !pEntity || !pEntity->IsPlayer() ) + return NULL; +#if _DEBUG + return dynamic_cast<const CBasePlayer *>( pEntity ); +#else + return static_cast<const CBasePlayer *>( pEntity ); +#endif +} + + +//-------------------------------------------------------------------------------------------------------------- +/** + * DEPRECATED: Use CollectPlayers() instead. + * Iterate over all active players in the game, invoking functor on each. + * If functor returns false, stop iteration and return false. + */ +template < typename Functor > +bool ForEachPlayer( Functor &func ) +{ + for( int i=1; i<=gpGlobals->maxClients; ++i ) + { + CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) ); + + if (player == NULL) + continue; + + if (FNullEnt( player->edict() )) + continue; + + if (!player->IsPlayer()) + continue; + + if( !player->IsConnected() ) + continue; + + if (func( player ) == false) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------------------------- +/** + * The interface for an iterative player functor + */ +class IPlayerFunctor +{ +public: + virtual void OnBeginIteration( void ) { } // invoked once before iteration begins + + virtual bool operator() ( CBasePlayer *player ) = 0; + + virtual void OnEndIteration( bool allElementsIterated ) { } // invoked once after iteration is complete whether successful or not +}; + + +//-------------------------------------------------------------------------------------------------------------- +/** + * DEPRECATED: Use CollectPlayers() instead. + * Specialization of ForEachPlayer template for IPlayerFunctors + */ +template <> +inline bool ForEachPlayer( IPlayerFunctor &func ) +{ + func.OnBeginIteration(); + + bool isComplete = true; + + for( int i=1; i<=gpGlobals->maxClients; ++i ) + { + CBasePlayer *player = static_cast<CBasePlayer *>( UTIL_PlayerByIndex( i ) ); + + if (player == NULL) + continue; + + if (FNullEnt( player->edict() )) + continue; + + if (!player->IsPlayer()) + continue; + + if( !player->IsConnected() ) + continue; + + if (func( player ) == false) + { + isComplete = false; + break; + } + } + + func.OnEndIteration( isComplete ); + + return isComplete; +} + +//-------------------------------------------------------------------------------------------------------------- +// +// Collect all valid, connected players into given vector. +// Returns number of players collected. +// +#define COLLECT_ONLY_LIVING_PLAYERS true +#define APPEND_PLAYERS true +template < typename T > +int CollectPlayers( CUtlVector< T * > *playerVector, int team = TEAM_ANY, bool isAlive = false, bool shouldAppend = false ) +{ + if ( !shouldAppend ) + { + playerVector->RemoveAll(); + } + + for( int i=1; i<=gpGlobals->maxClients; ++i ) + { + CBasePlayer *player = UTIL_PlayerByIndex( i ); + + if ( player == NULL ) + continue; + + if ( FNullEnt( player->edict() ) ) + continue; + + if ( !player->IsPlayer() ) + continue; + + if ( !player->IsConnected() ) + continue; + + if ( team != TEAM_ANY && player->GetTeamNumber() != team ) + continue; + + if ( isAlive && !player->IsAlive() ) + continue; + + playerVector->AddToTail( assert_cast< T * >( player ) ); + } + + return playerVector->Count(); +} + +template < typename T > +int CollectHumanPlayers( CUtlVector< T * > *playerVector, int team = TEAM_ANY, bool isAlive = false, bool shouldAppend = false ) +{ + if ( !shouldAppend ) + { + playerVector->RemoveAll(); + } + + for( int i=1; i<=gpGlobals->maxClients; ++i ) + { + CBasePlayer *player = UTIL_PlayerByIndex( i ); + + if ( player == NULL ) + continue; + + if ( FNullEnt( player->edict() ) ) + continue; + + if ( !player->IsPlayer() ) + continue; + + if ( player->IsBot() ) + continue; + + if ( !player->IsConnected() ) + continue; + + if ( team != TEAM_ANY && player->GetTeamNumber() != team ) + continue; + + if ( isAlive && !player->IsAlive() ) + continue; + + playerVector->AddToTail( assert_cast< T * >( player ) ); + } + + return playerVector->Count(); +} + +enum +{ + VEHICLE_ANALOG_BIAS_NONE = 0, + VEHICLE_ANALOG_BIAS_FORWARD, + VEHICLE_ANALOG_BIAS_REVERSE, +}; + +#endif // PLAYER_H |