1651 lines
58 KiB
C++
1651 lines
58 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef PLAYER_H
|
|
#define PLAYER_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "PlayerState.h"
|
|
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
|
#include "basecombatcharacter.h"
|
|
#include "game/server/iplayerinfo.h"
|
|
#include "hintsystem.h"
|
|
#include "playerlocaldata.h"
|
|
#include "usercmd.h"
|
|
#include "util_shared.h"
|
|
|
|
#if defined USES_ECON_ITEMS
|
|
#include "econ_item_view.h"
|
|
#include "game_item_schema.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() { 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 ¶ms,
|
|
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) {
|
|
ChangeTeam(iTeamNum, false, false);
|
|
}
|
|
virtual void ChangeTeam(int iTeamNum, bool bAutoTeam, bool bSilent);
|
|
|
|
// 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; }
|
|
|
|
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
|