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
|
|
@ -1566,8 +1566,10 @@ void Bot::updateEmotions () {
|
|||
}
|
||||
|
||||
void Bot::overrideConditions () {
|
||||
const auto tid = getCurrentTaskId ();
|
||||
|
||||
// check if we need to escape from bomb
|
||||
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_isAlive && getCurrentTaskId () != Task::EscapeFromBomb && getCurrentTaskId () != Task::Camp && isOutOfBombTimer ()) {
|
||||
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted () && m_isAlive && tid != Task::EscapeFromBomb && tid != Task::Camp && isOutOfBombTimer ()) {
|
||||
completeTask (); // complete current task
|
||||
|
||||
// then start escape from bomb immediate
|
||||
|
|
@ -1583,11 +1585,11 @@ void Bot::overrideConditions () {
|
|||
const int nearestToEnemyPoint = graph.getNearest (m_enemy->v.origin);
|
||||
|
||||
if (nearestToEnemyPoint != kInvalidNodeIndex && nearestToEnemyPoint != m_currentNodeIndex && cr::abs (graph[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) {
|
||||
if (getCurrentTaskId () != Task::MoveToPosition && !cr::fequal (getTask ()->desire, TaskPri::Hide)) {
|
||||
if (tid != Task::MoveToPosition && !cr::fequal (getTask ()->desire, TaskPri::Hide)) {
|
||||
startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + length / (m_moveSpeed * 2.0f), true);
|
||||
}
|
||||
else {
|
||||
if (getCurrentTaskId () == Task::MoveToPosition && getTask ()->data != nearestToEnemyPoint) {
|
||||
if (tid == Task::MoveToPosition && getTask ()->data != nearestToEnemyPoint) {
|
||||
clearTask (Task::MoveToPosition);
|
||||
startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + length / (m_moveSpeed * 2.0f), true);
|
||||
}
|
||||
|
|
@ -1595,14 +1597,14 @@ void Bot::overrideConditions () {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (length <= 250.0f && (m_states & Sense::SeeingEnemy) && getCurrentTaskId () == Task::MoveToPosition) {
|
||||
if (length <= 250.0f && (m_states & Sense::SeeingEnemy) && tid == Task::MoveToPosition) {
|
||||
clearTask (Task::MoveToPosition); // remove any move tasks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// special handling for sniping
|
||||
if (usesSniper () && (m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) && m_sniperStopTime > game.time () && getCurrentTaskId () != Task::SeekCover) {
|
||||
if (usesSniper () && (m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) && m_sniperStopTime > game.time () && tid != Task::SeekCover) {
|
||||
m_moveSpeed = 0.0f;
|
||||
m_strafeSpeed = 0.0f;
|
||||
|
||||
|
|
@ -1610,7 +1612,7 @@ void Bot::overrideConditions () {
|
|||
}
|
||||
|
||||
// special handling for reloading
|
||||
if (!bots.isRoundOver () && getCurrentTaskId () == Task::Normal && m_reloadState != Reload::None && m_isReloading && !isDucking () && !isInNarrowPlace ()) {
|
||||
if (!bots.isRoundOver () && tid == Task::Normal && m_reloadState != Reload::None && m_isReloading && !isDucking () && !isInNarrowPlace ()) {
|
||||
if (m_reloadState != Reload::None || m_isReloading) {
|
||||
const auto maxClip = conf.findWeaponById (m_currentWeapon).maxClip;
|
||||
const auto curClip = getAmmoInClip ();
|
||||
|
|
@ -1689,7 +1691,7 @@ void Bot::refreshEnemyPredict () {
|
|||
if (game.isNullEntity (m_enemy) && !game.isNullEntity (m_lastEnemy) && !m_lastEnemyOrigin.empty ()) {
|
||||
const auto distanceToLastEnemySq = m_lastEnemyOrigin.distanceSq (pev->origin);
|
||||
|
||||
if (distanceToLastEnemySq > cr::sqrf (128.0f) && (distanceToLastEnemySq < cr::sqrf (2048.0f) || usesSniper ())) {
|
||||
if (distanceToLastEnemySq > cr::sqrf (256.0f) && (distanceToLastEnemySq < cr::sqrf (2048.0f) || usesSniper ())) {
|
||||
m_aimFlags |= AimFlags::PredictPath;
|
||||
}
|
||||
const bool denyLastEnemy = pev->velocity.lengthSq2d () > 0.0f && distanceToLastEnemySq < cr::sqrf (256.0f) && m_shootTime + 2.5f > game.time ();
|
||||
|
|
@ -1921,8 +1923,8 @@ void Bot::filterTasks () {
|
|||
else if (m_isVIP || m_isReloading || (sniping && usesSniper ())) {
|
||||
ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading
|
||||
}
|
||||
else if (m_lastEnemyOrigin.distance2d (pev->origin) < 200.0f) {
|
||||
ratio *= 5.0f;
|
||||
else if (m_lastEnemyOrigin.distanceSq2d (pev->origin) < cr::sqrf (200.0f)) {
|
||||
ratio *= 3.0f;
|
||||
}
|
||||
else if (m_isCreature) {
|
||||
ratio = 0.0f;
|
||||
|
|
@ -3208,12 +3210,12 @@ void Bot::showDebugOverlay () {
|
|||
StringRef debugData = strings.format (
|
||||
"\n\n\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\n"
|
||||
"Item: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\n"
|
||||
"SP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\n"
|
||||
"SP=%.02f SSP=%.02f I=%d CG=%d PG=%d G=%d T: %.02f MT: %d\n"
|
||||
"Enemy=%s Pickup=%s Type=%s Terrain=%s Stuck=%s\n",
|
||||
pev->netname.str (), m_healthValue, pev->armorvalue,
|
||||
tid, tasks[tid], getTask ()->desire, weapon, getAmmoInClip (),
|
||||
getAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags.trim (),
|
||||
m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - game.time (),
|
||||
m_moveSpeed, m_strafeSpeed, index, m_chosenGoalIndex, m_prevGoalIndex, goal, m_navTimeset - game.time (),
|
||||
pev->movetype, enemy, pickup, personalities[m_personality], boolValue (m_checkTerrain),
|
||||
boolValue (m_isStuck));
|
||||
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ Vector Bot::getBodyOffsetError (float distance) {
|
|||
return m_aimLastError;
|
||||
}
|
||||
|
||||
Vector Bot::getEnemyBodyOffset () {
|
||||
Vector Bot::getEnemyBodyOffset () {
|
||||
// the purpose of this function, is to make bot aiming not so ideal. it's mutate m_enemyOrigin enemy vector
|
||||
// returned from visibility check function.
|
||||
|
||||
|
|
@ -586,7 +586,7 @@ Vector Bot::getCustomHeight (float distance) {
|
|||
Long, Middle, Short
|
||||
};
|
||||
|
||||
constexpr float offsetRanges[9][3] = {
|
||||
constexpr float kOffsetRanges[9][3] = {
|
||||
{ 0.0f, 0.0f, 0.0f }, // none
|
||||
{ 0.0f, 0.0f, 0.0f }, // melee
|
||||
{ 0.5f, -0.1f, -1.5f }, // pistol
|
||||
|
|
@ -613,7 +613,7 @@ Vector Bot::getCustomHeight (float distance) {
|
|||
else if (distance > kSprayDistance && distance <= kDoubleSprayDistance) {
|
||||
distanceIndex = DistanceIndex::Middle;
|
||||
}
|
||||
return { 0.0f, 0.0f, offsetRanges[m_weaponType][distanceIndex] };
|
||||
return { 0.0f, 0.0f, kOffsetRanges[m_weaponType][distanceIndex] };
|
||||
}
|
||||
|
||||
bool Bot::isFriendInLineOfFire (float distance) {
|
||||
|
|
@ -711,7 +711,9 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
|
|||
bool Bot::isPenetrableObstacle2 (const Vector &dest) {
|
||||
// this function returns if enemy can be shoot through some obstacle
|
||||
|
||||
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal || !conf.findWeaponById (m_currentWeapon).penetratePower) {
|
||||
auto power = conf.findWeaponById (m_currentWeapon).penetratePower;
|
||||
|
||||
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal || !power) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1353,10 +1355,13 @@ void Bot::attackMovement () {
|
|||
|
||||
if (m_difficulty >= Difficulty::Normal && isOnFloor () && m_duckTime < game.time ()) {
|
||||
if (distance < 768.0f) {
|
||||
if (rg.get (0, 1000) < rg.get (5, 10) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) {
|
||||
pev->button |= IN_JUMP;
|
||||
if (pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) {
|
||||
m_jumpTime = game.time () + m_frameInterval * 2.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_duckTime = game.time () + m_frameInterval * 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isReloading) {
|
||||
|
|
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -277,6 +277,66 @@ void Bot::checkDarkness () {
|
|||
m_checkDarkTime = game.time () + rg.get (2.0f, 4.0f);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void Bot::updateBodyAngles () {
|
||||
// set the body angles to point the gun correctly
|
||||
pev->angles.x = -pev->v_angle.x * (1.0f / 3.0f);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue