750 lines
30 KiB
C++
750 lines
30 KiB
C++
//========= 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 "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<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 {
|
|
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<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
|