yapb-noob-edition/inc/yapb.h

1193 lines
37 KiB
C++

//
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
// Copyright © 2004-2022 YaPB Project <yapb@jeefo.net>.
//
// SPDX-License-Identifier: MIT
//
#pragma once
#include <hlsdk/extdll.h>
#include <hlsdk/metamod.h>
#include <hlsdk/physint.h>
#include <crlib/crlib.h>
// use all the cr-library
using namespace cr;
#include <product.h>
#include <module.h>
// forwards
class Bot;
class BotGraph;
class BotManager;
// defines bots tasks
CR_DECLARE_SCOPED_ENUM (Task,
Normal = 0,
Pause,
MoveToPosition,
FollowUser,
PickupItem,
Camp,
PlantBomb,
DefuseBomb,
Attack,
Hunt,
SeekCover,
ThrowExplosive,
ThrowFlashbang,
ThrowSmoke,
DoubleJump,
EscapeFromBomb,
ShootBreakable,
Hide,
Blind,
Spraypaint,
)
// bot menu ids
CR_DECLARE_SCOPED_ENUM (Menu,
None = 0,
Main,
Features,
Control,
WeaponMode,
Personality,
Difficulty,
TeamSelect,
TerroristSelect,
CTSelect,
Commands,
NodeMainPage1,
NodeMainPage2,
NodeRadius,
NodeType,
NodeFlag,
NodeAutoPath,
NodePath,
KickPage1,
KickPage2,
KickPage3,
KickPage4
)
// bomb say string
CR_DECLARE_SCOPED_ENUM (BombPlantedSay,
ChatSay = cr::bit (1),
Chatter = cr::bit (2)
)
// chat types id's
CR_DECLARE_SCOPED_ENUM (Chat,
Kill = 0, // id to kill chat array
Dead, // id to dead chat array
Plant, // id to bomb chat array
TeamAttack, // id to team-attack chat array
TeamKill, // id to team-kill chat array
Hello, // id to welcome chat array
NoKeyword, // id to no keyword chat array
Count // number for array
)
// personalities defines
CR_DECLARE_SCOPED_ENUM (Personality,
Normal = 0,
Rusher,
Careful,
Invalid = -1
)
// bot difficulties
CR_DECLARE_SCOPED_ENUM (Difficulty,
Noob,
Easy,
Normal,
Hard,
Expert,
Invalid = -1
)
// collision states
CR_DECLARE_SCOPED_ENUM (CollisionState,
Undecided,
Probing,
NoMove,
Jump,
Duck,
StrafeLeft,
StrafeRight
)
// counter-strike team id's
CR_DECLARE_SCOPED_ENUM (Team,
Terrorist = 0,
CT,
Spectator,
Unassigned,
Invalid = -1
)
// item status for StatusIcon message
CR_DECLARE_SCOPED_ENUM (ItemStatus,
Nightvision = cr::bit (0),
DefusalKit = cr::bit (1)
)
// client flags
CR_DECLARE_SCOPED_ENUM (ClientFlags,
Used = cr::bit (0),
Alive = cr::bit (1),
Admin = cr::bit (2),
Icon = cr::bit (3)
)
// bot create status
CR_DECLARE_SCOPED_ENUM (BotCreateResult,
Success,
MaxPlayersReached,
GraphError,
TeamStacked
)
// radio messages
CR_DECLARE_SCOPED_ENUM (Radio,
CoverMe = 1,
YouTakeThePoint = 2,
HoldThisPosition = 3,
RegroupTeam = 4,
FollowMe = 5,
TakingFireNeedAssistance = 6,
GoGoGo = 11,
TeamFallback = 12,
StickTogetherTeam = 13,
GetInPositionAndWaitForGo = 14,
StormTheFront = 15,
ReportInTeam = 16,
RogerThat = 21,
EnemySpotted = 22,
NeedBackup = 23,
SectorClear = 24,
ImInPosition = 25,
ReportingIn = 26,
ShesGonnaBlow = 27,
Negative = 28,
EnemyDown = 29
)
// chatter system (extending enum above, messages 30-39 is reserved)
CR_DECLARE_SCOPED_ENUM (Chatter,
SpotTheBomber = 40,
FriendlyFire,
DiePain,
Blind,
GoingToPlantBomb,
RescuingHostages,
GoingToCamp,
HeardNoise,
TeamAttack,
ReportingIn,
GuardingDroppedC4,
Camping,
PlantingBomb,
DefusingBomb,
InCombat,
SeekingEnemies,
Nothing,
EnemyDown,
UsingHostages,
FoundC4,
WonTheRound,
ScaredEmotion,
HeardTheEnemy,
SniperWarning,
SniperKilled,
VIPSpotted,
GuardingVIPSafety,
GoingToGuardVIPSafety,
QuickWonRound,
OneEnemyLeft,
TwoEnemiesLeft,
ThreeEnemiesLeft,
NoEnemiesLeft,
FoundC4Plant,
WhereIsTheC4,
DefendingBombsite,
BarelyDefused,
NiceShotCommander,
NiceShotPall,
GoingToGuardHostages,
GoingToGuardDroppedC4,
OnMyWay,
LeadOnSir,
PinnedDown,
GottaFindC4,
YouHeardTheMan,
LostCommander,
NewRound,
CoverMe,
BehindSmoke,
BombsiteSecured,
Count
)
// counter strike weapon classes (types)
CR_DECLARE_SCOPED_ENUM (WeaponType,
None,
Melee,
Pistol,
Shotgun,
ZoomRifle,
Rifle,
SMG,
Sniper,
Heavy
)
// counter-strike weapon id's
CR_DECLARE_SCOPED_ENUM (Weapon,
P228 = 1,
Shield = 2,
Scout = 3,
Explosive = 4,
XM1014 = 5,
C4 = 6,
MAC10 = 7,
AUG = 8,
Smoke = 9,
Elite = 10,
FiveSeven = 11,
UMP45 = 12,
SG550 = 13,
Galil = 14,
Famas = 15,
USP = 16,
Glock18 = 17,
AWP = 18,
MP5 = 19,
M249 = 20,
M3 = 21,
M4A1 = 22,
TMP = 23,
G3SG1 = 24,
Flashbang = 25,
Deagle = 26,
SG552 = 27,
AK47 = 28,
Knife = 29,
P90 = 30,
Armor = 31,
ArmorHelm = 32,
Defuser = 33
)
// buy counts
CR_DECLARE_SCOPED_ENUM (BuyState,
PrimaryWeapon = 0,
ArmorVestHelm,
SecondaryWeapon,
Ammo,
DefusalKit,
Grenades,
NightVision,
Done
)
// economics limits
CR_DECLARE_SCOPED_ENUM (EcoLimit,
PrimaryGreater = 0,
SmgCTGreater,
SmgTEGreater,
ShotgunGreater,
ShotgunLess,
HeavyGreater,
HeavyLess,
ProstockNormal,
ProstockRusher,
ProstockCareful,
ShieldGreater
)
// defines for pickup items
CR_DECLARE_SCOPED_ENUM (Pickup,
None = 0,
Weapon,
DroppedC4,
PlantedC4,
Hostage,
Button,
Shield,
DefusalKit
)
// fight style type
CR_DECLARE_SCOPED_ENUM (Fight,
None = 0,
Strafe,
Stay
)
// dodge type
CR_DECLARE_SCOPED_ENUM (Dodge,
None = 0,
Left,
Right
)
// reload state
CR_DECLARE_SCOPED_ENUM (Reload,
None = 0, // no reload state currently
Primary, // primary weapon reload state
Secondary // secondary weapon reload state
)
// collision probes
CR_DECLARE_SCOPED_ENUM (CollisionProbe,
Jump = cr::bit (0), // probe jump when colliding
Duck = cr::bit (1), // probe duck when colliding
Strafe = cr::bit (2) // probe strafing when colliding
)
// game start messages for counter-strike...
CR_DECLARE_SCOPED_ENUM (BotMsg,
None = 1,
TeamSelect = 2,
ClassSelect = 3,
Buy = 100,
Radio = 200,
Say = 10000,
SayTeam = 10001
)
// sensing states
CR_DECLARE_SCOPED_ENUM (Sense,
SeeingEnemy = cr::bit (0), // seeing an enemy
HearingEnemy = cr::bit (1), // hearing an enemy
SuspectEnemy = cr::bit (2), // suspect enemy behind obstacle
PickupItem = cr::bit (3), // pickup item nearby
ThrowExplosive = cr::bit (4), // could throw he grenade
ThrowFlashbang = cr::bit (5), // could throw flashbang
ThrowSmoke = cr::bit (6) // could throw smokegrenade
)
// positions to aim at
CR_DECLARE_SCOPED_ENUM (AimFlags,
Nav = cr::bit (0), // aim at nav point
Camp = cr::bit (1), // aim at camp vector
PredictPath = cr::bit (2), // aim at predicted path
LastEnemy = cr::bit (3), // aim at last enemy
Entity = cr::bit (4), // aim at entity like buttons, hostages
Enemy = cr::bit (5), // aim at enemy
Grenade = cr::bit (6), // aim for grenade throw
Override = cr::bit (7), // overrides all others (blinded)
Danger = cr::bit (8) // additional danger falg
)
// famas/glock burst mode status + m4a1/usp silencer
CR_DECLARE_SCOPED_ENUM (BurstMode,
On = cr::bit (0),
Off = cr::bit (1)
)
// visibility flags
CR_DECLARE_SCOPED_ENUM (Visibility,
Head = cr::bit (1),
Body = cr::bit (2),
Other = cr::bit (3),
None = 0
)
// channel for skip traceline
CR_DECLARE_SCOPED_ENUM (TraceChannel,
Enemy = 0,
Body,
Num
)
// frustum sides
CR_DECLARE_SCOPED_ENUM (FrustumSide,
Top = 0,
Bottom,
Left,
Right,
Near,
Far,
Num
)
// some hardcoded desire defines used to override calculated ones
namespace TaskPri {
static constexpr float Normal { 35.0f };
static constexpr float Pause { 36.0f };
static constexpr float Camp { 37.0f };
static constexpr float Spraypaint { 38.0f };
static constexpr float FollowUser { 39.0f };
static constexpr float MoveToPosition { 50.0f };
static constexpr float DefuseBomb { 89.0f };
static constexpr float PlantBomb { 89.0f };
static constexpr float Attack { 90.0f };
static constexpr float SeekCover { 91.0f };
static constexpr float Hide { 92.0f };
static constexpr float Throw { 99.0f };
static constexpr float DoubleJump { 99.0f };
static constexpr float Blind { 100.0f };
static constexpr float ShootBreakable { 100.0f };
static constexpr float EscapeFromBomb { 100.0f };
}
// storage file magic
constexpr char kPodbotMagic[8] = "PODWAY!";
constexpr int32 kStorageMagic = 0x59415042; // storage magic for yapb-data files
constexpr int32 kStorageMagicUB = 0x544f4255; //support also the fork format (merged back into yapb)
constexpr float kInfiniteDistance = 9999999.0f;
constexpr float kGrenadeCheckTime = 2.15f;
constexpr float kSprayDistance = 260.0f;
constexpr float kDoubleSprayDistance = kSprayDistance * 2;
constexpr float kMaxChatterRepeatInteval = 99.0f;
constexpr int kInfiniteDistanceLong = static_cast <int> (kInfiniteDistance);
constexpr int kMaxNodeLinks = 8;
constexpr int kMaxPracticeDamageValue = 2040;
constexpr int kMaxPracticeGoalValue = 2040;
constexpr int kMaxNodes = 2048;
constexpr int kMaxWeapons = 32;
constexpr int kNumWeapons = 26;
constexpr int kMaxCollideMoves = 3;
constexpr int kGameMaxPlayers = 32;
constexpr int kGameTeamNum = 2;
constexpr int kInvalidNodeIndex = -1;
constexpr int kMaxBucketSize = static_cast <int> (kMaxNodes * 0.65);
constexpr int kMaxBucketsInsidePos = kMaxNodes * 8 / kMaxBucketSize + 1;
constexpr int kMaxNodesInsideBucket = kMaxBucketSize / kMaxBucketsInsidePos;
// weapon masks
constexpr auto kPrimaryWeaponMask = (cr::bit (Weapon::XM1014) | cr::bit (Weapon::M3) | cr::bit (Weapon::MAC10) | cr::bit (Weapon::UMP45) | cr::bit (Weapon::MP5) | cr::bit (Weapon::TMP) | cr::bit (Weapon::P90) | cr::bit (Weapon::AUG) | cr::bit (Weapon::M4A1) | cr::bit (Weapon::SG552) | cr::bit (Weapon::AK47) | cr::bit (Weapon::Scout) | cr::bit (Weapon::SG550) | cr::bit (Weapon::AWP) | cr::bit (Weapon::G3SG1) | cr::bit (Weapon::M249) | cr::bit (Weapon::Famas) | cr::bit (Weapon::Galil));
constexpr auto kSecondaryWeaponMask = (cr::bit (Weapon::P228) | cr::bit (Weapon::Elite) | cr::bit (Weapon::USP) | cr::bit (Weapon::Glock18) | cr::bit (Weapon::Deagle) | cr::bit (Weapon::FiveSeven));
// links keywords and replies together
struct Keywords {
StringArray keywords;
StringArray replies;
StringArray usedReplies;
public:
Keywords () = default;
Keywords (const StringArray &keywords, const StringArray &replies) {
this->keywords.clear ();
this->replies.clear ();
this->usedReplies.clear ();
this->keywords.insert (0, keywords);
this->replies.insert (0, replies);
}
};
// tasks definition
struct BotTask {
using Function = void (Bot::*) ();
public:
Function func; // corresponding exec function in bot class
Task id; // major task/action carried out
float desire; // desire (filled in) for this task
int data; // additional data (node index)
float time; // time task expires
bool resume; // if task can be continued if interrupted
public:
BotTask (Function func, Task id, float desire, int data, float time, bool resume) : func (func), id (id), desire (desire), data (data), time (time), resume (resume) { }
};
// weapon properties structure
struct WeaponProp {
String classname;
int ammo1; // ammo index for primary ammo
int ammo1Max; // max primary ammo
int slot; // HUD slot (0 based)
int pos; // slot position
int id; // weapon ID
int flags; // flags???
};
// weapon info structure
struct WeaponInfo {
int id; // the weapon id value
const char *name; // name of the weapon when selecting it
const char *model; // model name to separate cs weapons
int price; // price when buying
int minPrimaryAmmo; // minimum primary ammo
int teamStandard; // used by team (number) (standard map)
int teamAS; // used by team (as map)
int buyGroup; // group in buy menu (standard map)
int buySelect; // select item in buy menu (standard map)
int buySelectT; // for counter-strike v1.6
int buySelectCT; // for counter-strike v1.6
int penetratePower; // penetrate power
int maxClip; // max ammo in clip
int type; // weapon class
bool primaryFireHold; // hold down primary fire button to use?
public:
WeaponInfo (int id,
const char *name,
const char *model,
int price,
int minPriAmmo,
int teamStd,
int teamAs,
int buyGroup,
int buySelect,
int buySelectT,
int buySelectCT,
int penetratePower,
int maxClip,
int type,
bool fireHold) : id (id), name (name), model (model), price (price), minPrimaryAmmo (minPriAmmo), teamStandard (teamStd),
teamAS (teamAs), buyGroup (buyGroup), buySelect (buySelect), buySelectT (buySelectT), buySelectCT (buySelectCT),
penetratePower (penetratePower), maxClip (maxClip), type (type), primaryFireHold (fireHold)
{ }
};
// clients noise
struct ClientNoise {
Vector pos;
float dist;
float last;
};
// defines frustum data for bot
struct FrustumPlane {
Vector normal;
Vector point;
float result;
};
// array of clients struct
struct Client {
edict_t *ent; // pointer to actual edict
Vector origin; // position in the world
int team; // bot team
int team2; // real bot team in free for all mode (csdm)
int flags; // client flags
int radio; // radio orders
int menu; // identifier to openen menu
int ping; // when bot latency is enabled, client ping stored here
int iconFlags[kGameMaxPlayers]; // flag holding chatter icons
float iconTimestamp[kGameMaxPlayers]; // timers for chatter icons
ClientNoise noise;
};
// define chatting collection structure
struct ChatCollection {
int chatProbability;
float chatDelay;
float timeNextChat;
int entityIndex;
String sayText;
StringArray lastUsedSentences;
};
// include bot graph stuff
#include <graph.h>
// main bot class
class Bot final {
private:
using RouteTwin = Twin <int, float>;
public:
friend class BotManager;
private:
uint32 m_states {}; // sensing bitstates
uint32 m_collideMoves[kMaxCollideMoves] {}; // sorted array of movements
uint32 m_collisionProbeBits {}; // bits of possible collision moves
uint32 m_collStateIndex {}; // index into collide moves
uint32 m_aimFlags {}; // aiming conditions
uint32 m_currentTravelFlags {}; // connection flags like jumping
int m_traceSkip[TraceChannel::Num] {}; // trace need to be skipped?
int m_messageQueue[32] {}; // stack for messages
int m_oldButtons {}; // our old buttons
int m_reloadState {}; // current reload state
int m_voicePitch; // bot voice pitch
int m_loosedBombNodeIndex {}; // nearest to loosed bomb node
int m_plantedBombNodeIndex {}; // nearest to planted bomb node
int m_currentNodeIndex {}; // current node index
int m_travelStartIndex {}; // travel start index to double jump action
int m_previousNodes[5] {}; // previous node indices from node find
int m_pathFlags {}; // current node flags
int m_needAvoidGrenade {}; // which direction to strafe away
int m_campDirection {}; // camp Facing direction
int m_campButtons {}; // buttons to press while camping
int m_tryOpenDoor {}; // attempt's to open the door
int m_liftState {}; // state of lift handling
int m_radioSelect {}; // radio entry
float m_headedTime {};
float m_prevTime {}; // time previously checked movement speed
float m_heavyTimestamp; // is it time to execute heavy-weight functions
float m_prevSpeed {}; // speed some frames before
float m_timeDoorOpen {}; // time to next door open check
float m_lastChatTime {}; // time bot last chatted
float m_timeLogoSpray {}; // time bot last spray logo
float m_knifeAttackTime {}; // time to rush with knife (at the beginning of the round)
float m_duckDefuseCheckTime {}; // time to check for ducking for defuse
float m_frameInterval; // bot's frame interval
float m_lastCommandTime; // time bot last thinked
float m_reloadCheckTime {}; // time to check reloading
float m_zoomCheckTime {}; // time to check zoom again
float m_shieldCheckTime {}; // time to check shiled drawing again
float m_grenadeCheckTime {}; // time to check grenade usage
float m_sniperStopTime {}; // bot switched to other weapon?
float m_lastEquipTime {}; // last time we equipped in buyzone
float m_duckTime {}; // time to duck
float m_jumpTime {}; // time last jump happened
float m_soundUpdateTime {}; // time to update the sound
float m_heardSoundTime {}; // last time noise is heard
float m_buttonPushTime {}; // time to push the button
float m_liftUsageTime {}; // time to use lift
float m_askCheckTime {}; // time to ask team
float m_collideTime {}; // time last collision
float m_firstCollideTime {}; // time of first collision
float m_probeTime {}; // time of probing different moves
float m_lastCollTime {}; // time until next collision check
float m_lookYawVel {}; // look yaw velocity
float m_lookPitchVel {}; // look pitch velocity
float m_lookUpdateTime {}; // lookangles update time
float m_aimErrorTime {}; // time to update error vector
float m_nextCampDirTime {}; // time next camp direction change
float m_lastFightStyleCheck {}; // time checked style
float m_strafeSetTime {}; // time strafe direction was set
float m_randomizeAnglesTime {}; // time last randomized location
float m_playerTargetTime {}; // time last targeting
float m_timeCamping {}; // time to camp
float m_lastUsedNodesTime {}; // last time bot followed nodes
float m_shootAtDeadTime {}; // time to shoot at dying players
float m_followWaitTime {}; // wait to follow time
float m_chatterTimes[Chatter::Count] {}; // chatter command timers
float m_navTimeset {}; // time node chosen by Bot
float m_moveSpeed {}; // current speed forward/backward
float m_strafeSpeed {}; // current speed sideways
float m_minSpeed {}; // minimum speed in normal mode
float m_oldCombatDesire {}; // holds old desire for filtering
float m_itemCheckTime {}; // time next search for items needs to be done
float m_joinServerTime; // time when bot joined the game
float m_playServerTime; // time bot spent in the game
float m_changeViewTime {}; // timestamp to change look at while at freezetime
bool m_moveToGoal {}; // bot currently moving to goal??
bool m_isStuck {}; // bot is stuck
bool m_isReloading {}; // bot is reloading a gun
bool m_forceRadio; // should bot use radio anyway?
bool m_defendedBomb {}; // defend action issued
bool m_defendHostage {}; // defend action issued
bool m_duckDefuse {}; // should or not bot duck to defuse bomb
bool m_checkKnifeSwitch {}; // is time to check switch to knife action
bool m_checkWeaponSwitch {}; // is time to check weapon switch
bool m_isUsingGrenade {}; // bot currently using grenade??
bool m_bombSearchOverridden {}; // use normal node if applicable when near the bomb
bool m_wantsToFire {}; // bot needs consider firing
bool m_jumpFinished {}; // has bot finished jumping
bool m_isLeader {}; // bot is leader of his team
bool m_checkTerrain {}; // check for terrain
bool m_moveToC4 {}; // ct is moving to bomb
bool m_grenadeRequested {}; // bot requested change to grenade
Pickup m_pickupType; // type of entity which needs to be used/picked up
PathWalk m_pathWalk; // pointer to current node from path
Dodge m_combatStrafeDir; // direction to strafe
Fight m_fightStyle; // combat style to use
CollisionState m_collisionState; // collision State
FindPath m_pathType; // which pathfinder to use
uint8 m_enemyParts {}; // visibility flags
TraceResult m_lastTrace[TraceChannel::Num]; // last trace result
edict_t *m_pickupItem {}; // pointer to entity of item to use/pickup
edict_t *m_itemIgnore {}; // pointer to entity to ignore for pickup
edict_t *m_liftEntity {}; // pointer to lift entity
edict_t *m_breakableEntity {}; // pointer to breakable entity
edict_t *m_targetEntity {}; // the entity that the bot is trying to reach
edict_t *m_avoidGrenade {}; // pointer to grenade entity to avoid
Vector m_liftTravelPos; // lift travel position
Vector m_moveAngles; // bot move angles
Vector m_idealAngles; // angle wanted
Vector m_randomizedIdealAngles; // angle wanted with noise
Vector m_angularDeviation; // angular deviation from current to ideal angles
Vector m_aimSpeed; // aim speed calculated
Vector m_aimLastError; // last calculated aim error
Vector m_prevOrigin; // origin some frames before
Vector m_lookAt; // vector bot should look at
Vector m_throw; // origin of node to throw grenades
Vector m_enemyOrigin; // target origin chosen for shooting
Vector m_grenade; // calculated vector for grenades
Vector m_entity; // origin of entities like buttons etc.
Vector m_camp; // aiming vector when camping.
Vector m_desiredVelocity; // desired velocity for jump nodes
Vector m_breakableOrigin; // origin of breakable
Array <edict_t *> m_hostages; // pointer to used hostage entities
Array <Route> m_routes; // pointer
Array <int32> m_goalHistory; // history of selected goals
BinaryHeap <RouteTwin> m_routeQue;
Path *m_path {}; // pointer to the current path node
String m_chatBuffer; // space for strings (say text...)
FrustumPlane m_frustum[FrustumSide::Num] {};
private:
int pickBestWeapon (int *vec, int count, int moneySave);
int findCampingDirection ();
int findAimingNode (const Vector &to);
int findNearestNode ();
int findBombNode ();
int findCoverNode (float maxDistance);
int findDefendNode (const Vector &origin);
int findBestGoal ();
int findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive);
int bestPrimaryCarried ();
int bestSecondaryCarried ();
int bestGrenadeCarried ();
int bestWeaponCarried ();
int changePointIndex (int index);
int numEnemiesNear (const Vector &origin, float radius);
int numFriendsNear (const Vector &origin, float radius);
float getBombTimeleft ();
float getReachTime ();
float isInFOV (const Vector &dest);
float getShiftSpeed ();
float getEnemyBodyOffsetCorrection (float distance);
float calculateScaleFactor (edict_t *ent);
bool canReplaceWeapon ();
bool canDuckUnder (const Vector &normal);
bool canJumpUp (const Vector &normal);
bool doneCanJumpUp (const Vector &normal, const Vector &right);
bool cantMoveForward (const Vector &normal, TraceResult *tr);
bool canStrafeLeft (TraceResult *tr);
bool canStrafeRight (TraceResult *tr);
bool isBlockedLeft ();
bool isBlockedRight ();
bool checkWallOnLeft ();
bool checkWallOnRight ();
bool updateNavigation ();
bool isEnemyThreat ();
bool isWeaponRestricted (int weaponIndex);
bool isWeaponRestrictedAMX (int weaponIndex);
bool isInViewCone (const Vector &origin);
bool checkBodyParts (edict_t *target);
bool seesEnemy (edict_t *player, bool ignoreFOV = false);
bool doPlayerAvoidance (const Vector &normal);
bool hasActiveGoal ();
bool advanceMovement ();
bool isBombDefusing (const Vector &bombOrigin);
bool isOccupiedNode (int index, bool needZeroVelocity = false);
bool seesItem (const Vector &dest, const char *classname);
bool lastEnemyShootable ();
bool rateGroundWeapon (edict_t *ent);
bool reactOnEnemy ();
bool selectBestNextNode ();
bool hasAnyWeapons ();
bool isDeadlyMove (const Vector &to);
bool isOutOfBombTimer ();
bool isWeaponBadAtDistance (int weaponIndex, float distance);
bool needToPauseFiring (float distance);
bool lookupEnemies ();
bool isEnemyHidden (edict_t *enemy);
bool isEnemyInvincible (edict_t *enemy);
bool isFriendInLineOfFire (float distance);
bool isGroupOfEnemies (const Vector &location, int numEnemies = 1, float radius = 256.0f);
bool isPenetrableObstacle (const Vector &dest);
bool isPenetrableObstacle2 (const Vector &dest);
bool isEnemyBehindShield (edict_t *enemy);
bool isEnemyInFrustum (edict_t *enemy);
bool checkChatKeywords (String &reply);
bool isReplyingToChat ();
bool isReachableNode (int index);
bool isBannedNode (int index);
bool updateLiftHandling ();
bool updateLiftStates ();
bool canRunHeavyWeight ();
void markStale ();
void instantChatter (int type);
void update ();
void runMovement ();
void checkSpawnConditions ();
void buyStuff ();
void changePitch (float speed);
void changeYaw (float speed);
void checkMsgQueue ();
void checkRadioQueue ();
void checkReload ();
void avoidGrenades ();
void checkGrenadesThrow ();
void checkBurstMode (float distance);
void checkSilencer ();
void updateAimDir ();
void updateLookAngles ();
void updateBodyAngles ();
void updateLookAnglesNewbie (const Vector &direction, float delta);
void setIdealReactionTimers (bool actual = false);
void updateHearing ();
void postprocessGoals (const IntArray &goals, int result[]);
void updatePickups ();
void checkTerrain (float movedDistance, const Vector &dirNormal);
void checkDarkness ();
void checkParachute ();
void getCampDirection (Vector *dest);
void updatePracticeValue (int damage);
void updatePracticeDamage (edict_t *attacker, int damage);
void findShortestPath (int srcIndex, int destIndex);
void calculateFrustum ();
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
void clearRoute ();
void debugMsgInternal (const char *str);
void frame ();
void resetCollision ();
void ignoreCollision ();
void setConditions ();
void overrideConditions ();
void updateEmotions ();
void setStrafeSpeed (const Vector &moveDir, float strafeSpeed);
void updateTeamJoin ();
void updateTeamCommands ();
void decideFollowUser ();
void attackMovement ();
void findValidNode ();
void fireWeapons ();
void selectWeapons (float distance, int index, int id, int choosen);
void focusEnemy ();
void selectBestWeapon ();
void selectSecondary ();
void selectWeaponByName (const char *name);
void selectWeaponById (int num);
void completeTask ();
void tasks ();
void trackEnemies ();
void choiceFreezetimeEntity ();
void normal_ ();
void spraypaint_ ();
void huntEnemy_ ();
void seekCover_ ();
void attackEnemy_ ();
void pause_ ();
void blind_ ();
void camp_ ();
void hide_ ();
void moveToPos_ ();
void plantBomb_ ();
void defuseBomb_ ();
void followUser_ ();
void throwExplosive_ ();
void throwFlashbang_ ();
void throwSmoke_ ();
void doublejump_ ();
void escapeFromBomb_ ();
void pickupItem_ ();
void shootBreakable_ ();
edict_t *lookupButton (const char *target);
edict_t *lookupBreakable ();
edict_t *correctGrenadeVelocity (const char *model);
const Vector &getEnemyBodyOffset ();
Vector calcThrow (const Vector &start, const Vector &stop);
Vector calcToss (const Vector &start, const Vector &stop);
Vector isBombAudible ();
Vector getBodyOffsetError (float distance);
uint8 computeMsec ();
private:
bool isOnLadder () const {
return pev->movetype == MOVETYPE_FLY;
}
bool isOnFloor () const {
return (pev->flags & (FL_ONGROUND | FL_PARTIALGROUND)) != 0;
}
bool isInWater () const {
return pev->waterlevel >= 2;
}
bool isInNarrowPlace () const {
return (m_pathFlags & NodeFlag::Narrow);
}
public:
entvars_t *pev;
int m_index; // saved bot index
int m_wantedTeam; // player team bot wants select
int m_wantedSkin; // player model bot wants to select
int m_difficulty; // bots hard level
int m_moneyAmount; // amount of money in bot's bank
float m_spawnTime {}; // time this bot spawned
float m_timeTeamOrder {}; // time of last radio command
float m_slowFrameTimestamp; // time to per-second think
float m_nextBuyTime {}; // next buy time
float m_checkDarkTime {}; // check for darkness time
float m_preventFlashing {}; // bot turned away from flashbang
float m_flashLevel {}; // flashlight level
float m_blindTime {}; // time when bot is blinded
float m_blindMoveSpeed {}; // mad speeds when bot is blind
float m_blindSidemoveSpeed {}; // mad side move speeds when bot is blind
float m_fallDownTime {}; // time bot started to fall
float m_duckForJump {}; // is bot needed to duck for double jump
float m_baseAgressionLevel; // base aggression level (on initializing)
float m_baseFearLevel; // base fear level (on initializing)
float m_agressionLevel; // dynamic aggression level (in game)
float m_fearLevel; // dynamic fear level (in game)
float m_nextEmotionUpdate; // next time to sanitize emotions
float m_updateTime {}; // skip some frames in bot thinking
float m_updateInterval {}; // interval between frames
float m_goalValue {}; // ranking value for this node
float m_viewDistance {}; // current view distance
float m_maxViewDistance {}; // maximum view distance
float m_retreatTime {}; // time to retreat?
float m_enemyUpdateTime {}; // time to check for new enemies
float m_enemyReachableTimer {}; // time to recheck if enemy reachable
float m_enemyIgnoreTimer {}; // ignore enemy for some time
float m_seeEnemyTime {}; // time bot sees enemy
float m_enemySurpriseTime {}; // time of surprise
float m_idealReactionTime {}; // time of base reaction
float m_actualReactionTime {}; // time of current reaction time
float m_timeNextTracking {}; // time node index for tracking player is recalculated
float m_firePause {}; // time to pause firing
float m_shootTime {}; // time to shoot
float m_timeLastFired {}; // time to last firing
float m_difficultyChange {}; // time when auto-difficulty was last applied to this bot
float m_kpdRatio; // kill per death ratio
float m_healthValue; // clamped bot health
int m_basePing; // base ping for bot
int m_numEnemiesLeft {}; // number of enemies alive left on map
int m_numFriendsLeft {}; // number of friend alive left on map
int m_retryJoin; // retry count for chosing team/class
int m_startAction; // team/class selection state
int m_voteKickIndex {}; // index of player to vote against
int m_lastVoteKick {}; // last index
int m_voteMap {}; // number of map to vote for
int m_logotypeIndex; // index for logotype
int m_buyState {}; // current count in buying
int m_blindButton {}; // buttons bot press, when blind
int m_radioOrder {}; // actual command
int m_prevGoalIndex {}; // holds destination goal node
int m_chosenGoalIndex {}; // used for experience, same as above
int m_lastDamageType {}; // stores last damage
int m_team {}; // bot team
int m_currentWeapon; // one current weapon for each bot
int m_weaponType; // current weapon type
int m_ammoInClip[kMaxWeapons] {}; // ammo in clip for each weapons
int m_ammo[MAX_AMMO_SLOTS] {}; // total ammo amounts
bool m_isVIP {}; // bot is vip?
bool m_notKilled; // has the player been killed or has he just respawned
bool m_notStarted; // team/class not chosen yet
bool m_ignoreBuyDelay {}; // when reaching buyzone in the middle of the round don't do pauses
bool m_inBombZone {}; // bot in the bomb zone or not
bool m_inBuyZone {}; // bot currently in buy zone
bool m_inVIPZone {}; // bot in the vip satefy zone
bool m_buyingFinished {}; // done with buying
bool m_buyPending {}; // bot buy is pending
bool m_hasDefuser {}; // does bot has defuser
bool m_hasNVG {}; // does bot has nightvision goggles
bool m_usesNVG {}; // does nightvision goggles turned on
bool m_hasC4 {}; // does bot has c4 bomb
bool m_hasProgressBar {}; // has progress bar on a HUD
bool m_jumpReady {}; // is double jump ready
bool m_canChooseAimDirection {}; // can choose aiming direction
bool m_isEnemyReachable {}; // direct line to enemy
edict_t *m_doubleJumpEntity {}; // pointer to entity that request double jump
edict_t *m_radioEntity {}; // pointer to entity issuing a radio command
edict_t *m_enemy {}; // pointer to enemy entity
edict_t *m_lastEnemy {}; // pointer to last enemy entity
edict_t *m_lastVictim {}; // pointer to killed entity
edict_t *m_trackingEdict {}; // pointer to last tracked player when camping/hiding
Vector m_pathOrigin; // origin of node
Vector m_destOrigin; // origin of move destination
Vector m_position; // position to move to in move to position task
Vector m_doubleJumpOrigin; // origin of double jump
Vector m_lastEnemyOrigin; // vector to last enemy origin
ChatCollection m_sayTextBuffer; // holds the index & the actual message of the last unprocessed text message of a player
BurstMode m_weaponBurstMode; // bot using burst mode? (famas/glock18, but also silencer mode)
Personality m_personality; // bots type
Array <BotTask> m_tasks;
Deque <int32> m_msgQueue;
public:
Bot (edict_t *bot, int difficulty, int personality, int team, int skin);
~Bot () = default;
public:
void logic (); /// the things that can be executed while skipping frames
void spawned ();
void takeBlind (int alpha);
void takeDamage (edict_t *inflictor, int damage, int armor, int bits);
void showDebugOverlay ();
void newRound ();
void resetPathSearchType ();
void enteredBuyZone (int buyState);
void pushMsgQueue (int message);
void prepareChatMessage (StringRef message);
void checkForChat ();
void showChaterIcon (bool show);
void clearSearchNodes ();
void checkBreakable (edict_t *touch);
void checkBreakablesAround ();
void startTask (Task id, float desire, int data, float time, bool resume);
void clearTask (Task id);
void filterTasks ();
void clearTasks ();
void dropWeaponForUser (edict_t *user, bool discardC4);
void sendToChat (StringRef message, bool teamOnly);
void pushChatMessage (int type, bool isTeamSay = false);
void pushRadioMessage (int message);
void pushChatterMessage (int message);
void tryHeadTowardRadioMessage ();
void kill ();
void kick ();
void resetDoubleJump ();
void startDoubleJump (edict_t *ent);
void sendBotToOrigin (const Vector &origin);
bool hasHostage ();
bool usesRifle ();
bool usesPistol ();
bool usesSniper ();
bool usesSubmachine ();
bool usesShotgun ();
bool usesHeavy ();
bool usesZoomableRifle ();
bool usesBadWeapon ();
bool usesCampGun ();
bool usesKnife ();
bool hasPrimaryWeapon ();
bool hasSecondaryWeapon ();
bool hasShield ();
bool isShieldDrawn ();
bool findBestNearestNode ();
bool seesEntity (const Vector &dest, bool fromBody = false);
bool canSkipNextTrace (TraceChannel channel);
int getAmmo ();
int getNearestToPlantedBomb ();
float getFrameInterval ();
float getConnectionTime ();
BotTask *getTask ();
public:
int getAmmoInClip () const {
return m_ammoInClip[m_currentWeapon];
}
Vector getCenter () const {
return (pev->absmax + pev->absmin) * 0.5;
};
Vector getEyesPos () const {
return pev->origin + pev->view_ofs;
};
Task getCurrentTaskId () {
return getTask ()->id;
}
edict_t *ent () {
return pev->pContainingEntity;
};
// bots array index
int index () const {
return m_index;
}
// entity index with worldspawn shift
int entindex () const {
return m_index + 1;
}
// get the current node index
int getCurrentNodeIndex () const {
return m_currentNodeIndex;
}
// set the last bot trace result
void setLastTraceResult (TraceChannel channel, TraceResult *traceResult) {
m_lastTrace[channel] = *traceResult;
}
// get the bot last trace result
TraceResult &getLastTraceResult (TraceChannel channel) {
return m_lastTrace[channel];
}
// prints debug message
template <typename ...Args> void debugMsg (const char *fmt, Args &&...args) {
debugMsgInternal (strings.format (fmt, cr::forward <Args> (args)...));
}
// execute client command helper
template <typename ...Args> void issueCommand (const char *fmt, Args &&...args);
};
#include "config.h"
#include "support.h"
#include "message.h"
#include "engine.h"
#include "manager.h"
#include "control.h"
// very global convars
extern ConVar cv_jasonmode;
extern ConVar cv_radio_mode;
extern ConVar cv_ignore_enemies;
extern ConVar cv_ignore_objectives;
extern ConVar cv_chat;
extern ConVar cv_language;
extern ConVar cv_show_latency;
extern ConVar cv_enable_query_hook;
extern ConVar cv_whose_your_daddy;
extern ConVar cv_chatter_path;
extern ConVar cv_quota;
extern ConVar cv_difficulty;
extern ConVar cv_attack_monsters;
extern ConVar cv_pickup_custom_items;
extern ConVar cv_economics_rounds;
extern ConVar cv_shoots_thru_walls;
extern ConVar cv_debug;
extern ConVar cv_debug_goal;
extern ConVar cv_save_bots_names;
extern ConVar cv_random_knife_attacks;
extern ConVar mp_freezetime;
extern ConVar mp_roundtime;
extern ConVar mp_timelimit;
extern ConVar mp_limitteams;
extern ConVar mp_autoteambalance;
extern ConVar mp_footsteps;
extern ConVar mp_startmoney;
// execute client command helper
template <typename ...Args> void Bot::issueCommand (const char *fmt, Args &&...args) {
game.botCommand (ent (), strings.format (fmt, cr::forward <Args> (args)...));
}