fix: bot is marked as stale when not needed
bot: port enemy noticeable function from regamedll
This commit is contained in:
parent
cf9817ab10
commit
2b2b82ee13
6 changed files with 122 additions and 28 deletions
|
|
@ -140,7 +140,7 @@ public:
|
||||||
~Game () = default;
|
~Game () = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// precaches internal stuff
|
// preaches internal stuff
|
||||||
void precache ();
|
void precache ();
|
||||||
|
|
||||||
// initialize levels
|
// initialize levels
|
||||||
|
|
|
||||||
|
|
@ -893,6 +893,7 @@ private:
|
||||||
bool updateLiftStates ();
|
bool updateLiftStates ();
|
||||||
bool canRunHeavyWeight ();
|
bool canRunHeavyWeight ();
|
||||||
bool isEnemyInSight (Vector &endPos);
|
bool isEnemyInSight (Vector &endPos);
|
||||||
|
bool isEnemyNoticeable (float range);
|
||||||
|
|
||||||
void doPlayerAvoidance (const Vector &normal);
|
void doPlayerAvoidance (const Vector &normal);
|
||||||
void selectCampButtons (int index);
|
void selectCampButtons (int index);
|
||||||
|
|
|
||||||
|
|
@ -1510,7 +1510,7 @@ void Bot::updateEmotions () {
|
||||||
if (m_nextEmotionUpdate > game.time ()) {
|
if (m_nextEmotionUpdate > game.time ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_agressionLevel > m_baseAgressionLevel) {
|
if (m_agressionLevel > m_baseAgressionLevel) {
|
||||||
m_agressionLevel -= 0.05f;
|
m_agressionLevel -= 0.05f;
|
||||||
}
|
}
|
||||||
|
|
@ -2105,21 +2105,26 @@ bool Bot::reactOnEnemy () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_enemyReachableTimer < game.time ()) {
|
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 lineDist = m_enemy->v.origin.distance (pev->origin);
|
||||||
auto pathDist = planner.preciseDistance (ownIndex, enemyIndex);
|
|
||||||
|
|
||||||
if (pathDist - lineDist > 112.0f || isOnLadder ()) {
|
if (isEnemyNoticeable (lineDist)) {
|
||||||
m_isEnemyReachable = false;
|
m_isEnemyReachable = true;
|
||||||
}
|
}
|
||||||
else {
|
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;
|
m_enemyReachableTimer = game.time () + 1.0f;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
100
src/combat.cpp
100
src/combat.cpp
|
|
@ -511,12 +511,10 @@ Vector Bot::getBodyOffsetError (float distance) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spot = m_enemy->v.origin;
|
spot = m_enemy->v.origin;
|
||||||
spot.z -= 3.0f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_enemyParts & Visibility::Body) {
|
else if (m_enemyParts & Visibility::Body) {
|
||||||
spot = m_enemy->v.origin;
|
spot = m_enemy->v.origin;
|
||||||
spot.z += 3.0f;
|
|
||||||
}
|
}
|
||||||
else if (m_enemyParts & Visibility::Other) {
|
else if (m_enemyParts & Visibility::Other) {
|
||||||
spot = m_enemyOrigin;
|
spot = m_enemyOrigin;
|
||||||
|
|
@ -525,15 +523,15 @@ Vector Bot::getBodyOffsetError (float distance) {
|
||||||
spot = m_enemyOrigin + getCustomHeight (distance);
|
spot = m_enemyOrigin + getCustomHeight (distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vector newSpot = spot;
|
Vector idealSpot = m_enemyOrigin;
|
||||||
|
|
||||||
if (m_difficulty < Difficulty::Expert && isEnemyInSight (newSpot)) {
|
if (m_difficulty < Difficulty::Expert && isEnemyInSight (idealSpot)) {
|
||||||
spot = newSpot + ((spot - newSpot) * 0.01f); // gradually adjust the aiming direction
|
spot = idealSpot + ((spot - idealSpot) * 0.01f); // gradually adjust the aiming direction
|
||||||
}
|
}
|
||||||
spot += compensation;
|
spot += compensation;
|
||||||
|
|
||||||
if (usesKnife () && m_difficulty >= Difficulty::Normal) {
|
if (usesKnife () && m_difficulty >= Difficulty::Normal) {
|
||||||
spot = m_enemyOrigin;
|
spot = m_enemyOrigin;bn
|
||||||
}
|
}
|
||||||
m_lastEnemyOrigin = spot;
|
m_lastEnemyOrigin = spot;
|
||||||
|
|
||||||
|
|
@ -549,7 +547,7 @@ Vector Bot::getCustomHeight (float distance) {
|
||||||
Long, Middle, Short
|
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 }, // none
|
||||||
{ 0.0f, 0.0f, 0.0f }, // melee
|
{ 0.0f, 0.0f, 0.0f }, // melee
|
||||||
{ 0.5f, -3.0f, -4.5f }, // pistol
|
{ 0.5f, -3.0f, -4.5f }, // pistol
|
||||||
|
|
@ -2067,3 +2065,91 @@ bool Bot::isEnemyInSight (Vector &endPos) {
|
||||||
endPos = aimHitTr.vecEndPos;
|
endPos = aimHitTr.vecEndPos;
|
||||||
return true;
|
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 <float> (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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -795,6 +795,8 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
|
||||||
if (bot->m_enemy == ent) {
|
if (bot->m_enemy == ent) {
|
||||||
bot->m_enemy = nullptr;
|
bot->m_enemy = nullptr;
|
||||||
bot->m_lastEnemy = nullptr;
|
bot->m_lastEnemy = nullptr;
|
||||||
|
}
|
||||||
|
else if (bot->ent () == ent) {
|
||||||
bot->markStale ();
|
bot->markStale ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1939,21 +1939,21 @@ void BotThreadWorker::startup (int workers) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int requetedThreadCount = workers;
|
int requestedThreadCount = workers;
|
||||||
int hardwareConcurrency = plat.hardwareConcurrency ();
|
int hardwareConcurrency = plat.hardwareConcurrency ();
|
||||||
|
|
||||||
if (requetedThreadCount == -1) {
|
if (requestedThreadCount == -1) {
|
||||||
requetedThreadCount = hardwareConcurrency / 4;
|
requestedThreadCount = hardwareConcurrency / 4;
|
||||||
|
|
||||||
if (requetedThreadCount == 0) {
|
if (requestedThreadCount == 0) {
|
||||||
requetedThreadCount = 1;
|
requestedThreadCount = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requetedThreadCount = cr::clamp (requetedThreadCount, 1, hardwareConcurrency);
|
requestedThreadCount = cr::clamp (requestedThreadCount, 1, hardwareConcurrency);
|
||||||
|
|
||||||
// notify user
|
// 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
|
// start up the worker
|
||||||
m_botWorker.startup (static_cast <int> (requetedThreadCount));
|
m_botWorker.startup (static_cast <int> (requestedThreadCount));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue