nav: fall controls are not good. (#656)
nav: fall controls are not good. nav: increased behavior rate in finding the best goal. nav: avoiding the door after hitting it. combat: if the enemy is using a sniper rifle, move. combat: enemy group functionality has been improved. combat: if we are doing a camping task, do not switch to a knife at close range. aim: slight changes to enemy prediction. --------- Co-authored-by: jeefo <dmitry@jeefo.net>
This commit is contained in:
parent
6152a2d2ce
commit
e717710bd1
9 changed files with 245 additions and 211 deletions
|
|
@ -133,10 +133,11 @@ bool Bot::isEnemyInDarkArea (edict_t *enemy) {
|
|||
if (!cv_check_darkness && game.isNullEntity (enemy)) {
|
||||
return false;
|
||||
}
|
||||
const auto &v = enemy->v;
|
||||
const auto scolor = illum.getSkyColor ();
|
||||
|
||||
// check if node near the enemy have a degraded light level
|
||||
const auto enemyNodeIndex = graph.getNearest (enemy->v.origin);
|
||||
const auto enemyNodeIndex = graph.getNearest (v.origin);
|
||||
|
||||
if (!graph.exists (enemyNodeIndex)) {
|
||||
return false;
|
||||
|
|
@ -149,9 +150,9 @@ bool Bot::isEnemyInDarkArea (edict_t *enemy) {
|
|||
}
|
||||
bool enemySemiTransparent = false;
|
||||
|
||||
const bool enemyHasGun = (enemy->v.weapons & kPrimaryWeaponMask) || (enemy->v.weapons & kSecondaryWeaponMask);
|
||||
const bool enemyHasFlashlightEnabled = !!(enemy->v.effects & EF_DIMLIGHT);
|
||||
const bool enemyIsAttacking = !!(enemy->v.oldbuttons & IN_ATTACK);
|
||||
const bool enemyHasGun = (v.weapons & kPrimaryWeaponMask) || (v.weapons & kSecondaryWeaponMask);
|
||||
const bool enemyIsAttacking = (v.button & IN_ATTACK) || (v.oldbuttons & IN_ATTACK);
|
||||
const bool enemyHasFlashlightEnabled = !!(v.effects & EF_DIMLIGHT);
|
||||
|
||||
if (!m_usesNVG && ((llevel < 3.0f && scolor > 50.0f) || (llevel < 25.0f && scolor <= 50.0f))
|
||||
&& !enemyHasFlashlightEnabled && (!enemyIsAttacking || !enemyHasGun)) {
|
||||
|
|
@ -163,7 +164,7 @@ bool Bot::isEnemyInDarkArea (edict_t *enemy) {
|
|||
enemySemiTransparent = true;
|
||||
}
|
||||
TraceResult result {};
|
||||
game.testLine (getEyesPos (), enemy->v.origin, m_isCreature ? TraceIgnore::None : TraceIgnore::Everything, ent (), &result);
|
||||
game.testLine (getEyesPos (), v.origin, m_isCreature ? TraceIgnore::None : TraceIgnore::Everything, ent (), &result);
|
||||
|
||||
return (result.flFraction <= 1.0f && result.pHit == enemy && (m_usesNVG || !enemySemiTransparent));
|
||||
}
|
||||
|
|
@ -193,7 +194,7 @@ bool Bot::checkBodyPartsWithOffsets (edict_t *target) {
|
|||
auto self = pev->pContainingEntity;
|
||||
|
||||
// creatures can't hurt behind anything
|
||||
const auto ignoreFlags = m_isCreature ? TraceIgnore::None : (cv_aim_trace_consider_glass ?TraceIgnore::Monsters : TraceIgnore::Everything);
|
||||
const auto ignoreFlags = m_isCreature ? TraceIgnore::None : (cv_aim_trace_consider_glass ? TraceIgnore::Monsters : TraceIgnore::Everything);
|
||||
|
||||
const auto hitsTarget = [&] () -> bool {
|
||||
return result.flFraction >= 1.0f || result.pHit == target;
|
||||
|
|
@ -390,7 +391,7 @@ bool Bot::lookupEnemies () {
|
|||
m_states |= Sense::SuspectEnemy;
|
||||
|
||||
const bool denyLastEnemy = pev->velocity.lengthSq2d () > 0.0f
|
||||
&& pev->origin.distanceSq2d (m_lastEnemyOrigin) < cr::sqrf (256.0f)
|
||||
&& m_lastEnemyOrigin.distanceSq (pev->origin) < cr::sqrf (256.0f)
|
||||
&& m_shootTime + 1.5f > game.time ();
|
||||
|
||||
if (!(m_aimFlags & (AimFlags::Enemy | AimFlags::PredictPath | AimFlags::Danger))
|
||||
|
|
@ -1244,10 +1245,9 @@ void Bot::fireWeapons () {
|
|||
if (cv_stab_close_enemies && m_difficulty >= Difficulty::Normal
|
||||
&& m_healthValue > 80.0f
|
||||
&& !game.isNullEntity (m_enemy)
|
||||
&& m_healthValue >= m_enemy->v.health
|
||||
&& distance < 100.0f
|
||||
&& !isOnLadder ()
|
||||
&& !isGroupOfEnemies (pev->origin)) {
|
||||
&& !isGroupOfEnemies (pev->origin)
|
||||
&& getCurrentTaskId () != Task::Camp) {
|
||||
|
||||
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
|
||||
return;
|
||||
|
|
@ -1428,13 +1428,14 @@ void Bot::attackMovement () {
|
|||
approach = 49;
|
||||
}
|
||||
}
|
||||
const bool isEnemyCone = isInViewCone (m_enemy->v.origin);
|
||||
|
||||
// only take cover when bomb is not planted and enemy can see the bot or the bot is VIP
|
||||
if (!game.is (GameFlags::CSDM) && !isKnifeMode ()) {
|
||||
if ((m_states & Sense::SeeingEnemy)
|
||||
&& approach < 30
|
||||
&& !bots.isBombPlanted ()
|
||||
&& (isInViewCone (m_enemy->v.origin) || m_isVIP || m_isReloading)) {
|
||||
&& (isEnemyCone || m_isVIP || m_isReloading)) {
|
||||
|
||||
if (m_retreatTime < game.time ()) {
|
||||
startTask (Task::SeekCover, TaskPri::SeekCover, kInvalidNodeIndex, 0.0f, true);
|
||||
|
|
@ -1467,10 +1468,7 @@ void Bot::attackMovement () {
|
|||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
else if (distanceSq < cr::sqrf (1024.0f)) {
|
||||
if (isGroupOfEnemies (m_enemy->v.origin)) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
else if (rand < (usesSubmachine () ? 50 : 30)) {
|
||||
if (rand < (usesSubmachine () ? 50 : 30)) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1478,10 +1476,7 @@ void Bot::attackMovement () {
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (isGroupOfEnemies (m_enemy->v.origin)) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
else if (rand < (usesSubmachine () ? 80 : 90)) {
|
||||
if (rand < (usesSubmachine () ? 80 : 90)) {
|
||||
m_fightStyle = Fight::Stay;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1505,7 +1500,12 @@ void Bot::attackMovement () {
|
|||
// fire hurts friend value here is from previous frame, but acceptable, and saves us alot of cpu cycles
|
||||
if (approach < 30 || m_fireHurtsFriend || ((usesPistol () || usesShotgun ())
|
||||
&& distanceSq < cr::sqrf (pistolStrafeDistance)
|
||||
&& isInViewCone (m_enemyOrigin))) {
|
||||
&& isEnemyCone)) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
const auto enemyWeaponIsSniper = (m_enemy->v.weapons & kSniperWeaponMask);
|
||||
|
||||
if (enemyWeaponIsSniper && isEnemyCone) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
m_lastFightStyleCheck = game.time () + 3.0f;
|
||||
|
|
@ -1515,7 +1515,7 @@ void Bot::attackMovement () {
|
|||
m_moveSpeed = -pev->maxspeed;
|
||||
}
|
||||
|
||||
if (usesKnife () && isInViewCone (m_enemy->v.origin)) {
|
||||
if (usesKnife () && isEnemyCone) {
|
||||
m_fightStyle = Fight::Strafe;
|
||||
}
|
||||
|
||||
|
|
@ -1624,7 +1624,7 @@ void Bot::attackMovement () {
|
|||
|
||||
if (m_difficulty >= Difficulty::Normal && isOnFloor () && m_duckTime < game.time ()) {
|
||||
if (distanceSq < cr::sqrf (kSprayDistanceX2)) {
|
||||
if (rg (0, 1000) < rg (5, 10) && pev->velocity.length2d () > 150.0f && isInViewCone (m_enemy->v.origin)) {
|
||||
if (rg (0, 1000) < rg (5, 10) && pev->velocity.length2d () > 150.0f && isEnemyCone) {
|
||||
pev->button |= IN_JUMP;
|
||||
}
|
||||
}
|
||||
|
|
@ -2003,28 +2003,29 @@ void Bot::updateTeamCommands () {
|
|||
m_timeTeamOrder = game.time () + rg (15.0f, 30.0f);
|
||||
}
|
||||
|
||||
bool Bot::isGroupOfEnemies (const Vector &location, int numEnemies, float radius) {
|
||||
bool Bot::isGroupOfEnemies (const Vector &location) {
|
||||
int numPlayers = 0;
|
||||
|
||||
// needs a square radius
|
||||
const float radiusSq = cr::sqrf (radius);
|
||||
const float radiusSq = cr::sqrf (768.0f);
|
||||
|
||||
// search the world for enemy players...
|
||||
for (const auto &client : util.getClients ()) {
|
||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent ()) {
|
||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team == m_team || client.ent == ent ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (client.ent->v.origin.distanceSq (location) < radiusSq) {
|
||||
if (client.team == m_team) {
|
||||
return false; // don't target our teammates...
|
||||
}
|
||||
|
||||
if (numPlayers++ > numEnemies) {
|
||||
return true;
|
||||
if (!seesEntity (client.origin)) {
|
||||
continue;
|
||||
}
|
||||
++numPlayers;
|
||||
}
|
||||
}
|
||||
|
||||
if (numPlayers < 2) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2541,7 +2542,7 @@ bool Bot::isEnemyNoticeable (float range) {
|
|||
if (isCrouching) {
|
||||
// crouching and motionless - very tough to notice
|
||||
closeChance = 80.0f;
|
||||
farChance = 5.0f; // takes about three seconds to notice (50% chance)
|
||||
farChance = 5.0f; // takes about three seconds to notice (50% chance)
|
||||
}
|
||||
// standing
|
||||
else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue