fix: breakable problems on some maps
nav: do not consider busy nodes as long-radii nav: more fixes to player avoidance
This commit is contained in:
parent
f0b74452d3
commit
2a6ca1d914
3 changed files with 51 additions and 21 deletions
|
|
@ -268,7 +268,7 @@ edict_t *Bot::lookupBreakable () {
|
||||||
|
|
||||||
// check if this isn't a triggered (bomb) breakable and if it takes damage. if true, shoot the crap!
|
// check if this isn't a triggered (bomb) breakable and if it takes damage. if true, shoot the crap!
|
||||||
if (util.isBreakableEntity (hit)) {
|
if (util.isBreakableEntity (hit)) {
|
||||||
m_breakableOrigin = tr.vecEndPos;
|
m_breakableOrigin = game.getEntityOrigin (hit);
|
||||||
m_breakableEntity = hit;
|
m_breakableEntity = hit;
|
||||||
|
|
||||||
return hit;
|
return hit;
|
||||||
|
|
@ -276,14 +276,26 @@ edict_t *Bot::lookupBreakable () {
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto isGoodForUs = [&] (edict_t *ent) -> bool {
|
||||||
|
if (game.isNullEntity (ent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const auto &br : m_ignoredBreakable) {
|
||||||
|
if (br == ent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
auto hit = doLookup (pev->origin, m_destOrigin, detectBreakableDistance);
|
auto hit = doLookup (pev->origin, m_destOrigin, detectBreakableDistance);
|
||||||
|
|
||||||
if (!game.isNullEntity (hit)) {
|
if (isGoodForUs (hit)) {
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
hit = doLookup (getEyesPos (), m_destOrigin, detectBreakableDistance);
|
hit = doLookup (getEyesPos (), m_destOrigin, detectBreakableDistance);
|
||||||
|
|
||||||
if (!game.isNullEntity (hit)) {
|
if (isGoodForUs (hit)) {
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
m_breakableEntity = nullptr;
|
m_breakableEntity = nullptr;
|
||||||
|
|
@ -4146,7 +4158,7 @@ void Bot::enteredBuyZone (int buyState) {
|
||||||
|
|
||||||
// if bot is in buy zone, try to buy ammo for this weapon...
|
// if bot is in buy zone, try to buy ammo for this weapon...
|
||||||
if (m_seeEnemyTime + 12.0f < game.time ()
|
if (m_seeEnemyTime + 12.0f < game.time ()
|
||||||
&& m_lastEquipTime + 15.0f < game.time ()
|
&& m_lastEquipTime + 30.0f < game.time ()
|
||||||
&& m_inBuyZone
|
&& m_inBuyZone
|
||||||
&& (bots.getRoundStartTime () + rg (10.0f, 20.0f) + mp_buytime.as <float> () < game.time ())
|
&& (bots.getRoundStartTime () + rg (10.0f, 20.0f) + mp_buytime.as <float> () < game.time ())
|
||||||
&& !bots.isBombPlanted ()
|
&& !bots.isBombPlanted ()
|
||||||
|
|
|
||||||
|
|
@ -474,19 +474,26 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
return; // no player avoiding when with semiclip plugin
|
return; // no player avoiding when with semiclip plugin
|
||||||
}
|
}
|
||||||
m_hindrance = nullptr;
|
m_hindrance = nullptr;
|
||||||
float distanceSq = cr::sqrf (512.0f);
|
float distanceSq = cr::sqrf (pev->maxspeed);
|
||||||
|
|
||||||
const auto ownPrio = bots.getPlayerPriority (ent ());
|
const auto ownPrio = bots.getPlayerPriority (ent ());
|
||||||
|
|
||||||
auto clearCamp = [] (edict_t *ent) {
|
auto clearCamp = [&] (edict_t *ent) {
|
||||||
auto bot = bots[ent];
|
auto bot = bots[ent];
|
||||||
|
|
||||||
if (bot) {
|
if (bot) {
|
||||||
auto tid = bot->getCurrentTaskId ();
|
const auto tid = bot->getCurrentTaskId ();
|
||||||
|
const auto tid2 = getCurrentTaskId ();
|
||||||
|
|
||||||
if (tid == Task::Camp || tid == Task::Hide || tid == Task::Pause) {
|
if ((m_currentNodeIndex == bot->m_currentNodeIndex)
|
||||||
|
&& (tid == Task::Camp || tid == Task::Hide || tid == Task::Pause)) {
|
||||||
bot->completeTask ();
|
bot->completeTask ();
|
||||||
}
|
}
|
||||||
|
if ((m_currentNodeIndex == bot->m_currentNodeIndex)
|
||||||
|
&& tid2 == Task::Camp || tid2 == Task::Hide || tid2 == Task::Pause) {
|
||||||
|
completeTask ();
|
||||||
|
findValidNode ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -499,6 +506,7 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
|
|
||||||
// give some priorities to bot avoidance
|
// give some priorities to bot avoidance
|
||||||
if (ownPrio < otherPrio) {
|
if (ownPrio < otherPrio) {
|
||||||
|
clearCamp (client.ent);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,6 +516,7 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
|
|
||||||
// ignore because we're already avoiding someone better
|
// ignore because we're already avoiding someone better
|
||||||
if (avoidPrio < otherPrio) {
|
if (avoidPrio < otherPrio) {
|
||||||
|
clearCamp (m_hindrance);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -551,7 +560,10 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
const auto &dir = (pev->origin - m_hindrance->v.origin).normalize2d_apx ();
|
const auto &dir = (pev->origin - m_hindrance->v.origin).normalize2d_apx ();
|
||||||
|
|
||||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||||
if (m_avoidAction == Dodge::None && m_path->radius > 16.0f && !isInNarrowPlace ()) {
|
if ((m_avoidAction == Dodge::None
|
||||||
|
&& m_path->radius > 16.0f
|
||||||
|
&& !isInNarrowPlace ())
|
||||||
|
|| m_moveSpeed < 0.0f) {
|
||||||
if ((dir | right.normalize2d_apx ()) > 0.0f) {
|
if ((dir | right.normalize2d_apx ()) > 0.0f) {
|
||||||
m_avoidAction = Dodge::Left;
|
m_avoidAction = Dodge::Left;
|
||||||
|
|
||||||
|
|
@ -565,16 +577,12 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
setStrafeSpeed (normal, -pev->maxspeed);
|
setStrafeSpeed (normal, -pev->maxspeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_isStuck = false;
|
|
||||||
m_navTimeset = game.time ();
|
m_navTimeset = game.time ();
|
||||||
|
|
||||||
if (distanceSq < cr::sqrf (96.0f)) {
|
if (distanceSq < cr::sqrf (96.0f)) {
|
||||||
if ((dir | forward.normalize2d_apx ()) < 0.0f) {
|
if ((dir | forward.normalize2d_apx ()) < 0.0f) {
|
||||||
m_moveSpeed = -pev->maxspeed;
|
m_moveSpeed = -pev->maxspeed;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
m_moveSpeed = pev->maxspeed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
}
|
}
|
||||||
|
|
@ -1316,12 +1324,6 @@ bool Bot::updateNavigation () {
|
||||||
desiredDistanceSq = 0.0f;
|
desiredDistanceSq = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// always increase reachability distance for occupied nodes
|
|
||||||
if (!(graph[m_path->number].flags & NodeFlag::Crouch) && isOccupiedNode (m_path->number, pathHasFlags)) {
|
|
||||||
desiredDistanceSq = cr::sqrf (96.0f);
|
|
||||||
nodeDistanceSq *= 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// needs precise placement - check if we get past the point
|
// needs precise placement - check if we get past the point
|
||||||
if (desiredDistanceSq < cr::sqrf (20.0f) && nodeDistanceSq < cr::sqrf (30.0f)) {
|
if (desiredDistanceSq < cr::sqrf (20.0f) && nodeDistanceSq < cr::sqrf (30.0f)) {
|
||||||
const auto predictRangeSq = m_pathOrigin.distanceSq (pev->origin + pev->velocity * m_frameInterval);
|
const auto predictRangeSq = m_pathOrigin.distanceSq (pev->origin + pev->velocity * m_frameInterval);
|
||||||
|
|
@ -1344,7 +1346,7 @@ bool Bot::updateNavigation () {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeDistanceSq <= desiredDistanceSq) {
|
if (nodeDistanceSq < desiredDistanceSq) {
|
||||||
// did we reach a destination node?
|
// did we reach a destination node?
|
||||||
if (getTask ()->data == m_currentNodeIndex) {
|
if (getTask ()->data == m_currentNodeIndex) {
|
||||||
if (m_chosenGoalIndex != kInvalidNodeIndex) {
|
if (m_chosenGoalIndex != kInvalidNodeIndex) {
|
||||||
|
|
@ -1816,7 +1818,9 @@ bool Bot::findNextBestNodeEx (const IntArray &data, bool handleFails) {
|
||||||
lessDist[i] = kInfiniteDistance;
|
lessDist[i] = kInfiniteDistance;
|
||||||
lessIndex[i] = kInvalidNodeIndex;
|
lessIndex[i] = kInvalidNodeIndex;
|
||||||
}
|
}
|
||||||
const auto &numToSkip = handleFails ? 1 : rg (1, 4);
|
|
||||||
|
// in case low node density do not skip previous ones, in case of fail reduce max nodes to skip
|
||||||
|
const auto &numToSkip = graph.length () < 512 ? 0 : (handleFails ? 1 : rg (1, 4));
|
||||||
|
|
||||||
for (const auto &i : data) {
|
for (const auto &i : data) {
|
||||||
const auto &path = graph[i];
|
const auto &path = graph[i];
|
||||||
|
|
|
||||||
|
|
@ -1467,6 +1467,20 @@ void Bot::shootBreakable_ () {
|
||||||
completeTask ();
|
completeTask ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
TraceResult tr {};
|
||||||
|
game.testLine (pev->origin, m_breakableOrigin, TraceIgnore::None, ent (), &tr);
|
||||||
|
|
||||||
|
if (tr.pHit != m_breakableEntity || !util.isVisible (tr.vecEndPos, ent ())) {
|
||||||
|
m_ignoredBreakable.push (tr.pHit);
|
||||||
|
|
||||||
|
m_breakableEntity = nullptr;
|
||||||
|
m_breakableOrigin = nullptr;
|
||||||
|
|
||||||
|
completeTask ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_aimFlags |= AimFlags::Override;
|
m_aimFlags |= AimFlags::Override;
|
||||||
pev->button |= m_campButtons;
|
pev->button |= m_campButtons;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue