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:
parent
53df621dfc
commit
9ddcef2dd4
4 changed files with 76 additions and 13 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,15 +504,27 @@ 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)) {
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue