From ae9beff1512094b70c57b4e4e79504c05486b6ed Mon Sep 17 00:00:00 2001 From: commandcobra7 <91374215+commandcobra7@users.noreply.github.com> Date: Sun, 10 Sep 2023 11:12:15 +0300 Subject: [PATCH] fix: texts have been corrected. (#477) task: normal: skip sniper node if no sniper weapon. task: normal: don't walk if there are no enemies left and they are using knives. task: attack: get proper function if bots lose close node after attack task. nav: unnecessary codes cleared. combat: attack movements reviewed. bot: enemy hearing is now better. (thanks for the @spodlesniy idea) desire: increased desire to seek cover by distance. (made for zombie plague mod) --------- Co-authored-by: jeefo --- cfg/addons/yapb/conf/yapb.cfg | 14 ++++---- inc/graph.h | 2 +- inc/yapb.h | 1 - src/botlib.cpp | 68 +++++++++++++++++------------------ src/combat.cpp | 31 ++++++++++------ src/graph.cpp | 2 +- src/navigate.cpp | 33 +++++++++-------- src/tasks.cpp | 17 +++++++-- src/vision.cpp | 8 ----- 9 files changed, 92 insertions(+), 84 deletions(-) diff --git a/cfg/addons/yapb/conf/yapb.cfg b/cfg/addons/yapb/conf/yapb.cfg index f47f1fe..22c8959 100644 --- a/cfg/addons/yapb/conf/yapb.cfg +++ b/cfg/addons/yapb/conf/yapb.cfg @@ -235,13 +235,6 @@ yb_pickup_best "1" // yb_ignore_objectives "0" -// -// Allows or disallows the ability for random knife attacks when bot is rushing and no enemy is nearby. -// --- -// Default: "1", Min: "0", Max: "1" -// -yb_random_knife_attacks "1" - // // Enables or disables bots chat functionality. // --- @@ -681,6 +674,13 @@ yb_camping_time_min "15.0" // yb_camping_time_max "45.0" +// +// Allows or disallows the ability for random knife attacks when bot is rushing and no enemy is nearby. +// --- +// Default: "1", Min: "0", Max: "1" +// +yb_random_knife_attacks "1" + // // Maximum number for path length, to predict the enemy. // --- diff --git a/inc/graph.h b/inc/graph.h index e8d04be..a854030 100644 --- a/inc/graph.h +++ b/inc/graph.h @@ -260,7 +260,7 @@ public: void showFileInfo (); void emitNotify (int32_t sound); - IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1); + IntArray getNearestInRadius (float radius, const Vector &origin, int maxCount = -1); const IntArray &getNodesInBucket (const Vector &pos); public: diff --git a/inc/yapb.h b/inc/yapb.h index 3063aaa..123c136 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -883,7 +883,6 @@ extern ConVar cv_shoots_thru_walls; extern ConVar cv_debug; extern ConVar cv_debug_goal; extern ConVar cv_save_bots_names; -extern ConVar cv_random_knife_attacks; extern ConVar cv_rotate_bots; extern ConVar cv_graph_url; extern ConVar cv_graph_url_upload; diff --git a/src/botlib.cpp b/src/botlib.cpp index 4932261..05f0fbc 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -38,7 +38,6 @@ ConVar cv_pickup_custom_items ("pickup_custom_items", "0", "Allows or disallows ConVar cv_pickup_ammo_and_kits ("pickup_ammo_and_kits", "0", "Allows bots pickup mod items like ammo, health kits and suits."); ConVar cv_pickup_best ("pickup_best", "1", "Allows or disallows bots to pickup best weapons."); ConVar cv_ignore_objectives ("ignore_objectives", "0", "Allows or disallows bots to do map objectives, i.e. plant/defuse bombs, and saves hostages."); -ConVar cv_random_knife_attacks ("random_knife_attacks", "1", "Allows or disallows the ability for random knife attacks when bot is rushing and no enemy is nearby."); // game console variables ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef); @@ -1684,7 +1683,7 @@ void Bot::refreshEnemyPredict () { if (game.isNullEntity (m_enemy) && !game.isNullEntity (m_lastEnemy) && !m_lastEnemyOrigin.empty ()) { const auto distanceToLastEnemySq = m_lastEnemyOrigin.distanceSq (pev->origin); - if (distanceToLastEnemySq > cr::sqrf (384.0f) && (distanceToLastEnemySq < cr::sqrf (2048.0f) || usesSniper ())) { + if (distanceToLastEnemySq > cr::sqrf (128.0f) && (distanceToLastEnemySq < cr::sqrf (2048.0f) || usesSniper ())) { m_aimFlags |= AimFlags::PredictPath; } const bool denyLastEnemy = pev->velocity.lengthSq2d () > 0.0f && distanceToLastEnemySq < cr::sqrf (256.0f); @@ -1902,6 +1901,9 @@ void Bot::filterTasks () { else if (m_isVIP || m_isReloading || (sniping && usesSniper ())) { ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading } + else if (m_lastEnemyOrigin.distance2d (pev->origin) < 200.0f) { + ratio *= 5.0f; + } else if (m_isCreature) { ratio = 0.0f; } @@ -3354,12 +3356,12 @@ void Bot::updatePracticeValue (int damage) { const auto health = static_cast (m_healthValue); // max goal value - constexpr int maxGoalValue = PracticeLimit::Goal; + constexpr int kMaxGoalValue = PracticeLimit::Goal; // only rate goal node if bot died because of the damage // FIXME: could be done a lot better, however this cares most about damage done by sniping or really deadly weapons if (health - damage <= 0) { - practice.setValue (m_team, m_chosenGoalIndex, m_prevGoalIndex, cr::clamp (practice.getValue (m_team, m_chosenGoalIndex, m_prevGoalIndex) - health / 20, -maxGoalValue, maxGoalValue)); + practice.setValue (m_team, m_chosenGoalIndex, m_prevGoalIndex, cr::clamp (practice.getValue (m_team, m_chosenGoalIndex, m_prevGoalIndex) - health / 20, -kMaxGoalValue, kMaxGoalValue)); } } @@ -3376,7 +3378,7 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) { if (attackerTeam == victimTeam) { return; } - constexpr int maxDamageValue = PracticeLimit::Damage; + constexpr int kMaxDamageValue = PracticeLimit::Damage; // if these are bots also remember damage to rank destination of the bot m_goalValue -= static_cast (damage); @@ -3398,13 +3400,13 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) { if (m_healthValue > 20.0f) { if (victimTeam == Team::Terrorist || victimTeam == Team::CT) { - practice.setDamage (victimIndex, victimIndex, victimIndex, cr::clamp (practice.getDamage (victimTeam, victimIndex, victimIndex), 0, maxDamageValue)); + practice.setDamage (victimIndex, victimIndex, victimIndex, cr::clamp (practice.getDamage (victimTeam, victimIndex, victimIndex), 0, kMaxDamageValue)); } } const auto updateDamage = util.isFakeClient (attacker) ? 10 : 7; // store away the damage done - const auto damageValue = cr::clamp (practice.getDamage (m_team, victimIndex, attackerIndex) + damage / updateDamage, 0, maxDamageValue); + const auto damageValue = cr::clamp (practice.getDamage (m_team, victimIndex, attackerIndex) + damage / updateDamage, 0, kMaxDamageValue); if (damageValue > practice.getHighestDamageForTeam (m_team)) { practice.setHighestDamageForTeam (m_team, damageValue); @@ -3650,17 +3652,18 @@ bool Bot::isOutOfBombTimer () { } void Bot::updateHearing () { - int hearEnemyIndex = kInvalidNodeIndex; + if (game.is (GameFlags::FreeForAll)) { + return; + } + edict_t *hearedEnemy = nullptr; float nearestDistanceSq = kInfiniteDistance; // setup potential visibility set from engine auto set = game.getVisibilitySet (this, false); // loop through all enemy clients to check for hearable stuff - for (int i = 0; i < game.maxClients (); ++i) { - const auto &client = util.getClient (i); - - if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent () || client.team == m_team || client.noise.last < game.time ()) { + for (const auto &client : util.getClients ()) { + if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent () || client.team == m_team || !client.ent || client.noise.last < game.time ()) { continue; } @@ -3674,18 +3677,13 @@ void Bot::updateHearing () { } if (distanceSq < nearestDistanceSq) { - hearEnemyIndex = i; + hearedEnemy = client.ent; nearestDistanceSq = distanceSq; } } - edict_t *player = nullptr; - - if (hearEnemyIndex >= 0 && util.getClient (hearEnemyIndex).team != m_team && !game.is (GameFlags::FreeForAll)) { - player = util.getClient (hearEnemyIndex).ent; - } // did the bot hear someone ? - if (player != nullptr && util.isPlayer (player)) { + if (hearedEnemy != nullptr && util.isPlayer (hearedEnemy)) { // change to best weapon if heard something if (m_shootTime < game.time () - 5.0f && isOnFloor () && m_currentWeapon != Weapon::C4 && m_currentWeapon != Weapon::Explosive && m_currentWeapon != Weapon::Smoke && m_currentWeapon != Weapon::Flashbang && !isKnifeMode ()) { selectBestWeapon (); @@ -3700,26 +3698,26 @@ void Bot::updateHearing () { // didn't bot already have an enemy ? take this one... if (m_lastEnemyOrigin.empty () || m_lastEnemy == nullptr) { - m_lastEnemy = player; - m_lastEnemyOrigin = player->v.origin; + m_lastEnemy = hearedEnemy; + m_lastEnemyOrigin = hearedEnemy->v.origin; } // bot had an enemy, check if it's the heard one else { - if (player == m_lastEnemy) { + if (hearedEnemy == m_lastEnemy) { // bot sees enemy ? then bail out ! if (m_states & Sense::SeeingEnemy) { return; } - m_lastEnemyOrigin = player->v.origin; + m_lastEnemyOrigin = hearedEnemy->v.origin; } else { // if bot had an enemy but the heard one is nearer, take it instead const float distanceSq = m_lastEnemyOrigin.distanceSq (pev->origin); - if (distanceSq > player->v.origin.distanceSq (pev->origin) && m_seeEnemyTime + 2.0f < game.time ()) { - m_lastEnemy = player; - m_lastEnemyOrigin = player->v.origin; + if (distanceSq > hearedEnemy->v.origin.distanceSq (pev->origin) && m_seeEnemyTime + 2.0f < game.time ()) { + m_lastEnemy = hearedEnemy; + m_lastEnemyOrigin = hearedEnemy->v.origin; } else { return; @@ -3728,9 +3726,9 @@ void Bot::updateHearing () { } // check if heard enemy can be seen - if (checkBodyParts (player)) { - m_enemy = player; - m_lastEnemy = player; + if (checkBodyParts (hearedEnemy)) { + m_enemy = hearedEnemy; + m_lastEnemy = hearedEnemy; m_lastEnemyOrigin = m_enemyOrigin; m_states |= Sense::SeeingEnemy; @@ -3739,11 +3737,11 @@ void Bot::updateHearing () { // check if heard enemy can be shoot through some obstacle else { - if (cv_shoots_thru_walls.bool_ () && m_difficulty >= Difficulty::Normal && m_lastEnemy == player && rg.chance (conf.getDifficultyTweaks (m_difficulty)->hearThruPct) && m_seeEnemyTime + 3.0f > game.time () && isPenetrableObstacle (player->v.origin)) { - m_enemy = player; - m_lastEnemy = player; - m_enemyOrigin = player->v.origin; - m_lastEnemyOrigin = player->v.origin; + if (cv_shoots_thru_walls.bool_ () && m_difficulty >= Difficulty::Normal && m_lastEnemy == hearedEnemy && rg.chance (conf.getDifficultyTweaks (m_difficulty)->hearThruPct) && m_seeEnemyTime + 3.0f > game.time () && isPenetrableObstacle (hearedEnemy->v.origin)) { + m_enemy = hearedEnemy; + m_lastEnemy = hearedEnemy; + m_enemyOrigin = hearedEnemy->v.origin; + m_lastEnemyOrigin = hearedEnemy->v.origin; m_states |= (Sense::SeeingEnemy | Sense::SuspectEnemy); m_seeEnemyTime = game.time (); @@ -3840,7 +3838,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) { } float Bot::getShiftSpeed () { - if (getCurrentTaskId () == Task::SeekCover || (m_aimFlags & AimFlags::Enemy) || isDucking () || (pev->button & IN_DUCK) || (m_oldButtons & IN_DUCK) || (m_currentTravelFlags & PathFlag::Jump) || (m_pathFlags & NodeFlag::Ladder) || isOnLadder () || isInWater () || m_isStuck) { + if (getCurrentTaskId () == Task::SeekCover || (m_aimFlags & AimFlags::Enemy) || isDucking () || (pev->button & IN_DUCK) || (m_oldButtons & IN_DUCK) || (m_currentTravelFlags & PathFlag::Jump) || (m_pathFlags & NodeFlag::Ladder) || isOnLadder () || isInWater () || isKnifeMode () || m_isStuck || m_numEnemiesLeft <= 0) { return pev->maxspeed; } return pev->maxspeed * 0.4f; diff --git a/src/combat.cpp b/src/combat.cpp index 414b6e5..39d8d23 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -1161,11 +1161,14 @@ void Bot::attackMovement () { else if (usesRifle () || usesSubmachine () || usesHeavy ()) { const int rand = rg.get (1, 100); - if (distance < 500.0f) { + if (distance < 768.0f) { m_fightStyle = Fight::Strafe; } else if (distance < 1024.0f) { - if (rand < (usesSubmachine () ? 50 : 30)) { + if (isGroupOfEnemies (m_enemy->v.origin)) { + m_fightStyle = Fight::Strafe; + } + else if (rand < (usesSubmachine () ? 50 : 30)) { m_fightStyle = Fight::Strafe; } else { @@ -1173,7 +1176,10 @@ void Bot::attackMovement () { } } else { - if (rand < (usesSubmachine () ? 80 : 90)) { + if (isGroupOfEnemies (m_enemy->v.origin)) { + m_fightStyle = Fight::Strafe; + } + else if (rand < (usesSubmachine () ? 80 : 90)) { m_fightStyle = Fight::Stay; } else { @@ -1199,9 +1205,12 @@ void Bot::attackMovement () { m_moveSpeed = -pev->maxspeed; } - if (usesKnife ()) { - m_fightStyle = Fight::None; - m_lastFightStyleCheck = game.time (); + if (usesKnife () && isInViewCone (m_enemy->v.origin)) { + m_fightStyle = Fight::Strafe; + } + + if (usesPistol () && distance < 768.0f) { + m_fightStyle = Fight::Strafe; } if (m_fightStyle == Fight::Strafe) { @@ -1270,7 +1279,7 @@ void Bot::attackMovement () { } // do not move forward/backward is too far - if (distance > 1024.0) { + if (distance > 1024.0f) { m_moveSpeed = 0.0f; } } @@ -1280,7 +1289,7 @@ void Bot::attackMovement () { if (alreadyDucking) { m_duckTime = game.time () + m_frameInterval * 2.0f; } - else if ((distance > kDoubleSprayDistance && hasPrimaryWeapon ()) && (m_enemyParts & (Visibility::Head | Visibility::Body)) && getCurrentTaskId () != Task::SeekCover && getCurrentTaskId () != Task::Hunt) { + else if ((distance > 768.0f && hasPrimaryWeapon ()) && (m_enemyParts & (Visibility::Head | Visibility::Body)) && getCurrentTaskId () != Task::SeekCover && getCurrentTaskId () != Task::Hunt) { const int enemyNearestIndex = graph.getNearest (m_enemy->v.origin); if (vistab.visible (m_currentNodeIndex, enemyNearestIndex, VisIndex::Crouch) && vistab.visible (enemyNearestIndex, m_currentNodeIndex, VisIndex::Crouch)) { @@ -1293,7 +1302,7 @@ void Bot::attackMovement () { if (m_difficulty >= Difficulty::Normal && isOnFloor () && m_duckTime < game.time ()) { if (distance < 768.0f) { - if (rg.get (0, 1000) < rg.get (7, 12) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) { + if (rg.get (0, 1000) < rg.get (5, 10) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) { pev->button |= IN_JUMP; } } @@ -1308,7 +1317,7 @@ void Bot::attackMovement () { Vector right, forward; pev->v_angle.angleVectors (&forward, &right, nullptr); - const auto &front = right * m_moveSpeed * 0.2f; + const auto &front = forward * m_moveSpeed * 0.2f; const auto &side = right * m_strafeSpeed * 0.2f; const auto &spot = pev->origin + front + side + pev->velocity * m_frameInterval; @@ -1907,7 +1916,7 @@ void Bot::checkGrenadesThrow () { const float radius = cr::max (192.0f, m_lastEnemy->v.velocity.length2d ()); const Vector &pos = m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin; - auto predicted = graph.getNarestInRadius (radius, pos, 12); + auto predicted = graph.getNearestInRadius (radius, pos, 12); if (predicted.empty ()) { m_states &= ~Sense::ThrowExplosive; diff --git a/src/graph.cpp b/src/graph.cpp index a87c629..b9642d0 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -539,7 +539,7 @@ int BotGraph::getNearest (const Vector &origin, const float range, int flags) { return index; } -IntArray BotGraph::getNarestInRadius (float radius, const Vector &origin, int maxCount) { +IntArray BotGraph::getNearestInRadius (float radius, const Vector &origin, int maxCount) { // returns all nodes within radius from position const float radiusSq = cr::sqrf (radius); diff --git a/src/navigate.cpp b/src/navigate.cpp index 11f2511..be06bba 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -429,9 +429,9 @@ void Bot::doPlayerAvoidance (const Vector &normal) { } m_hindrance = nullptr; - float distanceSq = cr::sqrf (348.0f); + float distanceSq = cr::sqrf (384.0f); - if (getCurrentTaskId () == Task::Attack || isOnLadder () || isInNarrowPlace ()) { + if (isOnLadder () || isInNarrowPlace ()) { return; } const auto ownPrio = bots.getPlayerPriority (ent ()); @@ -512,7 +512,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { m_isStuck = false; // standing still, no need to check? - if (m_lastCollTime < game.time () && getCurrentTaskId () != Task::Attack) { + if (m_lastCollTime < game.time () && getCurrentTaskId () != Task::Attack) { // didn't we move enough previously? if (movedDistance < 2.0f && (m_prevSpeed > 20.0f || m_prevVelocity < m_moveSpeed / 2)) { m_prevTime = game.time (); // then consider being stuck @@ -610,19 +610,19 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { dirLeft = true; } const auto &testDir = m_moveSpeed > 0.0f ? forward : -forward; - constexpr float blockDistance = 32.0f; + constexpr float kBlockDistance = 32.0f; // now check which side is blocked - src = pev->origin + right * blockDistance; - dst = src + testDir * blockDistance; + src = pev->origin + right * kBlockDistance; + dst = src + testDir * kBlockDistance; game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr); if (!cr::fequal (tr.flFraction, 1.0f)) { blockedRight = true; } - src = pev->origin - right * blockDistance; - dst = src + testDir * blockDistance; + src = pev->origin - right * kBlockDistance; + dst = src + testDir * kBlockDistance; game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr); @@ -714,8 +714,9 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { state[i] += 5; } } - else + else { state[i] = 0; + } ++i; // weighted all possible moves, now sort them to start with most probable @@ -823,6 +824,7 @@ void Bot::moveToGoal () { } } } + m_lastUsedNodesTime = game.time (); // special movement for swimming here if (isInWater ()) { @@ -959,7 +961,7 @@ bool Bot::updateNavigation () { constexpr auto kLadderOffset = Vector (0.0f, 0.0f, 16.0f); m_pathOrigin = m_path->origin + kLadderOffset; } - else if (m_pathOrigin.z < pev->origin.z + 16.0f && !isOnLadder () && isOnFloor () && !(pev->flags & FL_DUCKING)) { + else if (m_pathOrigin.z < pev->origin.z + 16.0f && !isOnLadder () && isOnFloor () && !isDucking ()) { m_moveSpeed = pev->origin.distance (m_pathOrigin); if (m_moveSpeed < 150.0f) { @@ -1037,7 +1039,6 @@ bool Bot::updateNavigation () { } } } - } } @@ -1173,13 +1174,13 @@ bool Bot::updateNavigation () { // did we reach a destination node? if (getTask ()->data == m_currentNodeIndex) { if (m_chosenGoalIndex != kInvalidNodeIndex) { - constexpr int maxGoalValue = PracticeLimit::Goal; + constexpr int kMaxGoalValue = PracticeLimit::Goal; // add goal values int goalValue = practice.getValue (m_team, m_chosenGoalIndex, m_currentNodeIndex); const int addedValue = static_cast (m_healthValue * 0.5f + m_goalValue * 0.5f); - goalValue = cr::clamp (goalValue + addedValue, -maxGoalValue, maxGoalValue); + goalValue = cr::clamp (goalValue + addedValue, -kMaxGoalValue, kMaxGoalValue); // update the practice for team practice.setValue (m_team, m_chosenGoalIndex, m_currentNodeIndex, goalValue); @@ -1782,7 +1783,7 @@ int Bot::findNearestNode () { // try to search ANYTHING that can be reached if (!graph.exists (index)) { nearestDistanceSq = cr::sqrf (kMaxDistance); - const auto &nearestNodes = graph.getNarestInRadius (kMaxDistance, pev->origin); + const auto &nearestNodes = graph.getNearestInRadius (kMaxDistance, pev->origin); for (const auto &i : nearestNodes) { const auto &path = graph[i]; @@ -1809,7 +1810,6 @@ int Bot::findNearestNode () { } } - // worst case, take any node... if (!graph.exists (index)) { index = graph.getNearestNoBuckets (origin); @@ -2174,7 +2174,7 @@ bool Bot::selectBestNextNode () { continue; } - // skip itn't connected links + // skip isn't connected links if (!graph.isConnected (link.index, nextNodeIndex) || !graph.isConnected (link.index, prevNodeIndex)) { continue; } @@ -3095,7 +3095,6 @@ edict_t *Bot::lookupButton (StringRef target) { return result; } - bool Bot::isReachableNode (int index) { // this function return whether bot able to reach index node or not, depending on several factors. diff --git a/src/tasks.cpp b/src/tasks.cpp index 4f8c9f0..3f2138b 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -13,6 +13,8 @@ ConVar cv_camping_allowed ("camping_allowed", "1", "Allows or disallows bots to ConVar cv_camping_time_min ("camping_time_min", "15.0", "Lower bound of time from which time for camping is calculated", true, 5.0f, 90.0f); ConVar cv_camping_time_max ("camping_time_max", "45.0", "Upper bound of time until which time for camping is calculated", true, 15.0f, 120.0f); +ConVar cv_random_knife_attacks ("random_knife_attacks", "1", "Allows or disallows the ability for random knife attacks when bot is rushing and no enemy is nearby."); + void Bot::normal_ () { m_aimFlags |= AimFlags::Nav; @@ -95,6 +97,11 @@ void Bot::normal_ () { campingAllowed = false; } + // skip sniper node if we don't have sniper weapon + if (campingAllowed && !usesSniper () && (m_pathFlags & NodeFlag::Sniper)) { + campingAllowed = false; + } + if (campingAllowed) { // crouched camping here? if (m_pathFlags & NodeFlag::Crouch) { @@ -446,7 +453,11 @@ void Bot::attackEnemy_ () { } else { completeTask (); - m_destOrigin = m_lastEnemyOrigin; + findNextBestNode (); + + if (!m_lastEnemyOrigin.empty ()) { + m_destOrigin = m_lastEnemyOrigin; + } } m_navTimeset = game.time (); } @@ -1034,7 +1045,7 @@ void Bot::followUser_ () { // didn't choose goal node yet? if (!hasActiveGoal ()) { int destIndex = graph.getNearest (m_targetEntity->v.origin); - auto points = graph.getNarestInRadius (200.0f, m_targetEntity->v.origin); + auto points = graph.getNearestInRadius (200.0f, m_targetEntity->v.origin); for (auto &newIndex : points) { // if node not yet used, assign it as dest @@ -1560,7 +1571,7 @@ void Bot::pickupItem_ () { int nearestHostageNodeIndex = kInvalidNodeIndex; // find the nearest 'unused' hostage within the area - game.searchEntities (pev->origin, 768.0f, [&] (edict_t *ent) { + game.searchEntities (pev->origin, 1024.0f, [&] (edict_t *ent) { if (!util.isHostageEntity (ent)) { return EntitySearchResult::Continue; } diff --git a/src/vision.cpp b/src/vision.cpp index 2f26737..91bb9e7 100644 --- a/src/vision.cpp +++ b/src/vision.cpp @@ -155,11 +155,6 @@ void Bot::updateAimDir () { m_timeNextTracking = game.time () + rg.get (0.5f, 1.0f); m_trackingEdict = m_lastEnemy; - - // feel free to fire if shootable - if (!usesSniper () && lastEnemyShootable ()) { - m_wantsToFire = true; - } } else { doFailPredict (); @@ -195,9 +190,6 @@ void Bot::updateAimDir () { m_lookAt = m_destOrigin; } } - else if (m_seeEnemyTime + 3.0f > game.time () && !m_lastEnemyOrigin.empty ()) { - m_lookAt = m_lastEnemyOrigin; - } else { m_lookAt = m_destOrigin; }