hl2_src-leak-2017/src/game/server/tf/tf_player.h

1556 lines
57 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=============================================================================
#ifndef TF_PLAYER_H
#define TF_PLAYER_H
#pragma once
#include "basemultiplayerplayer.h"
#include "server_class.h"
#include "tf_achievementdata.h"
#include "tf_playeranimstate.h"
#include "tf_shareddefs.h"
#include "tf_obj.h"
#include "tf_player_shared.h"
#include "tf_playerclass.h"
#include "entity_tfstart.h"
#include "steam/steam_gameserver.h"
#include "ihasattributes.h"
#include "tf_item_inventory.h"
class CTFPlayer;
class CTFTeam;
class CTFGoal;
class CTFGoalItem;
class CTFItem;
class CTFWeaponBuilder;
//class CBaseObject;
class CTFWeaponBase;
class CIntroViewpoint;
class CTriggerAreaCapture;
class CTFWeaponBaseGun;
class CCaptureZone;
class CTFReviveMarker;
class CWaveSpawnPopulator;
class CTFTauntProp;
class CTFDroppedWeapon;
//=============================================================================
//
// Player State Information
//
class CPlayerStateInfo
{
public:
int m_nPlayerState;
const char *m_pStateName;
// Enter/Leave state.
void ( CTFPlayer::*pfnEnterState )();
void ( CTFPlayer::*pfnLeaveState )();
// Think (called every frame).
void ( CTFPlayer::*pfnThink )();
};
enum EAmmoSource
{
kAmmoSource_Pickup, // this came from either a box of ammo or a player's dropped weapon
kAmmoSource_Resupply, // resupply cabinet and/or full respawn
kAmmoSource_DispenserOrCart, // the player is standing next to an engineer's dispenser or pushing the cart in a payload game
};
//=============================================================================
//
// TF Player
//
class CTFPlayer : public CBaseMultiplayerPlayer, public IHasAttributes, public IInventoryUpdateListener
{
public:
DECLARE_CLASS( CTFPlayer, CBaseMultiplayerPlayer );
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
CTFPlayer();
~CTFPlayer();
//=============================================================================
// HPE_BEGIN:
// [msmith] Added a player type so we can distinguish between bots and humans.
//=============================================================================
enum TFPlayerType{
HUMAN_PLAYER,
TEMP_BOT,
TRAINING_BOT
};
//=============================================================================
// HPE_END
//=============================================================================
// Creation/Destruction.
static CTFPlayer *CreatePlayer( const char *className, edict_t *ed );
static CTFPlayer *Instance( int iEnt );
virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo );
virtual void SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize );
virtual void Spawn();
virtual void ForceRespawn();
void ForceRegenerateAndRespawn( void );
virtual CBaseEntity *EntSelectSpawnPoint( void );
virtual void InitialSpawn();
static void PrecacheMvM();
static void PrecacheKart();
private:
static void PrecachePlayerModels();
static void PrecacheTFPlayer();
public:
virtual void Precache();
virtual bool IsReadyToPlay( void );
virtual bool IsReadyToSpawn( void );
virtual bool ShouldGainInstantSpawn( void );
virtual void ResetScores( void );
virtual void UpdateOnRemove( void );
void CheckInstantLoadoutRespawn( void );
virtual void ResetPerRoundStats( void );
void HandleCommand_JoinTeam( const char *pTeamName );
void HandleCommand_JoinClass( const char *pClassName, bool bAllowSpawn = true );
void HandleCommand_JoinTeam_NoMenus( const char *pTeamName );
void CreateViewModel( int iViewModel = 0 );
CBaseViewModel *GetOffHandViewModel();
void SendOffHandViewModelActivity( Activity activity );
virtual void CheatImpulseCommands( int iImpulse );
virtual void PlayerRunCommand( CUserCmd *ucmd, IMoveHelper *moveHelper );
virtual void CommitSuicide( bool bExplode = false, bool bForce = false );
// Combats
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
virtual int TakeHealth( float flHealth, int bitsDamageType );
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
virtual void Event_Killed( const CTakeDamageInfo &info );
virtual void PlayerDeathThink( void );
virtual void DetermineAssistForKill( const CTakeDamageInfo &info );
virtual void SetNumberofDominations( int iDominations )
{
// Check for some bogus values, which are sneaking in somehow
if ( iDominations < 0 )
{
Assert( iDominations >= 0 );
iDominations = 0;
}
else if ( iDominations >= MAX_PLAYERS )
{
Assert( iDominations < MAX_PLAYERS );
iDominations = MAX_PLAYERS-1;
}
m_iNumberofDominations = iDominations;
}
virtual int GetNumberofDominations( void ) { return m_iNumberofDominations; }
void OnKilledOther_Effects( CBaseEntity *pVictim, const CTakeDamageInfo &info );
virtual int OnTakeDamage( const CTakeDamageInfo &inputInfo );
void AddConnectedPlayers( CUtlVector<CTFPlayer*> &vecPlayers, CTFPlayer *pPlayerToConsider );
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
virtual void DamageEffect(float flDamage, int fDamageType);
void OnDealtDamage( CBaseCombatCharacter *pVictim, const CTakeDamageInfo &info ); // invoked when we deal damage to another victim
int GetDamagePerSecond( void ) const;
void ResetDamagePerSecond( void );
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const;
void ApplyPushFromDamage( const CTakeDamageInfo &info, Vector vecDir );
void PlayDamageResistSound( float flStartDamage, float flModifiedDamage );
bool CheckBlockBackstab( CTFPlayer *pTFAttacker );
virtual bool Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon );
void SetHealthBuffTime( float flTime ) { m_flHealthBuffTime = flTime; }
CTFWeaponBase *GetActiveTFWeapon( void ) const;
bool IsActiveTFWeapon( const CSchemaItemDefHandle &weaponHandle ) const;
bool IsActiveTFWeapon( CEconItemDefinition *weaponHandle ) const;
virtual void RemoveAllWeapons();
virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ) OVERRIDE; // Adds weapon to player
void SaveMe( void );
void FireBullet( CTFWeaponBase *pWpn, const FireBulletsInfo_t &info, bool bDoEffects, int nDamageType, int nCustomDamageType = TF_DMG_CUSTOM_NONE );
void ImpactWaterTrace( trace_t &trace, const Vector &vecStart );
void NoteWeaponFired();
bool HasItem( void ) const; // Currently can have only one item at a time.
void SetItem( CTFItem *pItem );
CTFItem *GetItem( void ) const;
void SaveLastWeaponSlot( void );
void SetRememberLastWeapon( bool bRememberLastWeapon ) { m_bRememberLastWeapon = bRememberLastWeapon; }
void SetRememberActiveWeapon( bool bRememberActiveWeapon ) { m_bRememberActiveWeapon = bRememberActiveWeapon; }
void Regenerate( bool bRefillHealthAndAmmo = true );
float GetNextRegenTime( void ){ return m_flNextRegenerateTime; }
void SetNextRegenTime( float flTime ){ m_flNextRegenerateTime = flTime; }
float GetNextChangeClassTime( void ){ return m_flNextChangeClassTime; }
void SetNextChangeClassTime( float flTime ){ m_flNextChangeClassTime = flTime; }
float GetNextChangeTeamTime( void ){ return m_flNextChangeTeamTime; }
void SetNextChangeTeamTime( float flTime ){ m_flNextChangeTeamTime = flTime; }
virtual void RemoveAllItems( bool removeSuit );
virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon );
bool DropCurrentWeapon( void );
void DropFlag( bool bSilent = false );
void DropRune( bool bApplyForce = true, int nTeam = TEAM_ANY );
void TFWeaponRemove( int iWeaponID );
bool TFWeaponDrop( CTFWeaponBase *pWeapon, bool bThrowForward );
// Class.
CTFPlayerClass *GetPlayerClass( void ) { return &m_PlayerClass; }
const CTFPlayerClass *GetPlayerClass( void ) const { return &m_PlayerClass; }
int GetDesiredPlayerClassIndex( void ) { return m_Shared.m_iDesiredPlayerClass; }
void SetDesiredPlayerClassIndex( int iClass ) { m_Shared.m_iDesiredPlayerClass = iClass; }
// Team.
void ForceChangeTeam( int iTeamNum, bool bFullTeamSwitch = false );
virtual void ChangeTeam( int iTeamNum, bool bAutoTeam, bool bSilent, bool bAutoBalance = false ) OVERRIDE;
virtual void ChangeTeam( int iTeamNum ) OVERRIDE { BaseClass::ChangeTeam( iTeamNum ); }
// mp_fadetoblack
void HandleFadeToBlack( void );
// Flashlight controls for SFM - JasonM
virtual int FlashlightIsOn( void );
virtual void FlashlightTurnOn( void );
virtual void FlashlightTurnOff( void );
// Think.
virtual void PreThink();
virtual void PostThink();
virtual void ItemPostFrame();
virtual void Weapon_FrameUpdate( void );
virtual void Weapon_HandleAnimEvent( animevent_t *pEvent );
virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
virtual void GetStepSoundVelocities( float *velwalk, float *velrun );
virtual void SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking );
virtual const char *GetOverrideStepSound( const char *pszBaseStepSoundName );
virtual void OnEmitFootstepSound( const CSoundParameters& params, const Vector& vecOrigin, float fVolume );
virtual void ModifyEmitSoundParams( EmitSound_t &params );
// Utility.
void UpdateModel( void );
void UpdateSkin( int iTeam );
int GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound, EAmmoSource eAmmoSource );
virtual int GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound = false );
virtual void RemoveAmmo( int iCount, int iAmmoIndex );
virtual void RemoveAmmo( int iCount, const char *szName );
virtual int GetAmmoCount( int iAmmoIndex ) const;
int GetMaxAmmo( int iAmmoIndex, int iClassIndex = -1 );
virtual int GetMaxHealth() const OVERRIDE;
int GetMaxHealthForBuffing() const;
int GetRuneHealthBonus() const;
//-----------------------------------------------------------------------------------------------------
// Return true if we are a "mini boss" in Mann Vs Machine mode
bool IsMiniBoss( void ) const;
void SetIsMiniBoss( bool isMiniBoss ) { m_bIsMiniBoss = isMiniBoss; }
bool CanAttack( int iCanAttackFlags = 0 );
void RemoveMeleeCrit( void );
// This passes the event to the client's and server's CPlayerAnimState.
void DoAnimationEvent( PlayerAnimEvent_t event, int mData = 0 );
virtual void HandleAnimEvent( animevent_t *pEvent ) OVERRIDE;
virtual bool ClientCommand( const CCommand &args );
void ClientHearVox( const char *pSentence );
void DisplayLocalItemStatus( CTFGoal *pGoal );
int BuildObservableEntityList( void );
virtual int GetNextObserverSearchStartPoint( bool bReverse ); // Where we should start looping the player list in a FindNextObserverTarget call
virtual CBaseEntity *FindNextObserverTarget(bool bReverse);
virtual bool IsValidObserverTarget(CBaseEntity * target); // true, if player is allowed to see this target
virtual bool SetObserverTarget(CBaseEntity * target);
virtual bool ModeWantsSpectatorGUI( int iMode ) { return (iMode != OBS_MODE_FREEZECAM && iMode != OBS_MODE_DEATHCAM); }
void FindInitialObserverTarget( void );
CBaseEntity *FindNearestObservableTarget( Vector vecOrigin, float flMaxDist );
virtual void ValidateCurrentObserverTarget( void );
void CheckUncoveringSpies( CTFPlayer *pTouchedPlayer );
void Touch( CBaseEntity *pOther );
virtual void RefreshCollisionBounds( void );
float GetMovementForwardPull( void ) const;
bool CanPlayerMove() const;
float TeamFortress_CalculateMaxSpeed( bool bIgnoreSpecialAbility = false ) const;
void TeamFortress_SetSpeed();
EHANDLE TeamFortress_GetDisguiseTarget( int nTeam, int nClass );
void TeamFortress_ClientDisconnected();
void RemoveAllOwnedEntitiesFromWorld( bool bExplodeBuildings = false );
void RemoveOwnedProjectiles();
int GetNumActivePipebombs( void );
Vector EstimateProjectileImpactPosition( CTFWeaponBaseGun *weapon ); // estimate where a projectile fired from the given weapon will initially hit (it may bounce on from there)
Vector EstimateProjectileImpactPosition( float pitch, float yaw, float initVel ); // estimate where a projectile fired will initially hit (it may bounce on from there)
Vector EstimateStickybombProjectileImpactPosition( float pitch, float yaw, float charge ); // Estimate where a stickybomb projectile will hit, using given pitch, yaw, and weapon charge (0-1)
CTFTeamSpawn *GetSpawnPoint( void ){ return m_pSpawnPoint; }
void SetAnimation( PLAYER_ANIM playerAnim );
bool IsPlayerClass( int iClass ) const;
void PlayFlinch( const CTakeDamageInfo &info );
float PlayCritReceivedSound( void );
void PainSound( const CTakeDamageInfo &info );
void DeathSound( const CTakeDamageInfo &info );
virtual const char* GetSceneSoundToken( void );
void StunSound( CTFPlayer* pAttacker, int iStunFlags, int iOldStunFlags=0 );
void SetSeeCrit( bool bAllSeeCrit, bool bMiniCrit, bool bShowDisguisedCrit ) { m_bAllSeeCrit = bAllSeeCrit; m_bMiniCrit = bMiniCrit; m_bShowDisguisedCrit = bShowDisguisedCrit; }
void SetAttackBonusEffect( EAttackBonusEffects_t effect ) { m_eBonusAttackEffect = effect; }
EAttackBonusEffects_t GetAttackBonusEffect( void ) { return m_eBonusAttackEffect; }
// TF doesn't want the explosion ringing sound
virtual void OnDamagedByExplosion( const CTakeDamageInfo &info ) { return; }
void OnBurnOther( CTFPlayer *pTFPlayerVictim, CTFWeaponBase *pWeapon );
// Buildables
void SetWeaponBuilder( CTFWeaponBuilder *pBuilder );
CTFWeaponBuilder *GetWeaponBuilder( void );
int GetBuildResources( void );
void RemoveBuildResources( int iAmount );
void AddBuildResources( int iAmount );
bool IsBuilding( void );
int CanBuild( int iObjectType, int iObjectMode = 0 );
CBaseObject *GetObject( int index ) const;
CBaseObject *GetObjectOfType( int iObjectType, int iObjectMode = 0 ) const;
int GetObjectCount( void ) const;
int GetNumObjects( int iObjectType, int iObjectMode = 0 );
void RemoveAllObjects( bool bExplodeBuildings = false );
void StopPlacement( void );
int StartedBuildingObject( int iObjectType );
void StoppedBuilding( int iObjectType );
void FinishedObject( CBaseObject *pObject );
void AddObject( CBaseObject *pObject );
void OwnedObjectDestroyed( CBaseObject *pObject );
void RemoveObject( CBaseObject *pObject );
bool PlayerOwnsObject( CBaseObject *pObject );
void DetonateObjectOfType( int iObjectType, int iObjectMode = 0, bool bIgnoreSapperState = false );
void StartBuildingObjectOfType( int iType, int iObjectMode = 0 );
float GetObjectBuildSpeedMultiplier( int iObjectType, bool bIsRedeploy ) const;
void OnSapperPlaced( CBaseEntity *sappedObject ); // invoked when we place a sapper on an enemy building
bool IsPlacingSapper( void ) const; // return true if we are a spy who placed a sapper on a building in the last few moments
void OnSapperStarted( float flStartTime );
void OnSapperFinished( float flStartTime );
bool IsSapping( void ) const;
int GetSappingEvent( void) const;
void ClearSappingEvent( void );
void ClearSappingTracking( void );
CTFTeam *GetTFTeam( void );
CTFTeam *GetOpposingTFTeam( void );
void TeleportEffect( void );
void RemoveTeleportEffect( void );
bool HasTheFlag( ETFFlagType exceptionTypes[] = NULL, int nNumExceptions = 0 ) const;
virtual bool IsAllowedToPickUpFlag( void ) const;
// Death & Ragdolls.
virtual void CreateRagdollEntity( void );
void CreateRagdollEntity( bool bGib, bool bBurning, bool bElectrocuted, bool bOnGround, bool bCloakedCorpse, bool bGoldRagdoll, bool bIceRagdoll, bool bBecomeAsh, int iDamageCustom = 0, bool bCritOnHardHit = false );
void DestroyRagdoll( void );
CNetworkHandle( CBaseEntity, m_hRagdoll ); // networked entity handle
virtual bool ShouldGib( const CTakeDamageInfo &info ) OVERRIDE;
bool HasBombinomiconEffectOnDeath( void );
void StopRagdollDeathAnim( void );
void SetGibbedOnLastDeath( bool bGibbed ) { m_bGibbedOnLastDeath = bGibbed; }
bool WasGibbedOnLastDeath( void ) { return m_bGibbedOnLastDeath; }
// Feign Death
void SpyDeadRingerDeath( const CTakeDamageInfo& info );
void FeignDeath( const CTakeDamageInfo& info );
void CreateFeignDeathRagdoll( const CTakeDamageInfo& info, bool bGib, bool bBurning, bool bDisguised );
// Dropping Ammo
bool ShouldDropAmmoPack( void );
void DropAmmoPack( const CTakeDamageInfo &info, bool bEmpty, bool bDisguisedWeapon );
void DropExtraAmmo( const CTakeDamageInfo& info, bool bFromDeath = false );
void DropHealthPack( const CTakeDamageInfo &info, bool bEmpty );
void DropCurrencyPack( CurrencyRewards_t nSize = TF_CURRENCY_PACK_SMALL, int nAmount = 0, bool bForceDistribute = false, CBasePlayer* pMoneyMaker = NULL ); // Only pass in an amount when nSize = TF_CURRENCY_PACK_CUSTOM
bool CanDisguise( void );
bool CanDisguise_OnKill( void );
bool CanGoInvisible( bool bAllowWhileCarryingFlag = false );
void RemoveInvisibility( void );
bool CanStartPhase( void );
void RemoveDisguise( void );
bool DoClassSpecialSkill( void );
bool EndClassSpecialSkill( void );
bool CanPickupBuilding( CBaseObject *pPickupObject );
bool TryToPickupBuilding( void );
float GetLastDamageReceivedTime( void ) { return m_flLastDamageTime; }
float GetLastEntityDamagedTime( void ) { return m_flLastDamageDoneTime; }
void SetLastEntityDamagedTime( float flTime ) { m_flLastDamageDoneTime = flTime; }
CBaseEntity *GetLastEntityDamaged( void ) { return m_hLastDamageDoneEntity; }
void SetLastEntityDamaged( CBaseEntity *pEnt ) { m_hLastDamageDoneEntity = pEnt; }
void SetClassMenuOpen( bool bIsOpen );
bool IsClassMenuOpen( void );
float GetCritMult( void ) { return m_Shared.GetCritMult(); }
void RecordDamageEvent( const CTakeDamageInfo &info, bool bKill, int nVictimPrevHealth ) { m_Shared.RecordDamageEvent(info,bKill,nVictimPrevHealth); }
bool GetHudClassAutoKill( void ){ return m_bHudClassAutoKill; }
void SetHudClassAutoKill( bool bAutoKill ){ m_bHudClassAutoKill = bAutoKill; }
bool GetMedigunAutoHeal( void ){ return m_bMedigunAutoHeal; }
void SetMedigunAutoHeal( bool bMedigunAutoHeal ){ m_bMedigunAutoHeal = bMedigunAutoHeal; }
CBaseEntity *MedicGetHealTarget( void );
float MedicGetChargeLevel( CTFWeaponBase **pRetMedigun = NULL );
bool IsCallingForMedic( void ) const; // return true if this player has called for a Medic in the last few seconds
float GetTimeSinceCalledForMedic( void ) const;
void NoteMedicCall( void );
bool ShouldAutoRezoom( void ) { return m_bAutoRezoom; }
void SetAutoRezoom( bool bAutoRezoom ) { m_bAutoRezoom = bAutoRezoom; }
bool ShouldAutoReload( void ){ return m_bAutoReload; }
void SetAutoReload( bool bAutoReload ) { m_bAutoReload = bAutoReload; }
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer );
virtual bool CanBeAutobalanced();
Vector GetClassEyeHeight( void );
void UpdateExpression( void );
void ClearExpression( void );
virtual IResponseSystem *GetResponseSystem();
virtual bool SpeakConceptIfAllowed( int iConcept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
virtual bool CanSpeakVoiceCommand( void );
virtual bool ShouldShowVoiceSubtitleToEnemy( void );
virtual void NoteSpokeVoiceCommand( const char *pszScenePlayed );
void SpeakWeaponFire( int iCustomConcept = MP_CONCEPT_NONE );
void ClearWeaponFireScene( void );
virtual int DrawDebugTextOverlays( void );
float m_flNextVoiceCommandTime;
int m_iVoiceSpamCounter;
float m_flNextSpeakWeaponFire;
virtual int CalculateTeamBalanceScore( void );
bool ShouldAnnounceAchievement( void ) OVERRIDE;
virtual void OnAchievementEarned( int iAchievement );
void CheckObserverSettings(); // checks, if target still valid (didn't die etc)
CTriggerAreaCapture *GetControlPointStandingOn( void );
CCaptureZone *GetCaptureZoneStandingOn( void );
CCaptureZone *GetClosestCaptureZone( void );
// given a vector of points, return the point we can actually travel to the quickest (requires a nav mesh)
CTeamControlPoint *SelectClosestControlPointByTravelDistance( CUtlVector< CTeamControlPoint * > *pointVector ) const;
bool CanAirDash( void ) const;
virtual bool CanBreatheUnderwater() const OVERRIDE;
bool CanGetWet() const;
virtual bool IsDeflectable() { return true; }
//=============================================================================
// HPE_BEGIN:
// [msmith] Added a player type so we can distinguish between bots and humans.
//=============================================================================
inline TFPlayerType GetPlayerType(){ return m_playerType; }
inline void SetPlayerType( TFPlayerType playerType ){ m_playerType = playerType; }
//=============================================================================
// HPE_END
//=============================================================================
virtual void OnNavAreaChanged( CNavArea *enteredArea, CNavArea *leftArea ); // invoked (by UpdateLastKnownArea) when we enter a new nav area (or it is reset to NULL)
bool IsThreatAimingTowardMe( CBaseEntity *threat, float cosTolerance = 0.8f ) const; // return true if the given threat is aiming in our direction
bool IsThreatFiringAtMe( CBaseEntity *threat ) const; // return true if the given threat is aiming in our direction and firing its weapon
bool IsInCombat( void ) const; // return true if we are engaged in active combat
void PlayerUse( void );
void InputIgnitePlayer( inputdata_t &inputdata );
void InputSetCustomModel( inputdata_t &inputdata );
void InputSetCustomModelOffset( inputdata_t &inputdata );
void InputSetCustomModelRotation( inputdata_t &inputdata );
void InputClearCustomModelRotation( inputdata_t &inputdata );
void InputSetCustomModelRotates( inputdata_t &inputdata );
void InputSetCustomModelVisibleToSelf( inputdata_t &inputdata );
void InputSetForcedTauntCam( inputdata_t &inputdata );
void InputExtinguishPlayer( inputdata_t &inputdata );
void InputBleedPlayer( inputdata_t &inputdata );
void InputTriggerLootIslandAchievement( inputdata_t &inputdata );
void InputTriggerLootIslandAchievement2( inputdata_t &inputdata );
void InputRollRareSpell( inputdata_t &inputdata );
void InputRoundSpawn( inputdata_t &inputdata );
bool InAirDueToExplosion( void ) { return (!(GetFlags() & FL_ONGROUND) && (GetWaterLevel() == WL_NotInWater) && (m_iBlastJumpState != 0) ); }
bool InAirDueToKnockback( void ) { return (!(GetFlags() & FL_ONGROUND) && (GetWaterLevel() == WL_NotInWater) && ( (m_iBlastJumpState != 0) || m_Shared.InCond( TF_COND_KNOCKED_INTO_AIR ) || m_Shared.InCond( TF_COND_GRAPPLINGHOOK ) || m_Shared.InCond( TF_COND_GRAPPLINGHOOK_SAFEFALL ) ) ); }
bool IsCoaching() const { return m_bIsCoaching; }
void SetIsCoaching( bool bIsCoaching );
void SetCoach( CTFPlayer *pCoach ) { m_hCoach = pCoach; }
CTFPlayer* GetCoach() const { return m_hCoach; }
void SetStudent( CTFPlayer *pStudent ) { m_hStudent = pStudent; }
CTFPlayer* GetStudent() const { return m_hStudent; }
void DoNoiseMaker(); // Halloween event item support.
bool IsWormsGearEquipped( void ) const;
bool IsRobotCostumeEquipped( void ) const;
bool IsDemowolf( void ) const;
bool IsFrankenHeavy( void ) const;
bool IsFairyHeavy( void ) const;
bool IsZombieCostumeEquipped( void ) const;
bool HasWearablesEquipped( const CSchemaItemDefHandle *ppItemDefs, int nWearables ) const;
CEconItemView *GetEquippedItemForLoadoutSlot( int iLoadoutSlot ){ return m_Inventory.GetInventoryItemByItemID( m_EquippedLoadoutItemIndices[iLoadoutSlot] ); }
CBaseEntity *GetEntityForLoadoutSlot( int iLoadoutSlot ); //Gets whatever entity is associated with the loadout slot (wearable or weapon)
CTFWearable *GetEquippedWearableForLoadoutSlot( int iLoadoutSlot );
//Base entity overrides
// Functions that intercept Base Calls for Attribute Checking
void ApplyAbsVelocityImpulse ( const Vector &vecImpulse );
bool ApplyPunchImpulseX ( float flImpulse );
void ApplyAirBlastImpulse( const Vector &vecImpulse );
void SetUseBossHealthBar( bool bUseBossHealthBar ) { m_bUseBossHealthBar = bUseBossHealthBar; }
void SetUsingVRHeadset( bool bState ){ m_bUsingVRHeadset = bState; }
static bool m_bTFPlayerNeedsPrecache;
// IHasAttributes
CAttributeManager *GetAttributeManager( void ) { return &m_AttributeManager; }
CAttributeContainer *GetAttributeContainer( void ) { return NULL; }
CBaseEntity *GetAttributeOwner( void ) { return NULL; }
CAttributeList *GetAttributeList( void ) { return &m_AttributeList; }
virtual void ReapplyProvision( void ) { return; }
protected:
CNetworkVarEmbedded( CAttributeContainerPlayer, m_AttributeManager );
//----------------------------
// INVENTORY MANAGEMENT
public:
// IInventoryUpdateListener
virtual void InventoryUpdated( CPlayerInventory *pInventory );
virtual void SOCacheUnsubscribed( const CSteamID & steamIDOwner ) { m_Shared.SetLoadoutUnavailable( true ); }
// Inventory access
CTFPlayerInventory *Inventory( void ) { return &m_Inventory; }
private:
CTFPlayerInventory m_Inventory;
// Items that have been equipped on this player instance (the inventory loadout may have changed)
itemid_t m_EquippedLoadoutItemIndices[CLASS_LOADOUT_POSITION_COUNT];
public:
void UpdateInventory( bool bInit );
void VerifySOCache();
CNetworkVarEmbedded( CTFPlayerShared, m_Shared );
friend class CTFPlayerShared;
int m_flNextTimeCheck; // Next time the player can execute a "timeleft" command
CNetworkVar( bool, m_bSaveMeParity );
CNetworkVar( bool, m_bIsCoaching);
CNetworkHandle( CTFPlayer, m_hCoach );
CNetworkHandle( CTFPlayer, m_hStudent );
float m_flLastCoachCommand;
CNetworkVar( bool, m_bIsABot );
CNetworkVar( int, m_nBotSkill );
int StateGet( void ) const;
void SetOffHandWeapon( CTFWeaponBase *pWeapon );
void HolsterOffHandWeapon( void );
CTFWeaponBase* GetOffHandWeapon( void ) { return m_hOffHandWeapon; }
float GetSpawnTime() { return m_flSpawnTime; }
virtual void SelectItem( const char *pstr, int iSubType = 0 ) OVERRIDE;
virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ) OVERRIDE;
virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget , const Vector *pVelocity ) OVERRIDE;
virtual void OnMyWeaponFired( CBaseCombatWeapon *weapon ); // call this when this player fires a weapon to allow other systems to react
bool ItemsMatch( TFPlayerClassData_t *pData, CEconItemView *pCurWeaponItem, CEconItemView *pNewWeaponItem, CTFWeaponBase *pWpnEntity = NULL );
void ManageRegularWeapons( TFPlayerClassData_t *pData );
void ManageRegularWeaponsLegacy( TFPlayerClassData_t *pData ); // Older, pre-inventory method of managing regular weapons
void ManageBuilderWeapons( TFPlayerClassData_t *pData );
virtual CBaseEntity *GiveNamedItem( const char *szName, int iSubType = 0, const CEconItemView *pScriptItem = NULL, bool bForce = false );
void PostInventoryApplication( void );
bool ItemIsAllowed( CEconItemView *pItem );
void RemovePlayerAttributes( bool bSetBonuses );
void ApplySetBonuses( void );
void GetActiveSets( CUtlVector<const CEconItemSetDefinition *> *pItemSets );
void ValidateWeapons( TFPlayerClassData_t *pData, bool bResetWeapons );
void ValidateWearables( TFPlayerClassData_t *pData );
CEconItemView* GetLoadoutItem( int iClass, int iSlot, bool bReportWhitelistFails = false );
void UseActionSlotItemPressed( void );
void UseActionSlotItemReleased( void );
bool IsFireproof( void ) const;
bool AddToSpyKnife( float value, bool force );
private:
void GetHorriblyHackedRailgunPosition( const Vector& vStart, Vector *out_pvStartPos );
void MaybeDrawRailgunBeam( IRecipientFilter *pFilter, CTFWeaponBase *pWeapon, const Vector& vStartPos, const Vector& vEndPos );
// Taunts
public:
bool IsReadyToTauntWithPartner( void ) const { return m_bIsReadyToHighFive; }
CTFPlayer * GetTauntPartner( void ) { return m_hHighFivePartner; }
float GetTauntYaw( void ) { return m_flTauntYaw; }
float GetPrevTauntYaw( void ) { return m_flPrevTauntYaw; }
void SetTauntYaw( float flTauntYaw );
CTFPlayer * FindPartnerTauntInitiator( void );
void AcceptTauntWithPartner( CTFPlayer *initiator );
void MimicTauntFromPartner( CTFPlayer *initiator );
bool CanMoveDuringTaunt();
bool ShouldStopTaunting();
bool IsTauntInitiator() const { return m_bIsTauntInitiator; }
bool IsTauntForceMovingForward() const { return m_bTauntForceMoveForward; }
float GetTauntMoveAcceleration() const { return m_flTauntMoveAccelerationTime; }
float GetTauntMoveSpeed() const { return m_flTauntForceMoveForwardSpeed; }
float GetTauntTurnAccelerationTime() const { return m_flTauntTurnAccelerationTime; }
virtual int GetAllowedTauntPartnerTeam() const;
CEconItemView *GetTauntEconItemView() { return m_TauntEconItemView.IsValid() ? &m_TauntEconItemView : NULL; }
int GetTauntConcept( CEconItemDefinition *pItemDef );
bool PlayTauntSceneFromItem( CEconItemView *pEconItemView );
void OnTauntSucceeded( const char* pszSceneName, int iTauntIndex = 0, int iTauntConcept = 0 );
void Taunt( taunts_t iTauntIndex = TAUNT_BASE_WEAPON, int iTauntConcept = 0 );
bool IsTaunting( void ) const { return m_Shared.InCond( TF_COND_TAUNTING ); }
void DoTauntAttack( void );
bool IsAllowedToTaunt( void );
bool FindOpenTauntPartnerPosition( CEconItemView *pEconItemView, Vector &position, float *flTolerance );
bool IsAllowedToInitiateTauntWithPartner( CEconItemView *pEconItemView, char *pszErrorMessage = NULL, int cubErrorMessage = 0 );
void CancelTaunt( void );
void StopTaunt( void );
void EndLongTaunt();
float GetTauntRemoveTime( void ) const { return m_flTauntRemoveTime; }
bool IsAllowedToRemoveTaunt() const { return m_bAllowedToRemoveTaunt; }
void HandleTauntCommand( int iTauntSlot = 0 );
QAngle m_angTauntCamera;
CHandle< CBaseEntity > m_hTauntItem;
void ClearTauntAttack();
float GetTauntAttackTime() const { return m_flTauntAttackTime; }
void SetRPSResult( int iRPSResult ) { m_iTauntRPSResult = iRPSResult; }
void HandleWeaponSlotAfterTaunt();
float GetCurrentTauntMoveSpeed() const { return m_flCurrentTauntMoveSpeed; }
void SetCurrentTauntMoveSpeed( float flSpeed ) { m_flCurrentTauntMoveSpeed = flSpeed; }
float GetVehicleReverseTime() const { return m_flVehicleReverseTime; }
void SetVehicleReverseTime( float flTime ) { m_flVehicleReverseTime = flTime; }
private:
void GetReadyToTauntWithPartner( void );
void CancelTauntWithPartner( void );
void StopTauntSoundLoop();
float PlayTauntOutroScene();
float PlayTauntRemapInputScene();
void ParseSharedTauntDataFromEconItemView( CEconItemView *pEconItemView );
CNetworkVar( bool, m_bAllowMoveDuringTaunt );
CNetworkVar( bool, m_bIsReadyToHighFive );
CNetworkHandle( CTFPlayer, m_hHighFivePartner );
CNetworkVar( int, m_nForceTauntCam );
CNetworkVar( float, m_flTauntYaw );
CNetworkVar( int, m_nActiveTauntSlot );
CNetworkVar( item_definition_index_t, m_iTauntItemDefIndex );
CNetworkVar( float, m_flCurrentTauntMoveSpeed );
CNetworkVar( float, m_flVehicleReverseTime );
bool m_bTauntForceMoveForward;
float m_flTauntForceMoveForwardSpeed;
float m_flTauntMoveAccelerationTime;
float m_flTauntTurnSpeed;
float m_flTauntTurnAccelerationTime;
float m_flPrevTauntYaw;
EHANDLE m_hTauntScene;
CHandle< CTFTauntProp > m_hTauntProp;
bool m_bInitTaunt;
bool m_bTauntMimic;
bool m_bIsTauntInitiator;
float m_flTauntSoundTime;
CUtlString m_strTauntSoundName;
float m_flTauntSoundLoopTime;
CUtlString m_strTauntSoundLoopName;
CEconItemView m_TauntEconItemView;
enum TauntStage_t
{
TAUNT_NONE = 0,
TAUNT_INTRO,
TAUNT_OUTRO
} m_TauntStage;
bool m_bAllowedToRemoveTaunt;
float m_flTauntStartTime;
float m_flTauntRemoveTime;
float m_flTauntOutroTime;
Vector m_vecTauntStartPosition;
float m_flNextAllowTauntRemapInputTime;
float m_flTauntAttackTime;
float m_flTauntInhaleTime;
taunt_attack_t m_iTauntAttack;
int m_iTauntAttackCount;
int m_iTauntRPSResult;
int m_iPreTauntWeaponSlot;
int m_iPreTauntFOV;
float m_flNextReflectZap;
public:
virtual int GetSpecialDSP( void );
virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
void SetDeathFlags( int iDeathFlags ) { m_iDeathFlags = iDeathFlags; }
int GetDeathFlags() { return m_iDeathFlags; }
void SetMaxSentryKills( int iMaxSentryKills ) { m_iMaxSentryKills = iMaxSentryKills; }
int GetMaxSentryKills() { return m_iMaxSentryKills; }
CNetworkVar( bool, m_iSpawnCounter );
void CheckForIdle( void );
inline bool IsAwayFromKeyboard( void ) { return m_bIsAFK; }
void PickWelcomeObserverPoint();
virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
void StopRandomExpressions( void ) { m_flNextRandomExpressionTime = -1; }
void StartRandomExpressions( void ) { m_flNextRandomExpressionTime = gpGlobals->curtime; }
virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec<MAX_EDICTS> *pEntityTransmitBits ) const;
CTFWeaponBase *Weapon_OwnsThisID( int iWeaponID ) const;
CTFWeaponBase *Weapon_GetWeaponByType( int iType );
medigun_charge_types GetChargeEffectBeingProvided( void );
// Achievements
void AwardAchievement( int iAchievement, int iCount = 1 );
void HandleAchievement_Medic_AssistHeavy( CTFPlayer *pPunchVictim );
void HandleAchievement_Pyro_BurnFromBehind( CTFPlayer *pBurner );
void ClearPunchVictims( void ) { m_aPunchVictims.RemoveAll(); }
void ClearBurnFromBehindAttackers( void ) { m_aBurnFromBackAttackers.RemoveAll(); }
int RocketJumped( void ) { return m_iBlastJumpState & TF_PLAYER_ROCKET_JUMPED; }
int StickyJumped( void ) { return m_iBlastJumpState & TF_PLAYER_STICKY_JUMPED; }
void SetBlastJumpState( int iState, bool bPlaySound = false );
void ClearBlastJumpState( void );
int GetPreviousTeam( void ) { return m_iPreviousteam; }
bool IsArenaSpectator( void ) { return m_bArenaSpectator; }
float GetTeamJoinTime( void ) { return m_flTeamJoinTime; }
void MarkTeamJoinTime( void ) { m_flTeamJoinTime = gpGlobals->curtime; }
void PlayerJustPlayed( bool bPlayed ) { m_bJustPlayed = bPlayed; }
bool DidPlayerJustPlay( void ) { return m_bJustPlayed; }
bool IsCapturingPoint( void );
bool m_bSuicideExplode;
bool m_bScattergunJump;
int m_iOldStunFlags;
bool m_bFlipViewModels;
int m_iBlastJumpState;
float m_flBlastJumpLandTime;
bool m_bTakenBlastDamageSinceLastMovement;
void SetTargetDummy( void ){ m_bIsTargetDummy = true; }
bool ShouldCollideWithSentry( void ){ return m_bCollideWithSentry; }
bool IsAnyEnemySentryAbleToAttackMe( void ) const; // return true if any enemy sentry has LOS and is facing me and is in range to attack
int GetHealthBefore( void ) { return m_iHealthBefore; }
int GetAutoTeam( int nPreferedTeam = TF_TEAM_AUTOASSIGN );
bool ShouldForceAutoTeam( void );
float m_flCommentOnCarrying;
int GetTeamChangeCount( void ) { return m_iTeamChanges; }
int GetClassChangeCount( void ) { return m_iClassChanges; }
void IncrementKillCountSinceLastDeploy( const CTakeDamageInfo &info );
void ForceItemRemovalOnRespawn( void ) { m_bForceItemRemovalOnRespawn = true; }
// Item Testing
public:
void ItemTesting_Start( KeyValues *pKV );
void ItemTesting_UpdateBots( KeyValues *pKV );
CEconItemView *ItemTesting_GetTestItem( int iClass, int iSlot );
void ItemTesting_DeleteItems();
public:
struct itemtest_t
{
KeyValues *pKV;
CEconItemView scriptItem;
};
CUtlVector<itemtest_t> m_ItemsToTest;
bool m_bItemTestingRespawn;
bool IsMissionEnemy( void ){ return m_bIsMissionEnemy; }
void MarkAsMissionEnemy( void ){ m_bIsMissionEnemy = true; }
bool IsSupportEnemy( void ){ return m_bIsSupportEnemy; }
void MarkAsSupportEnemy( void ){ m_bIsSupportEnemy = true; }
void MarkAsLimitedSupportEnemy( void ){ m_bIsLimitedSupportEnemy = true; }
// In-game currency
int GetCurrency( void ) const { return m_nCurrency; }
void SetCurrency( int nAmount ){ m_nCurrency = nAmount; }
void AddCurrency( int nAmount );
void RemoveCurrency( int nAmount );
// Set the amount of money this bot is worth when killed. We re-use m_nCurrency, because bots don't collect currency.
void SetCustomCurrencyWorth( int nAmount ) { m_nCurrency = nAmount; }
// Bounty Mode
int GetExperienceLevel( void ) { return m_nExperienceLevel; }
void SetExperienceLevel( int nValue ) { m_nExperienceLevel.Set( MAX( nValue, 1 ) ); }
int GetExperiencePoints( void ) { return m_nExperiencePoints; }
void SetExperiencePoints( int nValue ) { m_nExperiencePoints = MAX( nValue, 0 ); }
void AddExperiencePoints( int nValue, bool bGiveCurrency = false, CTFPlayer *pSource = NULL );
void CalculateExperienceLevel( bool bAnnounce = true );
void RefundExperiencePoints( void );
void RememberUpgrade( int iPlayerClass, CEconItemView *pItem, int iUpgrade, int nCost, bool bDowngrade = false ); // store this upgrade for restoring at a checkpoint
void ForgetFirstUpgradeForItem( CEconItemView *pItem ); // erase the first upgrade stored for this item (for powerup bottles)
void ClearUpgradeHistory( void );
void ReapplyItemUpgrades ( CEconItemView *pItem );
void ReapplyPlayerUpgrades ( void );
void SetWaveSpawnPopulator( CWaveSpawnPopulator *pWave ){ m_pWaveSpawnPopulator = pWave; }
CUtlVector< CUpgradeInfo >* GetRefundableUpgrades( void ) { return &m_RefundableUpgrades; }
void ResetRefundableUpgrades( void ) { m_RefundableUpgrades.RemoveAll(); }
void BeginPurchasableUpgrades( void );
void EndPurchasableUpgrades( void );
bool CanPurchaseUpgrades( void ) const { Assert( m_nCanPurchaseUpgradesCount >= 0 ); return m_nCanPurchaseUpgradesCount > 0; }
void PlayReadySound( void );
void AccumulateSentryGunDamageDealt( float damage );
void ResetAccumulatedSentryGunDamageDealt();
float GetAccumulatedSentryGunDamageDealt();
void IncrementSentryGunKillCount( void );
void ResetAccumulatedSentryGunKillCount();
int GetAccumulatedSentryGunKillCount();
bool PlaySpecificSequence( const char *pSequenceName );
void SetWaterExitTime( float flTime ){ m_flWaterExitTime = flTime; }
float GetWaterExitTime( void ){ return m_flWaterExitTime; }
void MerasmusPlayerBombExplode( bool bExcludeMe = true );
void DropDeathCallingCard( CTFPlayer* pTFAttacker, CTFPlayer* pTFVictim );
//---------------------------------
// support entity IO for forcing speech concepts
void InputSpeakResponseConcept( inputdata_t &inputdata );
//---------------------------------
float GetTimeSinceLastThink( void ) const { return ( m_flLastThinkTime >= 0.f ) ? gpGlobals->curtime - m_flLastThinkTime : -1.f; }
float GetRespawnTimeOverride( void ) const { return m_flRespawnTimeOverride; }
const char *GetRespawnLocationOverride( void ) const { return ( m_strRespawnLocationOverride == NULL_STRING ) ? NULL : m_strRespawnLocationOverride.ToCStr(); }
void SetRespawnOverride( float flRespawnTime, string_t respawnLocation ) { m_flRespawnTimeOverride = flRespawnTime; m_strRespawnLocationOverride = respawnLocation; }
void ResetIdleCheck( void ) { m_flLastAction = gpGlobals->curtime; }
// Matchmaking
void SetMatchSafeToLeave( bool bMatchSafeToLeave ) { m_bMatchSafeToLeave = bMatchSafeToLeave; }
void SetPrevRoundTeamNum( int nTeamNum ){ m_nPrevRoundTeamNum = nTeamNum; }
int GetPrevRoundTeamNum( void ){ return m_nPrevRoundTeamNum; }
protected:
// Creation/Destruction.
virtual void InitClass( void );
void GiveDefaultItems();
bool SelectSpawnSpotByType( const char *pEntClassName, CBaseEntity* &pSpot ); // "info_player_teamspawn"
bool SelectSpawnSpotByName( const char *pEntName, CBaseEntity* &pSpot ); // named info_player_teamspawn, i.e. "my_blue_offense_respawns"
void RemoveNemesisRelationships();
void RemoveAllItems();
// Think.
void TFPlayerThink();
void UpdateTimers( void );
// Regeneration due to being a Medic, or derived from items
void RegenThink();
void RuneRegenThink();
void RegenAmmoInternal( int iAmmo, float flRegen );
void ResetPlayerClass( void );
virtual void Internal_HandleMapEvent( inputdata_t &inputdata ) OVERRIDE;
private:
float m_flAccumulatedHealthRegen; // Regeneration can be in small amounts, so we accumulate it and apply when it's > 1
float m_flNextAmmoRegenAt;
float m_flLastHealthRegenAt;
float m_flAccumulatedRuneHealthRegen;
float m_flNextRuneAmmoRegenAt;
float m_flLastRuneHealthRegenAt;
float m_flAccumulatedAmmoRegens[TF_AMMO_SECONDARY+1]; // Only support regenerating primary & secondary right now
// Bots.
friend void Bot_Think( CTFPlayer *pBot );
// Physics.
void PhysObjectSleep();
void PhysObjectWake();
// Ammo pack.
bool CalculateAmmoPackPositionAndAngles( CTFWeaponBase *pWeapon, Vector &vecOrigin, QAngle &vecAngles );
void AmmoPackCleanUp( void );
// State.
CPlayerStateInfo *StateLookupInfo( int nState );
void StateEnter( int nState );
void StateLeave( void );
void StateTransition( int nState );
void StateEnterWELCOME( void );
void StateThinkWELCOME( void );
void StateEnterPICKINGTEAM( void );
void StateEnterACTIVE( void );
void StateEnterOBSERVER( void );
void StateThinkOBSERVER( void );
void StateEnterDYING( void );
void StateThinkDYING( void );
virtual bool SetObserverMode(int mode);
virtual void AttemptToExitFreezeCam( void );
bool PlayGesture( const char *pGestureName );
bool GetResponseSceneFromConcept( int iConcept, char *chSceneBuffer, int numSceneBufferBytes );
public:
// Achievement data storage
CAchievementData m_AchievementData;
CTFPlayerAnimState *m_PlayerAnimState;
private:
// Map introductions
int m_iIntroStep;
CHandle<CIntroViewpoint> m_hIntroView;
float m_flIntroShowHintAt;
float m_flIntroShowEventAt;
bool m_bHintShown;
bool m_bAbortFreezeCam;
bool m_bSeenRoundInfo;
bool m_bRegenerating;
// Items.
CNetworkHandle( CTFItem, m_hItem );
// Combat.
CNetworkHandle( CTFWeaponBase, m_hOffHandWeapon );
float m_flHealthBuffTime;
int m_iHealthBefore;
float m_flNextRegenerateTime;
float m_flNextChangeClassTime;
float m_flNextChangeTeamTime;
bool m_bAllSeeCrit;
bool m_bMiniCrit;
bool m_bShowDisguisedCrit;
EAttackBonusEffects_t m_eBonusAttackEffect;
int m_iTeamChanges;
int m_iClassChanges;
// Ragdolls.
Vector m_vecTotalBulletForce;
// State.
CPlayerStateInfo *m_pStateInfo;
// Spawn Point
CTFTeamSpawn *m_pSpawnPoint;
// Networked.
CNetworkQAngle( m_angEyeAngles ); // Copied from EyeAngles() so we can send it to the client.
CTFPlayerClass m_PlayerClass;
int m_iLastWeaponFireUsercmd; // Firing a weapon. Last usercmd we shot a bullet on.
int m_iLastWeaponSlot; // To save last switch between lives
int m_iLastSkin;
CNetworkVar( float, m_flLastDamageTime );
float m_flLastDamageDoneTime;
CHandle< CBaseEntity > m_hLastDamageDoneEntity;
float m_flLastHealedTime;
float m_flNextPainSoundTime;
int m_LastDamageType;
int m_iDeathFlags; // TF_DEATH_* flags with additional death info
int m_iMaxSentryKills; // most kills by a single sentry
int m_iNumberofDominations; // number of active dominations for this player
bool m_bPlayedFreezeCamSound;
bool m_bSwitchedClass;
bool m_bRememberLastWeapon;
bool m_bRememberActiveWeapon;
int m_iActiveWeaponTypePriorToDeath;
CHandle< CTFWeaponBuilder > m_hWeaponBuilder;
CUtlVector<EHANDLE> m_aObjects; // List of player objects
bool m_bIsClassMenuOpen;
Vector m_vecLastDeathPosition;
float m_flSpawnTime;
float m_flLastAction;
float m_flTimeInSpawn;
CUtlVector<EHANDLE> m_hObservableEntities;
CUtlVector<float> m_aBurnOtherTimes; // vector of times this player has burned others
bool m_bHudClassAutoKill;
// Background expressions
string_t m_iszExpressionScene;
EHANDLE m_hExpressionSceneEnt;
float m_flNextRandomExpressionTime;
bool m_bSpeakingConceptAsDisguisedSpy;
bool m_bMedigunAutoHeal;
bool m_bAutoRezoom; // does the player want to re-zoom after each shot for sniper rifles
bool m_bAutoReload;
bool m_bForceItemRemovalOnRespawn;
int m_nPrevRoundTeamNum;
public:
// Powerplay cheats
bool SetPowerplayEnabled( bool bOn );
bool PlayerHasPowerplay( void );
void PowerplayThink( void );
CNetworkVar( bool, m_bInPowerPlay );
bool IsGoingFeignDeath( void ) { return m_bGoingFeignDeath; }
void SetDeployingBombState( BombDeployingState_t nDeployingBombState ) { m_nDeployingBombState = nDeployingBombState; }
BombDeployingState_t GetDeployingBombState( void ) const { return m_nDeployingBombState; }
void SetPendingMerasmusPlayerBombExplode( void ){ m_bPendingMerasmusPlayerBombExplode = true; }
private:
// Achievement data
CUtlVector<EHANDLE> m_aPunchVictims;
CUtlVector<EHANDLE> m_aBurnFromBackAttackers;
int m_iLeftGroundHealth; // health we were at the last time we left the ground
float m_flTeamJoinTime;
bool m_bCreatedRocketJumpParticles;
bool m_bJustPlayed;
int m_iPreviousteam;
bool m_bGibbedOnLastDeath;
CUtlMap<int, float> m_Cappers;
float m_fMaxHealthTime;
// Feign death.
bool m_bGoingFeignDeath;
CHandle<CBaseEntity> m_hFeignRagdoll; // Don't use the normal ragdoll.
Vector m_vecFeignDeathVelocity;
CNetworkVar( bool, m_bArenaSpectator );
bool m_bArenaIsAFK; // used to detect when players are AFK during an Arena-mode round
bool m_bIsAFK;
BombDeployingState_t m_nDeployingBombState;
bool m_bIsMissionEnemy;
bool m_bIsSupportEnemy;
bool m_bIsLimitedSupportEnemy;
// In-game currency
CNetworkVar( int, m_nCurrency );
CNetworkVar( bool, m_bIsMiniBoss );
// Bounty Mode
CNetworkVar( uint32, m_nExperienceLevel );
CNetworkVar( uint32, m_nExperienceLevelProgress ); // Networked progress bar
uint32 m_nExperiencePoints; // Raw player-only value
// Matchmaking
// is this player bound to the match on penalty of abandon. Sync'd via local-player-only DT
CNetworkVar( bool, m_bMatchSafeToLeave );
CWaveSpawnPopulator *m_pWaveSpawnPopulator;
float m_flLastReadySoundTime;
int m_nCanPurchaseUpgradesCount;
CUtlVector< CUpgradeInfo > m_RefundableUpgrades;
public:
// Marking for death.
CHandle<CTFPlayer> m_pMarkedForDeathTarget;
CountdownTimer m_playerMovementStuckTimer; // for destroying stuck bots in MvM
QAngle m_qPreviousChargeEyeAngle; // Previous EyeAngles to compute deltas for legal mouse movement
private:
//=============================================================================
// HPE_BEGIN:
// [msmith] Added a player type so we can distinguish between bots and humans.
//=============================================================================
TFPlayerType m_playerType;
//=============================================================================
// HPE_END
//=============================================================================
bool m_bIsTargetDummy;
bool m_bCollideWithSentry;
IntervalTimer m_calledForMedicTimer;
CountdownTimer m_placedSapperTimer;
CountdownTimer m_inCombatThrottleTimer;
mutable char m_bIsCalculatingMaximumSpeed;
public:
float GetDesiredHeadScale() const;
float GetHeadScaleSpeed() const;
float GetDesiredTorsoScale() const;
float GetTorsoScaleSpeed() const;
float GetDesiredHandScale() const;
float GetHandScaleSpeed() const;
bool IsInPurgatory( void ) const;
bool HasPurgatoryBuff( void ) const;
void SetBombHeadTimestamp();
float GetTimeSinceWasBombHead() const;
float GetKartSpeedBoost( void );
float GetKartHealth( void ) { return m_iKartHealth; }
void AddKartDamage( int iDamage ) { m_iKartHealth = Max(0, m_iKartHealth + iDamage); }
float GetKartKnockbackMultiplier( float flExtraMultiplier ) const;
void ResetKartDamage();
CBaseEntity *GetKartBombHeadTarget() const { return m_hKartBombHeadTarget; }
void SetKartBombHeadTarget( CBaseEntity* pEnt ) { m_hKartBombHeadTarget = pEnt; }
void AddHalloweenKartPushEvent( CTFPlayer *pOther, CBaseEntity *pInflictor, CBaseEntity *pWeapon, Vector vForce, int iDamage, int iDamageType = 0 );
QAngle GetAnimRenderAngles( void ) { return m_PlayerAnimState->GetRenderAngles(); }
void CancelEurekaTeleport();
CNetworkVar( int, m_iKartState );
CNetworkVar( float, m_flKartNextAvailableBoost );
float m_flHHHKartAttackTime;
// Wrenchmotron teleport
bool m_bIsTeleportingUsingEurekaEffect;
private:
void UpdateHalloween( void );
Vector m_vHalloweenKartPush;
float m_flHalloweenKartPushEventTime;
bool m_bCheckKartCollision;
EHANDLE m_hKartBombHeadTarget;
float m_flNextBonusDucksVOAllowedTime;
CNetworkVar( int, m_iKartHealth );
float m_flGhostLastHitByKartTime;
bool m_bIsInPurgatory; // for 2011 Halloween event
CountdownTimer m_purgatoryBuffTimer;
CountdownTimer m_purgatoryPainMultiplierTimer;
int m_purgatoryPainMultiplier;
CNetworkVar( float, m_flHeadScale );
CNetworkVar( float, m_flTorsoScale );
CNetworkVar( float, m_flHandScale );
//CountdownTimer m_fireproofTimer; // if active, we're fireproof
// Wrenchmotron teleport
CountdownTimer m_teleportHomeFlashTimer;
eEurekaTeleportTargets m_eEurekaTeleportTarget;
float m_accumulatedSentryGunDamageDealt; // for Sentry Buster missions in MvM
int m_accumulatedSentryGunKillCount; // for Sentry Buster missions in MvM
static const int DPS_Period = 90; // The duration of the sliding window for calculating DPS, in seconds
int *m_damageRateArray; // One array element per second, for accumulating damage done during that time
int m_lastDamageRateIndex;
int m_peakDamagePerSecond;
CNetworkVar( uint16, m_nActiveWpnClip );
uint16 m_nActiveWpnClipPrev;
float m_flNextClipSendTime;
float m_flWaterExitTime;
bool m_bPendingMerasmusPlayerBombExplode;
float m_fLastBombHeadTimestamp;
bool m_bIsSapping;
int m_iSappingEvent;
float m_flSapStartTime;
float m_flLastThinkTime;
float m_flRespawnTimeOverride;
string_t m_strRespawnLocationOverride;
CountdownTimer m_booTimer;
CNetworkVar( bool, m_bUseBossHealthBar );
CNetworkVar( bool, m_bUsingVRHeadset );
CNetworkVar( bool, m_bForcedSkin );
CNetworkVar( int, m_nForcedSkin );
private:
CHandle< CTFReviveMarker > m_hReviveMarker;
public:
CTFReviveMarker *GetReviveMarker( void ) { return m_hReviveMarker; }
// Send ForcePlayerViewAngles user message. Handled in __MsgFunc_ForcePlayerViewAngles in
// clientmode_tf.cpp. Sets Local and Abs angles, along with TauntYaw and VehicleMovingAngles.
void ForcePlayerViewAngles( const QAngle& qTeleportAngles );
CBaseEntity *GetGrapplingHookTarget() const { return m_hGrapplingHookTarget; }
void SetGrapplingHookTarget( CBaseEntity *pTarget, bool bShouldBleed = false );
bool IsUsingActionSlot() const { return m_bUsingActionSlot; }
void SetSecondaryLastWeapon( CBaseCombatWeapon *pSecondaryLastWeapon ) { m_hSecondaryLastWeapon = pSecondaryLastWeapon; }
CBaseCombatWeapon* GetSecondaryLastWeapon() const { return m_hSecondaryLastWeapon; }
bool CanBeForcedToLaugh( void );
void CreateDisguiseWeaponList( CTFPlayer *pDisguiseTarget );
void ClearDisguiseWeaponList();
bool CanPickupDroppedWeapon( const CTFDroppedWeapon *pWeapon );
CTFDroppedWeapon* GetDroppedWeaponInRange();
bool HasCampaignMedal( int iMedal );
void SetCampaignMedalActive( int iMedal ){ m_iCampaignMedals |= iMedal; }
void InspectButtonPressed();
void InspectButtonReleased();
bool IsInspecting() const;
void SetNextScorePointForPD( float flTime ){ m_flNextScorePointForPD = flTime; }
bool CanScorePointForPD( void ) const;
void AddCustomAttribute( const char *pszAttributeName, float flVal, float flDuration = -1.f );
void RemoveCustomAttribute( const char *pszAttributeName );
int GetSkinOverride() const { return m_iPlayerSkinOverride; }
bool ShouldGetBonusPointsForExtinguishEvent( int userID );
void SetLastAutobalanceTime( float flTime ) { m_flLastAutobalanceTime = flTime; }
float GetLastAutobalanceTime() { return m_flLastAutobalanceTime; }
private:
bool PickupWeaponFromOther( CTFDroppedWeapon *pDroppedWeapon );
bool TryToPickupDroppedWeapon();
float m_flSendPickupWeaponMessageTime;
void ModifyDamageInfo( CTakeDamageInfo *pInfo, const CBaseEntity *pTarget );
CNetworkHandle( CBaseEntity, m_hGrapplingHookTarget );
float m_flLastSeenHookTarget;
int m_nHookAttachedPlayers;
CNetworkHandle( CBaseCombatWeapon, m_hSecondaryLastWeapon );
CNetworkVar( bool, m_bUsingActionSlot );
CNetworkVar( float, m_flInspectTime );
CUtlVector< CHandle< CTFWeaponBase > > m_hDisguiseWeaponList; // copy disguise target weapons to this list
CNetworkVar( int, m_iCampaignMedals );
float m_flNextScorePointForPD;
float m_flLastRuneChargeUpdate;
float m_flLastDamageResistSoundTime;
void UpdateCustomAttributes();
void RemoveAllCustomAttributes();
CUtlMap< CUtlString, float > m_mapCustomAttributes;
CNetworkVar( int, m_iPlayerSkinOverride );
CUtlMap<int, float> m_PlayersExtinguished; // userID and most recent time they were extinguished for bonus points
float m_flLastAutobalanceTime;
// begin passtime
public:
bool SayAskForBall();
bool m_bPasstimeBallSlippery;
// end passtime
virtual bool ShouldForceTransmitsForTeam( int iTeam ) OVERRIDE;
virtual bool IsTruceValidForEnt( void ) const OVERRIDE;
};
//-----------------------------------------------------------------------------
// Purpose: Utility function to convert an entity into a tf player.
// Input: pEntity - the entity to convert into a player
//-----------------------------------------------------------------------------
inline CTFPlayer *ToTFPlayer( CBaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
Assert( dynamic_cast<CTFPlayer*>( pEntity ) != 0 );
return static_cast< CTFPlayer* >( pEntity );
}
inline bool CTFPlayer::IsFireproof( void ) const
{
return m_Shared.InCond( TF_COND_FIRE_IMMUNE );
}
inline bool CTFPlayer::HasPurgatoryBuff( void ) const
{
return m_purgatoryBuffTimer.HasStarted() && !m_purgatoryBuffTimer.IsElapsed();
}
inline void CTFPlayer::OnSapperPlaced( CBaseEntity *sappedObject )
{
m_placedSapperTimer.Start( 3.0f );
}
inline void CTFPlayer::OnSapperStarted( float flStartTime )
{
if (m_iSappingEvent == TF_SAPEVENT_NONE && m_flSapStartTime == 0.00 )
{
m_flSapStartTime = flStartTime;
m_bIsSapping = true;
m_iSappingEvent = TF_SAPEVENT_PLACED;
}
}
inline void CTFPlayer::OnSapperFinished( float flStartTime )
{
if (m_iSappingEvent == TF_SAPEVENT_NONE && flStartTime == m_flSapStartTime )
{
m_bIsSapping = false;
m_flSapStartTime = 0.00;
m_iSappingEvent = TF_SAPEVENT_DONE;
}
}
inline bool CTFPlayer::IsSapping( void ) const
{
return m_bIsSapping;
}
inline int CTFPlayer::GetSappingEvent( void ) const
{
return m_iSappingEvent;
}
inline void CTFPlayer::ClearSappingEvent( void )
{
m_iSappingEvent = TF_SAPEVENT_NONE;
}
inline void CTFPlayer::ClearSappingTracking( void )
{
ClearSappingEvent();
m_bIsSapping = false;
m_flSapStartTime = 0.00;
}
inline bool CTFPlayer::IsPlacingSapper( void ) const
{
return !m_placedSapperTimer.IsElapsed();
}
inline int CTFPlayer::StateGet( void ) const
{
return m_Shared.m_nPlayerState;
}
inline bool CTFPlayer::IsInCombat( void ) const
{
// the simplest condition is whether we've been firing our weapon very recently
return GetTimeSinceWeaponFired() < 2.0f;
}
inline bool CTFPlayer::IsCallingForMedic( void ) const
{
return m_calledForMedicTimer.HasStarted() && m_calledForMedicTimer.IsLessThen( 5.0f );
}
inline float CTFPlayer::GetTimeSinceCalledForMedic() const
{
return m_calledForMedicTimer.GetElapsedTime();
}
inline void CTFPlayer::NoteMedicCall( void )
{
m_calledForMedicTimer.Start();
}
inline bool CTFPlayer::IsInPurgatory( void ) const
{
return m_Shared.InCond( TF_COND_PURGATORY );
}
inline void CTFPlayer::AccumulateSentryGunDamageDealt( float damage )
{
m_accumulatedSentryGunDamageDealt += damage;
}
inline void CTFPlayer::ResetAccumulatedSentryGunDamageDealt()
{
m_accumulatedSentryGunDamageDealt = 0.0f;
}
inline float CTFPlayer::GetAccumulatedSentryGunDamageDealt()
{
return m_accumulatedSentryGunDamageDealt;
}
inline void CTFPlayer::IncrementSentryGunKillCount( void )
{
++m_accumulatedSentryGunKillCount;
}
inline void CTFPlayer::ResetAccumulatedSentryGunKillCount()
{
m_accumulatedSentryGunKillCount = 0;
}
inline int CTFPlayer::GetAccumulatedSentryGunKillCount()
{
return m_accumulatedSentryGunKillCount;
}
inline int CTFPlayer::GetDamagePerSecond( void ) const
{
return m_peakDamagePerSecond;
}
inline void CTFPlayer::ResetDamagePerSecond( void )
{
for( int i=0; i<DPS_Period; ++i )
{
m_damageRateArray[i] = 0;
}
m_lastDamageRateIndex = -1;
m_peakDamagePerSecond = 0;
}
//=============================================================================
//
// CObserverPoint
//
class CObserverPoint : public CPointEntity
{
DECLARE_CLASS( CObserverPoint, CPointEntity );
public:
DECLARE_DATADESC();
CObserverPoint();
virtual void Activate( void );
bool CanUseObserverPoint( CTFPlayer *pPlayer );
virtual int UpdateTransmitState();
void InputEnable( inputdata_t &inputdata );
void InputDisable( inputdata_t &inputdata );
bool IsDefaultWelcome( void ) { return m_bDefaultWelcome; }
bool IsMatchSummary( void ) { return m_bMatchSummary; }
void SetDisabled( bool bDisabled ){ m_bDisabled = bDisabled; }
public:
bool m_bDisabled;
bool m_bDefaultWelcome;
EHANDLE m_hAssociatedTeamEntity;
string_t m_iszAssociateTeamEntityName;
float m_flFOV;
bool m_bMatchSummary;
};
#endif // TF_PLAYER_H