Corrected usage of think interval for each bot.

Fixed double-jump task behaviour;.
Lowered CPU usage in player avoidance code.
Removed unused commands from 'yb help'.
Dirty fix for #44.
This commit is contained in:
jeefo 2017-02-06 22:31:54 +03:00
commit 62e9cccf7b
8 changed files with 152 additions and 120 deletions

View file

@ -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);

View file

@ -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

View file

@ -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 ();

View file

@ -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;

View file

@ -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, ...)

View file

@ -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 (!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);

View file

@ -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;

View file

@ -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);
@ -368,7 +349,6 @@ void Bot::CheckCloseAvoidance (const Vector &dirNormal)
if (nearestDistance < 56.0f && (dirToPoint | g_pGlobals->v_forward.Get2D ()) < 0.0f)
m_moveSpeed = -pev->maxspeed;
}
}
}
void Bot::CheckTerrain (float movedDistance, const Vector &dirNormal)
@ -376,8 +356,6 @@ 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)