hearing: randomize listen position for heard sounds
graph: restore cvar variables values to initial values when disabling graph editor cfg: update primary config with actual cvars vision: remove unnecessary angles clamp combat: allow to disable engine potential visibility checks combat: do not aim to head on long distances with AWP, shotguns or with high recoil bot: set the minimum think fps to 30.0
This commit is contained in:
parent
867abdb288
commit
cc01693de9
11 changed files with 110 additions and 46 deletions
|
|
@ -235,6 +235,13 @@ yb_pickup_best "1"
|
|||
//
|
||||
yb_ignore_objectives "0"
|
||||
|
||||
//
|
||||
// Affect bot's vision by smoke clouds.
|
||||
// ---
|
||||
// Default: "2", Min: "0", Max: "2"
|
||||
//
|
||||
yb_smoke_grenade_checks "2"
|
||||
|
||||
//
|
||||
// Enables or disables bots chat functionality.
|
||||
// ---
|
||||
|
|
@ -252,9 +259,9 @@ yb_chat_percent "30"
|
|||
//
|
||||
// Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.
|
||||
// ---
|
||||
// Default: "2", Min: "0", Max: "3"
|
||||
// Default: "1", Min: "0", Max: "3"
|
||||
//
|
||||
yb_shoots_thru_walls "2"
|
||||
yb_shoots_thru_walls "1"
|
||||
|
||||
//
|
||||
// Enables or disables searching world for enemies.
|
||||
|
|
@ -284,6 +291,13 @@ yb_check_enemy_invincibility "0"
|
|||
//
|
||||
yb_stab_close_enemies "1"
|
||||
|
||||
//
|
||||
// Use engine to check potential visibility of a enemy.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_use_engine_pvs_check "0"
|
||||
|
||||
//
|
||||
// Binds specified key for opening bots menu.
|
||||
// ---
|
||||
|
|
@ -352,6 +366,13 @@ yb_threadpool_workers "-1"
|
|||
//
|
||||
yb_grenadier_mode "0"
|
||||
|
||||
//
|
||||
// Make bots ignore enemies for a specified here time in seconds on new round. Useful for Zombie Plague mods.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "540"
|
||||
//
|
||||
yb_ignore_enemies_after_spawn_time "0"
|
||||
|
||||
//
|
||||
// Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.
|
||||
// ---
|
||||
|
|
@ -442,9 +463,9 @@ yb_quota_match "0"
|
|||
//
|
||||
// Specifies how many times per second bot code will run.
|
||||
// ---
|
||||
// Default: "26.0", Min: "24.0", Max: "90.0"
|
||||
// Default: "30.0", Min: "24.0", Max: "90.0"
|
||||
//
|
||||
yb_think_fps "26.0"
|
||||
yb_think_fps "30.0"
|
||||
|
||||
//
|
||||
// Specifies amount of time in seconds when bots will be killed if no humans left alive.
|
||||
|
|
|
|||
|
|
@ -427,8 +427,8 @@ namespace TaskPri {
|
|||
constexpr auto kInfiniteDistance = 9999999.0f;
|
||||
constexpr auto kInvalidLightLevel = kInfiniteDistance;
|
||||
constexpr auto kGrenadeCheckTime = 0.6f;
|
||||
constexpr auto kSprayDistance = 260.0f;
|
||||
constexpr auto kDoubleSprayDistance = kSprayDistance * 2;
|
||||
constexpr auto kSprayDistance = 360.0f;
|
||||
constexpr auto kSprayDistanceX2 = kSprayDistance * 2;
|
||||
constexpr auto kMaxChatterRepeatInterval = 99.0f;
|
||||
constexpr auto kViewFrameUpdate = 1.0f / 30.0f;
|
||||
constexpr auto kGrenadeDamageRadius = 385.0f;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ public:
|
|||
{ }
|
||||
};
|
||||
|
||||
// save old values of changed cvars to revert them back when editing turned off
|
||||
struct GraphSaveVarValue {
|
||||
float timelimit {};
|
||||
float freezetime {};
|
||||
float roundtime {};
|
||||
} m_graphSaveVarValues;
|
||||
|
||||
private:
|
||||
StringArray m_args {};
|
||||
Array <BotCmd> m_cmds {};
|
||||
|
|
|
|||
10
inc/yapb.h
10
inc/yapb.h
|
|
@ -790,6 +790,11 @@ private:
|
|||
return m_weaponType == WeaponType::Sniper;
|
||||
}
|
||||
|
||||
// returns true if bot is using a sniper rifle (awp)
|
||||
bool usesSniperAWP () const {
|
||||
return m_currentWeapon == Weapon::AWP;
|
||||
}
|
||||
|
||||
// returns true if bot is using a rifle
|
||||
bool usesRifle () const {
|
||||
return usesZoomableRifle () || m_weaponType == WeaponType::Rifle;
|
||||
|
|
@ -834,6 +839,11 @@ private:
|
|||
bool usesKnife () const {
|
||||
return m_weaponType == WeaponType::Melee;
|
||||
}
|
||||
|
||||
// checks if weapon recoil is high
|
||||
bool isRecoilHigh () const {
|
||||
return pev->punchangle.x < -1.45f;
|
||||
}
|
||||
};
|
||||
|
||||
#include "config.h"
|
||||
|
|
|
|||
|
|
@ -1711,6 +1711,7 @@ void Bot::overrideConditions () {
|
|||
m_isReloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_seeEnemyTime + 2.5f < game.time () && (m_states & (Sense::SuspectEnemy | Sense::HearingEnemy))) {
|
||||
m_moveSpeed = m_fearLevel > m_agressionLevel ? 0.0f : getShiftSpeed ();
|
||||
m_navTimeset = game.time ();
|
||||
|
|
@ -1785,10 +1786,14 @@ void Bot::refreshEnemyPredict () {
|
|||
}
|
||||
const bool denyLastEnemy = pev->velocity.lengthSq2d () > 0.0f
|
||||
&& distanceToLastEnemySq < cr::sqrf (256.0f)
|
||||
&& m_shootTime + 2.5f > game.time ();
|
||||
&& m_shootTime + 1.5f > game.time ();
|
||||
|
||||
if (!denyLastEnemy && seesEntity (m_lastEnemyOrigin, true)) {
|
||||
m_aimFlags |= AimFlags::LastEnemy;
|
||||
if (!(m_aimFlags & (AimFlags::Enemy | AimFlags::PredictPath)) && !denyLastEnemy && seesEntity (m_lastEnemyOrigin, true)) {
|
||||
const auto weaponPenetratePower = conf.findWeaponById (m_currentWeapon).penetratePower;
|
||||
|
||||
if (isPenetrableObstacle3 (m_lastEnemyOrigin, weaponPenetratePower)) {
|
||||
m_aimFlags |= AimFlags::LastEnemy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1801,7 +1806,7 @@ void Bot::setLastVictim (edict_t *ent) {
|
|||
m_lastVictim = ent;
|
||||
m_lastVictimOrigin = ent->v.origin + ent->v.view_ofs;
|
||||
|
||||
m_forgetLastVictimTimer.start (rg.get (0.5f, 0.8f));
|
||||
m_forgetLastVictimTimer.start (rg.get (1.0f, 2.0f));
|
||||
}
|
||||
|
||||
void Bot::setConditions () {
|
||||
|
|
@ -3869,7 +3874,7 @@ void Bot::updateHearing () {
|
|||
}
|
||||
|
||||
// did the bot hear someone ?
|
||||
if (hearedEnemy != nullptr && util.isPlayer (hearedEnemy)) {
|
||||
if (util.isPlayer (hearedEnemy)) {
|
||||
// change to best weapon if heard something
|
||||
if (m_shootTime < game.time () - 5.0f
|
||||
&& isOnFloor ()
|
||||
|
|
@ -3889,10 +3894,20 @@ void Bot::updateHearing () {
|
|||
pushChatterMessage (Chatter::HeardTheEnemy);
|
||||
}
|
||||
|
||||
auto getHeardOriginWithError = [&] () -> Vector {
|
||||
auto error = kSprayDistance * cr::powf (nearestDistanceSq, 0.5f) / 2048.0f;
|
||||
auto origin = hearedEnemy->v.origin;
|
||||
|
||||
origin.x = origin.x + rg.get (-error, error);
|
||||
origin.y = origin.y + rg.get (-error, error);
|
||||
|
||||
return origin;
|
||||
};
|
||||
|
||||
// didn't bot already have an enemy ? take this one...
|
||||
if (m_lastEnemyOrigin.empty () || game.isNullEntity (m_lastEnemy)) {
|
||||
m_lastEnemy = hearedEnemy;
|
||||
m_lastEnemyOrigin = hearedEnemy->v.origin;
|
||||
m_lastEnemyOrigin = getHeardOriginWithError ();
|
||||
}
|
||||
|
||||
// bot had an enemy, check if it's the heard one
|
||||
|
|
@ -3902,7 +3917,7 @@ void Bot::updateHearing () {
|
|||
if (m_states & Sense::SeeingEnemy) {
|
||||
return;
|
||||
}
|
||||
m_lastEnemyOrigin = hearedEnemy->v.origin;
|
||||
m_lastEnemyOrigin = getHeardOriginWithError ();
|
||||
}
|
||||
else {
|
||||
// if bot had an enemy but the heard one is nearer, take it instead
|
||||
|
|
@ -3910,7 +3925,7 @@ void Bot::updateHearing () {
|
|||
|
||||
if (distanceSq > hearedEnemy->v.origin.distanceSq (pev->origin) && m_seeEnemyTime + 2.0f < game.time ()) {
|
||||
m_lastEnemy = hearedEnemy;
|
||||
m_lastEnemyOrigin = hearedEnemy->v.origin;
|
||||
m_lastEnemyOrigin = getHeardOriginWithError ();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ ConVar cv_ignore_enemies ("ignore_enemies", "0", "Enables or disables searching
|
|||
ConVar cv_check_enemy_rendering ("check_enemy_rendering", "0", "Enables or disables checking enemy rendering flags. Useful for some mods.");
|
||||
ConVar cv_check_enemy_invincibility ("check_enemy_invincibility", "0", "Enables or disables checking enemy invincibility. Useful for some mods.");
|
||||
ConVar cv_stab_close_enemies ("stab_close_enemies", "1", "Enables or disables bot ability to stab the enemy with knife if bot is in good condition.");
|
||||
ConVar cv_use_engine_pvs_check ("use_engine_pvs_check", "0", "Use engine to check potential visibility of a enemy.");
|
||||
|
||||
ConVar mp_friendlyfire ("mp_friendlyfire", nullptr, Var::GameRef);
|
||||
ConVar sv_gravity ("sv_gravity", nullptr, Var::GameRef);
|
||||
|
|
@ -293,7 +294,12 @@ bool Bot::lookupEnemies () {
|
|||
|
||||
// the old enemy is no longer visible or
|
||||
if (game.isNullEntity (newEnemy)) {
|
||||
auto set = game.getVisibilitySet (this, true); // setup potential visibility set from engine
|
||||
auto set = nullptr;
|
||||
|
||||
// setup potential visibility set from engine
|
||||
if (cv_use_engine_pvs_check.bool_ ()) {
|
||||
game.getVisibilitySet (this, true);
|
||||
}
|
||||
|
||||
// ignore shielded enemies, while we have real one
|
||||
edict_t *shieldEnemy = nullptr;
|
||||
|
|
@ -306,7 +312,7 @@ bool Bot::lookupEnemies () {
|
|||
}
|
||||
|
||||
// check the engine PVS
|
||||
if (!game.checkVisibility (interesting, set)) {
|
||||
if (cv_use_engine_pvs_check.bool_ () && !game.checkVisibility (interesting, set)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +342,7 @@ bool Bot::lookupEnemies () {
|
|||
player = client.ent;
|
||||
|
||||
// check the engine PVS
|
||||
if (!game.checkVisibility (player, set)) {
|
||||
if (cv_use_engine_pvs_check.bool_ () && !game.checkVisibility (player, set)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +520,7 @@ bool Bot::lookupEnemies () {
|
|||
}
|
||||
|
||||
Vector Bot::getBodyOffsetError (float distance) {
|
||||
if (game.isNullEntity (m_enemy) || distance < kDoubleSprayDistance) {
|
||||
if (game.isNullEntity (m_enemy) || distance < kSprayDistanceX2) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -570,7 +576,12 @@ Vector Bot::getEnemyBodyOffset () {
|
|||
else if (util.isPlayer (m_enemy)) {
|
||||
// now take in account different parts of enemy body
|
||||
if (m_enemyParts & (Visibility::Head | Visibility::Body)) {
|
||||
const auto headshotPct = conf.getDifficultyTweaks (m_difficulty)->headshotPct;
|
||||
auto headshotPct = conf.getDifficultyTweaks (m_difficulty)->headshotPct;
|
||||
|
||||
// with to much recoil or using specific weapons choice to aim to the chest
|
||||
if (distance > kSprayDistance && (isRecoilHigh () || usesSniperAWP () || usesShotgun ())) {
|
||||
headshotPct = 0;
|
||||
}
|
||||
|
||||
// now check is our skill match to aim at head, else aim at enemy body
|
||||
if (m_enemyBodyPartSet == m_enemy || rg.chance (headshotPct)) {
|
||||
|
|
@ -639,10 +650,10 @@ Vector Bot::getCustomHeight (float distance) {
|
|||
auto distanceIndex = DistanceIndex::Short;
|
||||
|
||||
// set distance index appropriate to distance
|
||||
if (distance < 2048.0f && distance > kDoubleSprayDistance) {
|
||||
if (distance < 2048.0f && distance > kSprayDistanceX2) {
|
||||
distanceIndex = DistanceIndex::Long;
|
||||
}
|
||||
else if (distance > kSprayDistance && distance <= kDoubleSprayDistance) {
|
||||
else if (distance > kSprayDistance && distance <= kSprayDistanceX2) {
|
||||
distanceIndex = DistanceIndex::Middle;
|
||||
}
|
||||
return { 0.0f, 0.0f, kOffsetRanges[m_weaponType][distanceIndex] };
|
||||
|
|
@ -834,24 +845,23 @@ bool Bot::needToPauseFiring (float distance) {
|
|||
if (distance < kSprayDistance) {
|
||||
return false;
|
||||
}
|
||||
else if (distance < kDoubleSprayDistance) {
|
||||
else if (distance < kSprayDistanceX2) {
|
||||
offset = 2.75f;
|
||||
}
|
||||
else if ((m_states & Sense::SuspectEnemy) && distance < kDoubleSprayDistance) {
|
||||
else if ((m_states & Sense::SuspectEnemy) && distance < kSprayDistanceX2) {
|
||||
return false;
|
||||
}
|
||||
const float xPunch = cr::sqrf (cr::deg2rad (pev->punchangle.x));
|
||||
const float yPunch = cr::sqrf (cr::deg2rad (pev->punchangle.y));
|
||||
|
||||
const float interval = m_frameInterval;
|
||||
const float tolerance = (100.0f - static_cast <float> (m_difficulty) * 25.0f) / 99.0f;
|
||||
const float baseTime = distance > kDoubleSprayDistance ? 0.65f : 0.48f;
|
||||
const float baseTime = distance > kSprayDistance ? 0.65f : 0.48f;
|
||||
const float maxRecoil = static_cast <float> (conf.getDifficultyTweaks (m_difficulty)->maxRecoil);
|
||||
|
||||
// check if we need to compensate recoil
|
||||
if (cr::tanf (cr::sqrtf (cr::abs (xPunch) + cr::abs (yPunch))) * distance > offset + maxRecoil + tolerance) {
|
||||
if (m_firePause < game.time ()) {
|
||||
m_firePause = game.time () + rg.get (baseTime, baseTime + maxRecoil * 0.01f * tolerance) - interval;
|
||||
m_firePause = game.time () + rg.get (baseTime, baseTime + maxRecoil * 0.01f * tolerance) - m_frameInterval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1229,16 +1239,9 @@ void Bot::attackMovement () {
|
|||
|
||||
// only take cover when bomb is not planted and enemy can see the bot or the bot is VIP
|
||||
if (!game.is (GameFlags::CSDM)) {
|
||||
if (m_retreatTime < game.time () && approach < 30 && !bots.isBombPlanted ()) {
|
||||
const auto enemyCone = util.getConeDeviation (m_enemy, pev->origin);
|
||||
const auto seeingEnemy = (m_states & Sense::SeeingEnemy);
|
||||
const auto enemyWeaponIsSniper = (m_enemy->v.weapons & kSniperWeaponMask);
|
||||
|
||||
// make bot seek cover
|
||||
if ((enemyCone > 0.8f && seeingEnemy) || (enemyWeaponIsSniper && enemyCone > 0.95f)) {
|
||||
startTask (Task::SeekCover, TaskPri::SeekCover, kInvalidNodeIndex, 0.0f, false);
|
||||
m_moveSpeed = -pev->maxspeed;
|
||||
}
|
||||
if ((m_states & Sense::SeeingEnemy) && approach < 30 && !bots.isBombPlanted () && (isInViewCone (m_enemy->v.origin) || m_isVIP)) {
|
||||
m_moveSpeed = -pev->maxspeed;
|
||||
startTask (Task::SeekCover, TaskPri::SeekCover, kInvalidNodeIndex, 0.0f, true);
|
||||
}
|
||||
else if (approach < 50) {
|
||||
m_moveSpeed = 0.0f;
|
||||
|
|
@ -1292,7 +1295,7 @@ void Bot::attackMovement () {
|
|||
if (isDucking () || isInNarrowPlace ()) {
|
||||
m_fightStyle = Fight::Stay;
|
||||
}
|
||||
const auto pistolStrafeDistance = game.is (GameFlags::CSDM) ? kDoubleSprayDistance * 3.0f : kDoubleSprayDistance;
|
||||
const auto pistolStrafeDistance = game.is (GameFlags::CSDM) ? kSprayDistanceX2 * 3.0f : kSprayDistanceX2;
|
||||
|
||||
// fire hurts friend value here is from previous frame, but acceptable, and saves us alot of cpu cycles
|
||||
if (approach < 30 || m_fireHurtsFriend || ((usesPistol () || usesShotgun ())
|
||||
|
|
@ -1317,7 +1320,7 @@ void Bot::attackMovement () {
|
|||
};
|
||||
|
||||
auto strafeUpdateTime = [] () {
|
||||
return game.time () + rg.get (0.8f, 1.25f);
|
||||
return game.time () + rg.get (0.3f, 1.0f);
|
||||
};
|
||||
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
|
|
@ -1392,7 +1395,7 @@ void Bot::attackMovement () {
|
|||
if (alreadyDucking) {
|
||||
m_duckTime = game.time () + m_frameInterval * 3.0f;
|
||||
}
|
||||
else if ((distance > 768.0f && hasPrimaryWeapon ())
|
||||
else if ((distance > kSprayDistanceX2 && hasPrimaryWeapon ())
|
||||
&& (m_enemyParts & (Visibility::Head | Visibility::Body))
|
||||
&& getCurrentTaskId () != Task::SeekCover
|
||||
&& getCurrentTaskId () != Task::Hunt) {
|
||||
|
|
@ -1409,7 +1412,7 @@ void Bot::attackMovement () {
|
|||
}
|
||||
|
||||
if (m_difficulty >= Difficulty::Normal && isOnFloor () && m_duckTime < game.time ()) {
|
||||
if (distance < kDoubleSprayDistance) {
|
||||
if (distance < kSprayDistanceX2) {
|
||||
if (rg.get (0, 1000) < rg.get (5, 10) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) {
|
||||
pev->button |= IN_JUMP;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -496,6 +496,10 @@ int BotControl::cmdNodeOn () {
|
|||
}
|
||||
|
||||
if (graph.hasEditFlag (GraphEdit::On)) {
|
||||
m_graphSaveVarValues.roundtime = mp_roundtime.float_ ();
|
||||
m_graphSaveVarValues.freezetime = mp_freezetime.float_ ();
|
||||
m_graphSaveVarValues.timelimit = mp_timelimit.float_ ();
|
||||
|
||||
mp_roundtime.set (9);
|
||||
mp_freezetime.set (0);
|
||||
mp_timelimit.set (0);
|
||||
|
|
@ -511,6 +515,11 @@ int BotControl::cmdNodeOff () {
|
|||
graph.clearEditFlag (GraphEdit::On | GraphEdit::Auto | GraphEdit::Noclip);
|
||||
enableDrawModels (false);
|
||||
|
||||
// revert cvars back to their values
|
||||
mp_roundtime.set (m_graphSaveVarValues.roundtime);
|
||||
mp_freezetime.set (m_graphSaveVarValues.freezetime);
|
||||
mp_timelimit.set (m_graphSaveVarValues.timelimit);
|
||||
|
||||
msg ("Graph editor has been disabled.");
|
||||
}
|
||||
else if (strValue (option) == "models") {
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ bool Game::checkVisibility (edict_t *ent, uint8_t *set) {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 48; ++i) {
|
||||
for (int i = 0; i < MAX_ENT_LEAFS; ++i) {
|
||||
const auto leaf = ent->leafnums[i];
|
||||
|
||||
if (leaf == -1) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ ConVar cv_kick_after_player_connect ("kick_after_player_connect", "1", "Kick the
|
|||
ConVar cv_quota ("quota", "9", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar cv_quota_mode ("quota_mode", "normal", "Specifies the type of quota.\nAllowed values: 'normal', 'fill', and 'match'.\nIf 'fill', the server will adjust bots to keep N players in the game, where N is yb_quota.\nIf 'match', the server will maintain a 1:N ratio of humans to bots, where N is yb_quota_match.", false);
|
||||
ConVar cv_quota_match ("quota_match", "0", "Number of players to match if yb_quota_mode set to 'match'", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar cv_think_fps ("think_fps", "26.0", "Specifies how many times per second bot code will run.", true, 24.0f, 90.0f);
|
||||
ConVar cv_think_fps ("think_fps", "30.0", "Specifies how many times per second bot code will run.", true, 24.0f, 90.0f);
|
||||
ConVar cv_think_fps_disable ("think_fps_disable", "0", "Allows to completely disable think fps on Xash3D.", true, 0.0f, 1.0f, Var::Xash3D);
|
||||
|
||||
ConVar cv_autokill_delay ("autokill_delay", "0.0", "Specifies amount of time in seconds when bots will be killed if no humans left alive.", true, 0.0f, 90.0f);
|
||||
|
|
|
|||
|
|
@ -975,7 +975,7 @@ bool Bot::updateNavigation () {
|
|||
const auto prevNodeIndex = m_previousNodes[0];
|
||||
|
||||
// do a precise movement when very near
|
||||
if (graph.exists (prevNodeIndex) && !(graph[prevNodeIndex].flags & NodeFlag::Ladder) && ladderDistance < 64.0f) {
|
||||
if (!isDucking () && graph.exists (prevNodeIndex) && !(graph[prevNodeIndex].flags & NodeFlag::Ladder) && ladderDistance < 64.0f) {
|
||||
m_moveSpeed = pev->maxspeed * 0.4f;
|
||||
|
||||
// do not duck while not on ladder
|
||||
|
|
@ -1114,14 +1114,14 @@ bool Bot::updateNavigation () {
|
|||
}
|
||||
|
||||
float desiredDistanceSq = cr::sqrf (4.0f);
|
||||
const float nodeDistanceSq = pev->origin.distanceSq (m_pathOrigin);
|
||||
const float nodeDistanceSq = pev->origin.distanceSq2d (m_pathOrigin);
|
||||
|
||||
// initialize the radius for a special node type, where the node is considered to be reached
|
||||
if (m_pathFlags & NodeFlag::Lift) {
|
||||
desiredDistanceSq = cr::sqrf (50.0f);
|
||||
}
|
||||
else if (isDucking () || (m_pathFlags & NodeFlag::Goal)) {
|
||||
desiredDistanceSq = cr::sqrf (25.0f);
|
||||
desiredDistanceSq = cr::sqrf (12.0f);
|
||||
|
||||
// on cs_ maps goals are usually hostages, so increase reachability distance for them, they (hostages) picked anyway
|
||||
if (game.mapIs (MapFlags::HostageRescue) && (m_pathFlags & NodeFlag::Goal)) {
|
||||
|
|
|
|||
|
|
@ -463,7 +463,6 @@ void Bot::updateLookAngles () {
|
|||
m_idealAngles.x += cr::clamp (delta * m_lookPitchVel, -89.0f, 89.0f);
|
||||
|
||||
pev->v_angle = m_idealAngles;
|
||||
pev->v_angle.clampAngles ();
|
||||
|
||||
updateBodyAngles ();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue