2015-06-30 12:46:07 +03:00
/*
*
* 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"
2017-10-12 17:50:56 +03:00
const int MAX_BUY_WEAPON_PRIMARY = 13 ;
const int MAX_BUY_WEAPON_SECONDARY = 3 ;
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
enum
{
BOT_PROGGRESS_DRAW = 0 , // draw status bar progress
BOT_PROGGRESS_START , // init status bar progress
BOT_PROGGRESS_HIDE , // hide status bar progress
} ;
2016-01-19 14:54:31 +03:00
2015-09-16 23:19:21 +03:00
class CCSBot ;
class BotChatterInterface ;
2015-06-30 12:46:07 +03:00
class BotState
{
public :
virtual void OnEnter ( CCSBot * me ) { }
virtual void OnUpdate ( CCSBot * me ) { }
virtual void OnExit ( CCSBot * me ) { }
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const = 0 ;
} ;
2015-06-30 12:46:07 +03:00
class IdleState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Idle " ; }
} ;
2015-06-30 12:46:07 +03:00
class HuntState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Hunt " ; }
2016-01-19 14:54:31 +03:00
2017-10-12 17:50:56 +03:00
void ClearHuntArea ( ) { m_huntArea = nullptr ; }
2017-07-01 23:40:10 +03:00
2015-06-30 12:46:07 +03:00
private :
CNavArea * m_huntArea ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class AttackState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Attack " ; }
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
void SetCrouchAndHold ( bool crouch ) { m_crouchAndHold = crouch ; }
2015-06-30 12:46:07 +03:00
void StopAttacking ( CCSBot * me ) ;
protected :
enum DodgeStateType
{
STEADY_ON ,
SLIDE_LEFT ,
SLIDE_RIGHT ,
JUMP ,
NUM_ATTACK_STATES
} m_dodgeState ;
2015-08-02 20:45:57 +03:00
2015-06-30 12:46:07 +03:00
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 ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class InvestigateNoiseState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " InvestigateNoise " ; }
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
private :
2016-01-25 20:02:57 +03:00
void AttendCurrentNoise ( CCSBot * me ) ;
2015-06-30 12:46:07 +03:00
Vector m_checkNoisePosition ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class BuyState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Buy " ; }
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
private :
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 ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class MoveToState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " MoveTo " ; }
2016-01-19 14:54:31 +03:00
void SetGoalPosition ( const Vector & pos ) { m_goalPosition = pos ; }
void SetRouteType ( RouteType route ) { m_routeType = route ; }
2015-06-30 12:46:07 +03:00
private :
Vector m_goalPosition ;
RouteType m_routeType ;
bool m_radioedPlan ;
bool m_askedForCover ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class FetchBombState : public BotState
{
public :
2016-01-19 14:54:31 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " FetchBomb " ; }
} ;
2015-06-30 12:46:07 +03:00
class PlantBombState : public BotState
{
public :
2016-01-19 14:54:31 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " PlantBomb " ; }
} ;
2015-06-30 12:46:07 +03:00
class DefuseBombState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " DefuseBomb " ; }
} ;
2015-06-30 12:46:07 +03:00
class HideState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Hide " ; }
2016-01-19 14:54:31 +03:00
public :
2016-02-23 02:13:52 +03:00
void SetHidingSpot ( const Vector & pos ) { m_hidingSpot = pos ; }
const Vector & GetHidingSpot ( ) const { return m_hidingSpot ; }
2016-01-19 14:54:31 +03:00
2016-02-23 02:13:52 +03:00
void SetSearchArea ( CNavArea * area ) { m_searchFromArea = area ; }
void SetSearchRange ( float range ) { m_range = range ; }
2016-01-19 14:54:31 +03:00
2016-02-23 02:13:52 +03:00
void SetDuration ( float time ) { m_duration = time ; }
void SetHoldPosition ( bool hold ) { m_isHoldingPosition = hold ; }
2016-01-19 14:54:31 +03:00
2016-02-23 02:13:52 +03:00
bool IsAtSpot ( ) const { return m_isAtSpot ; }
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
private :
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 ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class EscapeFromBombState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " EscapeFromBomb " ; }
} ;
2015-06-30 12:46:07 +03:00
class FollowState : public BotState
{
public :
2016-01-25 20:02:57 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " Follow " ; }
2016-01-19 14:54:31 +03:00
2017-11-22 20:27:55 +03:00
void SetLeader ( CBasePlayer * pLeader ) { m_leader = pLeader ; }
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
private :
2016-01-25 20:02:57 +03:00
void ComputeLeaderMotionState ( float leaderSpeed ) ;
2016-01-19 14:54:31 +03:00
2017-10-12 17:50:56 +03:00
EntityHandle < CBasePlayer > m_leader ;
2015-06-30 12:46:07 +03:00
Vector m_lastLeaderPos ;
bool m_isStopped ;
float m_stoppedTimestamp ;
enum LeaderMotionStateType
{
INVALID ,
STOPPED ,
WALKING ,
RUNNING
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
} m_leaderMotionState ;
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
IntervalTimer m_leaderMotionStateTime ;
bool m_isSneaking ;
float m_lastSawLeaderTime ;
CountdownTimer m_repathInterval ;
IntervalTimer m_walkTime ;
bool m_isAtWalkSpeed ;
float m_waitTime ;
CountdownTimer m_idleTimer ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class UseEntityState : public BotState
{
public :
2016-01-19 14:54:31 +03:00
virtual void OnEnter ( CCSBot * me ) ;
virtual void OnUpdate ( CCSBot * me ) ;
virtual void OnExit ( CCSBot * me ) ;
2016-02-04 03:18:26 +03:00
virtual const char * GetName ( ) const { return " UseEntity " ; }
2016-01-19 14:54:31 +03:00
2017-11-22 20:27:55 +03:00
void SetEntity ( CBaseEntity * pEntity ) { m_entity = pEntity ; }
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
private :
2017-10-12 17:50:56 +03:00
EntityHandle < CBaseEntity > m_entity ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// The Counter-strike Bot
2015-06-30 12:46:07 +03:00
class CCSBot : public CBot
{
public :
2017-10-12 17:50:56 +03:00
CCSBot ( ) ; // constructor initializes all values to zero
2016-06-18 17:48:19 +03:00
virtual BOOL TakeDamage ( entvars_t * pevInflictor , entvars_t * pevAttacker , float flDamage , int bitsDamageType ) ; // invoked when injured by something (EXTEND) - returns the amount of damage inflicted
2017-07-01 23:40:10 +03:00
virtual void Killed ( entvars_t * pevAttacker , int iGib ) ; // invoked when killed (EXTEND)
2016-02-04 03:18:26 +03:00
virtual void RoundRespawn ( ) ;
2017-07-01 23:40:10 +03:00
virtual void Blind ( float duration , float holdTime , float fadeTime , int alpha = 255 ) ; // player blinded by a flashbang
virtual void OnTouchingWeapon ( CWeaponBox * box ) ; // invoked when in contact with a CWeaponBox
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
virtual bool Initialize ( const BotProfile * profile ) ; // (EXTEND) prepare bot for action
2016-02-04 03:18:26 +03:00
virtual void SpawnBot ( ) ; // (EXTEND) spawn the bot into the game
2015-06-30 12:46:07 +03:00
2016-02-04 03:18:26 +03:00
virtual void Upkeep ( ) ; // lightweight maintenance, invoked frequently
virtual void Update ( ) ; // heavyweight algorithms, invoked less often
2015-06-30 12:46:07 +03:00
2016-02-04 03:18:26 +03:00
virtual void Walk ( ) ;
2017-07-01 23:40:10 +03:00
virtual bool Jump ( bool mustJump = false ) ; // returns true if jump was started
2015-06-30 12:46:07 +03:00
2017-11-22 20:27:55 +03:00
virtual void OnEvent ( GameEventType event , CBaseEntity * pEntity = nullptr , CBaseEntity * pOther = nullptr ) ; // invoked when event occurs in the game (some events have NULL entity)
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
# define CHECK_FOV true
2017-11-22 20:27:55 +03:00
virtual bool IsVisible ( const Vector * pos , bool testFOV = false ) const ; // return true if we can see the point
virtual bool IsVisible ( CBasePlayer * pPlayer , bool testFOV = false , unsigned char * visParts = nullptr ) const ; // return true if we can see any part of the player
2015-06-30 12:46:07 +03:00
2017-11-22 20:27:55 +03:00
virtual bool IsEnemyPartVisible ( VisiblePartType part ) const ; // if enemy is visible, return the part we see for our current enemy
2015-06-30 12:46:07 +03:00
public :
2016-02-04 03:18:26 +03:00
void Disconnect ( ) ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// behavior properties
2016-02-04 03:18:26 +03:00
float GetCombatRange ( ) const ;
bool IsRogue ( ) const ; // return true if we dont listen to teammates or pursue scenario goals
2016-01-19 14:54:31 +03:00
void SetRogue ( bool rogue ) ;
2016-02-04 03:18:26 +03:00
bool IsHurrying ( ) const ; // return true if we are in a hurry
2016-01-19 14:54:31 +03:00
void Hurry ( float duration ) ; // force bot to hurry
2016-02-04 03:18:26 +03:00
bool IsSafe ( ) const ; // return true if we are in a safe region
2017-10-12 17:50:56 +03:00
bool IsWellPastSafe ( ) const ; // return true if it is well past the early, "safe", part of the round
bool IsEndOfSafeTime ( ) const ; // return true if we were in the safe time last update, but not now
float GetSafeTimeRemaining ( ) const ; // return the amount of "safe time" we have left
2016-02-04 03:18:26 +03:00
float GetSafeTime ( ) const ; // return what we think the total "safe time" for this map is
2016-02-23 02:13:52 +03:00
//bool IsUnhealthy() const; // returns true if bot is low on health
2016-01-19 14:54:31 +03:00
// behaviors
2016-02-04 03:18:26 +03:00
void Idle ( ) ;
2017-10-12 17:50:56 +03:00
void Hide ( CNavArea * searchFromArea = nullptr , float duration = - 1.0f , float hideRange = 750.0f , bool holdPosition = false ) ; // DEPRECATED: Use TryToHide() instead
2016-01-19 14:54:31 +03:00
# define USE_NEAREST true
2017-10-12 17:50:56 +03:00
bool TryToHide ( CNavArea * searchFromArea = nullptr , float duration = - 1.0f , float hideRange = 750.0f , bool holdPosition = false , bool useNearest = false ) ; // try to hide nearby, return false if cannot
2015-06-30 12:46:07 +03:00
2017-10-12 17:50:56 +03:00
void Hide ( const Vector * hidingSpot , float duration = - 1.0f , bool holdPosition = false ) ; // move to the given hiding place
2016-02-04 03:18:26 +03:00
bool IsHiding ( ) const ; // returns true if bot is currently hiding
2017-07-01 23:40:10 +03:00
bool IsAtHidingSpot ( ) const ; // return true if we are hiding and at our hiding spot
2016-02-04 03:18:26 +03:00
bool TryToRetreat ( ) ; // retreat to a nearby hiding spot, away from enemies
2015-06-30 12:46:07 +03:00
2016-02-04 03:18:26 +03:00
void Hunt ( ) ;
2017-07-01 23:40:10 +03:00
bool IsHunting ( ) const ; // returns true if bot is currently hunting
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
void Attack ( CBasePlayer * victim ) ;
2017-07-01 23:40:10 +03:00
void FireWeaponAtEnemy ( ) ; // fire our active weapon towards our current enemy
2016-02-04 03:18:26 +03:00
void StopAttacking ( ) ;
2017-07-01 23:40:10 +03:00
bool IsAttacking ( ) const ; // returns true if bot is currently engaging a target
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
void MoveTo ( const Vector * pos , RouteType route = SAFEST_ROUTE ) ; // move to potentially distant position
bool IsMovingTo ( ) const ; // return true if we are in the MoveTo state
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void PlantBomb ( ) ;
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void FetchBomb ( ) ; // bomb has been dropped - go get it
2017-07-01 23:40:10 +03:00
bool NoticeLooseBomb ( ) const ; // return true if we noticed the bomb on the ground or on radar
bool CanSeeLooseBomb ( ) const ; // return true if we directly see the loose bomb
2016-02-04 03:18:26 +03:00
bool IsCarryingBomb ( ) const ;
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void DefuseBomb ( ) ;
2017-07-01 23:40:10 +03:00
bool IsDefusingBomb ( ) const ; // returns true if bot is currently defusing the bomb
bool CanSeePlantedBomb ( ) const ; // return true if we directly see the planted bomb
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void EscapeFromBomb ( ) ;
2017-07-01 23:40:10 +03:00
bool IsEscapingFromBomb ( ) const ; // return true if we are escaping from the bomb
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void RescueHostages ( ) ;
2017-11-22 20:27:55 +03:00
void UseEntity ( CBaseEntity * pEntity ) ; // use the entity
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
bool IsBuying ( ) const ;
2015-06-30 12:46:07 +03:00
2024-01-31 15:16:37 +03:00
# ifdef REGAMEDLL_FIXES
void Kill ( ) ;
# endif
2017-11-22 20:27:55 +03:00
void Panic ( CBasePlayer * pEnemy ) ; // look around in panic
void Follow ( CBasePlayer * pPlayer ) ; // begin following given Player
2017-07-01 23:40:10 +03:00
void ContinueFollowing ( ) ; // continue following our leader after finishing what we were doing
void StopFollowing ( ) ; // stop following
bool IsFollowing ( ) const ; // return true if we are following someone (not necessarily in the follow state)
CBasePlayer * GetFollowLeader ( ) ; // return the leader we are following
float GetFollowDuration ( ) const ; // return how long we've been following our leader
bool CanAutoFollow ( ) const ; // return true if we can auto-follow
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsNotMoving ( ) const ; // return true if we are currently standing still
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
void AimAtEnemy ( ) ; // point our weapon towards our enemy
void StopAiming ( ) ; // stop aiming at enemy
2017-07-01 23:40:10 +03:00
bool IsAimingAtEnemy ( ) const ; // returns true if we are trying to aim at an enemy
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsSurprised ( ) const ; // return true if we are "surprised"
2016-02-04 03:18:26 +03:00
float GetSurpriseDelay ( ) const ;
void ClearSurpriseDelay ( ) ;
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
float GetStateTimestamp ( ) const ; // get time current state was entered
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsDoingScenario ( ) const ; // return true if we will do scenario-related tasks
2016-01-19 14:54:31 +03:00
// scenario / gamestate
2017-07-01 23:40:10 +03:00
CSGameState * GetGameState ( ) ; // return an interface to this bot's gamestate
const CSGameState * GetGameState ( ) const ; // return an interface to this bot's gamestate
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsAtBombsite ( ) ; // return true if we are in a bomb planting zone
bool GuardRandomZone ( float range = 500.0f ) ; // pick a random zone and hide near it
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsBusy ( ) const ; // return true if we are busy doing something important
2016-01-19 14:54:31 +03:00
// high-level tasks
2015-06-30 12:46:07 +03:00
enum TaskType
{
2016-01-19 14:54:31 +03:00
SEEK_AND_DESTROY ,
2015-06-30 12:46:07 +03:00
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 ,
2016-01-19 14:54:31 +03:00
NUM_TASKS
2015-06-30 12:46:07 +03:00
} ;
2017-11-22 20:27:55 +03:00
void SetTask ( TaskType task , CBaseEntity * pEntity = nullptr ) ; // set our current "task"
2016-02-04 03:18:26 +03:00
TaskType GetTask ( ) const ;
CBaseEntity * GetTaskEntity ( ) ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// behavior modifiers
2015-06-30 12:46:07 +03:00
enum DispositionType
{
2017-07-01 23:40:10 +03:00
ENGAGE_AND_INVESTIGATE , // engage enemies on sight and investigate enemy noises
2016-01-19 14:54:31 +03:00
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
2015-06-30 12:46:07 +03:00
} ;
2017-07-01 23:40:10 +03:00
void SetDisposition ( DispositionType disposition ) ; // define how we react to enemies
DispositionType GetDisposition ( ) const ; // return enum describing current disposition
2016-01-19 14:54:31 +03:00
void IgnoreEnemies ( float duration ) ; // ignore enemies for a short duration
2015-06-30 12:46:07 +03:00
enum MoraleType
{
TERRIBLE = - 3 ,
BAD = - 2 ,
NEGATIVE = - 1 ,
NEUTRAL = 0 ,
POSITIVE = 1 ,
GOOD = 2 ,
EXCELLENT = 3 ,
} ;
2016-02-04 03:18:26 +03:00
MoraleType GetMorale ( ) const ; // return enum describing current morale
void IncreaseMorale ( ) ;
void DecreaseMorale ( ) ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// listening for noises
2017-07-01 23:40:10 +03:00
bool IsNoiseHeard ( ) const ; // return true if we have heard a noise
2017-10-12 17:50:56 +03:00
bool ShouldInvestigateNoise ( float * retNoiseDist = nullptr ) ;
2017-07-01 23:40:10 +03:00
void InvestigateNoise ( ) ; // investigate recent enemy noise
const Vector * GetNoisePosition ( ) const ; // return position of last heard noise, or NULL if none heard
2016-02-04 03:18:26 +03:00
CNavArea * GetNoiseArea ( ) const ; // return area where noise was heard
2017-07-01 23:40:10 +03:00
void ForgetNoise ( ) ; // clear the last heard noise
2016-02-04 03:18:26 +03:00
bool CanSeeNoisePosition ( ) const ; // return true if we directly see where we think the noise came from
2016-02-23 02:13:52 +03:00
float GetNoiseRange ( ) const ; // return approximate distance to last noise heard
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool CanHearNearbyEnemyGunfire ( float range = - 1.0f ) const ; // return true if we hear nearby threatening enemy gunfire within given range (-1 == infinite)
PriorityType GetNoisePriority ( ) const ; // return priority of last heard noise
2016-01-19 14:54:31 +03:00
// radio and chatter
2017-07-01 23:40:10 +03:00
void SendRadioMessage ( GameEventType event ) ; // send voice chatter
2016-02-04 03:18:26 +03:00
BotChatterInterface * GetChatter ( ) ; // return an interface to this bot's chatter system
bool RespondToHelpRequest ( CBasePlayer * them , Place place , float maxRange = - 1.0f ) ; // decide if we should move to help the player, return true if we will
2016-01-19 14:54:31 +03:00
void StartVoiceFeedback ( float duration ) ;
2017-07-01 23:40:10 +03:00
bool IsUsingVoice ( ) const ; // new-style "voice" chatter gets voice feedback
2016-01-19 14:54:31 +03:00
// enemies
// BOTPORT: GetEnemy() collides with GetEnemy() in CBaseEntity - need to use different nomenclature
2017-11-22 20:27:55 +03:00
void SetEnemy ( CBasePlayer * pEnemy ) ; // set given player as our current enemy
2016-02-04 03:18:26 +03:00
CBasePlayer * GetEnemy ( ) ;
int GetNearbyEnemyCount ( ) const ; // return max number of nearby enemies we've seen recently
unsigned int GetEnemyPlace ( ) const ; // return location where we see the majority of our enemies
2017-07-01 23:40:10 +03:00
bool CanSeeBomber ( ) const ; // return true if we can see the bomb carrier
2016-02-04 03:18:26 +03:00
CBasePlayer * GetBomber ( ) const ;
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
int GetNearbyFriendCount ( ) const ; // return number of nearby teammates
2017-07-01 23:40:10 +03:00
CBasePlayer * GetClosestVisibleFriend ( ) const ; // return the closest friend that we can see
CBasePlayer * GetClosestVisibleHumanFriend ( ) const ; // return the closest human friend that we can see
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsOutnumbered ( ) const ; // return true if we are outnumbered by enemies
2016-02-04 03:18:26 +03:00
int OutnumberedCount ( ) const ; // return number of enemies we are outnumbered by
2016-01-19 14:54:31 +03:00
# define ONLY_VISIBLE_ENEMIES true
CBasePlayer * GetImportantEnemy ( bool checkVisibility = false ) const ; // return the closest "important" enemy for the given scenario (bomb carrier, VIP, hostage escorter)
2017-07-01 23:40:10 +03:00
void UpdateReactionQueue ( ) ; // update our reaction time queue
2016-02-04 03:18:26 +03:00
CBasePlayer * GetRecognizedEnemy ( ) ; // return the most dangerous threat we are "conscious" of
bool IsRecognizedEnemyReloading ( ) ; // return true if the enemy we are "conscious" of is reloading
2017-07-01 23:40:10 +03:00
bool IsRecognizedEnemyProtectedByShield ( ) ; // return true if the enemy we are "conscious" of is hiding behind a shield
float GetRangeToNearestRecognizedEnemy ( ) ; // return distance to closest enemy we are "conscious" of
2016-02-04 03:18:26 +03:00
CBasePlayer * GetAttacker ( ) const ; // return last enemy that hurt us
float GetTimeSinceAttacked ( ) const ; // return duration since we were last injured by an attacker
2017-07-01 23:40:10 +03:00
float GetFirstSawEnemyTimestamp ( ) const ; // time since we saw any enemies
2016-02-04 03:18:26 +03:00
float GetLastSawEnemyTimestamp ( ) const ;
float GetTimeSinceLastSawEnemy ( ) const ;
float GetTimeSinceAcquiredCurrentEnemy ( ) const ;
2017-07-01 23:40:10 +03:00
bool HasNotSeenEnemyForLongTime ( ) const ; // return true if we haven't seen an enemy for "a long time"
2016-02-04 03:18:26 +03:00
const Vector & GetLastKnownEnemyPosition ( ) const ;
bool IsEnemyVisible ( ) const ; // is our current enemy visible
float GetEnemyDeathTimestamp ( ) const ;
bool IsFriendInLineOfFire ( ) ; // return true if a friend is in our weapon's way
bool IsAwareOfEnemyDeath ( ) const ; // return true if we *noticed* that our enemy died
int GetLastVictimID ( ) const ; // return the ID (entindex) of the last victim we killed, or zero
2016-01-19 14:54:31 +03:00
// navigation
2016-02-04 03:18:26 +03:00
bool HasPath ( ) const ;
void DestroyPath ( ) ;
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
float GetFeetZ ( ) const ; // return Z of bottom of feet
2015-06-30 12:46:07 +03:00
enum PathResult
{
2016-01-19 14:54:31 +03:00
PROGRESSING , // we are moving along the path
END_OF_PATH , // we reached the end of the path
PATH_FAILURE , // we failed to reach the end of the path
2015-06-30 12:46:07 +03:00
} ;
2016-01-19 14:54:31 +03:00
# define NO_SPEED_CHANGE false
2017-07-01 23:40:10 +03:00
PathResult UpdatePathMovement ( bool allowSpeedChange = true ) ; // move along our computed path - if allowSpeedChange is true, bot will walk when near goal to ensure accuracy
2015-06-30 12:46:07 +03:00
2016-02-23 02:13:52 +03:00
bool AStarSearch ( CNavArea * startArea , CNavArea * goalArea ) ; // find shortest path from startArea to goalArea - don't actually buid the path
2017-07-01 23:40:10 +03:00
bool ComputePath ( CNavArea * goalArea , const Vector * goal , RouteType route ) ; // compute path to goal position
2016-02-04 03:18:26 +03:00
bool StayOnNavMesh ( ) ;
2017-07-01 23:40:10 +03:00
CNavArea * GetLastKnownArea ( ) const ; // return the last area we know we were inside of
2016-02-04 03:18:26 +03:00
const Vector & GetPathEndpoint ( ) const ; // return final position of our current path
float GetPathDistanceRemaining ( ) const ; // eturn estimated distance left to travel along path
void ResetStuckMonitor ( ) ;
2016-02-23 02:13:52 +03:00
bool IsAreaVisible ( CNavArea * area ) const ; // is any portion of the area visible to this bot
2016-01-19 14:54:31 +03:00
const Vector & GetPathPosition ( int numpath ) const ;
2017-10-12 17:50:56 +03:00
bool GetSimpleGroundHeightWithFloor ( const Vector * pos , float * height , Vector * normal = nullptr ) ; // find "simple" ground height, treating current nav area as part of the floor
2015-06-30 12:46:07 +03:00
2017-07-01 23:40:10 +03:00
Place GetPlace ( ) const ; // get our current radio chatter place
2015-06-30 12:46:07 +03:00
2017-07-01 23:40:10 +03:00
bool IsUsingLadder ( ) const ; // returns true if we are in the process of negotiating a ladder
2016-02-04 03:18:26 +03:00
void GetOffLadder ( ) ;
2015-06-30 12:46:07 +03:00
2017-11-22 20:27:55 +03:00
void SetGoalEntity ( CBaseEntity * pEntity ) ;
2017-10-12 17:50:56 +03:00
template < typename T = CBaseEntity >
T * GetGoalEntity ( ) ;
2015-06-30 12:46:07 +03:00
2017-07-01 23:40:10 +03:00
bool IsNearJump ( ) const ; // return true if nearing a jump in the path
float GetApproximateFallDamage ( float height ) const ; // return how much damage will will take from the given fall height
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
void ForceRun ( float duration ) ; // force the bot to run if it moves for the given duration
void Wiggle ( ) ; // random movement, for getting un-stuck
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsFriendInTheWay ( const Vector * goalPos ) const ; // return true if a friend is between us and the given position
void FeelerReflexAdjustment ( Vector * goalPosition ) ; // do reflex avoidance movements if our "feelers" are touched
2016-01-19 14:54:31 +03:00
// looking around
void SetLookAngles ( float yaw , float pitch ) ; // set our desired look angles
2017-07-01 23:40:10 +03:00
void UpdateLookAngles ( ) ; // move actual view angles towards desired ones
void UpdateLookAround ( bool updateNow = false ) ; // update "looking around" mechanism
2016-01-19 14:54:31 +03:00
void InhibitLookAround ( float duration ) ; // block all "look at" and "looking around" behavior for given duration - just look ahead
// TODO: Clean up notion of "forward angle" and "look ahead angle"
2017-07-01 23:40:10 +03:00
void SetForwardAngle ( float angle ) ; // define our forward facing
2016-01-19 14:54:31 +03:00
void SetLookAheadAngle ( float angle ) ; // define default look ahead angle
// look at the given point in space for the given duration (-1 means forever)
void SetLookAt ( const char * desc , const Vector * pos , PriorityType pri , float duration = - 1.0f , bool clearIfClose = false , float angleTolerance = 5.0f ) ;
2017-07-01 23:40:10 +03:00
void ClearLookAt ( ) ; // stop looking at a point in space and just look ahead
2016-01-19 14:54:31 +03:00
bool IsLookingAtSpot ( PriorityType pri = PRIORITY_LOW ) const ; // return true if we are looking at spot with equal or higher priority
2017-07-01 23:40:10 +03:00
bool IsViewMoving ( float angleVelThreshold = 1.0f ) const ; // returns true if bot's view angles are rotating (not still)
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
const Vector & GetEyePosition ( ) const
2016-01-19 14:54:31 +03:00
{
m_eyePos = pev - > origin + pev - > view_ofs ;
return m_eyePos ;
}
2016-02-04 03:18:26 +03:00
float ComputeWeaponSightRange ( ) ; // return line-of-sight distance to obstacle along weapon fire ray
2017-10-12 17:50:56 +03:00
bool IsSignificantlyCloser ( const CBasePlayer * testPlayer , const CBasePlayer * referencePlayer ) const ; // return true if testPlayer is significantly closer than referencePlayer
2016-01-19 14:54:31 +03:00
// approach points
2016-02-04 03:18:26 +03:00
void ComputeApproachPoints ( ) ; // determine the set of "approach points" representing where the enemy can enter this region
2016-02-23 02:13:52 +03:00
void UpdateApproachPoints ( ) ; // recompute the approach point set if we have moved far enough to invalidate the current ones
2016-02-04 03:18:26 +03:00
void ClearApproachPoints ( ) ;
2017-07-01 23:40:10 +03:00
void DrawApproachPoints ( ) ; // for debugging
2016-01-19 14:54:31 +03:00
float GetHidingSpotCheckTimestamp ( HidingSpot * spot ) const ; // return time when given spot was last checked
2017-07-01 23:40:10 +03:00
void SetHidingSpotCheckTimestamp ( HidingSpot * spot ) ; // set the timestamp of the given spot to now
2016-01-19 14:54:31 +03:00
// weapon query and equip
# define MUST_EQUIP true
2017-07-01 23:40:10 +03:00
void EquipBestWeapon ( bool mustEquip = false ) ; // equip the best weapon we are carrying that has ammo
void EquipPistol ( ) ; // equip our pistol
void EquipKnife ( ) ; // equip our knife
2016-01-19 14:54:31 +03:00
# define DONT_USE_SMOKE_GRENADE true
2017-07-01 23:40:10 +03:00
bool EquipGrenade ( bool noSmoke = false ) ; // equip a grenade, return false if we cant
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
bool IsUsingKnife ( ) const ; // returns true if we have knife equipped
bool IsUsingPistol ( ) const ; // returns true if we have pistol equipped
2017-07-01 23:40:10 +03:00
bool IsUsingGrenade ( ) const ; // returns true if we have grenade equipped
bool IsUsingSniperRifle ( ) const ; // returns true if using a "sniper" rifle
2016-02-04 03:18:26 +03:00
bool IsUsingAWP ( ) const ; // returns true if we have AWP equipped
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
bool IsSniper ( ) const ; // return true if we have a sniper rifle in our inventory
bool IsSniping ( ) const ; // return true if we are actively sniping (moving to sniper spot or settled in)
2017-07-01 23:40:10 +03:00
bool IsUsingShotgun ( ) const ; // returns true if using a shotgun
bool IsUsingMachinegun ( ) const ; // returns true if using the big 'ol machinegun
void ThrowGrenade ( const Vector * target ) ; // begin the process of throwing the grenade
bool IsThrowingGrenade ( ) const ; // return true if we are in the process of throwing a grenade
2016-02-04 03:18:26 +03:00
bool HasGrenade ( ) const ; // return true if we have a grenade in our inventory
2016-01-19 14:54:31 +03:00
2016-02-04 03:18:26 +03:00
bool DoesActiveWeaponHaveSilencer ( ) const ;
bool IsUsingHEGrenade ( ) const ;
void StartRapidFire ( ) ;
void StopRapidFire ( ) ;
bool IsRapidFiring ( ) const ;
2016-01-19 14:54:31 +03:00
enum ZoomType { NO_ZOOM , LOW_ZOOM , HIGH_ZOOM } ;
2017-07-01 23:40:10 +03:00
ZoomType GetZoomLevel ( ) const ; // return the current zoom level of our weapon
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool AdjustZoom ( float range ) ; // change our zoom level to be appropriate for the given range
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool IsPrimaryWeaponEmpty ( ) const ; // return true if primary weapon doesn't exist or is totally out of ammo
2016-02-04 03:18:26 +03:00
bool IsPistolEmpty ( ) const ; // return true if secondary weapon doesn't exist or is totally out of ammo
int GetHostageEscortCount ( ) const ;
void IncreaseHostageEscortCount ( ) ;
float GetRangeToFarthestEscortedHostage ( ) const ;
void ResetWaitForHostagePatience ( ) ;
2017-07-01 23:40:10 +03:00
void ResetValues ( ) ; // reset internal data to initial state
2016-02-04 03:18:26 +03:00
void BotDeathThink ( ) ;
CBasePlayer * FindNearbyPlayer ( ) ;
void AdjustSafeTime ( ) ; // called when enemy seen to adjust safe time for this round
2017-11-22 20:27:55 +03:00
void EXPORT BotTouch ( CBaseEntity * pOther ) ;
2016-01-19 14:54:31 +03:00
bool HasAnyAmmo ( CBasePlayerWeapon * weapon ) const ;
2015-06-30 12:46:07 +03:00
private :
friend class CCSBotManager ;
2016-01-19 14:54:31 +03:00
// TODO: Get rid of these
2015-06-30 12:46:07 +03:00
friend class AttackState ;
friend class BuyState ;
2017-07-01 23:40:10 +03:00
char m_name [ 64 ] ; // copied from STRING(pev->netname) for debugging
2016-01-19 14:54:31 +03:00
// 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
2015-06-30 12:46:07 +03:00
mutable CountdownTimer m_rogueTimer ;
2016-01-19 14:54:31 +03:00
MoraleType m_morale ; // our current morale, based on our win/loss history
bool m_diedLastRound ; // true if we died last round
2017-07-01 23:40:10 +03:00
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
2016-01-19 14:54:31 +03:00
// TODO: implement through CountdownTimer
float m_surpriseDelay ; // when we were surprised
2015-06-30 12:46:07 +03:00
float m_surpriseTimestamp ;
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
bool m_isFollowing ; // true if we are following someone
2017-10-12 17:50:56 +03:00
EntityHandle < CBasePlayer > m_leader ; // the ID of who we are following
2016-01-19 14:54:31 +03:00
float m_followTimestamp ; // when we started following
2017-07-01 23:40:10 +03:00
float m_allowAutoFollowTime ; // time when we can auto follow
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
CountdownTimer m_hurryTimer ; // if valid, bot is in a hurry
2016-01-19 14:54:31 +03:00
// instances of each possible behavior state, to avoid dynamic memory allocation during runtime
2015-06-30 12:46:07 +03:00
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 ;
2016-01-19 14:54:31 +03:00
// TODO: Allow multiple simultaneous state machines (look around, etc)
2017-07-01 23:40:10 +03:00
void SetState ( BotState * state ) ; // set the current behavior state
2016-01-19 14:54:31 +03:00
BotState * m_state ; // current behavior state
2017-07-01 23:40:10 +03:00
float m_stateTimestamp ; // time state was entered
2016-01-19 14:54:31 +03:00
bool m_isAttacking ; // if true, special Attack state is overriding the state machine
TaskType m_task ; // our current task
2017-10-12 17:50:56 +03:00
EntityHandle < CBaseEntity > m_taskEntity ; // an entity used for our task
2016-01-19 14:54:31 +03:00
// navigation
2015-06-30 12:46:07 +03:00
Vector m_goalPosition ;
2017-10-12 17:50:56 +03:00
EHandle m_goalEntity ;
2016-01-19 14:54:31 +03:00
void MoveTowardsPosition ( const Vector * pos ) ; // move towards position, independant of view angle
2016-02-23 02:13:52 +03:00
void MoveAwayFromPosition ( const Vector * pos ) ; // move away from position, independant of view angle
2016-01-19 14:54:31 +03:00
void StrafeAwayFromPosition ( const Vector * pos ) ; // strafe (sidestep) away from position, independant of view angle
2017-07-01 23:40:10 +03:00
void StuckCheck ( ) ; // check if we have become stuck
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
CNavArea * m_currentArea ; // the nav area we are standing on
CNavArea * m_lastKnownArea ; // the last area we were in
2017-10-12 17:50:56 +03:00
EntityHandle < CBasePlayer > m_avoid ; // higher priority player we need to make way for
2015-06-30 12:46:07 +03:00
float m_avoidTimestamp ;
bool m_isJumpCrouching ;
bool m_isJumpCrouched ;
float m_jumpCrouchTimestamp ;
2016-01-19 14:54:31 +03:00
// path navigation data
2017-11-01 18:01:24 +03:00
enum { MAX_PATH_LENGTH = 256 } ;
2015-06-30 12:46:07 +03:00
struct ConnectInfo
{
2017-07-01 23:40:10 +03:00
CNavArea * area ; // the area along the path
2016-01-19 14:54:31 +03:00
NavTraverseType how ; // how to enter this area from the previous one
2017-07-01 23:40:10 +03:00
Vector pos ; // our movement goal position at this point in the path
2016-01-19 14:54:31 +03:00
const CNavLadder * ladder ; // if "how" refers to a ladder, this is it
}
2016-02-23 02:13:52 +03:00
m_path [ MAX_PATH_LENGTH ] ;
2015-06-30 12:46:07 +03:00
int m_pathLength ;
int m_pathIndex ;
float m_areaEnteredTimestamp ;
2017-07-01 23:40:10 +03:00
void BuildTrivialPath ( const Vector * goal ) ; // build trivial path to goal, assuming we are already in the same area
2016-01-19 14:54:31 +03:00
bool FindGrenadeTossPathTarget ( Vector * pos ) ;
CountdownTimer m_repathTimer ; // must have elapsed before bot can pathfind again
2016-02-04 03:18:26 +03:00
bool ComputePathPositions ( ) ; // determine actual path positions bot will move between along the path
void SetupLadderMovement ( ) ;
2016-01-19 14:54:31 +03:00
void SetPathIndex ( int newIndex ) ; // set the current index along the path
2016-02-04 03:18:26 +03:00
void DrawPath ( ) ;
2017-11-22 20:27:55 +03:00
int FindOurPositionOnPath ( Vector * close , bool local = false ) const ; // compute the closest point to our current position on our path
2017-10-12 17:50:56 +03:00
int FindPathPoint ( float aheadRange , Vector * point , int * prevIndex = nullptr ) ; // compute a point a fixed distance ahead along our path.
2016-01-19 14:54:31 +03:00
bool FindClosestPointOnPath ( const Vector * worldPos , int startIndex , int endIndex , Vector * close ) const ; // compute closest point on path to given point
2017-07-01 23:40:10 +03:00
bool IsStraightLinePathWalkable ( const Vector * goal ) const ; // test for un-jumpable height change, or unrecoverable fall
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
mutable CountdownTimer m_avoidFriendTimer ; // used to throttle how often we check for friends in our path
2016-01-19 14:54:31 +03:00
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
# define ONLY_JUMP_DOWN true
bool DiscontinuityJump ( float ground , bool onlyJumpDown = false , bool mustJump = false ) ; // check if we need to jump due to height change
2015-06-30 12:46:07 +03:00
enum LadderNavState
{
2016-01-19 14:54:31 +03:00
APPROACH_ASCENDING_LADDER , // prepare to scale a ladder
APPROACH_DESCENDING_LADDER , // prepare to go down ladder
2015-06-30 12:46:07 +03:00
FACE_ASCENDING_LADDER ,
FACE_DESCENDING_LADDER ,
2016-01-19 14:54:31 +03:00
MOUNT_ASCENDING_LADDER , // move toward ladder until "on" it
MOUNT_DESCENDING_LADDER , // move toward ladder until "on" it
2017-07-01 23:40:10 +03:00
ASCEND_LADDER , // go up the ladder
DESCEND_LADDER , // go down the ladder
2016-01-19 14:54:31 +03:00
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
2015-06-30 12:46:07 +03:00
}
m_pathLadderState ;
2017-07-01 23:40:10 +03:00
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
bool UpdateLadderMovement ( ) ; // called by UpdatePathMovement()
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
2016-01-19 14:54:31 +03:00
void ComputeLadderEndpoint ( bool isAscending ) ;
2017-07-01 23:40:10 +03:00
float m_pathLadderTimestamp ; // time when we started using ladder - for timeout check
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
CountdownTimer m_mustRunTimer ; // if nonzero, bot cannot walk
2016-01-19 14:54:31 +03:00
// game scenario mechanisms
2015-06-30 12:46:07 +03:00
CSGameState m_gameState ;
2016-01-19 14:54:31 +03:00
// hostages mechanism
2015-06-30 12:46:07 +03:00
byte m_hostageEscortCount ;
2016-02-04 03:18:26 +03:00
void UpdateHostageEscortCount ( ) ;
2015-06-30 12:46:07 +03:00
float m_hostageEscortCountTimestamp ;
bool m_isWaitingForHostage ;
CountdownTimer m_inhibitWaitingForHostageTimer ;
CountdownTimer m_waitForHostageTimer ;
2016-01-19 14:54:31 +03:00
// 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
2015-06-30 12:46:07 +03:00
float m_noiseCheckTimestamp ;
2017-07-01 23:40:10 +03:00
PriorityType m_noisePriority ; // priority of currently heard noise
2016-02-04 03:18:26 +03:00
bool UpdateLookAtNoise ( ) ; // return true if we decided to look towards the most recent noise source
2015-06-30 12:46:07 +03:00
bool m_isNoiseTravelRangeChecked ;
2016-01-19 14:54:31 +03:00
// "looking around" mechanism
2017-07-01 23:40:10 +03:00
float m_lookAroundStateTimestamp ; // time of next state change
2016-01-19 14:54:31 +03:00
float m_lookAheadAngle ; // our desired forward look angle
float m_forwardAngle ; // our current forward facing direction
2017-07-01 23:40:10 +03:00
float m_inhibitLookAroundTimestamp ; // time when we can look around again
2015-06-30 12:46:07 +03:00
enum LookAtSpotState
{
2017-07-01 23:40:10 +03:00
NOT_LOOKING_AT_SPOT , // not currently looking at a point in space
2016-01-19 14:54:31 +03:00
LOOK_TOWARDS_SPOT , // in the process of aiming at m_lookAtSpot
LOOK_AT_SPOT , // looking at m_lookAtSpot
NUM_LOOK_AT_SPOT_STATES
2015-06-30 12:46:07 +03:00
}
m_lookAtSpotState ;
2016-04-05 03:12:05 +03:00
2017-07-01 23:40:10 +03:00
Vector m_lookAtSpot ; // the spot we're currently looking at
2015-06-30 12:46:07 +03:00
PriorityType m_lookAtSpotPriority ;
2017-07-01 23:40:10 +03:00
float m_lookAtSpotDuration ; // how long we need to look at the spot
2016-01-19 14:54:31 +03:00
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
2017-07-01 23:40:10 +03:00
const char * m_lookAtDesc ; // for debugging
2016-02-04 03:18:26 +03:00
void UpdateLookAt ( ) ;
void UpdatePeripheralVision ( ) ; // update enounter spot timestamps, etc
2015-06-30 12:46:07 +03:00
float m_peripheralTimestamp ;
enum { MAX_APPROACH_POINTS = 16 } ;
2016-02-23 02:13:52 +03:00
Vector m_approachPoint [ MAX_APPROACH_POINTS ] ;
2015-06-30 12:46:07 +03:00
unsigned char m_approachPointCount ;
2016-01-19 14:54:31 +03:00
Vector m_approachPointViewPosition ; // the position used when computing current approachPoint set
2017-07-01 23:40:10 +03:00
bool BendLineOfSight ( const Vector * eye , const Vector * point , Vector * bend ) const ; // "bend" our line of sight until we can see the target point. Return bend point, false if cant bend.
bool FindApproachPointNearestPath ( Vector * pos ) ; // find the approach point that is nearest to our current path, ahead of us
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
bool m_isWaitingToTossGrenade ; // lining up throw
CountdownTimer m_tossGrenadeTimer ; // timeout timer for grenade tossing
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
SpotEncounter * m_spotEncounter ; // the spots we will encounter as we move thru our current area
2017-07-01 23:40:10 +03:00
float m_spotCheckTimestamp ; // when to check next encounter spot
2016-01-19 14:54:31 +03:00
// TODO: Add timestamp for each possible client to hiding spots
2015-06-30 12:46:07 +03:00
enum { MAX_CHECKED_SPOTS = 64 } ;
struct HidingSpotCheckInfo
{
HidingSpot * spot ;
float timestamp ;
2016-01-19 14:54:31 +03:00
}
2016-02-23 02:13:52 +03:00
m_checkedHidingSpot [ MAX_CHECKED_SPOTS ] ;
2015-06-30 12:46:07 +03:00
int m_checkedHidingSpotCount ;
2016-01-19 14:54:31 +03:00
// view angle mechanism
2017-07-01 23:40:10 +03:00
float m_lookPitch ; // our desired look pitch angle
2015-06-30 12:46:07 +03:00
float m_lookPitchVel ;
2017-07-01 23:40:10 +03:00
float m_lookYaw ; // our desired look yaw angle
2015-06-30 12:46:07 +03:00
float m_lookYawVel ;
2016-01-19 14:54:31 +03:00
// aim angle mechanism
mutable Vector m_eyePos ;
2017-07-01 23:40:10 +03:00
Vector m_aimOffset ; // current error added to victim's position to get actual aim spot
2016-01-19 14:54:31 +03:00
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
2017-07-01 23:40:10 +03:00
void SetAimOffset ( float accuracy ) ; // set the current aim offset
2016-02-04 03:18:26 +03:00
void UpdateAimOffset ( ) ; // wiggle aim error based on m_accuracy
2017-07-01 23:40:10 +03:00
Vector m_aimSpot ; // the spot we are currently aiming to fire at
2016-01-19 14:54:31 +03:00
// attack state data
2017-10-12 17:50:56 +03:00
DispositionType m_disposition ; // how we will react to enemies
CountdownTimer m_ignoreEnemiesTimer ; // how long will we ignore enemies
mutable EntityHandle < CBasePlayer > 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
2015-06-30 12:46:07 +03:00
float m_lastSawEnemyTimestamp ;
float m_firstSawEnemyTimestamp ;
float m_currentEnemyAcquireTimestamp ;
2017-07-01 23:40:10 +03:00
float m_enemyDeathTimestamp ; // if m_enemy is dead, this is when he died
2016-01-19 14:54:31 +03:00
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
2015-06-30 12:46:07 +03:00
struct WatchInfo
{
float timestamp ;
bool isEnemy ;
2016-01-19 14:54:31 +03:00
}
2016-02-23 02:13:52 +03:00
m_watchInfo [ MAX_CLIENTS ] ;
2017-10-12 17:50:56 +03:00
mutable EntityHandle < CBasePlayer > m_bomber ; // points to bomber if we can see him
int m_nearbyFriendCount ; // number of nearby teammates
mutable EntityHandle < CBasePlayer > m_closestVisibleFriend ; // the closest friend we can see
mutable EntityHandle < CBasePlayer > m_closestVisibleHumanFriend ; // the closest human friend we can see
2016-01-19 14:54:31 +03:00
2017-10-12 17:50:56 +03:00
# ifdef REGAMEDLL_ADD
IntervalTimer m_attentionInterval ; // time between attention checks
# endif
2016-01-19 14:54:31 +03:00
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
2017-07-01 23:40:10 +03:00
int m_lastVictimID ; // the entindex of the last victim we killed, or zero
2016-01-19 14:54:31 +03:00
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
2017-10-12 17:50:56 +03:00
bool DoEquip ( CBasePlayerWeapon * pWeapon ) ; // equip the given item
2016-01-19 14:54:31 +03:00
2017-07-01 23:40:10 +03:00
void ReloadCheck ( ) ; // reload our weapon if we must
2016-02-04 03:18:26 +03:00
void SilencerCheck ( ) ; // use silencer
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
float m_fireWeaponTimestamp ;
2016-01-19 14:54:31 +03:00
// reaction time system
2015-06-30 12:46:07 +03:00
enum { MAX_ENEMY_QUEUE = 20 } ;
struct ReactionState
{
2016-01-19 14:54:31 +03:00
// NOTE: player position & orientation is not currently stored separately
2017-10-12 17:50:56 +03:00
EntityHandle < CBasePlayer > player ;
2015-06-30 12:46:07 +03:00
bool isReloading ;
bool isProtectedByShield ;
2016-01-19 14:54:31 +03:00
}
2016-02-23 02:13:52 +03:00
m_enemyQueue [ MAX_ENEMY_QUEUE ] ; // round-robin queue for simulating reaction times
2015-06-30 12:46:07 +03:00
byte m_enemyQueueIndex ;
byte m_enemyQueueCount ;
2016-01-19 14:54:31 +03:00
byte m_enemyQueueAttendIndex ; // index of the timeframe we are "conscious" of
2017-07-01 23:40:10 +03:00
CBasePlayer * FindMostDangerousThreat ( ) ; // return most dangerous threat in my field of view (feeds into reaction time queue)
2016-01-19 14:54:31 +03:00
// stuck detection
2015-06-30 12:46:07 +03:00
bool m_isStuck ;
2016-01-19 14:54:31 +03:00
float m_stuckTimestamp ; // time when we got stuck
2017-07-01 23:40:10 +03:00
Vector m_stuckSpot ; // the location where we became stuck
2015-06-30 12:46:07 +03:00
NavRelativeDirType m_wiggleDirection ;
float m_wiggleTimestamp ;
2016-01-19 14:54:31 +03:00
float m_stuckJumpTimestamp ; // time for next jump when stuck
2015-06-30 12:46:07 +03:00
enum { MAX_VEL_SAMPLES = 5 } ;
2016-02-23 02:13:52 +03:00
float m_avgVel [ MAX_VEL_SAMPLES ] ;
2015-06-30 12:46:07 +03:00
int m_avgVelIndex ;
int m_avgVelCount ;
Vector m_lastOrigin ;
2016-01-19 14:54:31 +03:00
// chatter mechanism
2017-10-12 17:50:56 +03:00
GameEventType m_lastRadioCommand ; // last radio command we recieved
2016-02-04 03:18:26 +03:00
void RespondToRadioCommands ( ) ;
2017-07-01 23:40:10 +03:00
bool IsRadioCommand ( GameEventType event ) const ; // returns true if the radio message is an order to do something
2016-01-25 20:02:57 +03:00
# define NO_FORCE false
2016-01-19 14:54:31 +03:00
void EndVoiceFeedback ( bool force = true ) ;
float m_lastRadioRecievedTimestamp ; // time we recieved a radio message
float m_lastRadioSentTimestamp ; // time when we send a radio message
2017-10-12 17:50:56 +03:00
EntityHandle < CBasePlayer > m_radioSubject ; // who issued the radio message
2017-07-01 23:40:10 +03:00
Vector m_radioPosition ; // position referred to in radio message
2015-06-30 12:46:07 +03:00
float m_voiceFeedbackStartTimestamp ;
2016-01-19 14:54:31 +03:00
float m_voiceFeedbackEndTimestamp ; // new-style "voice" chatter gets voice feedback
2015-06-30 12:46:07 +03:00
BotChatterInterface m_chatter ;
2016-01-19 14:54:31 +03:00
// learn map mechanism
const CNavNode * m_navNodeList ;
2015-06-30 12:46:07 +03:00
CNavNode * m_currentNode ;
NavDirType m_generationDir ;
2016-04-05 03:12:05 +03:00
2015-06-30 12:46:07 +03:00
enum ProcessType
{
2016-01-19 14:54:31 +03:00
PROCESS_NORMAL ,
2015-06-30 12:46:07 +03:00
PROCESS_LEARN ,
PROCESS_ANALYZE_ALPHA ,
PROCESS_ANALYZE_BETA ,
PROCESS_SAVE ,
}
m_processMode ;
CountdownTimer m_mumbleTimer ;
CountdownTimer m_booTimer ;
CountdownTimer m_relocateTimer ;
2016-01-19 14:54:31 +03:00
CNavNode * AddNode ( const Vector * destPos , const Vector * normal , NavDirType dir , CNavNode * source ) ;
2016-02-04 03:18:26 +03:00
void StartLearnProcess ( ) ;
void UpdateLearnProcess ( ) ;
bool LearnStep ( ) ;
void StartAnalyzeAlphaProcess ( ) ;
void UpdateAnalyzeAlphaProcess ( ) ;
bool AnalyzeAlphaStep ( ) ;
void StartAnalyzeBetaProcess ( ) ;
void UpdateAnalyzeBetaProcess ( ) ;
bool AnalyzeBetaStep ( ) ;
void StartSaveProcess ( ) ;
void UpdateSaveProcess ( ) ;
void StartNormalProcess ( ) ;
2017-10-12 17:50:56 +03:00
# ifdef REGAMEDLL_ADD
2017-11-22 20:27:55 +03:00
bool IsNoticable ( const CBasePlayer * pPlayer , unsigned char visibleParts ) const ; // return true if we "notice" given player
2017-10-12 17:50:56 +03:00
# endif
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// Inlines
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetCombatRange ( ) const
2016-01-19 14:54:31 +03:00
{
return m_combatRange ;
}
inline void CCSBot : : SetRogue ( bool rogue )
{
m_isRogue = rogue ;
}
inline void CCSBot : : Hurry ( float duration )
{
m_hurryTimer . Start ( duration ) ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetSafeTime ( ) const
2016-01-19 14:54:31 +03:00
{
return m_safeTime ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsCarryingBomb ( ) const
2016-01-19 14:54:31 +03:00
{
return m_bHasC4 ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsFollowing ( ) const
2016-01-19 14:54:31 +03:00
{
return m_isFollowing ;
}
2016-02-04 03:18:26 +03:00
inline CBasePlayer * CCSBot : : GetFollowLeader ( )
2016-01-19 14:54:31 +03:00
{
return m_leader ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetFollowDuration ( ) const
2016-01-19 14:54:31 +03:00
{
return gpGlobals - > time - m_followTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : CanAutoFollow ( ) const
2016-01-19 14:54:31 +03:00
{
return ( gpGlobals - > time > m_allowAutoFollowTime ) ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : AimAtEnemy ( )
2016-01-19 14:54:31 +03:00
{
m_isAimingAtEnemy = true ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : StopAiming ( )
2016-01-19 14:54:31 +03:00
{
m_isAimingAtEnemy = false ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsAimingAtEnemy ( ) const
2016-01-19 14:54:31 +03:00
{
return m_isAimingAtEnemy ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsSurprised ( ) const
2016-01-19 14:54:31 +03:00
{
2016-02-23 02:13:52 +03:00
if ( gpGlobals - > time - m_surpriseTimestamp < 5.0f )
return true ;
return false ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetSurpriseDelay ( ) const
2016-01-19 14:54:31 +03:00
{
2016-02-23 02:13:52 +03:00
if ( ! IsSurprised ( ) )
return 0.0f ;
return m_surpriseDelay ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : ClearSurpriseDelay ( )
2016-01-19 14:54:31 +03:00
{
m_surpriseDelay = 0.0f ;
m_surpriseTimestamp = 0.0f ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetStateTimestamp ( ) const
2016-01-19 14:54:31 +03:00
{
return m_stateTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline CSGameState * CCSBot : : GetGameState ( )
2016-01-19 14:54:31 +03:00
{
return & m_gameState ;
}
2016-02-04 03:18:26 +03:00
inline const CSGameState * CCSBot : : GetGameState ( ) const
2016-01-19 14:54:31 +03:00
{
return & m_gameState ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsAtBombsite ( )
2016-01-19 14:54:31 +03:00
{
2016-01-25 20:02:57 +03:00
return ( m_signals . GetState ( ) & SIGNAL_BOMB ) = = SIGNAL_BOMB ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline CCSBot : : MoraleType CCSBot : : GetMorale ( ) const
2016-01-19 14:54:31 +03:00
{
return m_morale ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsNoiseHeard ( ) const
2016-01-19 14:54:31 +03:00
{
if ( m_noiseTimestamp < = 0.0f )
return false ;
// primitive reaction time simulation - cannot "hear" noise until reaction time has elapsed
if ( gpGlobals - > time - m_noiseTimestamp > = GetProfile ( ) - > GetReactionTime ( ) )
return true ;
return false ;
}
2017-11-22 20:27:55 +03:00
inline void CCSBot : : SetTask ( TaskType task , CBaseEntity * pEntity )
2016-01-19 14:54:31 +03:00
{
m_task = task ;
2017-11-22 20:27:55 +03:00
m_taskEntity = pEntity ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline CCSBot : : TaskType CCSBot : : GetTask ( ) const
2016-01-19 14:54:31 +03:00
{
return m_task ;
}
2016-02-04 03:18:26 +03:00
inline CBaseEntity * CCSBot : : GetTaskEntity ( )
2016-01-19 14:54:31 +03:00
{
return m_taskEntity ;
}
2016-02-04 03:18:26 +03:00
inline CNavArea * CCSBot : : GetNoiseArea ( ) const
2016-01-19 14:54:31 +03:00
{
return m_noiseArea ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : ForgetNoise ( )
2016-01-19 14:54:31 +03:00
{
m_noiseTimestamp = 0.0f ;
}
2016-02-04 03:18:26 +03:00
inline PriorityType CCSBot : : GetNoisePriority ( ) const
2016-01-19 14:54:31 +03:00
{
return m_noisePriority ;
}
2016-02-04 03:18:26 +03:00
inline BotChatterInterface * CCSBot : : GetChatter ( )
2016-01-19 14:54:31 +03:00
{
return & m_chatter ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsUsingVoice ( ) const
2016-01-19 14:54:31 +03:00
{
2016-01-25 20:02:57 +03:00
return ( m_voiceFeedbackEndTimestamp ! = 0.0f ) ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline CBasePlayer * CCSBot : : GetEnemy ( )
2016-01-19 14:54:31 +03:00
{
return m_enemy ;
}
2016-02-04 03:18:26 +03:00
inline int CCSBot : : GetNearbyEnemyCount ( ) const
2016-01-19 14:54:31 +03:00
{
return Q_min ( GetEnemiesRemaining ( ) , m_nearbyEnemyCount ) ;
}
2016-02-04 03:18:26 +03:00
inline unsigned int CCSBot : : GetEnemyPlace ( ) const
2016-01-19 14:54:31 +03:00
{
return m_enemyPlace ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : CanSeeBomber ( ) const
2016-01-19 14:54:31 +03:00
{
2017-10-12 17:50:56 +03:00
return m_bomber . IsValid ( ) ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline CBasePlayer * CCSBot : : GetBomber ( ) const
2016-01-19 14:54:31 +03:00
{
return m_bomber ;
}
2016-02-04 03:18:26 +03:00
inline int CCSBot : : GetNearbyFriendCount ( ) const
2016-01-19 14:54:31 +03:00
{
return Q_min ( GetFriendsRemaining ( ) , m_nearbyFriendCount ) ;
}
2016-02-04 03:18:26 +03:00
inline CBasePlayer * CCSBot : : GetClosestVisibleFriend ( ) const
2016-01-19 14:54:31 +03:00
{
return m_closestVisibleFriend ;
}
2016-02-04 03:18:26 +03:00
inline CBasePlayer * CCSBot : : GetClosestVisibleHumanFriend ( ) const
2016-01-19 14:54:31 +03:00
{
return m_closestVisibleHumanFriend ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetTimeSinceAttacked ( ) const
2016-01-19 14:54:31 +03:00
{
return gpGlobals - > time - m_attackedTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetFirstSawEnemyTimestamp ( ) const
2016-01-19 14:54:31 +03:00
{
return m_firstSawEnemyTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetLastSawEnemyTimestamp ( ) const
2016-01-19 14:54:31 +03:00
{
return m_lastSawEnemyTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetTimeSinceLastSawEnemy ( ) const
2016-01-19 14:54:31 +03:00
{
return gpGlobals - > time - m_lastSawEnemyTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetTimeSinceAcquiredCurrentEnemy ( ) const
2016-01-19 14:54:31 +03:00
{
return gpGlobals - > time - m_currentEnemyAcquireTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline const Vector & CCSBot : : GetLastKnownEnemyPosition ( ) const
2016-01-19 14:54:31 +03:00
{
return m_lastEnemyPosition ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsEnemyVisible ( ) const
2016-01-19 14:54:31 +03:00
{
return m_isEnemyVisible ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetEnemyDeathTimestamp ( ) const
2016-01-19 14:54:31 +03:00
{
return m_enemyDeathTimestamp ;
}
2016-02-04 03:18:26 +03:00
inline int CCSBot : : GetLastVictimID ( ) const
2016-01-19 14:54:31 +03:00
{
return m_lastVictimID ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : HasPath ( ) const
2016-01-19 14:54:31 +03:00
{
return m_pathLength ! = 0 ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : DestroyPath ( )
2016-01-19 14:54:31 +03:00
{
m_pathLength = 0 ;
2017-10-12 17:50:56 +03:00
m_pathLadder = nullptr ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline CNavArea * CCSBot : : GetLastKnownArea ( ) const
2016-01-19 14:54:31 +03:00
{
return m_lastKnownArea ;
}
2016-02-04 03:18:26 +03:00
inline const Vector & CCSBot : : GetPathEndpoint ( ) const
2016-01-19 14:54:31 +03:00
{
2016-02-23 02:13:52 +03:00
return m_path [ m_pathLength - 1 ] . pos ;
2016-01-19 14:54:31 +03:00
}
inline const Vector & CCSBot : : GetPathPosition ( int numpath ) const
{
2016-02-23 02:13:52 +03:00
return m_path [ numpath ] . pos ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsUsingLadder ( ) const
2016-01-19 14:54:31 +03:00
{
2017-10-12 17:50:56 +03:00
return m_pathLadder ! = nullptr ;
2016-01-19 14:54:31 +03:00
}
2017-11-22 20:27:55 +03:00
inline void CCSBot : : SetGoalEntity ( CBaseEntity * pEntity )
2016-01-19 14:54:31 +03:00
{
2017-11-22 20:27:55 +03:00
m_goalEntity = pEntity ;
2016-01-19 14:54:31 +03:00
}
2017-10-12 17:50:56 +03:00
template < typename T >
inline T * CCSBot : : GetGoalEntity ( )
2016-01-19 14:54:31 +03:00
{
2017-10-12 17:50:56 +03:00
return m_goalEntity . Get < T > ( ) ;
2016-01-19 14:54:31 +03:00
}
inline void CCSBot : : ForceRun ( float duration )
{
Run ( ) ;
m_mustRunTimer . Start ( duration ) ;
}
inline void CCSBot : : SetLookAngles ( float yaw , float pitch )
{
m_lookYaw = yaw ;
m_lookPitch = pitch ;
}
inline void CCSBot : : SetForwardAngle ( float angle )
{
m_forwardAngle = angle ;
}
inline void CCSBot : : SetLookAheadAngle ( float angle )
{
m_lookAheadAngle = angle ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : ClearLookAt ( )
2016-01-19 14:54:31 +03:00
{
//PrintIfWatched("ClearLookAt()\n");
m_lookAtSpotState = NOT_LOOKING_AT_SPOT ;
2017-10-12 17:50:56 +03:00
m_lookAtDesc = nullptr ;
2016-01-19 14:54:31 +03:00
}
inline bool CCSBot : : IsLookingAtSpot ( PriorityType pri ) const
{
if ( m_lookAtSpotState ! = NOT_LOOKING_AT_SPOT & & m_lookAtSpotPriority > = pri )
return true ;
return false ;
}
inline bool CCSBot : : IsViewMoving ( float angleVelThreshold ) const
{
if ( m_lookYawVel < angleVelThreshold & & m_lookYawVel > - angleVelThreshold & &
m_lookPitchVel < angleVelThreshold & & m_lookPitchVel > - angleVelThreshold )
{
return false ;
}
2016-02-23 02:13:52 +03:00
2016-01-19 14:54:31 +03:00
return true ;
}
2017-10-12 17:50:56 +03:00
inline bool CCSBot : : IsSignificantlyCloser ( const CBasePlayer * testPlayer , const CBasePlayer * referencePlayer ) const
{
if ( ! referencePlayer | | ! testPlayer )
return true ;
float testDist = ( pev - > origin - testPlayer - > pev - > origin ) . Length ( ) ;
float referenceDist = ( pev - > origin - referencePlayer - > pev - > origin ) . Length ( ) ;
const float significantRangeFraction = 0.7f ;
if ( testDist < referenceDist * significantRangeFraction )
return true ;
return false ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : ClearApproachPoints ( )
2016-01-19 14:54:31 +03:00
{
m_approachPointCount = 0 ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsThrowingGrenade ( ) const
2016-01-19 14:54:31 +03:00
{
return m_isWaitingToTossGrenade ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : StartRapidFire ( )
2016-01-19 14:54:31 +03:00
{
m_isRapidFiring = true ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : StopRapidFire ( )
2016-01-19 14:54:31 +03:00
{
m_isRapidFiring = false ;
}
2016-02-04 03:18:26 +03:00
inline CCSBot : : ZoomType CCSBot : : GetZoomLevel ( ) const
2016-01-19 14:54:31 +03:00
{
if ( m_iFOV > 60.0f )
return NO_ZOOM ;
if ( m_iFOV > 25.0f )
return LOW_ZOOM ;
return HIGH_ZOOM ;
}
2016-02-04 03:18:26 +03:00
inline int CCSBot : : GetHostageEscortCount ( ) const
2016-01-19 14:54:31 +03:00
{
return m_hostageEscortCount ;
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : IncreaseHostageEscortCount ( )
2016-01-19 14:54:31 +03:00
{
2017-11-22 20:27:55 +03:00
m_hostageEscortCount + + ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline void CCSBot : : ResetWaitForHostagePatience ( )
2016-01-19 14:54:31 +03:00
{
m_isWaitingForHostage = false ;
m_inhibitWaitingForHostageTimer . Invalidate ( ) ;
}
2016-02-04 03:18:26 +03:00
inline float CCSBot : : GetFeetZ ( ) const
2016-01-19 14:54:31 +03:00
{
if ( IsCrouching ( ) )
{
2016-05-11 17:06:43 +03:00
const Vector crouch ( 0 , 0 , - StepHeight ) ;
2016-01-19 14:54:31 +03:00
return ( pev - > origin + crouch ) . z ;
}
else
{
2016-05-11 17:06:43 +03:00
const Vector stand ( 0 , 0 , - HalfHumanHeight ) ;
2016-01-19 14:54:31 +03:00
return ( pev - > origin + stand ) . z ;
}
}
2016-02-04 03:18:26 +03:00
inline const Vector * CCSBot : : GetNoisePosition ( ) const
2016-01-19 14:54:31 +03:00
{
if ( m_noiseTimestamp > 0.0f )
return & m_noisePosition ;
2017-10-12 17:50:56 +03:00
return nullptr ;
2016-01-19 14:54:31 +03:00
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsAwareOfEnemyDeath ( ) const
2016-01-19 14:54:31 +03:00
{
if ( GetEnemyDeathTimestamp ( ) = = 0.0f )
return false ;
2017-10-12 17:50:56 +03:00
if ( ! m_enemy . IsValid ( ) )
2016-01-19 14:54:31 +03:00
return true ;
if ( ! m_enemy - > IsAlive ( ) & & gpGlobals - > time - GetEnemyDeathTimestamp ( ) > ( 1.0f - GetProfile ( ) - > GetSkill ( ) ) )
return true ;
return false ;
}
2016-02-04 03:18:26 +03:00
inline bool CCSBot : : IsNotMoving ( ) const
2016-01-19 14:54:31 +03:00
{
const float stillSpeed = 10.0f ;
return pev - > velocity . IsLengthLessThan ( stillSpeed ) ;
}
inline bool CCSBot : : HasAnyAmmo ( CBasePlayerWeapon * weapon ) const
{
return ( weapon - > m_iClip ! = 0 | | m_rgAmmo [ weapon - > m_iPrimaryAmmoType ] > 0 ) ;
}
2015-06-30 12:46:07 +03:00
class CollectRetreatSpotsFunctor
{
public :
CollectRetreatSpotsFunctor ( CCSBot * me , float range )
{
m_me = me ;
m_count = 0 ;
m_range = range ;
}
enum { MAX_SPOTS = 256 } ;
bool operator ( ) ( CNavArea * area )
{
// collect all the hiding spots in this area
2017-11-22 20:27:55 +03:00
for ( auto const spot : * area - > GetHidingSpotList ( ) )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
if ( m_count > = MAX_SPOTS )
break ;
2015-06-30 12:46:07 +03:00
// make sure hiding spot is in range
if ( m_range > 0.0f )
2016-01-19 14:54:31 +03:00
{
2015-06-30 12:46:07 +03:00
if ( ( * spot - > GetPosition ( ) - m_me - > pev - > origin ) . IsLengthGreaterThan ( m_range ) )
continue ;
2016-01-19 14:54:31 +03:00
}
2015-06-30 12:46:07 +03:00
// if a Player is using this hiding spot, don't consider it
if ( IsSpotOccupied ( m_me , spot - > GetPosition ( ) ) )
{
// player is in hiding spot
2015-12-09 01:39:54 +03:00
// TODO: Check if player is moving or sitting still
2015-06-30 12:46:07 +03:00
continue ;
}
// don't select spot if an enemy can see it
2016-01-19 14:54:31 +03:00
if ( UTIL_IsVisibleToTeam ( * spot - > GetPosition ( ) + Vector ( 0 , 0 , HalfHumanHeight ) , OtherTeam ( m_me - > m_iTeam ) ) )
2015-06-30 12:46:07 +03:00
continue ;
// don't select spot if it is closest to an enemy
CBasePlayer * owner = UTIL_GetClosestPlayer ( spot - > GetPosition ( ) ) ;
2017-10-12 17:50:56 +03:00
if ( owner & & m_me - > m_iTeam ! = owner - > m_iTeam )
2015-06-30 12:46:07 +03:00
continue ;
2016-02-23 02:13:52 +03:00
m_spot [ m_count + + ] = spot - > GetPosition ( ) ;
2015-06-30 12:46:07 +03:00
}
// if we've filled up, stop searching
if ( m_count = = MAX_SPOTS )
return false ;
return true ;
}
CCSBot * m_me ;
float m_range ;
2016-02-23 02:13:52 +03:00
const Vector * m_spot [ MAX_SPOTS ] ;
2015-06-30 12:46:07 +03:00
int m_count ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
class FarthestHostage
{
public :
2015-12-09 01:39:54 +03:00
FarthestHostage ( const CCSBot * me )
2015-06-30 12:46:07 +03:00
{
m_me = me ;
2016-01-19 14:54:31 +03:00
m_farRange = - 1.0f ;
2015-06-30 12:46:07 +03:00
}
bool operator ( ) ( CHostage * hostage )
{
2016-01-19 14:54:31 +03:00
if ( hostage - > IsFollowing ( m_me ) )
{
float range = ( hostage - > Center ( ) - m_me - > pev - > origin ) . Length ( ) ;
if ( range > m_farRange )
{
m_farRange = range ;
}
}
return true ;
2015-06-30 12:46:07 +03:00
}
2015-12-09 01:39:54 +03:00
2015-06-30 12:46:07 +03:00
const CCSBot * m_me ;
float m_farRange ;
2016-02-04 03:18:26 +03:00
} ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
// Functor used with NavAreaBuildPath()
2015-06-30 12:46:07 +03:00
class PathCost
{
public :
2017-11-22 20:27:55 +03:00
PathCost ( CCSBot * pBot , RouteType route = SAFEST_ROUTE )
2015-06-30 12:46:07 +03:00
{
2017-11-22 20:27:55 +03:00
m_bot = pBot ;
2015-06-30 12:46:07 +03:00
m_route = route ;
}
2015-12-05 22:40:30 +03:00
float operator ( ) ( CNavArea * area , CNavArea * fromArea , const CNavLadder * ladder )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
const float baseDangerFactor = 100.0f ;
2015-12-05 22:40:30 +03:00
2016-01-19 14:54:31 +03:00
// respond to the danger modulated by our aggression (even super-aggressives pay SOME attention to danger)
2015-06-30 12:46:07 +03:00
float dangerFactor = ( 1.0f - ( 0.95f * m_bot - > GetProfile ( ) - > GetAggression ( ) ) ) * baseDangerFactor ;
2015-12-05 22:40:30 +03:00
2017-10-12 17:50:56 +03:00
if ( fromArea = = nullptr )
2015-06-30 12:46:07 +03:00
{
if ( m_route = = FASTEST_ROUTE )
return 0.0f ;
2016-01-19 14:54:31 +03:00
// first area in path, cost is just danger
return dangerFactor * area - > GetDanger ( m_bot - > m_iTeam - 1 ) ;
2015-06-30 12:46:07 +03:00
}
2016-01-19 14:54:31 +03:00
else if ( ( fromArea - > GetAttributes ( ) & NAV_JUMP ) & & ( area - > GetAttributes ( ) & NAV_JUMP ) )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
// cannot actually walk in jump areas - disallow moving from jump area to jump area
2015-06-30 12:46:07 +03:00
return - 1.0f ;
}
else
{
2016-01-19 14:54:31 +03:00
// compute distance from previous area to this area
2015-06-30 12:46:07 +03:00
float dist ;
if ( ladder )
{
2016-01-19 14:54:31 +03:00
// ladders are slow to use
2015-06-30 12:46:07 +03:00
const float ladderPenalty = 1.0f ;
dist = ladderPenalty * ladder - > m_length ;
2016-01-19 14:54:31 +03:00
// if we are currently escorting hostages, avoid ladders (hostages are confused by them)
2015-06-30 12:46:07 +03:00
//if (m_bot->GetHostageEscortCount())
// dist *= 100.0f;
}
else
{
2016-01-19 14:54:31 +03:00
dist = ( * area - > GetCenter ( ) - * fromArea - > GetCenter ( ) ) . Length ( ) ;
2015-06-30 12:46:07 +03:00
}
2016-01-19 14:54:31 +03:00
// compute distance travelled along path so far
2015-06-30 12:46:07 +03:00
float cost = dist + fromArea - > GetCostSoFar ( ) ;
2016-01-19 14:54:31 +03:00
// zombies ignore all path penalties
if ( cv_bot_zombie . value > 0.0f )
2015-06-30 12:46:07 +03:00
return cost ;
2016-01-19 14:54:31 +03:00
// add cost of "jump down" pain unless we're jumping into water
if ( ! area - > IsConnected ( fromArea , NUM_DIRECTIONS ) )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
// this is a "jump down" (one way drop) transition - estimate damage we will take to traverse it
2015-06-30 12:46:07 +03:00
float fallDistance = - fromArea - > ComputeHeightChange ( area ) ;
2016-01-19 14:54:31 +03:00
// if it's a drop-down ladder, estimate height from the bottom of the ladder to the lower area
//if (ladder && ladder->m_bottom.z < fromArea->GetCenter()->z && ladder->m_bottom.z > area->GetCenter()->z)
//{
// fallDistance = ladder->m_bottom.z - area->GetCenter()->z;
//}
2016-04-05 03:12:05 +03:00
2015-06-30 12:46:07 +03:00
float fallDamage = m_bot - > GetApproximateFallDamage ( fallDistance ) ;
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
if ( fallDamage > 0.0f )
{
2016-01-19 14:54:31 +03:00
// if the fall would kill us, don't use it
2015-06-30 12:46:07 +03:00
const float deathFallMargin = 10.0f ;
if ( fallDamage + deathFallMargin > = m_bot - > pev - > health )
return - 1.0f ;
2016-01-19 14:54:31 +03:00
// if we need to get there in a hurry, ignore minor pain
2015-06-30 12:46:07 +03:00
const float painTolerance = 15.0f * m_bot - > GetProfile ( ) - > GetAggression ( ) + 10.0f ;
if ( m_route ! = FASTEST_ROUTE | | fallDamage > painTolerance )
{
2016-01-19 14:54:31 +03:00
// cost is proportional to how much it hurts when we fall
// 10 points - not a big deal, 50 points - ouch!
2015-06-30 12:46:07 +03:00
cost + = 100.0f * fallDamage * fallDamage ;
}
}
}
2016-01-19 14:54:31 +03:00
// if this is a "crouch" area, add penalty
if ( area - > GetAttributes ( ) & NAV_CROUCH )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
// these areas are very slow to move through
2017-11-22 20:27:55 +03:00
real_t crouchPenalty = ( m_route = = FASTEST_ROUTE ) ? 20.0f : 5.0f ;
2016-01-19 14:54:31 +03:00
// avoid crouch areas if we are rescuing hostages
if ( m_bot - > GetHostageEscortCount ( ) )
{
crouchPenalty * = 3.0f ;
}
cost + = crouchPenalty * dist ;
2015-06-30 12:46:07 +03:00
}
2016-01-19 14:54:31 +03:00
// if this is a "jump" area, add penalty
if ( area - > GetAttributes ( ) & NAV_JUMP )
2015-06-30 12:46:07 +03:00
{
2016-01-19 14:54:31 +03:00
// jumping can slow you down
//const float jumpPenalty = (m_route == FASTEST_ROUTE) ? 100.0f : 0.5f;
2015-06-30 12:46:07 +03:00
const float jumpPenalty = 1.0f ;
cost + = jumpPenalty * dist ;
}
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
if ( m_route = = SAFEST_ROUTE )
{
2016-01-19 14:54:31 +03:00
// add in the danger of this path - danger is per unit length travelled
cost + = dist * dangerFactor * area - > GetDanger ( m_bot - > m_iTeam - 1 ) ;
2015-06-30 12:46:07 +03:00
}
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
if ( ! m_bot - > IsAttacking ( ) )
{
2016-01-19 14:54:31 +03:00
// add in cost of teammates in the way
// approximate density of teammates based on area
2015-06-30 12:46:07 +03:00
float size = ( area - > GetSizeX ( ) + area - > GetSizeY ( ) ) / 2.0f ;
2016-01-19 14:54:31 +03:00
// degenerate check
2015-06-30 12:46:07 +03:00
if ( size > = 1.0f )
{
2016-01-19 14:54:31 +03:00
// cost is proportional to the density of teammates in this area
2015-06-30 12:46:07 +03:00
const float costPerFriendPerUnit = 50000.0f ;
2016-02-23 02:13:52 +03:00
cost + = costPerFriendPerUnit * float ( area - > GetPlayerCount ( m_bot - > m_iTeam , m_bot ) ) / size ;
2015-06-30 12:46:07 +03:00
}
}
2016-01-19 14:54:31 +03:00
2015-06-30 12:46:07 +03:00
return cost ;
2016-01-19 14:54:31 +03:00
}
2015-12-05 22:40:30 +03:00
2015-06-30 12:46:07 +03:00
return 0.0f ;
}
2015-12-05 22:40:30 +03:00
2015-06-30 12:46:07 +03:00
private :
CCSBot * m_bot ;
RouteType m_route ;
2016-02-04 03:18:26 +03:00
} ;
2015-07-02 00:22:46 +03:00
2015-09-16 23:19:21 +03:00
class FollowTargetCollector
{
public :
2017-11-22 20:27:55 +03:00
FollowTargetCollector ( CBasePlayer * pPlayer )
2015-09-16 23:19:21 +03:00
{
2017-11-22 20:27:55 +03:00
m_player = pPlayer ;
m_forward . x = pPlayer - > pev - > velocity . x ;
m_forward . y = pPlayer - > pev - > velocity . y ;
2015-09-16 23:19:21 +03:00
float speed = m_forward . NormalizeInPlace ( ) ;
const float walkSpeed = 100.0f ;
if ( speed < walkSpeed )
{
2017-11-22 20:27:55 +03:00
m_cutoff . x = pPlayer - > pev - > origin . x ;
m_cutoff . y = pPlayer - > pev - > origin . y ;
2015-09-16 23:19:21 +03:00
m_forward . x = 0.0f ;
m_forward . y = 0.0f ;
}
else
{
2016-01-25 20:02:57 +03:00
const float k = 1.5f ;
2017-11-22 20:27:55 +03:00
real_t trimSpeed = ( speed < 200.0f ) ? speed : 200.0f ;
2015-09-16 23:19:21 +03:00
2017-11-22 20:27:55 +03:00
m_cutoff . x = pPlayer - > pev - > origin . x + k * trimSpeed * m_forward . x ;
m_cutoff . y = pPlayer - > pev - > origin . y + k * trimSpeed * m_forward . y ;
2015-09-16 23:19:21 +03:00
}
m_targetAreaCount = 0 ;
}
enum { MAX_TARGET_AREAS = 128 } ;
bool operator ( ) ( CNavArea * area )
{
if ( m_targetAreaCount > = MAX_TARGET_AREAS )
return false ;
// only use two-way connections
if ( ! area - > GetParent ( ) | | area - > IsConnected ( area - > GetParent ( ) , NUM_DIRECTIONS ) )
{
if ( m_forward . IsZero ( ) )
{
2016-02-23 02:13:52 +03:00
m_targetArea [ m_targetAreaCount + + ] = area ;
2015-09-16 23:19:21 +03:00
}
else
{
// collect areas in the direction of the player's forward motion
Vector2D to ( ( ( * area - > GetCenter ( ) ) . x - m_cutoff . x ) , ( * area - > GetCenter ( ) ) . y - m_cutoff . y ) ;
to . NormalizeInPlace ( ) ;
2017-11-22 20:27:55 +03:00
if ( DotProduct ( to , m_forward ) > 0.7071f )
{
2016-02-23 02:13:52 +03:00
m_targetArea [ m_targetAreaCount + + ] = area ;
2017-11-22 20:27:55 +03:00
}
2015-09-16 23:19:21 +03:00
}
}
return ( m_targetAreaCount < MAX_TARGET_AREAS ) ;
}
CBasePlayer * m_player ;
Vector2D m_forward ;
Vector2D m_cutoff ;
2016-02-23 02:13:52 +03:00
CNavArea * m_targetArea [ MAX_TARGET_AREAS ] ;
2015-09-16 23:19:21 +03:00
int m_targetAreaCount ;
2016-02-04 03:18:26 +03:00
} ;
2015-09-16 23:19:21 +03:00
2016-02-04 03:18:26 +03:00
void InstallBotControl ( ) ;
void Bot_ServerCommand ( ) ;
2016-10-05 18:27:50 +03:00
void Bot_RegisterCVars ( ) ;
2017-11-22 20:27:55 +03:00
int GetBotFollowCount ( CBasePlayer * pLeader ) ;
2016-01-19 14:54:31 +03:00
const Vector * FindNearbyRetreatSpot ( CCSBot * me , float maxRange ) ;
2015-06-30 12:46:07 +03:00
2016-01-19 14:54:31 +03:00
void drawProgressMeter ( float progress , char * title ) ;
void startProgressMeter ( const char * title ) ;
2016-02-04 03:18:26 +03:00
void hideProgressMeter ( ) ;
2015-06-30 12:46:07 +03:00
bool isSniperRifle ( CBasePlayerItem * item ) ;
float StayOnLadderLine ( CCSBot * me , const CNavLadder * ladder ) ;