//========= 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 &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 ¶ms ); // 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 *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 *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 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 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 m_aObjects; // List of player objects bool m_bIsClassMenuOpen; Vector m_vecLastDeathPosition; float m_flSpawnTime; float m_flLastAction; float m_flTimeInSpawn; CUtlVector m_hObservableEntities; CUtlVector 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 m_aPunchVictims; CUtlVector 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 m_Cappers; float m_fMaxHealthTime; // Feign death. bool m_bGoingFeignDeath; CHandle 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 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 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( 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