nav: rusher bots does not care any danger (idea from pbmm) nav: some changes in collision motion
This commit is contained in:
parent
9e48175e67
commit
eea78ac031
4 changed files with 113 additions and 205 deletions
217
src/navigate.cpp
217
src/navigate.cpp
|
|
@ -320,6 +320,15 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
|
|||
if (goalChoices[0] == kInvalidNodeIndex) {
|
||||
return m_chosenGoalIndex = graph.random ();
|
||||
}
|
||||
|
||||
// rusher bots does not care any danger (idea from pbmm)
|
||||
if (m_personality == Personality::Rusher) {
|
||||
const auto randomGoal = goalChoices[rg.get (0, 3)];
|
||||
|
||||
if (graph.exists (randomGoal)) {
|
||||
return m_chosenGoalIndex = randomGoal;
|
||||
}
|
||||
}
|
||||
bool sorting = false;
|
||||
|
||||
do {
|
||||
|
|
@ -344,7 +353,7 @@ void Bot::postprocessGoals (const IntArray &goals, int result[]) {
|
|||
|
||||
int recurseCount = 0;
|
||||
|
||||
auto isRecentOrHistorical = [&] (int index) -> bool {
|
||||
auto isRecentOrHistorical = [&] (int index) -> bool {
|
||||
if (m_prevGoalIndex == index || m_previousNodes[0] == index) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -590,65 +599,26 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
state[i] = 0;
|
||||
state[i + 1] = 0;
|
||||
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
Vector right {}, forward {};
|
||||
m_moveAngles.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
const Vector &dirToPoint = (pev->origin - m_destOrigin).normalize2d_apx ();
|
||||
const Vector &rightSide = right.normalize2d_apx ();
|
||||
|
||||
bool dirRight = false;
|
||||
bool dirLeft = false;
|
||||
bool blockedLeft = false;
|
||||
bool blockedRight = false;
|
||||
|
||||
if ((dirToPoint | rightSide) > 0.0f) {
|
||||
dirRight = true;
|
||||
}
|
||||
else {
|
||||
dirLeft = true;
|
||||
}
|
||||
const auto &testDir = m_moveSpeed > 0.0f ? forward : -forward;
|
||||
constexpr float kBlockDistance = 32.0f;
|
||||
|
||||
// now check which side is blocked
|
||||
src = pev->origin + right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedRight = true;
|
||||
}
|
||||
src = pev->origin - right * kBlockDistance;
|
||||
dst = src + testDir * kBlockDistance;
|
||||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedLeft = true;
|
||||
}
|
||||
|
||||
if (dirLeft) {
|
||||
if (canStrafeLeft (&tr)) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedLeft) {
|
||||
if (isBlockedLeft ()) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
++i;
|
||||
|
||||
if (dirRight) {
|
||||
if (canStrafeRight (&tr)) {
|
||||
state[i] += 5;
|
||||
}
|
||||
else {
|
||||
state[i] -= 5;
|
||||
}
|
||||
|
||||
if (blockedRight) {
|
||||
if (isBlockedRight ()) {
|
||||
state[i] -= 5;
|
||||
}
|
||||
}
|
||||
|
|
@ -787,44 +757,12 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
void Bot::moveToGoal () {
|
||||
findValidNode ();
|
||||
|
||||
bool prevLadder = false;
|
||||
|
||||
if (graph.exists (m_previousNodes[0])) {
|
||||
if (graph[m_previousNodes[0]].flags & NodeFlag::Ladder) {
|
||||
prevLadder = true;
|
||||
}
|
||||
}
|
||||
|
||||
// press duck button if we need to
|
||||
if ((m_pathFlags & NodeFlag::Crouch) && !(m_pathFlags & (NodeFlag::Camp | NodeFlag::Goal))) {
|
||||
pev->button |= IN_DUCK;
|
||||
}
|
||||
m_lastUsedNodesTime = game.time ();
|
||||
|
||||
// press jump button if we need to leave the ladder
|
||||
if (!(m_pathFlags & NodeFlag::Ladder) && prevLadder && isOnFloor () && isOnLadder () && m_moveSpeed > 50.0f && pev->velocity.length () < 50.0f) {
|
||||
pev->button |= IN_JUMP;
|
||||
m_jumpTime = game.time () + 1.0f;
|
||||
}
|
||||
|
||||
if (m_pathFlags & NodeFlag::Ladder) {
|
||||
if (m_pathOrigin.z < pev->origin.z + 16.0f && !isOnLadder () && isOnFloor () && !isDucking ()) {
|
||||
if (!prevLadder) {
|
||||
m_moveSpeed = pev->origin.distance (m_pathOrigin);
|
||||
}
|
||||
else {
|
||||
m_moveSpeed = 150.0f;
|
||||
}
|
||||
if (m_moveSpeed < 150.0f) {
|
||||
m_moveSpeed = 150.0f;
|
||||
}
|
||||
else if (m_moveSpeed > pev->maxspeed) {
|
||||
m_moveSpeed = pev->maxspeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastUsedNodesTime = game.time ();
|
||||
|
||||
// special movement for swimming here
|
||||
if (isInWater ()) {
|
||||
// check if we need to go forward or back press the correct buttons
|
||||
|
|
@ -955,7 +893,7 @@ bool Bot::updateNavigation () {
|
|||
}
|
||||
}
|
||||
|
||||
if ((m_pathFlags & NodeFlag::Ladder) || isOnLadder ()) {
|
||||
if (m_pathFlags & NodeFlag::Ladder) {
|
||||
if (m_pathOrigin.z >= (pev->origin.z + 16.0f)) {
|
||||
constexpr auto kLadderOffset = Vector (0.0f, 0.0f, 16.0f);
|
||||
m_pathOrigin = m_path->origin + kLadderOffset;
|
||||
|
|
@ -973,7 +911,7 @@ bool Bot::updateNavigation () {
|
|||
|
||||
// special detection if someone is using the ladder (to prevent to have bots-towers on ladders)
|
||||
for (const auto &client : util.getClients ()) {
|
||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || (client.ent->v.movetype != MOVETYPE_FLY) || client.ent == ent ()) {
|
||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || (client.ent->v.movetype != MOVETYPE_FLY) || client.team != m_team || client.ent == ent ()) {
|
||||
continue;
|
||||
}
|
||||
TraceResult tr {};
|
||||
|
|
@ -981,61 +919,24 @@ bool Bot::updateNavigation () {
|
|||
int previousNode = 0;
|
||||
|
||||
// more than likely someone is already using our ladder...
|
||||
if (client.ent->v.origin.distanceSq (m_path->origin) < cr::sqrf (40.0f)) {
|
||||
if ((client.team != m_team || game.is (GameFlags::FreeForAll)) && !cv_ignore_enemies.bool_ ()) {
|
||||
game.testLine (getEyesPos (), client.ent->v.origin, TraceIgnore::Monsters, ent (), &tr);
|
||||
if (client.ent->v.origin.distanceSq (m_path->origin) < cr::sqrf (48.0f)) {
|
||||
game.testHull (getEyesPos (), m_pathOrigin, TraceIgnore::Monsters, isDucking () ? head_hull : human_hull, ent (), &tr);
|
||||
|
||||
// bot found an enemy on his ladder - he should see him...
|
||||
if (tr.pHit == client.ent) {
|
||||
m_enemy = client.ent;
|
||||
m_lastEnemy = client.ent;
|
||||
m_lastEnemyOrigin = client.ent->v.origin;
|
||||
// someone is above or below us and is using the ladder already
|
||||
if (tr.pHit == client.ent && cr::abs (pev->origin.z - client.ent->v.origin.z) > 15.0f && (client.ent->v.movetype == MOVETYPE_FLY)) {
|
||||
const auto numPreviousNode = rg.get (0, 2);
|
||||
|
||||
m_enemyParts = Visibility::None;
|
||||
m_enemyParts |= (Visibility::Head | Visibility::Body);
|
||||
|
||||
m_states |= Sense::SeeingEnemy;
|
||||
m_seeEnemyTime = game.time ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
game.testHull (getEyesPos (), m_pathOrigin, TraceIgnore::Monsters, isDucking () ? head_hull : human_hull, ent (), &tr);
|
||||
|
||||
// someone is above or below us and is using the ladder already
|
||||
if (tr.pHit == client.ent && cr::abs (pev->origin.z - client.ent->v.origin.z) > 15.0f && (client.ent->v.movetype == MOVETYPE_FLY)) {
|
||||
if (graph.exists (m_previousNodes[0])) {
|
||||
if (!(graph[m_previousNodes[0]].flags & NodeFlag::Ladder)) {
|
||||
foundGround = true;
|
||||
previousNode = m_previousNodes[0];
|
||||
}
|
||||
else if (graph.exists (m_previousNodes[1])) {
|
||||
if (!(graph[m_previousNodes[1]].flags & NodeFlag::Ladder)) {
|
||||
foundGround = true;
|
||||
previousNode = m_previousNodes[1];
|
||||
}
|
||||
else if (graph.exists (m_previousNodes[2])) {
|
||||
if (!(graph[m_previousNodes[2]].flags & NodeFlag::Ladder)) {
|
||||
foundGround = true;
|
||||
previousNode = m_previousNodes[2];
|
||||
}
|
||||
else if (graph.exists (m_previousNodes[3])) {
|
||||
if (!(graph[m_previousNodes[3]].flags & NodeFlag::Ladder)) {
|
||||
foundGround = true;
|
||||
previousNode = m_previousNodes[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundGround) {
|
||||
if (getCurrentTaskId () != Task::MoveToPosition || !cr::fequal (getTask ()->desire, TaskPri::PlantBomb)) {
|
||||
changeNodeIndex (m_previousNodes[0]);
|
||||
startTask (Task::MoveToPosition, TaskPri::PlantBomb, previousNode, 0.0f, true);
|
||||
}
|
||||
for (int i = 0; i < numPreviousNode; ++i) {
|
||||
if (graph.exists (m_previousNodes[i]) && (graph[m_previousNodes[i]].flags & NodeFlag::Ladder)) {
|
||||
foundGround = true;
|
||||
previousNode = m_previousNodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundGround) {
|
||||
changeNodeIndex (m_previousNodes[0]);
|
||||
findPath (m_previousNodes[0], previousNode, m_pathType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2888,66 +2789,6 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Bot::changePitch (float speed) {
|
||||
// this function turns a bot towards its ideal_pitch
|
||||
|
||||
const float idealPitch = cr::wrapAngle (pev->idealpitch);
|
||||
const float curent = cr::wrapAngle (pev->v_angle.x);
|
||||
|
||||
// turn from the current v_angle pitch to the idealpitch by selecting
|
||||
// the quickest way to turn to face that direction
|
||||
|
||||
// find the difference in the curent and ideal angle
|
||||
float normalizePitch = cr::wrapAngle (idealPitch - curent);
|
||||
|
||||
if (normalizePitch > 0.0f) {
|
||||
if (normalizePitch > speed) {
|
||||
normalizePitch = speed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (normalizePitch < -speed) {
|
||||
normalizePitch = -speed;
|
||||
}
|
||||
}
|
||||
pev->v_angle.x = cr::wrapAngle (curent + normalizePitch);
|
||||
|
||||
if (pev->v_angle.x > 89.9f) {
|
||||
pev->v_angle.x = 89.9f;
|
||||
}
|
||||
|
||||
if (pev->v_angle.x < -89.9f) {
|
||||
pev->v_angle.x = -89.9f;
|
||||
}
|
||||
pev->angles.x = -pev->v_angle.x / 3;
|
||||
}
|
||||
|
||||
void Bot::changeYaw (float speed) {
|
||||
// this function turns a bot towards its ideal_yaw
|
||||
|
||||
const float idealPitch = cr::wrapAngle (pev->ideal_yaw);
|
||||
const float curent = cr::wrapAngle (pev->v_angle.y);
|
||||
|
||||
// turn from the current v_angle yaw to the ideal_yaw by selecting
|
||||
// the quickest way to turn to face that direction
|
||||
|
||||
// find the difference in the curent and ideal angle
|
||||
float normalizePitch = cr::wrapAngle (idealPitch - curent);
|
||||
|
||||
if (normalizePitch > 0.0f) {
|
||||
if (normalizePitch > speed) {
|
||||
normalizePitch = speed;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (normalizePitch < -speed) {
|
||||
normalizePitch = -speed;
|
||||
}
|
||||
}
|
||||
pev->v_angle.y = cr::wrapAngle (curent + normalizePitch);
|
||||
pev->angles.y = pev->v_angle.y;
|
||||
}
|
||||
|
||||
int Bot::getRandomCampDir () {
|
||||
// find a good node to look at when camping
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue