//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: Base combat character with no AI // // $NoKeywords: $ //=============================================================================// #ifndef BASECOMBATCHARACTER_H #define BASECOMBATCHARACTER_H #include #include "weapon_proficiency.h" #ifdef _WIN32 #pragma once #endif #ifdef INVASION_DLL #include "tf_shareddefs.h" #define POWERUP_THINK_CONTEXT "PowerupThink" #endif #include "ai_hull.h" #include "ai_utils.h" #include "baseentity.h" #include "baseflex.h" #include "cbase.h" #include "damagemodifier.h" #include "physics_impact_damage.h" #include "utllinkedlist.h" class CNavArea; class CScriptedTarget; typedef CHandle 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 { return m_lastNavArea; } // return the last nav area the player occupied - NULL if unknown virtual bool IsAreaTraversable(const CNavArea *area) const; // return true if we can use the given area 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 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 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