diff --git a/inc/yapb.h b/inc/yapb.h index 9de34a7..6a4ad33 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -362,6 +362,7 @@ private: private: int pickBestWeapon (Array &vec, int moneySave); int getRandomCampDir (); + int findAimingNode (const Vector &to, int &pathLength); int findNearestNode (); int findBombNode (); int findCoverNode (float maxDistance); diff --git a/src/botlib.cpp b/src/botlib.cpp index 6143839..31e349a 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -91,7 +91,7 @@ void Bot::avoidGrenades () { } // check if visible to the bot - if (!seesEntity (pent->v.origin) && isInFOV (pent->v.origin - getEyesPos ()) > pev->fov * 0.5f) { + if (isInFOV (pent->v.origin - getEyesPos ()) > pev->fov * 0.5f && !seesEntity (pent->v.origin)) { continue; } auto model = pent->v.model.str (9); @@ -3219,7 +3219,7 @@ void Bot::logic () { } // ensure we're not stuck destroying/picking something - if (m_navTimeset + getEstimatedNodeReachTime () < game.time () && !(m_states & Sense::SeeingEnemy) && m_moveToGoal) { + if (m_navTimeset + getEstimatedNodeReachTime () + 1.0f < game.time () && !(m_states & Sense::SeeingEnemy) && m_moveToGoal) { ensureEntitiesClear (); } diff --git a/src/combat.cpp b/src/combat.cpp index 84af927..e07f6c5 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -1437,7 +1437,7 @@ void Bot::attackMovement () { } } else if (m_fightStyle == Fight::Stay) { - const bool alreadyDucking = m_duckTime < game.time () || isDucking (); + const bool alreadyDucking = m_duckTime >= game.time () || isDucking () || ((pev->button | pev->oldbuttons) & IN_DUCK); if (alreadyDucking) { m_duckTime = game.time () + m_frameInterval * 3.0f; @@ -1458,6 +1458,14 @@ void Bot::attackMovement () { m_strafeSpeed = 0.0f; } + if (m_difficulty >= Difficulty::Normal && isOnFloor () && m_duckTime < game.time ()) { + if (distance < kSprayDistanceX2) { + if (rg (0, 1000) < rg (5, 10) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) { + pev->button |= IN_JUMP; + } + } + } + if (m_isReloading) { m_moveSpeed = -pev->maxspeed; m_duckTime = game.time () - 1.0f; diff --git a/src/navigate.cpp b/src/navigate.cpp index a9a625d..8bb7ea8 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -1670,6 +1670,33 @@ void Bot::clearSearchNodes () { m_chosenGoalIndex = kInvalidNodeIndex; } +int Bot::findAimingNode (const Vector &to, int &pathLength) { + // return the most distant node which is seen from the bot to the target and is within count + ensureCurrentNodeIndex (); + + const int destIndex = graph.getNearest (to); + int bestIndex = m_currentNodeIndex; + + if (destIndex == kInvalidNodeIndex) { + return kInvalidNodeIndex; + } + + auto result = planner.find (destIndex, m_currentNodeIndex, [&] (int index) { + ++pathLength; + + if (vistab.visible (m_currentNodeIndex, index)) { + bestIndex = index; + return false; + } + return true; + }); + + if (result && bestIndex == m_currentNodeIndex) { + return kInvalidNodeIndex; + } + return bestIndex; +} + bool Bot::findNextBestNode () { // this function find a node in the near of the bot if bot had lost his path of pathfinder needs // to be restarted over again. diff --git a/src/tasks.cpp b/src/tasks.cpp index 98cb5eb..4c3ab8a 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -631,6 +631,14 @@ void Bot::camp_ () { if (pathLength > 1 && graph.exists (predictNode)) { m_lookAtSafe = graph[predictNode].origin + pev->view_ofs; } + else { + pathLength = 0; + predictNode = findAimingNode (m_lastEnemyOrigin, pathLength); + + if (pathLength > 1 && graph.exists (predictNode)) { + m_lookAtSafe = graph[predictNode].origin + pev->view_ofs; + } + } } else { m_lookAtSafe = graph[getRandomCampDir ()].origin + pev->view_ofs;