//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Base combat character with no AI
//
// $NoKeywords: $
//=============================================================================//
# ifndef BASECOMBATCHARACTER_H
# define BASECOMBATCHARACTER_H
# include <limits.h>
# include "weapon_proficiency.h"
# ifdef _WIN32
# pragma once
# endif
# ifdef INVASION_DLL
# include "tf_shareddefs.h"
# define POWERUP_THINK_CONTEXT "PowerupThink"
# endif
# include "cbase.h"
# include "baseentity.h"
# include "baseflex.h"
# include "damagemodifier.h"
# include "utllinkedlist.h"
# include "ai_hull.h"
# include "ai_utils.h"
# include "physics_impact_damage.h"
class CNavArea ;
class CScriptedTarget ;
typedef CHandle < CBaseCombatWeapon > CBaseCombatWeaponHandle ;
// -------------------------------------
// Capability Bits
// -------------------------------------
enum Capability_t
{
bits_CAP_MOVE_GROUND = 0x00000001 , // walk/run
bits_CAP_MOVE_JUMP = 0x00000002 , // jump/leap
bits_CAP_MOVE_FLY = 0x00000004 , // can fly, move all around
bits_CAP_MOVE_CLIMB = 0x00000008 , // climb ladders
bits_CAP_MOVE_SWIM = 0x00000010 , // navigate in water // UNDONE - not yet implemented
bits_CAP_MOVE_CRAWL = 0x00000020 , // crawl // UNDONE - not yet implemented
bits_CAP_MOVE_SHOOT = 0x00000040 , // tries to shoot weapon while moving
bits_CAP_SKIP_NAV_GROUND_CHECK = 0x00000080 , // optimization - skips ground tests while computing navigation
bits_CAP_USE = 0x00000100 , // open doors/push buttons/pull levers
//bits_CAP_HEAR = 0x00000200, // can hear forced sounds
bits_CAP_AUTO_DOORS = 0x00000400 , // can trigger auto doors
bits_CAP_OPEN_DOORS = 0x00000800 , // can open manual doors
bits_CAP_TURN_HEAD = 0x00001000 , // can turn head, always bone controller 0
bits_CAP_WEAPON_RANGE_ATTACK1 = 0x00002000 , // can do a weapon range attack 1
bits_CAP_WEAPON_RANGE_ATTACK2 = 0x00004000 , // can do a weapon range attack 2
bits_CAP_WEAPON_MELEE_ATTACK1 = 0x00008000 , // can do a weapon melee attack 1
bits_CAP_WEAPON_MELEE_ATTACK2 = 0x00010000 , // can do a weapon melee attack 2
bits_CAP_INNATE_RANGE_ATTACK1 = 0x00020000 , // can do a innate range attack 1
bits_CAP_INNATE_RANGE_ATTACK2 = 0x00040000 , // can do a innate range attack 1
bits_CAP_INNATE_MELEE_ATTACK1 = 0x00080000 , // can do a innate melee attack 1
bits_CAP_INNATE_MELEE_ATTACK2 = 0x00100000 , // can do a innate melee attack 1
bits_CAP_USE_WEAPONS = 0x00200000 , // can use weapons (non-innate attacks)
//bits_CAP_STRAFE = 0x00400000, // strafe ( walk/run sideways)
bits_CAP_ANIMATEDFACE = 0x00800000 , // has animated eyes/face
bits_CAP_USE_SHOT_REGULATOR = 0x01000000 , // Uses the shot regulator for range attack1
bits_CAP_FRIENDLY_DMG_IMMUNE = 0x02000000 , // don't take damage from npc's that are D_LI
bits_CAP_SQUAD = 0x04000000 , // can form squads
bits_CAP_DUCK = 0x08000000 , // cover and reload ducking
bits_CAP_NO_HIT_PLAYER = 0x10000000 , // don't hit players
bits_CAP_AIM_GUN = 0x20000000 , // Use arms to aim gun, not just body
bits_CAP_NO_HIT_SQUADMATES = 0x40000000 , // none
bits_CAP_SIMPLE_RADIUS_DAMAGE = 0x80000000 , // Do not use robust radius damage model on this character.
} ;
# define bits_CAP_DOORS_GROUP (bits_CAP_AUTO_DOORS | bits_CAP_OPEN_DOORS)
# define bits_CAP_RANGE_ATTACK_GROUP (bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_WEAPON_RANGE_ATTACK2)
# define bits_CAP_MELEE_ATTACK_GROUP (bits_CAP_WEAPON_MELEE_ATTACK1 | bits_CAP_WEAPON_MELEE_ATTACK2)
class CBaseCombatWeapon ;
# define BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE 0.9f
enum Disposition_t
{
D_ER , // Undefined - error
D_HT , // Hate
D_FR , // Fear
D_LI , // Like
D_NU // Neutral
} ;
const int DEF_RELATIONSHIP_PRIORITY = INT_MIN ;
struct Relationship_t
{
EHANDLE entity ; // Relationship to a particular entity
Class_T classType ; // Relationship to a class CLASS_NONE = not class based (Def. in baseentity.h)
Disposition_t disposition ; // D_HT (Hate), D_FR (Fear), D_LI (Like), D_NT (Neutral)
int priority ; // Relative importance of this relationship (higher numbers mean more important)
DECLARE_SIMPLE_DATADESC ( ) ;
} ;
//-----------------------------------------------------------------------------
// Purpose: This should contain all of the combat entry points / functionality
// that are common between NPCs and players
//-----------------------------------------------------------------------------
class CBaseCombatCharacter : public CBaseFlex
{
DECLARE_CLASS ( CBaseCombatCharacter , CBaseFlex ) ;
public :
CBaseCombatCharacter ( void ) ;
~ CBaseCombatCharacter ( void ) ;
DECLARE_SERVERCLASS ( ) ;
DECLARE_DATADESC ( ) ;
DECLARE_PREDICTABLE ( ) ;
public :
virtual void Spawn ( void ) ;
virtual void Precache ( ) ;
virtual int Restore ( IRestore & restore ) ;
virtual const impactdamagetable_t & GetPhysicsImpactDamageTable ( void ) ;
int TakeHealth ( float flHealth , int bitsDamageType ) ;
void CauseDeath ( const CTakeDamageInfo & info ) ;
virtual bool FVisible ( CBaseEntity * pEntity , int traceMask = MASK_BLOCKLOS , CBaseEntity * * ppBlocker = NULL ) ; // true iff the parameter can be seen by me.
virtual bool FVisible ( const Vector & vecTarget , int traceMask = MASK_BLOCKLOS , CBaseEntity * * ppBlocker = NULL ) { return BaseClass : : FVisible ( vecTarget , traceMask , ppBlocker ) ; }
static void ResetVisibilityCache ( CBaseCombatCharacter * pBCC = NULL ) ;
# ifdef PORTAL
virtual bool FVisibleThroughPortal ( const CProp_Portal * pPortal , CBaseEntity * pEntity , int traceMask = MASK_BLOCKLOS , CBaseEntity * * ppBlocker = NULL ) ;
# endif
virtual bool FInViewCone ( CBaseEntity * pEntity ) ;
virtual bool FInViewCone ( const Vector & vecSpot ) ;
# ifdef PORTAL
virtual CProp_Portal * FInViewConeThroughPortal ( CBaseEntity * pEntity ) ;
virtual CProp_Portal * FInViewConeThroughPortal ( const Vector & vecSpot ) ;
# endif
virtual bool FInAimCone ( CBaseEntity * pEntity ) ;
virtual bool FInAimCone ( const Vector & vecSpot ) ;
virtual bool ShouldShootMissTarget ( CBaseCombatCharacter * pAttacker ) ;
virtual CBaseEntity * FindMissTarget ( void ) ;
// Do not call HandleInteraction directly, use DispatchInteraction
bool DispatchInteraction ( int interactionType , void * data , CBaseCombatCharacter * sourceEnt ) { return ( interactionType > 0 ) ? HandleInteraction ( interactionType , data , sourceEnt ) : false ; }
virtual bool HandleInteraction ( int interactionType , void * data , CBaseCombatCharacter * sourceEnt ) ;
virtual QAngle BodyAngles ( ) ;
virtual Vector BodyDirection2D ( void ) ;
virtual Vector BodyDirection3D ( void ) ;
virtual Vector HeadDirection2D ( void ) { return BodyDirection2D ( ) ; } ; // No head motion so just return body dir
virtual Vector HeadDirection3D ( void ) { return BodyDirection2D ( ) ; } ; // No head motion so just return body dir
virtual Vector EyeDirection2D ( void ) { return HeadDirection2D ( ) ; } ; // No eye motion so just return head dir
virtual Vector EyeDirection3D ( void ) { return HeadDirection3D ( ) ; } ; // No eye motion so just return head dir
virtual void SetTransmit ( CCheckTransmitInfo * pInfo , bool bAlways ) ;
// -----------------------
// Fog
// -----------------------
virtual bool IsHiddenByFog ( const Vector & target ) const ; ///< return true if given target cant be seen because of fog
virtual bool IsHiddenByFog ( CBaseEntity * target ) const ; ///< return true if given target cant be seen because of fog
virtual bool IsHiddenByFog ( float range ) const ; ///< return true if given distance is too far to see through the fog
virtual float GetFogObscuredRatio ( const Vector & target ) const ; ///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
virtual float GetFogObscuredRatio ( CBaseEntity * target ) const ; ///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
virtual float GetFogObscuredRatio ( float range ) const ; ///< return 0-1 ratio where zero is not obscured, and 1 is completely obscured
// -----------------------
// Vision
// -----------------------
enum FieldOfViewCheckType { USE_FOV , DISREGARD_FOV } ;
// Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
bool IsAbleToSee ( const CBaseEntity * entity , FieldOfViewCheckType checkFOV ) ;
bool IsAbleToSee ( CBaseCombatCharacter * pBCC , FieldOfViewCheckType checkFOV ) ;
virtual bool IsLookingTowards ( const CBaseEntity * target , float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const ; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsLookingTowards ( const Vector & target , float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const ; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsInFieldOfView ( CBaseEntity * entity ) const ; // Calls IsLookingTowards with the current field of view.
virtual bool IsInFieldOfView ( const Vector & pos ) const ;
enum LineOfSightCheckType
{
IGNORE_NOTHING ,
IGNORE_ACTORS
} ;
virtual bool IsLineOfSightClear ( CBaseEntity * entity , LineOfSightCheckType checkType = IGNORE_NOTHING ) const ; // strictly LOS check with no other considerations
virtual bool IsLineOfSightClear ( const Vector & pos , LineOfSightCheckType checkType = IGNORE_NOTHING , CBaseEntity * entityToIgnore = NULL ) const ;
// -----------------------
// Ammo
// -----------------------
virtual int GiveAmmo ( int iCount , int iAmmoIndex , bool bSuppressSound = false ) ;
int GiveAmmo ( int iCount , const char * szName , bool bSuppressSound = false ) ;
virtual void RemoveAmmo ( int iCount , int iAmmoIndex ) ;
virtual void RemoveAmmo ( int iCount , const char * szName ) ;
void RemoveAllAmmo ( ) ;
virtual int GetAmmoCount ( int iAmmoIndex ) const ;
int GetAmmoCount ( char * szName ) const ;
virtual Activity NPC_TranslateActivity ( Activity baseAct ) ;
// -----------------------
// Weapons
// -----------------------
CBaseCombatWeapon * Weapon_Create ( const char * pWeaponName ) ;
virtual Activity Weapon_TranslateActivity ( Activity baseAct , bool * pRequired = NULL ) ;
void Weapon_SetActivity ( Activity newActivity , float duration ) ;
virtual void Weapon_FrameUpdate ( void ) ;
virtual void Weapon_HandleAnimEvent ( animevent_t * pEvent ) ;
CBaseCombatWeapon * Weapon_OwnsThisType ( const char * pszWeapon , int iSubType = 0 ) const ; // True if already owns a weapon of this class
virtual bool Weapon_CanUse ( CBaseCombatWeapon * pWeapon ) ; // True is allowed to use this class of weapon
virtual void Weapon_Equip ( CBaseCombatWeapon * pWeapon ) ; // Adds weapon to player
virtual bool Weapon_EquipAmmoOnly ( CBaseCombatWeapon * pWeapon ) ; // Adds weapon ammo to player, leaves weapon
bool Weapon_Detach ( CBaseCombatWeapon * pWeapon ) ; // Clear any pointers to the weapon.
virtual void Weapon_Drop ( CBaseCombatWeapon * pWeapon , const Vector * pvecTarget = NULL , const Vector * pVelocity = NULL ) ;
virtual bool Weapon_Switch ( CBaseCombatWeapon * pWeapon , int viewmodelindex = 0 ) ; // Switch to given weapon if has ammo (false if failed)
virtual Vector Weapon_ShootPosition ( ) ; // gun position at current position/orientation
bool Weapon_IsOnGround ( CBaseCombatWeapon * pWeapon ) ;
CBaseEntity * Weapon_FindUsable ( const Vector & range ) ; // search for a usable weapon in this range
virtual bool Weapon_CanSwitchTo ( CBaseCombatWeapon * pWeapon ) ;
virtual bool Weapon_SlotOccupied ( CBaseCombatWeapon * pWeapon ) ;
virtual CBaseCombatWeapon * Weapon_GetSlot ( int slot ) const ;
CBaseCombatWeapon * Weapon_GetWpnForAmmo ( int iAmmoIndex ) ;
// For weapon strip
void Weapon_DropAll ( bool bDisallowWeaponPickup = false ) ;
virtual bool AddPlayerItem ( CBaseCombatWeapon * pItem ) { return false ; }
virtual bool RemovePlayerItem ( CBaseCombatWeapon * pItem ) { return false ; }
virtual bool CanBecomeServerRagdoll ( void ) { return true ; }
// -----------------------
// Damage
// -----------------------
// Don't override this for characters, override the per-life-state versions below
virtual int OnTakeDamage ( const CTakeDamageInfo & info ) ;
// Override these to control how your character takes damage in different states
virtual int OnTakeDamage_Alive ( const CTakeDamageInfo & info ) ;
virtual int OnTakeDamage_Dying ( const CTakeDamageInfo & info ) ;
virtual int OnTakeDamage_Dead ( const CTakeDamageInfo & info ) ;
virtual float GetAliveDuration ( void ) const ; // return time we have been alive (only valid when alive)
virtual void OnFriendDamaged ( CBaseCombatCharacter * pSquadmate , CBaseEntity * pAttacker ) { }
virtual void NotifyFriendsOfDamage ( CBaseEntity * pAttackerEntity ) { }
virtual bool HasEverBeenInjured ( int team = TEAM_ANY ) const ; // return true if we have ever been injured by a member of the given team
virtual float GetTimeSinceLastInjury ( int team = TEAM_ANY ) const ; // return time since we were hurt by a member of the given team
virtual void OnPlayerKilledOther ( CBaseEntity * pVictim , const CTakeDamageInfo & info ) { }
// utility function to calc damage force
Vector CalcDamageForceVector ( const CTakeDamageInfo & info ) ;
virtual int BloodColor ( ) ;
virtual Activity GetDeathActivity ( void ) ;
virtual bool CorpseGib ( const CTakeDamageInfo & info ) ;
virtual void CorpseFade ( void ) ; // Called instead of GibNPC() when gibs are disabled
virtual bool HasHumanGibs ( void ) ;
virtual bool HasAlienGibs ( void ) ;
virtual bool ShouldGib ( const CTakeDamageInfo & info ) { return false ; } // Always ragdoll, unless specified by the leaf class
float GetDamageAccumulator ( ) { return m_flDamageAccumulator ; }
int GetDamageCount ( void ) { return m_iDamageCount ; } // # of times NPC has been damaged. used for tracking 1-shot kills.
// Character killed (only fired once)
virtual void Event_Killed ( const CTakeDamageInfo & info ) ;
// Killed a character
void InputKilledNPC ( inputdata_t & inputdata ) ;
virtual void OnKilledNPC ( CBaseCombatCharacter * pKilled ) { } ;
// Exactly one of these happens immediately after killed (gibbed may happen later when the corpse gibs)
// Character gibbed or faded out (violence controls) (only fired once)
// returns true if gibs were spawned
virtual bool Event_Gibbed ( const CTakeDamageInfo & info ) ;
// Character entered the dying state without being gibbed (only fired once)
virtual void Event_Dying ( const CTakeDamageInfo & info ) ;
virtual void Event_Dying ( ) ;
// character died and should become a ragdoll now
// return true if converted to a ragdoll, false to use AI death
virtual bool BecomeRagdoll ( const CTakeDamageInfo & info , const Vector & forceVector ) ;
virtual void FixupBurningServerRagdoll ( CBaseEntity * pRagdoll ) ;
virtual bool BecomeRagdollBoogie ( CBaseEntity * pKiller , const Vector & forceVector , float duration , int flags ) ;
CBaseEntity * FindHealthItem ( const Vector & vecPosition , const Vector & range ) ;
virtual CBaseEntity * CheckTraceHullAttack ( float flDist , const Vector & mins , const Vector & maxs , int iDamage , int iDmgType , float forceScale = 1.0f , bool bDamageAnyNPC = false ) ;
virtual CBaseEntity * CheckTraceHullAttack ( const Vector & vStart , const Vector & vEnd , const Vector & mins , const Vector & maxs , int iDamage , int iDmgType , float flForceScale = 1.0f , bool bDamageAnyNPC = false ) ;
virtual CBaseCombatCharacter * MyCombatCharacterPointer ( void ) { return this ; }
// VPHYSICS
virtual void VPhysicsShadowCollision ( int index , gamevcollisionevent_t * pEvent ) ;
virtual void VPhysicsUpdate ( IPhysicsObject * pPhysics ) ;
float CalculatePhysicsStressDamage ( vphysics_objectstress_t * pStressOut , IPhysicsObject * pPhysics ) ;
void ApplyStressDamage ( IPhysicsObject * pPhysics , bool bRequireLargeObject ) ;
virtual void PushawayTouch ( CBaseEntity * pOther ) { }
void SetImpactEnergyScale ( float fScale ) { m_impactEnergyScale = fScale ; }
virtual void UpdateOnRemove ( void ) ;
virtual Disposition_t IRelationType ( CBaseEntity * pTarget ) ;
virtual int IRelationPriority ( CBaseEntity * pTarget ) ;
virtual void SetLightingOriginRelative ( CBaseEntity * pLightingOrigin ) ;
protected :
Relationship_t * FindEntityRelationship ( CBaseEntity * pTarget ) ;
public :
// Vehicle queries
virtual bool IsInAVehicle ( void ) const { return false ; }
virtual IServerVehicle * GetVehicle ( void ) { return NULL ; }
virtual CBaseEntity * GetVehicleEntity ( void ) { return NULL ; }
virtual bool ExitVehicle ( void ) { return false ; }
// Blood color (see BLOOD_COLOR_* macros in baseentity.h)
void SetBloodColor ( int nBloodColor ) ;
// Weapons..
CBaseCombatWeapon * GetActiveWeapon ( ) const ;
int WeaponCount ( ) const ;
CBaseCombatWeapon * GetWeapon ( int i ) const ;
bool RemoveWeapon ( CBaseCombatWeapon * pWeapon ) ;
virtual void RemoveAllWeapons ( ) ;
WeaponProficiency_t GetCurrentWeaponProficiency ( ) { return m_CurrentWeaponProficiency ; }
void SetCurrentWeaponProficiency ( WeaponProficiency_t iProficiency ) { m_CurrentWeaponProficiency = iProficiency ; }
virtual WeaponProficiency_t CalcWeaponProficiency ( CBaseCombatWeapon * pWeapon ) ;
virtual Vector GetAttackSpread ( CBaseCombatWeapon * pWeapon , CBaseEntity * pTarget = NULL ) ;
virtual float GetSpreadBias ( CBaseCombatWeapon * pWeapon , CBaseEntity * pTarget ) ;
virtual void DoMuzzleFlash ( ) ;
// Interactions
static void InitInteractionSystem ( ) ;
// Relationships
static void AllocateDefaultRelationships ( ) ;
static void SetDefaultRelationship ( Class_T nClass , Class_T nClassTarget , Disposition_t nDisposition , int nPriority ) ;
Disposition_t GetDefaultRelationshipDisposition ( Class_T nClassTarget ) ;
virtual void AddEntityRelationship ( CBaseEntity * pEntity , Disposition_t nDisposition , int nPriority ) ;
virtual bool RemoveEntityRelationship ( CBaseEntity * pEntity ) ;
virtual void AddClassRelationship ( Class_T nClass , Disposition_t nDisposition , int nPriority ) ;
virtual void ChangeTeam ( int iTeamNum ) ;
// Nav hull type
Hull_t GetHullType ( ) const { return m_eHull ; }
void SetHullType ( Hull_t hullType ) { m_eHull = hullType ; }
// FIXME: The following 3 methods are backdoor hack methods
// This is a sort of hack back-door only used by physgun!
void SetAmmoCount ( int iCount , int iAmmoIndex ) ;
// This is a hack to blat out the current active weapon...
// Used by weapon_slam + game_ui
void SetActiveWeapon ( CBaseCombatWeapon * pNewWeapon ) ;
void ClearActiveWeapon ( ) { SetActiveWeapon ( NULL ) ; }
virtual void OnChangeActiveWeapon ( CBaseCombatWeapon * pOldWeapon , CBaseCombatWeapon * pNewWeapon ) { }
// I can't use my current weapon anymore. Switch me to the next best weapon.
bool SwitchToNextBestWeapon ( CBaseCombatWeapon * pCurrent ) ;
// This is a hack to copy the relationship strings used by monstermaker
void SetRelationshipString ( string_t theString ) { m_RelationshipString = theString ; }
float GetNextAttack ( ) const { return m_flNextAttack ; }
void SetNextAttack ( float flWait ) { m_flNextAttack = flWait ; }
bool m_bForceServerRagdoll ;
// Pickup prevention
bool IsAllowedToPickupWeapons ( void ) { return ! m_bPreventWeaponPickup ; }
void SetPreventWeaponPickup ( bool bPrevent ) { m_bPreventWeaponPickup = bPrevent ; }
bool m_bPreventWeaponPickup ;
virtual CNavArea * GetLastKnownArea ( void ) const
{
# ifdef NEXT_BOT
return m_lastNavArea ;
# else
return NULL ;
# endif
} // return the last nav area the player occupied - NULL if unknown
virtual void ClearLastKnownArea ( void ) ;
virtual void UpdateLastKnownArea ( void ) ; // invoke this to update our last known nav area (since there is no think method chained to CBaseCombatCharacter)
virtual void OnNavAreaChanged ( CNavArea * enteredArea , CNavArea * leftArea ) { } // invoked (by UpdateLastKnownArea) when we enter a new nav area (or it is reset to NULL)
virtual bool IsAreaTraversable ( const CNavArea * area ) const ; // return true if we can use the given area
virtual void OnNavAreaRemoved ( CNavArea * removedArea ) ;
// -----------------------
// Notification from INextBots.
// -----------------------
virtual void OnPursuedBy ( INextBot * RESTRICT pPursuer ) { } // called every frame while pursued by a bot in DirectChase.
# ifdef GLOWS_ENABLE
// Glows
void AddGlowEffect ( void ) ;
void RemoveGlowEffect ( void ) ;
bool IsGlowEffectActive ( void ) ;
# endif // GLOWS_ENABLE
# ifdef INVASION_DLL
public :
// TF2 Powerups
virtual bool CanBePoweredUp ( void ) ;
bool HasPowerup ( int iPowerup ) ;
virtual bool CanPowerupNow ( int iPowerup ) ; // Return true if I can be powered by this powerup right now
virtual bool CanPowerupEver ( int iPowerup ) ; // Return true if I ever accept this powerup type
void SetPowerup ( int iPowerup , bool bState , float flTime = 0 , float flAmount = 0 , CBaseEntity * pAttacker = NULL , CDamageModifier * pDamageModifier = NULL ) ;
virtual bool AttemptToPowerup ( int iPowerup , float flTime , float flAmount = 0 , CBaseEntity * pAttacker = NULL , CDamageModifier * pDamageModifier = NULL ) ;
virtual float PowerupDuration ( int iPowerup , float flTime ) ;
virtual void PowerupStart ( int iPowerup , float flAmount = 0 , CBaseEntity * pAttacker = NULL , CDamageModifier * pDamageModifier = NULL ) ;
virtual void PowerupEnd ( int iPowerup ) ;
void PowerupThink ( void ) ;
virtual void PowerupThink ( int iPowerup ) ;
public :
CNetworkVar ( int , m_iPowerups ) ;
float m_flPowerupAttemptTimes [ MAX_POWERUPS ] ;
float m_flPowerupEndTimes [ MAX_POWERUPS ] ;
float m_flFractionalBoost ; // POWERUP_BOOST health fraction - specific powerup data
# endif
public :
// returns the last body region that took damage
int LastHitGroup ( ) const { return m_LastHitGroup ; }
protected :
void SetLastHitGroup ( int nHitGroup ) { m_LastHitGroup = nHitGroup ; }
public :
CNetworkVar ( float , m_flNextAttack ) ; // cannot attack again until this time
# ifdef GLOWS_ENABLE
protected :
CNetworkVar ( bool , m_bGlowEnabled ) ;
# endif // GLOWS_ENABLE
private :
Hull_t m_eHull ;
void UpdateGlowEffect ( void ) ;
void DestroyGlowEffect ( void ) ;
protected :
int m_bloodColor ; // color of blood particless
// -------------------
// combat ability data
// -------------------
float m_flFieldOfView ; // cosine of field of view for this character
Vector m_HackedGunPos ; // HACK until we can query end of gun
string_t m_RelationshipString ; // Used to load up relationship keyvalues
float m_impactEnergyScale ; // scale the amount of energy used to calculate damage this ent takes due to physics
public :
static int GetInteractionID ( ) ; // Returns the next interaction #
protected :
// Visibility-related stuff
bool ComputeLOS ( const Vector & vecEyePosition , const Vector & vecTarget ) const ;
private :
// For weapon strip
void ThrowDirForWeaponStrip ( CBaseCombatWeapon * pWeapon , const Vector & vecForward , Vector * pVecThrowDir ) ;
void DropWeaponForWeaponStrip ( CBaseCombatWeapon * pWeapon , const Vector & vecForward , const QAngle & vecAngles , float flDiameter ) ;
friend class CScriptedTarget ; // needs to access GetInteractionID()
static int m_lastInteraction ; // Last registered interaction #
static Relationship_t * * m_DefaultRelationship ;
// attack/damage
int m_LastHitGroup ; // the last body region that took damage
float m_flDamageAccumulator ; // so very small amounts of damage do not get lost.
int m_iDamageCount ; // # of times NPC has been damaged. used for tracking 1-shot kills.
// Weapon proficiency gets calculated each time an NPC changes his weapon, and then
// cached off as the CurrentWeaponProficiency.
WeaponProficiency_t m_CurrentWeaponProficiency ;
// ---------------
// Relationships
// ---------------
CUtlVector < Relationship_t > m_Relationship ; // Array of relationships
protected :
// shared ammo slots
CNetworkArrayForDerived ( int , m_iAmmo , MAX_AMMO_SLOTS ) ;
// Usable character items
CNetworkArray ( CBaseCombatWeaponHandle , m_hMyWeapons , MAX_WEAPONS ) ;
CNetworkHandle ( CBaseCombatWeapon , m_hActiveWeapon ) ;
friend class CCleanupDefaultRelationShips ;
IntervalTimer m_aliveTimer ;
unsigned int m_hasBeenInjured ; // bitfield corresponding to team ID that did the injury
// we do this because MAX_TEAMS is 32, which is wasteful for most games
enum { MAX_DAMAGE_TEAMS = 4 } ;
struct DamageHistory
{
int team ; // which team hurt us (TEAM_INVALID means slot unused)
IntervalTimer interval ; // how long has it been
} ;
DamageHistory m_damageHistory [ MAX_DAMAGE_TEAMS ] ;
// last known navigation area of player - NULL if unknown
CNavArea * m_lastNavArea ;
CAI_MoveMonitor m_NavAreaUpdateMonitor ;
int m_registeredNavTeam ; // ugly, but needed to clean up player team counts in nav mesh
} ;
inline float CBaseCombatCharacter : : GetAliveDuration ( void ) const
{
return m_aliveTimer . GetElapsedTime ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline int CBaseCombatCharacter : : WeaponCount ( ) const
{
return MAX_WEAPONS ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : i -
//-----------------------------------------------------------------------------
inline CBaseCombatWeapon * CBaseCombatCharacter : : GetWeapon ( int i ) const
{
Assert ( ( i > = 0 ) & & ( i < MAX_WEAPONS ) ) ;
return m_hMyWeapons [ i ] . Get ( ) ;
}
# ifdef INVASION_DLL
// Powerup Inlines
inline bool CBaseCombatCharacter : : CanBePoweredUp ( void ) { return true ; }
inline float CBaseCombatCharacter : : PowerupDuration ( int iPowerup , float flTime ) { return flTime ; }
inline void CBaseCombatCharacter : : PowerupEnd ( int iPowerup ) { return ; }
inline void CBaseCombatCharacter : : PowerupThink ( int iPowerup ) { return ; }
# endif
EXTERN_SEND_TABLE ( DT_BaseCombatCharacter ) ;
void RadiusDamage ( const CTakeDamageInfo & info , const Vector & vecSrc , float flRadius , int iClassIgnore , CBaseEntity * pEntityIgnore ) ;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CTraceFilterMelee : public CTraceFilterEntitiesOnly
{
public :
// It does have a base, but we'll never network anything below here..
DECLARE_CLASS_NOBASE ( CTraceFilterMelee ) ;
CTraceFilterMelee ( const IHandleEntity * passentity , int collisionGroup , CTakeDamageInfo * dmgInfo , float flForceScale , bool bDamageAnyNPC )
: m_pPassEnt ( passentity ) , m_collisionGroup ( collisionGroup ) , m_dmgInfo ( dmgInfo ) , m_pHit ( NULL ) , m_flForceScale ( flForceScale ) , m_bDamageAnyNPC ( bDamageAnyNPC )
{
}
virtual bool ShouldHitEntity ( IHandleEntity * pHandleEntity , int contentsMask ) ;
public :
const IHandleEntity * m_pPassEnt ;
int m_collisionGroup ;
CTakeDamageInfo * m_dmgInfo ;
CBaseEntity * m_pHit ;
float m_flForceScale ;
bool m_bDamageAnyNPC ;
} ;
# endif // BASECOMBATCHARACTER_H