From 2b2b82ee13ba568cd7cd60edf240e16a4c80474a Mon Sep 17 00:00:00 2001 From: jeefo Date: Sun, 7 May 2023 01:04:09 +0300 Subject: [PATCH] fix: bot is marked as stale when not needed bot: port enemy noticeable function from regamedll --- inc/engine.h | 2 +- inc/yapb.h | 1 + src/botlib.cpp | 29 ++++++++------ src/combat.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++---- src/linkage.cpp | 2 + src/manager.cpp | 16 ++++---- 6 files changed, 122 insertions(+), 28 deletions(-) diff --git a/inc/engine.h b/inc/engine.h index b6478a0..0d27607 100644 --- a/inc/engine.h +++ b/inc/engine.h @@ -140,7 +140,7 @@ public: ~Game () = default; public: - // precaches internal stuff + // preaches internal stuff void precache (); // initialize levels diff --git a/inc/yapb.h b/inc/yapb.h index 38c03b1..d245bb4 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -893,6 +893,7 @@ private: bool updateLiftStates (); bool canRunHeavyWeight (); bool isEnemyInSight (Vector &endPos); + bool isEnemyNoticeable (float range); void doPlayerAvoidance (const Vector &normal); void selectCampButtons (int index); diff --git a/src/botlib.cpp b/src/botlib.cpp index b0b970a..ce87fc1 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -1510,7 +1510,7 @@ void Bot::updateEmotions () { if (m_nextEmotionUpdate > game.time ()) { return; } - + if (m_agressionLevel > m_baseAgressionLevel) { m_agressionLevel -= 0.05f; } @@ -2105,21 +2105,26 @@ bool Bot::reactOnEnemy () { } if (m_enemyReachableTimer < game.time ()) { - int ownIndex = m_currentNodeIndex; - - if (ownIndex == kInvalidNodeIndex) { - ownIndex = findNearestNode (); - } - int enemyIndex = graph.getNearest (m_enemy->v.origin); - auto lineDist = m_enemy->v.origin.distance (pev->origin); - auto pathDist = planner.preciseDistance (ownIndex, enemyIndex); - if (pathDist - lineDist > 112.0f || isOnLadder ()) { - m_isEnemyReachable = false; + if (isEnemyNoticeable (lineDist)) { + m_isEnemyReachable = true; } else { - m_isEnemyReachable = true; + int ownIndex = m_currentNodeIndex; + + if (ownIndex == kInvalidNodeIndex) { + ownIndex = findNearestNode (); + } + auto enemyIndex = graph.getNearest (m_enemy->v.origin); + auto pathDist = planner.preciseDistance (ownIndex, enemyIndex); + + if (pathDist - lineDist > 112.0f || isOnLadder ()) { + m_isEnemyReachable = false; + } + else { + m_isEnemyReachable = true; + } } m_enemyReachableTimer = game.time () + 1.0f; } diff --git a/src/combat.cpp b/src/combat.cpp index 54c40c1..efff83b 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -511,12 +511,10 @@ Vector Bot::getBodyOffsetError (float distance) { } else { spot = m_enemy->v.origin; - spot.z -= 3.0f; } } else if (m_enemyParts & Visibility::Body) { spot = m_enemy->v.origin; - spot.z += 3.0f; } else if (m_enemyParts & Visibility::Other) { spot = m_enemyOrigin; @@ -525,15 +523,15 @@ Vector Bot::getBodyOffsetError (float distance) { spot = m_enemyOrigin + getCustomHeight (distance); } } - Vector newSpot = spot; + Vector idealSpot = m_enemyOrigin; - if (m_difficulty < Difficulty::Expert && isEnemyInSight (newSpot)) { - spot = newSpot + ((spot - newSpot) * 0.01f); // gradually adjust the aiming direction + if (m_difficulty < Difficulty::Expert && isEnemyInSight (idealSpot)) { + spot = idealSpot + ((spot - idealSpot) * 0.01f); // gradually adjust the aiming direction } spot += compensation; if (usesKnife () && m_difficulty >= Difficulty::Normal) { - spot = m_enemyOrigin; + spot = m_enemyOrigin;bn } m_lastEnemyOrigin = spot; @@ -549,7 +547,7 @@ Vector Bot::getCustomHeight (float distance) { Long, Middle, Short }; - static constexpr float offsetRanges[9][3] = { + constexpr float offsetRanges[9][3] = { { 0.0f, 0.0f, 0.0f }, // none { 0.0f, 0.0f, 0.0f }, // melee { 0.5f, -3.0f, -4.5f }, // pistol @@ -2067,3 +2065,91 @@ bool Bot::isEnemyInSight (Vector &endPos) { endPos = aimHitTr.vecEndPos; return true; } + +bool Bot::isEnemyNoticeable (float range) { + // this function is back ported from regamedll with small changes + + if (isOnLadder ()) { + return false; + } + + // determine percentage of player that is visible + float coverRatio = 0.0f; + + if (m_enemyParts & Visibility::Body) { + coverRatio += 40.0f; + } + + if (m_enemyParts & Visibility::Head) { + coverRatio += 10.0f; + } + + if (m_enemyParts & Visibility::Other) { + coverRatio += rg.get (10.0f, 25.0f); + } + constexpr float closeRange = 300.0f; + constexpr float farRange = 1000.0f; + + float rangeModifier; + if (range < closeRange) { + rangeModifier = 0.0f; + } + else if (range > farRange) { + rangeModifier = 1.0f; + } + else { + rangeModifier = (range - closeRange) / (farRange - closeRange); + } + + // harder to notice when crouched + bool isCrouching = (m_enemy->v.flags & FL_DUCKING) == FL_DUCKING; + + // moving players are easier to spot + float playerSpeedSq = m_enemy->v.velocity.lengthSq (); + float farChance, closeChance; + + constexpr float runSpeed = cr::sqrf (200.0f); + constexpr float walkSpeed = cr::sqrf (30.0f); + + if (playerSpeedSq > runSpeed) { + return true; // running players are always easy to spot (must be standing to run) + } + else if (playerSpeedSq > walkSpeed) { + // walking players are less noticeable far away + if (isCrouching) { + closeChance = 90.0f; + farChance = 60.0f; + } + // standing + else { + closeChance = 100.0f; + farChance = 75.0f; + } + } + else { + // motionless players are hard to notice + if (isCrouching) { + // crouching and motionless - very tough to notice + closeChance = 80.0f; + farChance = 5.0f; // takes about three seconds to notice (50% chance) + } + // standing + else { + closeChance = 100.0f; + farChance = 10.0f; + } + } + + float dispositionChance = closeChance + (farChance - closeChance) * rangeModifier; // combine posture, speed, and range chances + float noticeChance = dispositionChance * coverRatio / 100.0f; // determine actual chance of noticing player + + noticeChance += (0.5f + 0.5f * (static_cast (m_difficulty) * 25.0f)); + + // if we are alert, our chance of noticing is much higher + if (m_agressionLevel > m_fearLevel) { + noticeChance += 50.0f; + } + noticeChance = cr::max (0.1f, noticeChance * cr::abs (m_agressionLevel - m_fearLevel)); + + return rg.get (0.0f, 100.0f) < noticeChance; +} diff --git a/src/linkage.cpp b/src/linkage.cpp index d44d632..1a48e9c 100644 --- a/src/linkage.cpp +++ b/src/linkage.cpp @@ -795,6 +795,8 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion) if (bot->m_enemy == ent) { bot->m_enemy = nullptr; bot->m_lastEnemy = nullptr; + } + else if (bot->ent () == ent) { bot->markStale (); } } diff --git a/src/manager.cpp b/src/manager.cpp index 85ad940..2cdcb7a 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1939,21 +1939,21 @@ void BotThreadWorker::startup (int workers) { return; } - int requetedThreadCount = workers; + int requestedThreadCount = workers; int hardwareConcurrency = plat.hardwareConcurrency (); - if (requetedThreadCount == -1) { - requetedThreadCount = hardwareConcurrency / 4; + if (requestedThreadCount == -1) { + requestedThreadCount = hardwareConcurrency / 4; - if (requetedThreadCount == 0) { - requetedThreadCount = 1; + if (requestedThreadCount == 0) { + requestedThreadCount = 1; } } - requetedThreadCount = cr::clamp (requetedThreadCount, 1, hardwareConcurrency); + requestedThreadCount = cr::clamp (requestedThreadCount, 1, hardwareConcurrency); // notify user - game.print ("Starting up bot thread worker with %d threads.", requetedThreadCount); + game.print ("Starting up bot thread worker with %d threads.", requestedThreadCount); // start up the worker - m_botWorker.startup (static_cast (requetedThreadCount)); + m_botWorker.startup (static_cast (requestedThreadCount)); }