bot: perform a seek cover search mission to avoid infected creatures. (#707)
bot: perform a seek cover search mission to avoid infected creatures. nav: several changes in controlling the terrain.
This commit is contained in:
parent
590471d94c
commit
286e1c8621
10 changed files with 155 additions and 114 deletions
|
|
@ -173,7 +173,10 @@ int Bot::findBestGoal () {
|
|||
float campDesire = rg (0.0f, 100.0f) + defensive;
|
||||
|
||||
if (!usesCampGun ()) {
|
||||
campDesire *= 0.5f;
|
||||
campDesire = 0.0f;
|
||||
}
|
||||
else if (usesSniper ()) {
|
||||
campDesire = rg (1.5f, 2.5f) * campDesire;
|
||||
}
|
||||
|
||||
int tactic = GoalTactic::Defensive;
|
||||
|
|
@ -285,14 +288,14 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
|
|||
else if (tactic == GoalTactic::Goal && !graph.m_goalPoints.empty ()) { // map goal node
|
||||
|
||||
// force bomber to select closest goal, if round-start goal was reset by something
|
||||
if (m_hasC4 && bots.getRoundStartTime () + 20.0f < game.time ()) {
|
||||
if (m_isVIP || (m_hasC4 && bots.getRoundStartTime () + 20.0f < game.time ())) {
|
||||
float nearestDistanceSq = kInfiniteDistance;
|
||||
int count = 0;
|
||||
|
||||
for (const auto &point : graph.m_goalPoints) {
|
||||
const float distanceSq = graph[point].origin.distanceSq (pev->origin);
|
||||
|
||||
if (distanceSq > cr::sqrf (1024.0f)) {
|
||||
if (distanceSq > cr::sqrf (1024.0f) || isGroupOfEnemies (graph[point].origin)) {
|
||||
continue;
|
||||
}
|
||||
if (distanceSq < nearestDistanceSq) {
|
||||
|
|
@ -589,7 +592,7 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
|
|||
}
|
||||
}
|
||||
|
||||
void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||
void Bot::checkTerrain (const Vector &dirNormal) {
|
||||
|
||||
// if avoiding someone do not consider stuck
|
||||
TraceResult tr {};
|
||||
|
|
@ -599,6 +602,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
|
||||
// minimal speed for consider stuck
|
||||
const float minimalSpeed = isDucking () ? kMinMovedDistance : kMinMovedDistance * 4;
|
||||
const auto randomProbeTime = rg (0.75f, 1.15f);
|
||||
|
||||
// standing still, no need to check?
|
||||
if ((cr::abs (m_moveSpeed) >= minimalSpeed || cr::abs (m_strafeSpeed) >= minimalSpeed)
|
||||
|
|
@ -612,7 +616,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
m_firstCollideTime = 0.0f;
|
||||
}
|
||||
// didn't we move enough previously?
|
||||
else if (movedDistance < kMinMovedDistance && m_prevSpeed > 20.0f) {
|
||||
else if (m_movedDistance < kMinMovedDistance && (m_prevSpeed > 20.0f || m_prevVelocity < m_moveSpeed / 2)) {
|
||||
m_prevTime = game.time (); // then consider being stuck
|
||||
m_isStuck = true;
|
||||
|
||||
|
|
@ -642,9 +646,16 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_probeTime >= game.time ()) {
|
||||
m_isStuck = true;
|
||||
}
|
||||
else if (m_probeTime + randomProbeTime < game.time () && !cr::fzero (m_probeTime)) {
|
||||
resetCollision (); // resets its collision state because it was too long time in probing state
|
||||
}
|
||||
|
||||
// not stuck?
|
||||
if (!m_isStuck) {
|
||||
if (m_probeTime + rg (0.75f, 1.15f) < game.time ()) {
|
||||
if (m_probeTime + randomProbeTime < game.time ()) {
|
||||
resetCollision (); // reset collision memory if not being stuck for 0.5 secs
|
||||
}
|
||||
else {
|
||||
|
|
@ -845,7 +856,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
}
|
||||
|
||||
m_collideTime = game.time ();
|
||||
m_probeTime = game.time () + 0.5f;
|
||||
m_probeTime = game.time () + randomProbeTime;
|
||||
m_collisionProbeBits = bits;
|
||||
m_collisionState = CollisionState::Probing;
|
||||
m_collStateIndex = 0;
|
||||
|
|
@ -855,10 +866,9 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
if (m_collisionState == CollisionState::Probing) {
|
||||
if (m_probeTime < game.time ()) {
|
||||
m_collStateIndex++;
|
||||
m_probeTime = game.time () + 0.5f;
|
||||
m_probeTime = game.time () + randomProbeTime;
|
||||
|
||||
if (m_collStateIndex >= kMaxCollideMoves) {
|
||||
m_navTimeset = game.time () - 5.0f;
|
||||
resetCollision ();
|
||||
}
|
||||
}
|
||||
|
|
@ -867,7 +877,13 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
switch (m_collideMoves[m_collStateIndex]) {
|
||||
case CollisionState::Jump:
|
||||
if ((isOnFloor () || isInWater ()) && !isOnLadder ()) {
|
||||
pev->button |= IN_JUMP;
|
||||
if (isInWater ()
|
||||
|| !m_isCreature
|
||||
|| m_lastDamageTimestamp < game.time ()
|
||||
|| (m_currentTravelFlags & PathFlag::Jump)) {
|
||||
|
||||
pev->button |= IN_JUMP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -894,10 +910,8 @@ void Bot::checkFall () {
|
|||
if (isPreviousLadder ()) {
|
||||
return;
|
||||
}
|
||||
else if (graph.exists (m_currentNodeIndex)) {
|
||||
if (graph[m_currentNodeIndex].flags & NodeFlag::Ladder) {
|
||||
return;
|
||||
}
|
||||
else if ((m_pathFlags & NodeFlag::Ladder) && isPreviousLadder () && isOnLadder ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_checkFall) {
|
||||
|
|
@ -905,7 +919,7 @@ void Bot::checkFall () {
|
|||
m_checkFallPoint[0] = pev->origin;
|
||||
|
||||
if (!game.isNullEntity (m_enemy)) {
|
||||
m_checkFallPoint[1] = game.getEntityOrigin (m_enemy);
|
||||
m_checkFallPoint[1] = m_enemy->v.origin;
|
||||
}
|
||||
else if (m_currentNodeIndex != kInvalidNodeIndex) {
|
||||
m_checkFallPoint[1] = m_pathOrigin;
|
||||
|
|
@ -921,7 +935,7 @@ void Bot::checkFall () {
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_checkFall || !isOnFloor () || !m_fixFallTimer.elapsed ()) {
|
||||
if (!m_checkFall || !isOnFloor ()) {
|
||||
return;
|
||||
}
|
||||
m_checkFall = false;
|
||||
|
|
@ -931,25 +945,23 @@ void Bot::checkFall () {
|
|||
const float nowDistanceSq = pev->origin.distanceSq (m_checkFallPoint[1]);
|
||||
|
||||
if (nowDistanceSq > baseDistanceSq
|
||||
&& (nowDistanceSq > baseDistanceSq * 1.8f || nowDistanceSq > baseDistanceSq + 260.0f)
|
||||
&& baseDistanceSq >= cr::sqrf (124.0f) && nowDistanceSq >= cr::sqrf (146.0f)) {
|
||||
&& (nowDistanceSq > baseDistanceSq * 1.2f || nowDistanceSq > baseDistanceSq + 200.0f)
|
||||
&& baseDistanceSq >= cr::sqrf (80.0f) && nowDistanceSq >= cr::sqrf (100.0f)) {
|
||||
fixFall = true;
|
||||
}
|
||||
else if (cr::abs (m_checkFallPoint[1].z) > cr::abs (pev->origin.z) + 138.0f
|
||||
|| cr::abs (m_checkFallPoint[0].z) > cr::abs (pev->origin.z) + 138.0f) {
|
||||
else if (m_checkFallPoint[1].z > pev->origin.z + 128.0f
|
||||
&& m_checkFallPoint[0].z > pev->origin.z + 128.0f) {
|
||||
fixFall = true;
|
||||
}
|
||||
else if (m_currentNodeIndex != kInvalidNodeIndex
|
||||
&& nowDistanceSq > cr::sqrf (32.0f)
|
||||
&& cr::abs (m_checkFallPoint[1].z) > cr::abs (pev->origin.z) + 72.0f) {
|
||||
&& nowDistanceSq > cr::sqrf (16.0f)
|
||||
&& m_checkFallPoint[1].z > pev->origin.z + 62.0f) {
|
||||
fixFall = true;
|
||||
}
|
||||
|
||||
if (fixFall) {
|
||||
m_currentNodeIndex = kInvalidNodeIndex;
|
||||
findValidNode ();
|
||||
|
||||
m_fixFallTimer.start (1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1295,8 +1307,8 @@ bool Bot::updateNavigation () {
|
|||
const auto &dirToPoint = (pev->origin - origin).normalize2d_apx ();
|
||||
const auto &forwardMove = m_moveAngles.forward ().normalize2d_apx ();
|
||||
|
||||
if (distanceSq < cr::sqrf (80.0f)) {
|
||||
if ((dirToPoint | forwardMove) < 0.0f && !checkWallOnBehind ()) {
|
||||
if (distanceSq < cr::sqrf (96.0f)) {
|
||||
if ((dirToPoint | forwardMove) < 0.0f) {
|
||||
m_moveSpeed = -pev->maxspeed;
|
||||
}
|
||||
}
|
||||
|
|
@ -1308,7 +1320,7 @@ bool Bot::updateNavigation () {
|
|||
}
|
||||
|
||||
float desiredDistanceSq = cr::sqrf (8.0f);
|
||||
float nodeDistanceSq = pev->origin.distanceSq (m_pathOrigin);
|
||||
const float nodeDistanceSq = pev->origin.distanceSq (m_pathOrigin);
|
||||
|
||||
// initialize the radius for a special node type, where the node is considered to be reached
|
||||
if (m_pathFlags & NodeFlag::Lift) {
|
||||
|
|
@ -1948,8 +1960,7 @@ bool Bot::findNextBestNodeEx (const IntArray &data, bool handleFails) {
|
|||
float Bot::getEstimatedNodeReachTime () {
|
||||
const bool longTermReachability = (m_pathFlags & NodeFlag::Crouch)
|
||||
|| (m_pathFlags & NodeFlag::Ladder)
|
||||
|| (pev->button & IN_DUCK)
|
||||
|| (m_oldButtons & IN_DUCK);
|
||||
|| ((pev->button | pev->oldbuttons) & IN_DUCK);
|
||||
|
||||
float estimatedTime = longTermReachability ? 8.5f : 3.5f;
|
||||
|
||||
|
|
@ -1958,6 +1969,10 @@ float Bot::getEstimatedNodeReachTime () {
|
|||
return estimatedTime;
|
||||
}
|
||||
|
||||
if (m_lastDamageTimestamp < game.time () && !cr::fzero (m_lastDamageTimestamp) && !m_isStuck && m_isCreature) {
|
||||
return estimatedTime;
|
||||
}
|
||||
|
||||
// calculate 'real' time that we need to get from one node to another
|
||||
if (graph.exists (m_currentNodeIndex) && graph.exists (m_previousNodes[0])) {
|
||||
const float distanceSq = graph[m_previousNodes[0]].origin.distanceSq (graph[m_currentNodeIndex].origin);
|
||||
|
|
@ -3097,7 +3112,7 @@ bool Bot::isBlockedLeft () {
|
|||
pev->angles.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
// do a trace to the left...
|
||||
game.testLine (pev->origin, forward * direction - right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
||||
game.testLine (pev->origin, pev->origin - forward * direction - right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && !util.isDoorEntity (tr.pHit)) {
|
||||
|
|
@ -3110,8 +3125,8 @@ bool Bot::isBlockedRight () {
|
|||
TraceResult tr {};
|
||||
float direction = 48.0f;
|
||||
|
||||
if (m_moveSpeed < 0.0f) {
|
||||
direction = -48.0f;
|
||||
if (m_moveSpeed > 0.0f) {
|
||||
direction = 48.0f;
|
||||
}
|
||||
Vector right {}, forward {};
|
||||
pev->angles.angleVectors (&forward, &right, nullptr);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue