Merge pull request #46 from jeefo/develop
This commit is contained in:
commit
2ec5a730b0
9 changed files with 155 additions and 122 deletions
|
|
@ -524,6 +524,8 @@ const float TASKPRI_SHOOTBREAKABLE = 100.0f;
|
|||
const float TASKPRI_ESCAPEFROMBOMB = 100.0f;
|
||||
|
||||
const float MAX_GRENADE_TIMER = 2.34f;
|
||||
const float MAX_SPRAY_DISTANCE = 250.0f;
|
||||
const float MAX_SPRAY_DISTANCE_X2 = MAX_SPRAY_DISTANCE * 2;
|
||||
|
||||
const int MAX_HOSTAGES = 8;
|
||||
const int MAX_PATH_INDEX = 8;
|
||||
|
|
@ -745,6 +747,9 @@ private:
|
|||
int m_radioSelect; // radio entry
|
||||
float m_headedTime;
|
||||
|
||||
edict_t *m_avoid; // avoid players on our way
|
||||
float m_avoidTime; // time to avoid players around
|
||||
|
||||
float m_blindRecognizeTime; // time to recognize enemy
|
||||
float m_itemCheckTime; // time next search for items needs to be done
|
||||
PickupType m_pickupType; // type of entity which needs to be used/picked up
|
||||
|
|
@ -1177,6 +1182,8 @@ public:
|
|||
inline Vector Center (void) { return (pev->absmax + pev->absmin) * 0.5; };
|
||||
inline Vector EyePosition (void) { return pev->origin + pev->view_ofs; };
|
||||
|
||||
float GetThinkInterval (void);
|
||||
|
||||
// the main function that decides intervals of running bot ai
|
||||
void Think (void);
|
||||
|
||||
|
|
@ -1197,6 +1204,7 @@ public:
|
|||
void EnableChatterIcon (bool show);
|
||||
void DeleteSearchNodes (void);
|
||||
void VerifyBreakable (edict_t *touch);
|
||||
void AvoidPlayersOnTheWay (edict_t *touch);
|
||||
|
||||
void PushTask (TaskID id, float desire, int data, float time, bool canContinue);
|
||||
void RemoveCertainTask (TaskID id);
|
||||
|
|
@ -1220,7 +1228,10 @@ public:
|
|||
|
||||
void Kill (void);
|
||||
void Kick (bool keepQuota = false);
|
||||
|
||||
void ResetDoubleJumpState (void);
|
||||
void StartDoubleJump (edict_t *ent);
|
||||
|
||||
int FindPlantedBomb(void);
|
||||
|
||||
bool HasHostage (void);
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ private:
|
|||
int m_drawModels[DRAW_NUM];
|
||||
|
||||
// bot client command
|
||||
bool m_isBotCommand;
|
||||
char m_arguments[256];
|
||||
bool m_isBotCommand;
|
||||
int m_argumentCount;
|
||||
|
||||
edict_t *m_startEntity;
|
||||
|
|
@ -218,7 +218,7 @@ public:
|
|||
// gets custom engine argv for client command
|
||||
inline const char *GetOverrideArgv (int num)
|
||||
{
|
||||
return ExtractSingleField (m_arguments, num, false);
|
||||
return ExtractSingleField (m_arguments, num);
|
||||
}
|
||||
|
||||
// gets custom engine argc for client command
|
||||
|
|
@ -298,8 +298,8 @@ public:
|
|||
}
|
||||
|
||||
// static utility functions
|
||||
public:
|
||||
static const char *ExtractSingleField (const char *string, int id, bool terminate);
|
||||
private:
|
||||
const char *ExtractSingleField (const char *string, int id);
|
||||
};
|
||||
|
||||
// simplify access for console variables
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ typedef struct hudtextparms_s
|
|||
#define VEC_DUCK_VIEW Vector( 0, 0, 12 )
|
||||
|
||||
#define SVC_TEMPENTITY 23
|
||||
#define SVC_CENTERPRINT 26
|
||||
#define SVC_INTERMISSION 30
|
||||
#define SVC_CDTRACK 32
|
||||
#define SVC_WEAPONANIM 35
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ void Bot::AvoidGrenades (void)
|
|||
if ((ent->v.flags & FL_ONGROUND) == 0)
|
||||
{
|
||||
float distance = (ent->v.origin - pev->origin).GetLength ();
|
||||
float distanceMoved = ((ent->v.origin + ent->v.velocity * m_frameInterval) - pev->origin).GetLength ();
|
||||
float distanceMoved = ((ent->v.origin + ent->v.velocity * GetThinkInterval ()) - pev->origin).GetLength ();
|
||||
|
||||
if (distanceMoved < distance && distance < 500.0f)
|
||||
{
|
||||
|
|
@ -480,6 +480,30 @@ void Bot::VerifyBreakable (edict_t *touch)
|
|||
PushTask (TASK_SHOOTBREAKABLE, TASKPRI_SHOOTBREAKABLE, -1, 0.0f, false);
|
||||
}
|
||||
|
||||
void Bot::AvoidPlayersOnTheWay (edict_t *touch)
|
||||
{
|
||||
auto task = GetTaskId ();
|
||||
|
||||
if (task == TASK_PLANTBOMB || task == TASK_DEFUSEBOMB)
|
||||
return;
|
||||
|
||||
int ownId = GetIndex ();
|
||||
int otherId = engine.IndexOfEntity (touch);
|
||||
|
||||
if (ownId < otherId)
|
||||
return;
|
||||
|
||||
if (m_avoid != nullptr)
|
||||
{
|
||||
int currentId = engine.IndexOfEntity (m_avoid);
|
||||
|
||||
if (currentId < otherId)
|
||||
return;
|
||||
}
|
||||
m_avoid = touch;
|
||||
m_avoidTime = engine.Time () + 0.6f;
|
||||
}
|
||||
|
||||
edict_t *Bot::FindBreakable (void)
|
||||
{
|
||||
// this function checks if bot is blocked by a shoot able breakable in his moving direction
|
||||
|
|
@ -837,7 +861,7 @@ void Bot::FindItem (void)
|
|||
m_itemIgnore = ent;
|
||||
allowPickup = false;
|
||||
|
||||
if (!m_defendedBomb && m_difficulty >= 2 && Random.Int (0, 100) < 80)
|
||||
if (!m_defendedBomb && m_difficulty >= 2 && Random.Int (0, 100) < 75 && pev->health < 80)
|
||||
{
|
||||
int index = FindDefendWaypoint (entityOrigin);
|
||||
|
||||
|
|
@ -2971,7 +2995,7 @@ void Bot::PeriodicThink (void)
|
|||
m_lastChatTime = engine.Time ();
|
||||
g_lastChatTime = engine.Time ();
|
||||
|
||||
char *pickedPhrase = const_cast <char *> (g_chatFactory[CHAT_DEAD].GetRandomElement ().GetBuffer ());
|
||||
auto pickedPhrase = g_chatFactory[CHAT_DEAD].GetRandomElement ().GetBuffer ();
|
||||
bool sayBufferExists = false;
|
||||
|
||||
// search for last messages, sayed
|
||||
|
|
@ -2983,7 +3007,7 @@ void Bot::PeriodicThink (void)
|
|||
|
||||
if (!sayBufferExists)
|
||||
{
|
||||
PrepareChatMessage (pickedPhrase);
|
||||
PrepareChatMessage (const_cast <char *> (pickedPhrase));
|
||||
PushMessageQueue (GAME_MSG_SAY_CMD);
|
||||
|
||||
// add to ignore list
|
||||
|
|
@ -4230,7 +4254,7 @@ void Bot::RunTask_Throw_SG (void)
|
|||
|
||||
void Bot::RunTask_DoubleJump (void)
|
||||
{
|
||||
if (!IsAlive (m_doubleJumpEntity) || (m_aimFlags & AIM_ENEMY) || (m_travelStartIndex != -1 && GetTask ()->time + (waypoints.GetTravelTime (pev->maxspeed, waypoints.GetPath (m_travelStartIndex)->origin, m_doubleJumpOrigin) + 11.0) < engine.Time ()))
|
||||
if (!IsAlive (m_doubleJumpEntity) || (m_aimFlags & AIM_ENEMY) || (m_travelStartIndex != -1 && GetTask ()->time + (waypoints.GetTravelTime (pev->maxspeed, waypoints.GetPath (m_travelStartIndex)->origin, m_doubleJumpOrigin) + 11.0f) < engine.Time ()))
|
||||
{
|
||||
ResetDoubleJumpState ();
|
||||
return;
|
||||
|
|
@ -4246,25 +4270,26 @@ void Bot::RunTask_DoubleJump (void)
|
|||
m_moveSpeed = 0.0f;
|
||||
m_strafeSpeed = 0.0f;
|
||||
|
||||
bool inJump = (m_doubleJumpEntity->v.button & IN_JUMP) || (m_doubleJumpEntity->v.oldbuttons & IN_JUMP);
|
||||
|
||||
if (m_duckForJump < engine.Time ())
|
||||
pev->button |= IN_DUCK;
|
||||
else if (inJump && !(pev->oldbuttons & IN_JUMP))
|
||||
pev->button |= IN_JUMP;
|
||||
|
||||
MakeVectors (Vector::GetZero ());
|
||||
MakeVectors (Vector (0.0f, pev->angles.y, 0.0f));
|
||||
|
||||
Vector dest = EyePosition () + g_pGlobals->v_forward * 500.0f;
|
||||
dest.z = 180.0f;
|
||||
Vector src = pev->origin + Vector (0.0f, 0.0f, 45.0f);
|
||||
Vector dest = src + g_pGlobals->v_up * 256.0f;
|
||||
|
||||
TraceResult tr;
|
||||
engine.TestLine (EyePosition (), dest, TRACE_IGNORE_GLASS, GetEntity (), &tr);
|
||||
engine.TestLine (src, dest, TRACE_IGNORE_NONE, GetEntity (), &tr);
|
||||
|
||||
if (tr.flFraction < 1.0f && tr.pHit == m_doubleJumpEntity)
|
||||
{
|
||||
if (m_doubleJumpEntity->v.button & IN_JUMP)
|
||||
if (tr.flFraction < 1.0f && tr.pHit == m_doubleJumpEntity && inJump)
|
||||
{
|
||||
m_duckForJump = engine.Time () + Random.Float (3.0f, 5.0f);
|
||||
GetTask ()->time = engine.Time ();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4289,7 +4314,7 @@ void Bot::RunTask_DoubleJump (void)
|
|||
GetTask ()->data = destIndex;
|
||||
m_travelStartIndex = m_currentWaypointIndex;
|
||||
|
||||
// Always take the shortest path
|
||||
// always take the shortest path
|
||||
FindShortestPath (m_currentWaypointIndex, destIndex);
|
||||
|
||||
if (m_currentWaypointIndex == destIndex)
|
||||
|
|
@ -4859,7 +4884,7 @@ void Bot::BotAI (void)
|
|||
SetIdealReactionTimes ();
|
||||
|
||||
// calculate 2 direction vectors, 1 without the up/down component
|
||||
const Vector &dirOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval);
|
||||
const Vector &dirOld = m_destOrigin - (pev->origin + pev->velocity * GetThinkInterval ());
|
||||
const Vector &dirNormal = dirOld.Normalize2D ();
|
||||
|
||||
m_moveAngles = dirOld.ToAngles ();
|
||||
|
|
@ -5499,7 +5524,7 @@ void Bot::DiscardWeaponForUser (edict_t *user, bool discardC4)
|
|||
// this function, asks bot to discard his current primary weapon (or c4) to the user that requsted it with /drop*
|
||||
// command, very useful, when i'm don't have money to buy anything... )
|
||||
|
||||
if (IsAlive (user) && m_moneyAmount >= 2000 && HasPrimaryWeapon () && (user->v.origin - pev->origin).GetLength () <= 240.0f)
|
||||
if (IsAlive (user) && m_moneyAmount >= 2000 && HasPrimaryWeapon () && (user->v.origin - pev->origin).GetLength () <= 450.0f)
|
||||
{
|
||||
m_aimFlags |= AIM_ENTITY;
|
||||
m_lookAt = user->v.origin;
|
||||
|
|
@ -5530,6 +5555,17 @@ void Bot::DiscardWeaponForUser (edict_t *user, bool discardC4)
|
|||
}
|
||||
}
|
||||
|
||||
void Bot::StartDoubleJump (edict_t *ent)
|
||||
{
|
||||
ResetDoubleJumpState ();
|
||||
|
||||
m_doubleJumpOrigin = ent->v.origin;
|
||||
m_doubleJumpEntity = ent;
|
||||
|
||||
PushTask (TASK_DOUBLEJUMP, TASKPRI_DOUBLEJUMP, -1, engine.Time (), true);
|
||||
TeamSayText (FormatBuffer ("Ok %s, i will help you!", STRING (ent->v.netname)));
|
||||
}
|
||||
|
||||
void Bot::ResetDoubleJumpState (void)
|
||||
{
|
||||
TaskComplete ();
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ const Vector &Bot::GetAimPosition (void)
|
|||
}
|
||||
m_lastEnemyOrigin = targetOrigin;
|
||||
}
|
||||
const Vector &velocity = UsesSniper () ? Vector::GetZero () : 1.0f * m_frameInterval * (m_enemy->v.velocity - pev->velocity);
|
||||
const Vector &velocity = UsesSniper () ? Vector::GetZero () : 1.0f * GetThinkInterval () * (m_enemy->v.velocity - pev->velocity);
|
||||
|
||||
if (m_difficulty < 3 && !randomize.IsZero ())
|
||||
{
|
||||
|
|
@ -505,12 +505,9 @@ float Bot::GetZOffset (float distance)
|
|||
bool shotgun = (m_currentWeapon == WEAPON_XM1014 || m_currentWeapon == WEAPON_M3);
|
||||
bool m249 = m_currentWeapon == WEAPON_M249;
|
||||
|
||||
const float BurstDistance = 300.0f;
|
||||
const float DoubleBurstDistance = BurstDistance * 2;
|
||||
|
||||
float result = 3.5f;
|
||||
|
||||
if (distance < 2800.0f && distance > DoubleBurstDistance)
|
||||
if (distance < 2800.0f && distance > MAX_SPRAY_DISTANCE_X2)
|
||||
{
|
||||
if (sniper) result = 1.5f;
|
||||
else if (zoomableRifle) result = 4.5f;
|
||||
|
|
@ -520,7 +517,7 @@ float Bot::GetZOffset (float distance)
|
|||
else if (m249) result = 2.5f;
|
||||
else if (shotgun) result = 10.5f;
|
||||
}
|
||||
else if (distance > BurstDistance && distance <= DoubleBurstDistance)
|
||||
else if (distance > MAX_SPRAY_DISTANCE && distance <= MAX_SPRAY_DISTANCE_X2)
|
||||
{
|
||||
if (sniper) result = 2.5f;
|
||||
else if (zoomableRifle) result = 3.5f;
|
||||
|
|
@ -530,7 +527,7 @@ float Bot::GetZOffset (float distance)
|
|||
else if (m249) result = -1.0f;
|
||||
else if (shotgun) result = 10.0f;
|
||||
}
|
||||
else if (distance < BurstDistance)
|
||||
else if (distance < MAX_SPRAY_DISTANCE)
|
||||
{
|
||||
if (sniper) result = 4.5f;
|
||||
else if (zoomableRifle) result = -5.0f;
|
||||
|
|
@ -690,13 +687,11 @@ bool Bot::DoFirePause (float distance)
|
|||
if (GetShootingConeDeviation (GetEntity (), &m_enemyOrigin) > 0.92f && IsEnemyProtectedByShield (m_enemy))
|
||||
return true;
|
||||
}
|
||||
|
||||
float offset = 0.0f;
|
||||
const float SprayDistance = 250.0f;
|
||||
|
||||
if (distance < SprayDistance)
|
||||
if (distance < MAX_SPRAY_DISTANCE)
|
||||
return false;
|
||||
else if (distance < 2 * SprayDistance)
|
||||
else if (distance < MAX_SPRAY_DISTANCE_X2)
|
||||
offset = 10.0f;
|
||||
else
|
||||
offset = 5.0f;
|
||||
|
|
@ -704,10 +699,7 @@ bool Bot::DoFirePause (float distance)
|
|||
const float xPunch = DegreeToRadian (pev->punchangle.x);
|
||||
const float yPunch = DegreeToRadian (pev->punchangle.y);
|
||||
|
||||
float interval = m_thinkInterval;
|
||||
|
||||
if ((g_gameFlags & GAME_LEGACY) && Math::FltZero (interval))
|
||||
interval = (1.0f / 30.0f) * Random.Float (0.95f, 1.05f);
|
||||
float interval = GetThinkInterval ();
|
||||
|
||||
// check if we need to compensate recoil
|
||||
if (tanf (A_sqrtf (fabsf (xPunch * xPunch) + fabsf (yPunch * yPunch))) * distance > offset + 30.0f + ((100 - (m_difficulty * 25)) / 100.f))
|
||||
|
|
@ -805,7 +797,7 @@ void Bot::FinishWeaponSelection (float distance, int index, int id, int choosen)
|
|||
}
|
||||
|
||||
// need to care for burst fire?
|
||||
if (distance < 256.0f || m_blindTime > engine.Time ())
|
||||
if (distance < MAX_SPRAY_DISTANCE || m_blindTime > engine.Time ())
|
||||
{
|
||||
if (id == WEAPON_KNIFE)
|
||||
{
|
||||
|
|
@ -1192,7 +1184,7 @@ void Bot::CombatFight (void)
|
|||
{
|
||||
MakeVectors (pev->v_angle);
|
||||
|
||||
if (IsDeadlyDrop (pev->origin + (g_pGlobals->v_forward * m_moveSpeed * 0.2f) + (g_pGlobals->v_right * m_strafeSpeed * 0.2f) + (pev->velocity * m_frameInterval)))
|
||||
if (IsDeadlyDrop (pev->origin + (g_pGlobals->v_forward * m_moveSpeed * 0.2f) + (g_pGlobals->v_right * m_strafeSpeed * 0.2f) + (pev->velocity * GetThinkInterval ())))
|
||||
{
|
||||
m_strafeSpeed = -m_strafeSpeed;
|
||||
m_moveSpeed = -m_moveSpeed;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ void Engine::ChatPrintf (const char *fmt, ...)
|
|||
|
||||
MESSAGE_BEGIN (MSG_BROADCAST, FindMessageId (NETMSG_TEXTMSG));
|
||||
WRITE_BYTE (HUD_PRINTTALK);
|
||||
WRITE_STRING ("%s");
|
||||
WRITE_STRING (string);
|
||||
MESSAGE_END ();
|
||||
}
|
||||
|
|
@ -101,8 +102,7 @@ void Engine::CenterPrintf (const char *fmt, ...)
|
|||
}
|
||||
strcat (string, "\n");
|
||||
|
||||
MESSAGE_BEGIN (MSG_BROADCAST, FindMessageId (NETMSG_TEXTMSG));
|
||||
WRITE_BYTE (HUD_PRINTCENTER);
|
||||
MESSAGE_BEGIN (MSG_BROADCAST, SVC_CENTERPRINT);
|
||||
WRITE_STRING (string);
|
||||
MESSAGE_END ();
|
||||
}
|
||||
|
|
@ -345,7 +345,7 @@ void Engine::IssueBotCommand (edict_t *ent, const char *fmt, ...)
|
|||
return;
|
||||
|
||||
va_list ap;
|
||||
static char string[256];
|
||||
char string[256];
|
||||
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (string, SIZEOF_CHAR (string), fmt, ap);
|
||||
|
|
@ -354,7 +354,7 @@ void Engine::IssueBotCommand (edict_t *ent, const char *fmt, ...)
|
|||
if (IsNullString (string))
|
||||
return;
|
||||
|
||||
m_arguments[0] = 0x0;
|
||||
m_arguments[0] = '\0';
|
||||
m_argumentCount = 0;
|
||||
|
||||
m_isBotCommand = true;
|
||||
|
|
@ -407,16 +407,24 @@ void Engine::IssueBotCommand (edict_t *ent, const char *fmt, ...)
|
|||
}
|
||||
m_isBotCommand = false;
|
||||
|
||||
m_arguments[0] = 0x0;
|
||||
m_arguments[0] = '\0';
|
||||
m_argumentCount = 0;
|
||||
}
|
||||
|
||||
const char *Engine::ExtractSingleField (const char *string, int id, bool terminate)
|
||||
const char *Engine::ExtractSingleField (const char *string, int id)
|
||||
{
|
||||
// this function gets and returns a particular field in a string where several strings are concatenated
|
||||
|
||||
static char field[256];
|
||||
field[0] = 0x0;
|
||||
const int IterBufMax = 4;
|
||||
|
||||
static char arg[IterBufMax][256];
|
||||
static int iter = -1;
|
||||
|
||||
if (iter > IterBufMax - 1)
|
||||
iter = 0;
|
||||
|
||||
char *ptr = arg[++iter];
|
||||
ptr[0] = 0;
|
||||
|
||||
int pos = 0, count = 0, start = 0, stop = 0;
|
||||
int length = strlen (string);
|
||||
|
|
@ -452,19 +460,16 @@ const char *Engine::ExtractSingleField (const char *string, int id, bool termina
|
|||
int i = start;
|
||||
|
||||
for (; i <= stop; i++)
|
||||
field[i - start] = string[i];
|
||||
ptr[i - start] = string[i];
|
||||
|
||||
field[i - start] = 0;
|
||||
ptr[i - start] = 0;
|
||||
break;
|
||||
}
|
||||
count++; // we have parsed one field more
|
||||
}
|
||||
String::TrimExternalBuffer (ptr);
|
||||
|
||||
if (terminate)
|
||||
field[strlen (field) - 1] = 0;
|
||||
|
||||
String::TrimExternalBuffer (field);
|
||||
return field;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Engine::IssueCmd (const char *fmt, ...)
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
|
|||
}
|
||||
|
||||
// display some sort of help information
|
||||
else if (A_stricmp (arg0, "?") == 0 || A_stricmp (arg0, "help") == 0)
|
||||
else if (strcmp (arg0, "?") == 0 || strcmp (arg0, "help") == 0)
|
||||
{
|
||||
engine.ClientPrintf (ent, "Bot Commands:");
|
||||
engine.ClientPrintf (ent, "%s version\t - display version information.", self);
|
||||
|
|
@ -131,7 +131,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
|
|||
engine.ClientPrintf (ent, "%s votemap\t - allows dead bots to vote for specific map.", self);
|
||||
engine.ClientPrintf (ent, "%s cmenu\t - displaying bots command menu.", self);
|
||||
|
||||
if (A_stricmp (arg1, "full") == 0 || A_stricmp (arg1, "f") == 0 || A_stricmp (arg1, "?") == 0)
|
||||
if (strcmp (arg1, "full") == 0 || strcmp (arg1, "?") == 0)
|
||||
{
|
||||
engine.ClientPrintf (ent, "%s add_t\t - creates one random bot to terrorist team.", self);
|
||||
engine.ClientPrintf (ent, "%s add_ct\t - creates one random bot to ct team.", self);
|
||||
|
|
@ -140,8 +140,6 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
|
|||
engine.ClientPrintf (ent, "%s kill_t\t - kills all bots on terrorist team.", self);
|
||||
engine.ClientPrintf (ent, "%s kill_ct\t - kills all bots on ct team.", self);
|
||||
engine.ClientPrintf (ent, "%s list\t - display list of bots currently playing.", self);
|
||||
engine.ClientPrintf (ent, "%s order\t - execute specific command on specified bot.", self);
|
||||
engine.ClientPrintf (ent, "%s time\t - displays current time on server.", self);
|
||||
engine.ClientPrintf (ent, "%s deletewp\t - erase waypoint file from hard disk (permanently).", self);
|
||||
|
||||
if (!engine.IsDedicatedServer ())
|
||||
|
|
@ -151,6 +149,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c
|
|||
engine.Printf ("%s wp on noclip\t - enable noclip cheat", self);
|
||||
engine.Printf ("%s wp save nocheck\t - save waypoints without checking.", self);
|
||||
engine.Printf ("%s wp add\t - open menu for waypoint creation.", self);
|
||||
engine.Printf ("%s wp delete\t - delete waypoint nearest to host edict.", self);
|
||||
engine.Printf ("%s wp menu\t - open main waypoint menu.", self);
|
||||
engine.Printf ("%s wp addbasic\t - creates basic waypoints on map.", self);
|
||||
engine.Printf ("%s wp find\t - show direction to specified waypoint.", self);
|
||||
|
|
@ -497,6 +496,8 @@ void InitConfig (void)
|
|||
fp.Close ();
|
||||
}
|
||||
|
||||
engine.Printf ("INITING CHAT.CfG");
|
||||
|
||||
// CHAT SYSTEM CONFIG INITIALIZATION
|
||||
if (OpenConfig ("chat.cfg", "Chat file not found.", &fp, true))
|
||||
{
|
||||
|
|
@ -506,7 +507,9 @@ void InitConfig (void)
|
|||
while (fp.GetBuffer (line, 255))
|
||||
{
|
||||
SKIP_COMMENTS ();
|
||||
strncpy (section, Engine::ExtractSingleField (line, 0, 1), SIZEOF_CHAR (section));
|
||||
|
||||
String::TrimExternalBuffer (line);
|
||||
strncpy (section, line, SIZEOF_CHAR (section));
|
||||
|
||||
if (strcmp (section, "[KILLED]") == 0)
|
||||
{
|
||||
|
|
@ -552,8 +555,6 @@ void InitConfig (void)
|
|||
if (chatType != 3)
|
||||
line[79] = 0;
|
||||
|
||||
String::TrimExternalBuffer (line);
|
||||
|
||||
switch (chatType)
|
||||
{
|
||||
case 0:
|
||||
|
|
@ -957,8 +958,13 @@ void Touch (edict_t *pentTouched, edict_t *pentOther)
|
|||
Bot *bot = bots.GetBot (pentOther);
|
||||
|
||||
if (bot != nullptr)
|
||||
{
|
||||
if (IsValidPlayer (pentTouched))
|
||||
bot->AvoidPlayersOnTheWay (pentTouched);
|
||||
else
|
||||
bot->VerifyBreakable (pentTouched);
|
||||
}
|
||||
}
|
||||
if (g_gameFlags & GAME_METAMOD)
|
||||
RETURN_META (MRES_IGNORED);
|
||||
|
||||
|
|
@ -1614,20 +1620,12 @@ void ClientCommand (edict_t *ent)
|
|||
{
|
||||
case 1:
|
||||
case 2:
|
||||
if (FindNearestPlayer (reinterpret_cast <void **> (&bot), client->ent, 300.0f, true, true, true))
|
||||
if (FindNearestPlayer (reinterpret_cast <void **> (&bot), client->ent, 450.0f, true, true, true))
|
||||
{
|
||||
if (!bot->m_hasC4 && !bot->HasHostage ())
|
||||
{
|
||||
if (selection == 1)
|
||||
{
|
||||
bot->ResetDoubleJumpState ();
|
||||
|
||||
bot->m_doubleJumpOrigin = client->ent->v.origin;
|
||||
bot->m_doubleJumpEntity = client->ent;
|
||||
|
||||
bot->PushTask (TASK_DOUBLEJUMP, TASKPRI_DOUBLEJUMP, -1, engine.Time (), true);
|
||||
bot->TeamSayText (FormatBuffer ("Ok %s, i will help you!", STRING (ent->v.netname)));
|
||||
}
|
||||
bot->StartDoubleJump (client->ent);
|
||||
else if (selection == 2)
|
||||
bot->ResetDoubleJumpState ();
|
||||
}
|
||||
|
|
@ -1637,7 +1635,7 @@ void ClientCommand (edict_t *ent)
|
|||
|
||||
case 3:
|
||||
case 4:
|
||||
if (FindNearestPlayer (reinterpret_cast <void **> (&bot), ent, 300.0f, true, true, true))
|
||||
if (FindNearestPlayer (reinterpret_cast <void **> (&bot), ent, 450.0f, true, true, true))
|
||||
bot->DiscardWeaponForUser (ent, selection == 4 ? false : true);
|
||||
|
||||
DisplayMenuToClient (ent, BOT_MENU_COMMANDS);
|
||||
|
|
|
|||
|
|
@ -1036,6 +1036,14 @@ void Bot::ReleaseUsedName (void)
|
|||
}
|
||||
}
|
||||
|
||||
float Bot::GetThinkInterval (void)
|
||||
{
|
||||
if (Math::FltZero (m_thinkInterval))
|
||||
return m_frameInterval;
|
||||
|
||||
return m_thinkInterval;
|
||||
}
|
||||
|
||||
Bot::~Bot (void)
|
||||
{
|
||||
// this is bot destructor
|
||||
|
|
@ -1139,6 +1147,9 @@ void Bot::NewRound (void)
|
|||
m_numFriendsLeft = 0;
|
||||
m_numEnemiesLeft = 0;
|
||||
|
||||
m_avoid = nullptr;
|
||||
m_avoidTime = 0.0f;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
m_prevWptIndex[i] = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -320,45 +320,26 @@ void Bot::CheckCloseAvoidance (const Vector &dirNormal)
|
|||
if (m_seeEnemyTime + 1.5f < engine.Time ())
|
||||
return;
|
||||
|
||||
edict_t *nearest = nullptr;
|
||||
float nearestDist = 99999.0f;
|
||||
int playerCount = 0;
|
||||
if (m_avoidTime < engine.Time () || m_avoid == nullptr)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < engine.MaxClients (); i++)
|
||||
{
|
||||
const Client &client = g_clients[i];
|
||||
|
||||
if (!(client.flags & (CF_USED | CF_ALIVE)) || client.ent == GetEntity () || client.team != m_team)
|
||||
continue;
|
||||
|
||||
float distance = (client.ent->v.origin - pev->origin).GetLength ();
|
||||
|
||||
if (distance < nearestDist && distance < pev->maxspeed)
|
||||
{
|
||||
nearestDist = distance;
|
||||
nearest = client.ent;
|
||||
|
||||
playerCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerCount < 4 && IsValidPlayer (nearest))
|
||||
{
|
||||
MakeVectors (m_moveAngles); // use our movement angles
|
||||
|
||||
// try to predict where we should be next frame
|
||||
Vector moved = pev->origin + g_pGlobals->v_forward * m_moveSpeed * m_frameInterval;
|
||||
moved += g_pGlobals->v_right * m_strafeSpeed * m_frameInterval;
|
||||
moved += pev->velocity * m_frameInterval;
|
||||
float interval = GetThinkInterval ();
|
||||
|
||||
float nearestDistance = (nearest->v.origin - pev->origin).GetLength2D ();
|
||||
float nextFrameDistance = ((nearest->v.origin + nearest->v.velocity * m_frameInterval) - pev->origin).GetLength2D ();
|
||||
// try to predict where we should be next frame
|
||||
Vector moved = pev->origin + g_pGlobals->v_forward * m_moveSpeed * interval;
|
||||
moved += g_pGlobals->v_right * m_strafeSpeed * interval;
|
||||
moved += pev->velocity * interval;
|
||||
|
||||
float nearestDistance = (m_avoid->v.origin - pev->origin).GetLength2D ();
|
||||
float nextFrameDistance = ((m_avoid->v.origin + m_avoid->v.velocity * interval) - pev->origin).GetLength2D ();
|
||||
|
||||
// is player that near now or in future that we need to steer away?
|
||||
if ((nearest->v.origin - moved).GetLength2D () <= 48.0f || (nearestDistance <= 56.0f && nextFrameDistance < nearestDistance))
|
||||
if ((m_avoid->v.origin - moved).GetLength2D () <= 48.0f || (nearestDistance <= 56.0f && nextFrameDistance < nearestDistance))
|
||||
{
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
const Vector &dirToPoint = (pev->origin - nearest->v.origin).Get2D ();
|
||||
const Vector &dirToPoint = (pev->origin - m_avoid->v.origin).Get2D ();
|
||||
|
||||
if ((dirToPoint | g_pGlobals->v_right.Get2D ()) > 0.0f)
|
||||
SetStrafeSpeed (dirNormal, pev->maxspeed);
|
||||
|
|
@ -369,15 +350,12 @@ void Bot::CheckCloseAvoidance (const Vector &dirNormal)
|
|||
m_moveSpeed = -pev->maxspeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Bot::CheckTerrain (float movedDistance, const Vector &dirNormal)
|
||||
{
|
||||
m_isStuck = false;
|
||||
TraceResult tr;
|
||||
|
||||
CheckCloseAvoidance (dirNormal);
|
||||
|
||||
// Standing still, no need to check?
|
||||
// FIXME: doesn't care for ladder movement (handled separately) should be included in some way
|
||||
if ((m_moveSpeed >= 10.0f || m_strafeSpeed >= 10.0f) && m_lastCollTime < engine.Time () && m_seeEnemyTime + 0.8f < engine.Time () && GetTaskId () != TASK_ATTACK)
|
||||
|
|
@ -626,7 +604,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dirNormal)
|
|||
if (IsOnFloor () || IsInWater ())
|
||||
{
|
||||
pev->button |= IN_JUMP;
|
||||
m_jumpStateTimer = Random.Float (2.0f, 3.0f);
|
||||
m_jumpStateTimer = engine.Time () + Random.Float (0.7f, 1.5f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -648,6 +626,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dirNormal)
|
|||
}
|
||||
}
|
||||
}
|
||||
CheckCloseAvoidance (dirNormal);
|
||||
}
|
||||
|
||||
bool Bot::DoWaypointNav (void)
|
||||
|
|
@ -1187,7 +1166,7 @@ bool Bot::DoWaypointNav (void)
|
|||
}
|
||||
|
||||
// needs precise placement - check if we get past the point
|
||||
if (desiredDistance < 16.0f && waypointDistance < 30.0f && (pev->origin + (pev->velocity * m_frameInterval) - m_waypointOrigin).GetLength () > waypointDistance)
|
||||
if (desiredDistance < 16.0f && waypointDistance < 30.0f && (pev->origin + (pev->velocity * GetThinkInterval ()) - m_waypointOrigin).GetLength () > waypointDistance)
|
||||
desiredDistance = waypointDistance + 1.0f;
|
||||
|
||||
if (waypointDistance < desiredDistance)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue