aim: reducec headshot pct, if bot is too highskilled

aim: new cpu-friendly headshot penetration function (yb_shoots_thru_walls 3). still testing
nav: use more high range for checking occupied point.
nav: if last navigation node is used by someone, assume route ended
This commit is contained in:
jeefo 2023-04-02 14:13:52 +03:00
commit 9ddcef2dd4
No known key found for this signature in database
GPG key ID: 927BCA0779BEA8ED
4 changed files with 76 additions and 13 deletions

View file

@ -816,6 +816,7 @@ private:
bool isGroupOfEnemies (const Vector &location, int numEnemies = 1, float radius = 256.0f);
bool isPenetrableObstacle (const Vector &dest);
bool isPenetrableObstacle2 (const Vector &dest);
bool isPenetrableObstacle3 (const Vector &dest);
bool isEnemyBehindShield (edict_t *enemy);
bool isEnemyInFrustum (edict_t *enemy);
bool checkChatKeywords (String &reply);

View file

@ -2817,10 +2817,13 @@ void Bot::updateAimDir () {
else if (flags & AimFlags::PredictPath) {
TraceResult tr {};
if (m_lastEnemyOrigin.distanceSq (pev->origin) < cr::square (1560.0f) || usesSniper ()) {
auto distanceToLastEnemySq = m_lastEnemyOrigin.distanceSq (pev->origin);
auto maxDistanceToEnemySq = cr::square (1600.0f);
if ((distanceToLastEnemySq < maxDistanceToEnemySq || usesSniper ()) && util.isAlive (m_lastEnemy)) {
game.testLine (getEyesPos (), m_lastEnemyOrigin, TraceIgnore::Glass, pev->pContainingEntity, &tr);
if (tr.flFraction >= 0.2f || !tr.fStartSolid || tr.pHit != game.getStartEntity ()) {
if (tr.flFraction >= 0.2f || tr.pHit != game.getStartEntity ()) {
auto changePredictedEnemy = true;
if (m_timeNextTracking < game.time () && m_trackingEdict == m_lastEnemy && util.isAlive (m_lastEnemy)) {
@ -2855,6 +2858,9 @@ void Bot::updateAimDir () {
}
else {
m_aimFlags &= ~AimFlags::PredictPath; // forget enemy far away
if (distanceToLastEnemySq >= maxDistanceToEnemySq)
m_lastEnemyOrigin = nullptr;
}
}
else if (flags & AimFlags::Camp) {

View file

@ -7,7 +7,7 @@
#include <yapb.h>
ConVar cv_shoots_thru_walls ("yb_shoots_thru_walls", "2", "Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.", true, 0.0f, 2.0f);
ConVar cv_shoots_thru_walls ("yb_shoots_thru_walls", "2", "Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.", true, 0.0f, 3.0f);
ConVar cv_ignore_enemies ("yb_ignore_enemies", "0", "Enables or disables searching world for enemies.");
ConVar cv_check_enemy_rendering ("yb_check_enemy_rendering", "0", "Enables or disables checking enemy rendering flags. Useful for some mods.");
ConVar cv_check_enemy_invincibility ("yb_check_enemy_invincibility", "0", "Enables or disables checking enemy invincibility. Useful for some mods.");
@ -504,14 +504,26 @@ const Vector &Bot::getEnemyBodyOffset () {
aimPos += getBodyOffsetError (distance);
}
else if (util.isPlayer (m_enemy)) {
const float highOffset = m_difficulty > Difficulty::Normal ? 1.5f : 0.0f;
const float highOffset = cv_whose_your_daddy.bool_ () ? 1.5f : 0.0f;
// now take in account different parts of enemy body
if (m_enemyParts & (Visibility::Head | Visibility::Body)) {
auto headshotPct = conf.getDifficultyTweaks (m_difficulty)->headshotPct;
auto onLoosingStreak = m_fearLevel > m_agressionLevel || m_kpdRatio < 1.5f;
// reduce headshot percent in case we're play too good
if (!onLoosingStreak) {
headshotPct = cr::abs (headshotPct - headshotPct / 4);
}
// now check is our skill match to aim at head, else aim at enemy body
if (rg.chance (conf.getDifficultyTweaks (m_difficulty)->headshotPct)) {
aimPos.z = headOffset (m_enemy) + getEnemyBodyOffsetCorrection (distance);
if (rg.chance (headshotPct)) {
if (onLoosingStreak || cv_whose_your_daddy.bool_ ()) {
aimPos.z = headOffset (m_enemy) + getEnemyBodyOffsetCorrection (distance);
}
else {
aimPos = m_enemy->v.origin + m_enemy->v.view_ofs;
}
}
else {
aimPos.z += highOffset;
@ -610,16 +622,21 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
// this function returns true if enemy can be shoot through some obstacle, false otherwise.
// credits goes to Immortal_BLG
if (cv_shoots_thru_walls.int_ () == 2) {
auto method = cv_shoots_thru_walls.int_ ();
if (method == 2) {
return isPenetrableObstacle2 (dest);
}
else if (method == 3) {
return isPenetrableObstacle3 (dest);
}
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal) {
return false;
}
int penetratePower = conf.findWeaponById (m_currentWeapon).penetratePower;
auto power = conf.findWeaponById (m_currentWeapon).penetratePower;
if (penetratePower == 0) {
if (power == 0) {
return false;
}
TraceResult tr {};
@ -645,10 +662,10 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
const float distance = cr::square (75.0f);
if (obstacleDistance > 0.0f) {
while (penetratePower > 0) {
while (power > 0) {
if (obstacleDistance > distance) {
obstacleDistance -= distance;
penetratePower--;
power--;
continue;
}
@ -697,6 +714,45 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) {
return false;
}
bool Bot::isPenetrableObstacle3 (const Vector &dest) {
// this function returns if enemy can be shoot through some obstacle
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal || !conf.findWeaponById (m_currentWeapon).penetratePower) {
return false;
}
auto power = conf.findWeaponById (m_currentWeapon).penetratePower;
if (power == 0) {
return false;
}
TraceResult tr {};
Vector source = getEyesPos ();
const auto &dir = (dest - source).normalize () * 8.0f;
for (;;) {
game.testLine (source, dest, TraceIgnore::Monsters, ent (), &tr);
if (tr.fStartSolid) {
if (tr.fAllSolid) {
return false;
}
source += dir;
}
else {
// check if line hit anything
if (cr::fequal (tr.flFraction, 1.0f)) {
return true;
}
if (--power == 0) {
return false;
}
source = tr.vecEndPos + dir;
}
}
}
bool Bot::needToPauseFiring (float distance) {
// returns true if bot needs to pause between firing to compensate for punchangle & weapon spread

View file

@ -925,7 +925,7 @@ bool Bot::updateNavigation () {
getTask ()->data = kInvalidNodeIndex;
clearSearchNodes ();
return false;
return true;
}
if (nodeDistance < desiredDistance) {
@ -3220,7 +3220,7 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
}
auto length = client.origin.distanceSq (graph[index].origin);
if (length < cr::clamp (cr::square (graph[index].radius), cr::square (60.0f), cr::square (90.0f))) {
if (length < cr::clamp (cr::square (graph[index].radius) * 2.0f, cr::square (80.0f), cr::square (140.0f))) {
return true;
}
auto bot = bots[client.ent];