fix: bots use buttons too extensively
nav: added more cpu-friendly version to check if bot will fall in combat
This commit is contained in:
parent
0873975678
commit
6e09cee0ee
6 changed files with 54 additions and 37 deletions
|
|
@ -12,6 +12,7 @@ constexpr int kMaxNodeLinks = 8; // max links for single node
|
|||
|
||||
// defines for nodes flags field (32 bits are available)
|
||||
CR_DECLARE_SCOPED_ENUM (NodeFlag,
|
||||
Button = cr::bit (0), // use a nearby button (lifts, doors, etc.)
|
||||
Lift = cr::bit (1), // wait for lift to be down before approaching this node
|
||||
Crouch = cr::bit (2), // must crouch to reach this node
|
||||
Crossing = cr::bit (3), // a target node
|
||||
|
|
|
|||
|
|
@ -403,6 +403,7 @@ private:
|
|||
bool isKnifeMode ();
|
||||
bool isGrenadeWar ();
|
||||
bool isDeadlyMove (const Vector &to);
|
||||
bool isSafeToMove (const Vector &to);
|
||||
bool isOutOfBombTimer ();
|
||||
bool isWeaponBadAtDistance (int weaponIndex, float distance);
|
||||
bool needToPauseFiring (float distance);
|
||||
|
|
|
|||
|
|
@ -1962,12 +1962,7 @@ void Bot::filterTasks () {
|
|||
filter[Task::PickupItem].desire = 50.0f; // always pickup button
|
||||
}
|
||||
else {
|
||||
float distance = (500.0f - pev->origin.distance (game.getEntityOrigin (m_pickupItem))) * 0.2f;
|
||||
|
||||
if (distance > 50.0f) {
|
||||
distance = 50.0f;
|
||||
}
|
||||
filter[Task::PickupItem].desire = distance;
|
||||
filter[Task::PickupItem].desire = cr::max (50.0f, 500.0f - pev->origin.distance (game.getEntityOrigin (m_pickupItem)) * 0.2f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -1409,7 +1409,7 @@ void Bot::attackMovement () {
|
|||
m_duckTime = game.time () - 1.0f;
|
||||
}
|
||||
|
||||
if (!isInWater () && !isOnLadder () && (m_moveSpeed > 0.0f || m_strafeSpeed >= 0.0f)) {
|
||||
if (!isInWater () && !isOnLadder () && (m_moveSpeed > 0.0f || m_strafeSpeed > 0.0f)) {
|
||||
Vector right, forward;
|
||||
pev->v_angle.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
|
|
@ -1417,7 +1417,7 @@ void Bot::attackMovement () {
|
|||
const auto &side = right * m_strafeSpeed * 0.2f;
|
||||
const auto &spot = pev->origin + front + side + pev->velocity * m_frameInterval;
|
||||
|
||||
if (isDeadlyMove (spot)) {
|
||||
if (isSafeToMove (spot)) {
|
||||
m_strafeSpeed = -m_strafeSpeed;
|
||||
m_moveSpeed = -m_moveSpeed;
|
||||
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,7 @@ bool Bot::updateNavigation () {
|
|||
TraceResult tr {};
|
||||
|
||||
// check if we are going through a door...
|
||||
if (game.mapIs (MapFlags::HasDoors)) {
|
||||
if (game.mapIs (MapFlags::HasDoors) || (m_pathFlags & NodeFlag::Button)) {
|
||||
game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
if (!game.isNullEntity (tr.pHit) && game.isNullEntity (m_liftEntity) && util.isDoorEntity (tr.pHit)) {
|
||||
|
|
@ -1022,14 +1022,16 @@ bool Bot::updateNavigation () {
|
|||
if (pev->origin.distanceSq (game.getEntityOrigin (tr.pHit)) < cr::sqrf (50.0f)) {
|
||||
ignoreCollision (); // don't consider being stuck
|
||||
|
||||
// also 'use' the door randomly
|
||||
if (rg.chance (50)) {
|
||||
// do not use door directly under xash, or we will get failed assert in gamedll code
|
||||
if (game.is (GameFlags::Xash3D)) {
|
||||
pev->button |= IN_USE;
|
||||
}
|
||||
else {
|
||||
MDLL_Use (tr.pHit, ent ()); // also 'use' the door randomly
|
||||
MDLL_Use (tr.pHit, ent ());
|
||||
}
|
||||
m_buttonPushTime = game.time () + 1.5f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1037,6 +1039,8 @@ bool Bot::updateNavigation () {
|
|||
m_aimFlags &= ~(AimFlags::LastEnemy | AimFlags::PredictPath);
|
||||
m_canChooseAimDirection = false;
|
||||
|
||||
// delay task
|
||||
if (m_buttonPushTime < game.time ()) {
|
||||
auto button = lookupButton (tr.pHit->v.targetname.chars ());
|
||||
|
||||
// check if we got valid button
|
||||
|
|
@ -1046,9 +1050,10 @@ bool Bot::updateNavigation () {
|
|||
|
||||
m_navTimeset = game.time ();
|
||||
}
|
||||
}
|
||||
|
||||
// if bot hits the door, then it opens, so wait a bit to let it open safely
|
||||
if (pev->velocity.lengthSq2d () < cr::sqrf (10.0f) && m_timeDoorOpen < game.time ()) {
|
||||
if (pev->velocity.lengthSq2d () < cr::sqrf (2.0f) && m_timeDoorOpen < game.time ()) {
|
||||
startTask (Task::Pause, TaskPri::Pause, kInvalidNodeIndex, game.time () + 0.5f, false);
|
||||
m_timeDoorOpen = game.time () + 1.0f; // retry in 1 sec until door is open
|
||||
|
||||
|
|
@ -2865,40 +2870,39 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
|||
// this function eturns if given location would hurt Bot with falling damage
|
||||
|
||||
TraceResult tr {};
|
||||
const auto &direction = (to - pev->origin).normalize_apx (); // 1 unit long
|
||||
|
||||
constexpr auto kUnitsDown = 1000.0f;
|
||||
constexpr auto kFallLimit = 150.0f;
|
||||
|
||||
Vector check = to, down = to;
|
||||
down.z -= 1000.0f; // straight down 1000 units
|
||||
down.z -= kUnitsDown; // straight down 1000 units
|
||||
|
||||
game.testHull (check, down, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
game.testLine (check, down, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
if (tr.flFraction > 0.036f) { // we're not on ground anymore?
|
||||
tr.flFraction = 0.036f;
|
||||
}
|
||||
|
||||
float lastHeight = tr.flFraction * 1000.0f; // height from ground
|
||||
float lastHeight = tr.flFraction * kUnitsDown; // height from ground
|
||||
float distanceSq = to.distanceSq (check); // distance from goal
|
||||
|
||||
if (distanceSq <= cr::sqrf (30.0f) && lastHeight > 150.0f) {
|
||||
if (distanceSq <= cr::sqrf (16.0f) && lastHeight > kFallLimit) {
|
||||
return true;
|
||||
}
|
||||
const auto &moveDir = (to - pev->origin).normalize_apx (); // 1 unit long
|
||||
|
||||
while (distanceSq > cr::sqrf (30.0f)) {
|
||||
check = check - direction * 30.0f; // move 10 units closer to the goal...
|
||||
while (distanceSq > cr::sqrf (16.0f)) {
|
||||
check = check - moveDir * 16.0f; // move 16 units closer to the goal...
|
||||
|
||||
down = check;
|
||||
down.z -= 1000.0f; // straight down 1000 units
|
||||
down.z -= kUnitsDown; // straight down 1000 units
|
||||
|
||||
game.testHull (check, down, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
game.testLine (check, down, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
// wall blocking?
|
||||
if (tr.fStartSolid) {
|
||||
return false;
|
||||
}
|
||||
const float height = tr.flFraction * 1000.0f; // height from ground
|
||||
const auto height = tr.flFraction * 1000.0f; // height from ground
|
||||
|
||||
// drops more than 150 units?
|
||||
if (lastHeight < height - 150.0f) {
|
||||
if (lastHeight < height - kFallLimit) {
|
||||
return true;
|
||||
}
|
||||
lastHeight = height;
|
||||
|
|
@ -2907,6 +2911,18 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Bot::isSafeToMove (const Vector &to) {
|
||||
// simplified version of isDeadlyMove() just for combat movement checking
|
||||
|
||||
constexpr auto kUnitsDown = 1000.0f;
|
||||
constexpr auto kFallLimit = 150.0f;
|
||||
|
||||
TraceResult tr {};
|
||||
game.testLine (to, to + Vector { 0.0f, 0.0f, -kUnitsDown }, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
return tr.fStartSolid || tr.flFraction * kUnitsDown > kFallLimit;
|
||||
}
|
||||
|
||||
int Bot::getRandomCampDir () {
|
||||
// find a good node to look at when camping
|
||||
|
||||
|
|
@ -3033,12 +3049,16 @@ edict_t *Bot::lookupButton (StringRef target) {
|
|||
float nearestDistanceSq = kInfiniteDistance;
|
||||
edict_t *result = nullptr;
|
||||
|
||||
TraceResult tr {};
|
||||
|
||||
// find the nearest button which can open our target
|
||||
game.searchEntities ("target", target, [&] (edict_t *ent) {
|
||||
const Vector &pos = game.getEntityOrigin (ent);
|
||||
|
||||
game.testLine (pev->origin, pos, TraceIgnore::Monsters, pev->pContainingEntity, &tr);
|
||||
|
||||
// check if this place safe
|
||||
if (!isDeadlyMove (pos)) {
|
||||
if (tr.pHit == ent && tr.flFraction > 0.95f && !isDeadlyMove (pos)) {
|
||||
const float distanceSq = pev->origin.distanceSq (pos);
|
||||
|
||||
// check if we got more close button
|
||||
|
|
|
|||
|
|
@ -1676,16 +1676,13 @@ void Bot::pickupItem_ () {
|
|||
case Pickup::Button:
|
||||
m_aimFlags |= AimFlags::Entity;
|
||||
|
||||
if (game.isNullEntity (m_pickupItem) || m_buttonPushTime < game.time ()) {
|
||||
if (game.isNullEntity (m_pickupItem)) {
|
||||
completeTask ();
|
||||
m_pickupType = Pickup::None;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// find angles from bot origin to entity...
|
||||
const float angleToEntity = isInFOV (dest - getEyesPos ());
|
||||
|
||||
// near to the button?
|
||||
if (itemDistanceSq < cr::sqrf (90.0f)) {
|
||||
m_moveSpeed = 0.0f;
|
||||
|
|
@ -1693,6 +1690,9 @@ void Bot::pickupItem_ () {
|
|||
m_moveToGoal = false;
|
||||
m_checkTerrain = false;
|
||||
|
||||
// find angles from bot origin to entity...
|
||||
const float angleToEntity = isInFOV (dest - getEyesPos ());
|
||||
|
||||
// facing it directly?
|
||||
if (angleToEntity <= 10.0f) {
|
||||
MDLL_Use (m_pickupItem, ent ());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue