mirror of
https://github.com/rehlds/resemiclip.git
synced 2024-12-27 07:05:52 +03:00
642 lines
21 KiB
C
642 lines
21 KiB
C
|
/*
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License as published by the
|
||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||
|
* your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software Foundation,
|
||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*
|
||
|
* In addition, as a special exception, the author gives permission to
|
||
|
* link the code of this program with the Half-Life Game Engine ("HL
|
||
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||
|
* respects for all of the code used other than the HL Engine and MODs
|
||
|
* from Valve. If you modify this file, you may extend this exception
|
||
|
* to your version of the file, but you are not obligated to do so. If
|
||
|
* you do not wish to do so, delete this exception statement from your
|
||
|
* version.
|
||
|
*
|
||
|
*/
|
||
|
#pragma once
|
||
|
|
||
|
#include "bot/cs_gamestate.h"
|
||
|
#include "bot/cs_bot_manager.h"
|
||
|
#include "bot/cs_bot_chatter.h"
|
||
|
|
||
|
#define PRIMARY_WEAPON_BUY_COUNT 13
|
||
|
#define SECONDARY_WEAPON_BUY_COUNT 3
|
||
|
|
||
|
#define FLAG_PROGRESS_DRAW 0x0 // draw status bar progress
|
||
|
#define FLAG_PROGRESS_START 0x1 // init status bar progress
|
||
|
#define FLAG_PROGRESS_HIDE 0x2 // hide status bar progress
|
||
|
|
||
|
#define HI_X 0x01
|
||
|
#define LO_X 0x02
|
||
|
#define HI_Y 0x04
|
||
|
#define LO_Y 0x08
|
||
|
#define HI_Z 0x10
|
||
|
#define LO_Z 0x20
|
||
|
|
||
|
extern int _navAreaCount;
|
||
|
extern int _currentIndex;
|
||
|
|
||
|
extern struct BuyInfo primaryWeaponBuyInfoCT[PRIMARY_WEAPON_BUY_COUNT];
|
||
|
extern struct BuyInfo secondaryWeaponBuyInfoCT[SECONDARY_WEAPON_BUY_COUNT];
|
||
|
|
||
|
extern struct BuyInfo primaryWeaponBuyInfoT[PRIMARY_WEAPON_BUY_COUNT];
|
||
|
extern struct BuyInfo secondaryWeaponBuyInfoT[SECONDARY_WEAPON_BUY_COUNT];
|
||
|
|
||
|
class CCSBot;
|
||
|
class BotChatterInterface;
|
||
|
|
||
|
class BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const = 0;
|
||
|
};
|
||
|
|
||
|
class IdleState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Idle"; }
|
||
|
};
|
||
|
|
||
|
class HuntState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Hunt"; }
|
||
|
public:
|
||
|
CNavArea *m_huntArea;
|
||
|
};
|
||
|
|
||
|
class AttackState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Attack"; }
|
||
|
public:
|
||
|
enum DodgeStateType
|
||
|
{
|
||
|
STEADY_ON,
|
||
|
SLIDE_LEFT,
|
||
|
SLIDE_RIGHT,
|
||
|
JUMP,
|
||
|
NUM_ATTACK_STATES
|
||
|
} m_dodgeState;
|
||
|
|
||
|
float m_nextDodgeStateTimestamp;
|
||
|
CountdownTimer m_repathTimer;
|
||
|
float m_scopeTimestamp;
|
||
|
bool m_haveSeenEnemy;
|
||
|
bool m_isEnemyHidden;
|
||
|
float m_reacquireTimestamp;
|
||
|
float m_shieldToggleTimestamp;
|
||
|
bool m_shieldForceOpen;
|
||
|
float m_pinnedDownTimestamp;
|
||
|
bool m_crouchAndHold;
|
||
|
bool m_didAmbushCheck;
|
||
|
bool m_dodge;
|
||
|
bool m_firstDodge;
|
||
|
bool m_isCoward;
|
||
|
CountdownTimer m_retreatTimer;
|
||
|
};
|
||
|
|
||
|
class InvestigateNoiseState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "InvestigateNoise"; }
|
||
|
private:
|
||
|
void AttendCurrentNoise(CCSBot *me);
|
||
|
Vector m_checkNoisePosition;
|
||
|
};
|
||
|
|
||
|
class BuyState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Buy"; }
|
||
|
public:
|
||
|
bool m_isInitialDelay;
|
||
|
int m_prefRetries;
|
||
|
int m_prefIndex;
|
||
|
int m_retries;
|
||
|
bool m_doneBuying;
|
||
|
bool m_buyDefuseKit;
|
||
|
bool m_buyGrenade;
|
||
|
bool m_buyShield;
|
||
|
bool m_buyPistol;
|
||
|
};
|
||
|
|
||
|
class MoveToState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "MoveTo"; }
|
||
|
|
||
|
void SetGoalPosition(const Vector &pos) { m_goalPosition = pos; }
|
||
|
void SetRouteType(RouteType route) { m_routeType = route; }
|
||
|
|
||
|
private:
|
||
|
Vector m_goalPosition;
|
||
|
RouteType m_routeType;
|
||
|
bool m_radioedPlan;
|
||
|
bool m_askedForCover;
|
||
|
};
|
||
|
|
||
|
class FetchBombState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "FetchBomb"; }
|
||
|
};
|
||
|
|
||
|
class PlantBombState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "PlantBomb"; }
|
||
|
};
|
||
|
|
||
|
class DefuseBombState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "DefuseBomb"; }
|
||
|
};
|
||
|
|
||
|
class HideState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Hide"; }
|
||
|
|
||
|
public:
|
||
|
void SetHidingSpot(const Vector &pos) { m_hidingSpot = pos; }
|
||
|
const Vector &GetHidingSpot() const { return m_hidingSpot; }
|
||
|
|
||
|
void SetSearchArea(CNavArea *area) { m_searchFromArea = area; }
|
||
|
void SetSearchRange(float range) { m_range = range; }
|
||
|
|
||
|
void SetDuration(float time) { m_duration = time; }
|
||
|
void SetHoldPosition(bool hold) { m_isHoldingPosition = hold; }
|
||
|
|
||
|
bool IsAtSpot() const { return m_isAtSpot; }
|
||
|
|
||
|
public:
|
||
|
CNavArea *m_searchFromArea;
|
||
|
float m_range;
|
||
|
|
||
|
Vector m_hidingSpot;
|
||
|
bool m_isAtSpot;
|
||
|
float m_duration;
|
||
|
bool m_isHoldingPosition;
|
||
|
float m_holdPositionTime;
|
||
|
bool m_heardEnemy;
|
||
|
|
||
|
float m_firstHeardEnemyTime;
|
||
|
int m_retry;
|
||
|
Vector m_leaderAnchorPos;
|
||
|
};
|
||
|
|
||
|
class EscapeFromBombState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "EscapeFromBomb"; }
|
||
|
};
|
||
|
|
||
|
class FollowState: public BotState
|
||
|
{
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "Follow"; }
|
||
|
|
||
|
void SetLeader(CBaseEntity *leader) { m_leader = leader; }
|
||
|
|
||
|
public:
|
||
|
EHANDLE m_leader;
|
||
|
Vector m_lastLeaderPos;
|
||
|
bool m_isStopped;
|
||
|
float m_stoppedTimestamp;
|
||
|
|
||
|
enum LeaderMotionStateType
|
||
|
{
|
||
|
INVALID,
|
||
|
STOPPED,
|
||
|
WALKING,
|
||
|
RUNNING
|
||
|
|
||
|
} m_leaderMotionState;
|
||
|
|
||
|
IntervalTimer m_leaderMotionStateTime;
|
||
|
|
||
|
bool m_isSneaking;
|
||
|
float m_lastSawLeaderTime;
|
||
|
CountdownTimer m_repathInterval;
|
||
|
|
||
|
IntervalTimer m_walkTime;
|
||
|
bool m_isAtWalkSpeed;
|
||
|
|
||
|
float m_waitTime;
|
||
|
CountdownTimer m_idleTimer;
|
||
|
};
|
||
|
|
||
|
class UseEntityState: public BotState {
|
||
|
public:
|
||
|
virtual void OnEnter(CCSBot *me) {}
|
||
|
virtual void OnUpdate(CCSBot *me) {}
|
||
|
virtual void OnExit(CCSBot *me) {}
|
||
|
virtual const char *GetName() const { return "UseEntity"; }
|
||
|
|
||
|
void SetEntity(CBaseEntity *entity) { m_entity = entity; }
|
||
|
|
||
|
private:
|
||
|
EHANDLE m_entity;
|
||
|
};
|
||
|
|
||
|
// The Counter-strike Bot
|
||
|
class CCSBot: public CBot {
|
||
|
public:
|
||
|
virtual BOOL TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) = 0; // invoked when injured by something (EXTEND) - returns the amount of damage inflicted
|
||
|
virtual void Killed(entvars_t *pevAttacker, int iGib) = 0; // invoked when killed (EXTEND)
|
||
|
virtual void RoundRespawn() = 0;
|
||
|
virtual void Blind(float duration, float holdTime, float fadeTime, int alpha = 255) = 0; // player blinded by a flashbang
|
||
|
virtual void OnTouchingWeapon(CWeaponBox *box) = 0; // invoked when in contact with a CWeaponBox
|
||
|
|
||
|
virtual bool Initialize(const BotProfile *profile) = 0; // (EXTEND) prepare bot for action
|
||
|
virtual void SpawnBot() = 0; // (EXTEND) spawn the bot into the game
|
||
|
|
||
|
virtual void Upkeep() = 0; // lightweight maintenance, invoked frequently
|
||
|
virtual void Update() = 0; // heavyweight algorithms, invoked less often
|
||
|
|
||
|
virtual void Walk() = 0;
|
||
|
virtual bool Jump(bool mustJump = false) = 0; // returns true if jump was started
|
||
|
|
||
|
virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL) = 0; // invoked when event occurs in the game (some events have NULL entity)
|
||
|
|
||
|
#define CHECK_FOV true
|
||
|
virtual bool IsVisible(const Vector *pos, bool testFOV = false) const = 0; // return true if we can see the point
|
||
|
virtual bool IsVisible(CBasePlayer *player, bool testFOV = false, unsigned char *visParts = NULL) const = 0; // return true if we can see any part of the player
|
||
|
|
||
|
virtual bool IsEnemyPartVisible(VisiblePartType part) const = 0; // if enemy is visible, return the part we see for our current enemy
|
||
|
|
||
|
public:
|
||
|
const Vector &GetEyePosition() const
|
||
|
{
|
||
|
m_eyePos = pev->origin + pev->view_ofs;
|
||
|
return m_eyePos;
|
||
|
}
|
||
|
public:
|
||
|
friend class CCSBotManager;
|
||
|
|
||
|
// TODO: Get rid of these
|
||
|
friend class AttackState;
|
||
|
friend class BuyState;
|
||
|
|
||
|
char m_name[64]; // copied from STRING(pev->netname) for debugging
|
||
|
|
||
|
// behavior properties
|
||
|
float m_combatRange; // desired distance between us and them during gunplay
|
||
|
mutable bool m_isRogue; // if true, the bot is a "rogue" and listens to no-one
|
||
|
mutable CountdownTimer m_rogueTimer;
|
||
|
|
||
|
enum MoraleType
|
||
|
{
|
||
|
TERRIBLE = -3,
|
||
|
BAD = -2,
|
||
|
NEGATIVE = -1,
|
||
|
NEUTRAL = 0,
|
||
|
POSITIVE = 1,
|
||
|
GOOD = 2,
|
||
|
EXCELLENT = 3,
|
||
|
};
|
||
|
|
||
|
MoraleType m_morale; // our current morale, based on our win/loss history
|
||
|
bool m_diedLastRound; // true if we died last round
|
||
|
float m_safeTime; // duration at the beginning of the round where we feel "safe"
|
||
|
bool m_wasSafe; // true if we were in the safe time last update
|
||
|
NavRelativeDirType m_blindMoveDir; // which way to move when we're blind
|
||
|
bool m_blindFire; // if true, fire weapon while blinded
|
||
|
|
||
|
// TODO: implement through CountdownTimer
|
||
|
float m_surpriseDelay; // when we were surprised
|
||
|
float m_surpriseTimestamp;
|
||
|
|
||
|
bool m_isFollowing; // true if we are following someone
|
||
|
EHANDLE m_leader; // the ID of who we are following
|
||
|
float m_followTimestamp; // when we started following
|
||
|
float m_allowAutoFollowTime; // time when we can auto follow
|
||
|
|
||
|
CountdownTimer m_hurryTimer; // if valid, bot is in a hurry
|
||
|
|
||
|
// instances of each possible behavior state, to avoid dynamic memory allocation during runtime
|
||
|
IdleState m_idleState;
|
||
|
HuntState m_huntState;
|
||
|
AttackState m_attackState;
|
||
|
InvestigateNoiseState m_investigateNoiseState;
|
||
|
BuyState m_buyState;
|
||
|
MoveToState m_moveToState;
|
||
|
FetchBombState m_fetchBombState;
|
||
|
PlantBombState m_plantBombState;
|
||
|
DefuseBombState m_defuseBombState;
|
||
|
HideState m_hideState;
|
||
|
EscapeFromBombState m_escapeFromBombState;
|
||
|
FollowState m_followState;
|
||
|
UseEntityState m_useEntityState;
|
||
|
|
||
|
// TODO: Allow multiple simultaneous state machines (look around, etc)
|
||
|
BotState *m_state; // current behavior state
|
||
|
float m_stateTimestamp; // time state was entered
|
||
|
bool m_isAttacking; // if true, special Attack state is overriding the state machine
|
||
|
|
||
|
// high-level tasks
|
||
|
enum TaskType
|
||
|
{
|
||
|
SEEK_AND_DESTROY,
|
||
|
PLANT_BOMB,
|
||
|
FIND_TICKING_BOMB,
|
||
|
DEFUSE_BOMB,
|
||
|
GUARD_TICKING_BOMB,
|
||
|
GUARD_BOMB_DEFUSER,
|
||
|
GUARD_LOOSE_BOMB,
|
||
|
GUARD_BOMB_ZONE,
|
||
|
ESCAPE_FROM_BOMB,
|
||
|
HOLD_POSITION,
|
||
|
FOLLOW,
|
||
|
VIP_ESCAPE,
|
||
|
GUARD_VIP_ESCAPE_ZONE,
|
||
|
COLLECT_HOSTAGES,
|
||
|
RESCUE_HOSTAGES,
|
||
|
GUARD_HOSTAGES,
|
||
|
GUARD_HOSTAGE_RESCUE_ZONE,
|
||
|
MOVE_TO_LAST_KNOWN_ENEMY_POSITION,
|
||
|
MOVE_TO_SNIPER_SPOT,
|
||
|
SNIPING,
|
||
|
|
||
|
NUM_TASKS
|
||
|
};
|
||
|
TaskType m_task; // our current task
|
||
|
EHANDLE m_taskEntity; // an entity used for our task
|
||
|
|
||
|
// navigation
|
||
|
Vector m_goalPosition;
|
||
|
EHANDLE m_goalEntity;
|
||
|
|
||
|
CNavArea *m_currentArea; // the nav area we are standing on
|
||
|
CNavArea *m_lastKnownArea; // the last area we were in
|
||
|
EHANDLE m_avoid; // higher priority player we need to make way for
|
||
|
float m_avoidTimestamp;
|
||
|
bool m_isJumpCrouching;
|
||
|
bool m_isJumpCrouched;
|
||
|
float m_jumpCrouchTimestamp;
|
||
|
|
||
|
// path navigation data
|
||
|
enum { _MAX_PATH_LENGTH = 256 };
|
||
|
struct ConnectInfo
|
||
|
{
|
||
|
CNavArea *area; // the area along the path
|
||
|
NavTraverseType how; // how to enter this area from the previous one
|
||
|
Vector pos; // our movement goal position at this point in the path
|
||
|
const CNavLadder *ladder; // if "how" refers to a ladder, this is it
|
||
|
}
|
||
|
m_path[_MAX_PATH_LENGTH];
|
||
|
int m_pathLength;
|
||
|
int m_pathIndex;
|
||
|
float m_areaEnteredTimestamp;
|
||
|
|
||
|
CountdownTimer m_repathTimer; // must have elapsed before bot can pathfind again
|
||
|
|
||
|
mutable CountdownTimer m_avoidFriendTimer; // used to throttle how often we check for friends in our path
|
||
|
mutable bool m_isFriendInTheWay; // true if a friend is blocking our path
|
||
|
CountdownTimer m_politeTimer; // we'll wait for friend to move until this runs out
|
||
|
bool m_isWaitingBehindFriend; // true if we are waiting for a friend to move
|
||
|
|
||
|
enum LadderNavState
|
||
|
{
|
||
|
APPROACH_ASCENDING_LADDER, // prepare to scale a ladder
|
||
|
APPROACH_DESCENDING_LADDER, // prepare to go down ladder
|
||
|
FACE_ASCENDING_LADDER,
|
||
|
FACE_DESCENDING_LADDER,
|
||
|
MOUNT_ASCENDING_LADDER, // move toward ladder until "on" it
|
||
|
MOUNT_DESCENDING_LADDER, // move toward ladder until "on" it
|
||
|
ASCEND_LADDER, // go up the ladder
|
||
|
DESCEND_LADDER, // go down the ladder
|
||
|
DISMOUNT_ASCENDING_LADDER, // get off of the ladder
|
||
|
DISMOUNT_DESCENDING_LADDER, // get off of the ladder
|
||
|
MOVE_TO_DESTINATION, // dismount ladder and move to destination area
|
||
|
}
|
||
|
m_pathLadderState;
|
||
|
bool m_pathLadderFaceIn; // if true, face towards ladder, otherwise face away
|
||
|
const CNavLadder *m_pathLadder; // the ladder we need to use to reach the next area
|
||
|
NavRelativeDirType m_pathLadderDismountDir; // which way to dismount
|
||
|
float m_pathLadderDismountTimestamp; // time when dismount started
|
||
|
float m_pathLadderEnd; // if ascending, z of top, if descending z of bottom
|
||
|
float m_pathLadderTimestamp; // time when we started using ladder - for timeout check
|
||
|
|
||
|
CountdownTimer m_mustRunTimer; // if nonzero, bot cannot walk
|
||
|
|
||
|
// game scenario mechanisms
|
||
|
CSGameState m_gameState;
|
||
|
|
||
|
// hostages mechanism
|
||
|
byte m_hostageEscortCount;
|
||
|
float m_hostageEscortCountTimestamp;
|
||
|
bool m_isWaitingForHostage;
|
||
|
CountdownTimer m_inhibitWaitingForHostageTimer;
|
||
|
CountdownTimer m_waitForHostageTimer;
|
||
|
|
||
|
// listening mechanism
|
||
|
Vector m_noisePosition; // position we last heard non-friendly noise
|
||
|
float m_noiseTimestamp; // when we heard it (can get zeroed)
|
||
|
CNavArea *m_noiseArea; // the nav area containing the noise
|
||
|
float m_noiseCheckTimestamp;
|
||
|
PriorityType m_noisePriority; // priority of currently heard noise
|
||
|
bool m_isNoiseTravelRangeChecked;
|
||
|
|
||
|
// "looking around" mechanism
|
||
|
float m_lookAroundStateTimestamp; // time of next state change
|
||
|
float m_lookAheadAngle; // our desired forward look angle
|
||
|
float m_forwardAngle; // our current forward facing direction
|
||
|
float m_inhibitLookAroundTimestamp; // time when we can look around again
|
||
|
|
||
|
enum LookAtSpotState
|
||
|
{
|
||
|
NOT_LOOKING_AT_SPOT, // not currently looking at a point in space
|
||
|
LOOK_TOWARDS_SPOT, // in the process of aiming at m_lookAtSpot
|
||
|
LOOK_AT_SPOT, // looking at m_lookAtSpot
|
||
|
NUM_LOOK_AT_SPOT_STATES
|
||
|
}
|
||
|
m_lookAtSpotState;
|
||
|
Vector m_lookAtSpot; // the spot we're currently looking at
|
||
|
PriorityType m_lookAtSpotPriority;
|
||
|
float m_lookAtSpotDuration; // how long we need to look at the spot
|
||
|
float m_lookAtSpotTimestamp; // when we actually began looking at the spot
|
||
|
float m_lookAtSpotAngleTolerance; // how exactly we must look at the spot
|
||
|
bool m_lookAtSpotClearIfClose; // if true, the look at spot is cleared if it gets close to us
|
||
|
const char *m_lookAtDesc; // for debugging
|
||
|
float m_peripheralTimestamp;
|
||
|
|
||
|
enum { MAX_APPROACH_POINTS = 16 };
|
||
|
Vector m_approachPoint[MAX_APPROACH_POINTS];
|
||
|
unsigned char m_approachPointCount;
|
||
|
Vector m_approachPointViewPosition; // the position used when computing current approachPoint set
|
||
|
bool m_isWaitingToTossGrenade; // lining up throw
|
||
|
CountdownTimer m_tossGrenadeTimer; // timeout timer for grenade tossing
|
||
|
|
||
|
SpotEncounter *m_spotEncounter; // the spots we will encounter as we move thru our current area
|
||
|
float m_spotCheckTimestamp; // when to check next encounter spot
|
||
|
|
||
|
// TODO: Add timestamp for each possible client to hiding spots
|
||
|
enum { MAX_CHECKED_SPOTS = 64 };
|
||
|
struct HidingSpotCheckInfo
|
||
|
{
|
||
|
HidingSpot *spot;
|
||
|
float timestamp;
|
||
|
}
|
||
|
m_checkedHidingSpot[MAX_CHECKED_SPOTS];
|
||
|
int m_checkedHidingSpotCount;
|
||
|
|
||
|
// view angle mechanism
|
||
|
float m_lookPitch; // our desired look pitch angle
|
||
|
float m_lookPitchVel;
|
||
|
float m_lookYaw; // our desired look yaw angle
|
||
|
float m_lookYawVel;
|
||
|
|
||
|
// aim angle mechanism
|
||
|
mutable Vector m_eyePos;
|
||
|
Vector m_aimOffset; // current error added to victim's position to get actual aim spot
|
||
|
Vector m_aimOffsetGoal; // desired aim offset
|
||
|
float m_aimOffsetTimestamp; // time of next offset adjustment
|
||
|
float m_aimSpreadTimestamp; // time used to determine max spread as it begins to tighten up
|
||
|
Vector m_aimSpot; // the spot we are currently aiming to fire at
|
||
|
|
||
|
// attack state data
|
||
|
// behavior modifiers
|
||
|
enum DispositionType
|
||
|
{
|
||
|
ENGAGE_AND_INVESTIGATE, // engage enemies on sight and investigate enemy noises
|
||
|
OPPORTUNITY_FIRE, // engage enemies on sight, but only look towards enemy noises, dont investigate
|
||
|
SELF_DEFENSE, // only engage if fired on, or very close to enemy
|
||
|
IGNORE_ENEMIES, // ignore all enemies - useful for ducking around corners, running away, etc
|
||
|
|
||
|
NUM_DISPOSITIONS
|
||
|
};
|
||
|
DispositionType m_disposition; // how we will react to enemies
|
||
|
CountdownTimer m_ignoreEnemiesTimer; // how long will we ignore enemies
|
||
|
mutable EHANDLE m_enemy; // our current enemy
|
||
|
bool m_isEnemyVisible; // result of last visibility test on enemy
|
||
|
unsigned char m_visibleEnemyParts; // which parts of the visible enemy do we see
|
||
|
Vector m_lastEnemyPosition; // last place we saw the enemy
|
||
|
float m_lastSawEnemyTimestamp;
|
||
|
float m_firstSawEnemyTimestamp;
|
||
|
float m_currentEnemyAcquireTimestamp;
|
||
|
float m_enemyDeathTimestamp; // if m_enemy is dead, this is when he died
|
||
|
bool m_isLastEnemyDead; // true if we killed or saw our last enemy die
|
||
|
int m_nearbyEnemyCount; // max number of enemies we've seen recently
|
||
|
unsigned int m_enemyPlace; // the location where we saw most of our enemies
|
||
|
|
||
|
struct WatchInfo
|
||
|
{
|
||
|
float timestamp;
|
||
|
bool isEnemy;
|
||
|
}
|
||
|
m_watchInfo[MAX_CLIENTS];
|
||
|
mutable EHANDLE m_bomber; // points to bomber if we can see him
|
||
|
|
||
|
int m_nearbyFriendCount; // number of nearby teammates
|
||
|
mutable EHANDLE m_closestVisibleFriend; // the closest friend we can see
|
||
|
mutable EHANDLE m_closestVisibleHumanFriend; // the closest human friend we can see
|
||
|
|
||
|
CBasePlayer *m_attacker; // last enemy that hurt us (may not be same as m_enemy)
|
||
|
float m_attackedTimestamp; // when we were hurt by the m_attacker
|
||
|
|
||
|
int m_lastVictimID; // the entindex of the last victim we killed, or zero
|
||
|
bool m_isAimingAtEnemy; // if true, we are trying to aim at our enemy
|
||
|
bool m_isRapidFiring; // if true, RunUpkeep() will toggle our primary attack as fast as it can
|
||
|
IntervalTimer m_equipTimer; // how long have we had our current weapon equipped
|
||
|
float m_fireWeaponTimestamp;
|
||
|
|
||
|
// reaction time system
|
||
|
enum { MAX_ENEMY_QUEUE = 20 };
|
||
|
struct ReactionState
|
||
|
{
|
||
|
// NOTE: player position & orientation is not currently stored separately
|
||
|
EHANDLE player;
|
||
|
bool isReloading;
|
||
|
bool isProtectedByShield;
|
||
|
}
|
||
|
m_enemyQueue[MAX_ENEMY_QUEUE]; // round-robin queue for simulating reaction times
|
||
|
|
||
|
byte m_enemyQueueIndex;
|
||
|
byte m_enemyQueueCount;
|
||
|
byte m_enemyQueueAttendIndex; // index of the timeframe we are "conscious" of
|
||
|
|
||
|
// stuck detection
|
||
|
bool m_isStuck;
|
||
|
float m_stuckTimestamp; // time when we got stuck
|
||
|
Vector m_stuckSpot; // the location where we became stuck
|
||
|
NavRelativeDirType m_wiggleDirection;
|
||
|
float m_wiggleTimestamp;
|
||
|
float m_stuckJumpTimestamp; // time for next jump when stuck
|
||
|
|
||
|
enum { MAX_VEL_SAMPLES = 5 };
|
||
|
float m_avgVel[MAX_VEL_SAMPLES];
|
||
|
int m_avgVelIndex;
|
||
|
int m_avgVelCount;
|
||
|
Vector m_lastOrigin;
|
||
|
|
||
|
// chatter mechanism
|
||
|
GameEventType m_lastRadioCommand; // last radio command we recieved
|
||
|
|
||
|
float m_lastRadioRecievedTimestamp; // time we recieved a radio message
|
||
|
float m_lastRadioSentTimestamp; // time when we send a radio message
|
||
|
EHANDLE m_radioSubject; // who issued the radio message
|
||
|
Vector m_radioPosition; // position referred to in radio message
|
||
|
float m_voiceFeedbackStartTimestamp;
|
||
|
float m_voiceFeedbackEndTimestamp; // new-style "voice" chatter gets voice feedback
|
||
|
BotChatterInterface m_chatter;
|
||
|
|
||
|
// learn map mechanism
|
||
|
const CNavNode *m_navNodeList;
|
||
|
CNavNode *m_currentNode;
|
||
|
NavDirType m_generationDir;
|
||
|
NavAreaList::iterator m_analyzeIter;
|
||
|
|
||
|
enum ProcessType
|
||
|
{
|
||
|
PROCESS_NORMAL,
|
||
|
PROCESS_LEARN,
|
||
|
PROCESS_ANALYZE_ALPHA,
|
||
|
PROCESS_ANALYZE_BETA,
|
||
|
PROCESS_SAVE,
|
||
|
}
|
||
|
m_processMode;
|
||
|
CountdownTimer m_mumbleTimer;
|
||
|
CountdownTimer m_booTimer;
|
||
|
CountdownTimer m_relocateTimer;
|
||
|
};
|