graph: move light level calculation to thread worker

fix: nodes with light level 0.0 should trigger bots flashlight now
fix: gcc and msvc builds due to mistake in crlib
refactor: add more const-correctness (ongoing)
This commit is contained in:
jeefo 2023-06-24 03:23:22 +03:00
commit 3d2579c7ea
No known key found for this signature in database
GPG key ID: 927BCA0779BEA8ED
11 changed files with 121 additions and 111 deletions

@ -1 +1 @@
Subproject commit c4815b7445ae0fc509cba511deee0f2c67834704
Subproject commit 60e0b07a5f4cf630cd2ad49112129ac3e5859b5d

View file

@ -436,6 +436,7 @@ struct TaskPri {
};
constexpr auto kInfiniteDistance = 9999999.0f;
constexpr auto kInvalidLightLevel = kInfiniteDistance;
constexpr auto kGrenadeCheckTime = 0.6f;
constexpr auto kSprayDistance = 260.0f;
constexpr auto kDoubleSprayDistance = kSprayDistance * 2;

View file

@ -228,6 +228,7 @@ public:
void reset ();
void frame ();
void populateNodes ();
void syncInitLightLevels ();
void initLightLevels ();
void initNarrowPlaces ();
void addPath (int addIndex, int pathIndex, float distance);

View file

@ -737,16 +737,6 @@ public:
void sendBotToOrigin (const Vector &origin);
void markStale ();
bool hasHostage ();
bool usesRifle ();
bool usesPistol ();
bool usesSniper ();
bool usesSubmachine ();
bool usesShotgun ();
bool usesHeavy ();
bool usesZoomableRifle ();
bool usesBadWeapon ();
bool usesCampGun ();
bool usesKnife ();
bool hasPrimaryWeapon ();
bool hasSecondaryWeapon ();
bool hasShield ();
@ -809,6 +799,57 @@ public:
debugMsgInternal (strings.format (fmt, cr::forward <Args> (args)...));
}
private:
// returns true if bot is using a sniper rifle
bool usesSniper () const {
return m_weaponType == WeaponType::Sniper;
}
// returns true if bot is using a rifle
bool usesRifle () const {
return usesZoomableRifle () || m_weaponType == WeaponType::Rifle;
}
// returns true if bot is using a zoomable rifle
bool usesZoomableRifle () const {
return m_weaponType == WeaponType::ZoomRifle;
}
// returns true if bot is using a pistol
bool usesPistol () const {
return m_weaponType == WeaponType::Pistol;
}
// returns true if bot is using a SMG
bool usesSubmachine () const {
return m_weaponType == WeaponType::SMG;
}
// returns true if bot is using a shotgun
bool usesShotgun () const {
return m_weaponType == WeaponType::Shotgun;
}
// returns true if bot is using m249
bool usesHeavy () const {
return m_weaponType == WeaponType::Heavy;
}
// returns true if bot using not very good weapon
bool usesBadWeapon () const {
return usesShotgun () || m_currentWeapon == Weapon::UMP45 || m_currentWeapon == Weapon::MAC10 || m_currentWeapon == Weapon::TMP;
}
// returns true if bot using a camp gun
bool usesCampGun () const {
return usesSubmachine () || usesRifle () || usesSniper () || usesHeavy ();
}
// returns true if bot using knife
bool usesKnife () const {
return m_weaponType == WeaponType::Melee;
}
// execute client command helper
template <typename ...Args> void issueCommand (const char *fmt, Args &&...args);
};

View file

@ -704,9 +704,9 @@ void Bot::ensureEntitiesClear () {
if ((!m_isStuck || m_navTimeset + getEstimatedNodeReachTime () + m_frameInterval * 2.0f > game.time ()) && !(m_states & Sense::SeeingEnemy)) {
return;
}
const auto currentTask = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (currentTask == Task::PickupItem || (m_states & Sense::PickupItem)) {
if (tid == Task::PickupItem || (m_states & Sense::PickupItem)) {
if (!game.isNullEntity (m_pickupItem) && !m_hasProgressBar) {
m_itemIgnore = m_pickupItem; // clear these pointers, bot might be stuck getting to them
}
@ -715,11 +715,11 @@ void Bot::ensureEntitiesClear () {
m_pickupType = Pickup::None;
m_pickupItem = nullptr;
if (currentTask == Task::PickupItem) {
if (tid == Task::PickupItem) {
completeTask ();
}
}
else if (currentTask == Task::ShootBreakable) {
else if (tid == Task::ShootBreakable) {
if (!game.isNullEntity (m_breakableEntity)) {
m_ignoredBreakable.emplace (m_breakableEntity);
}
@ -1511,8 +1511,8 @@ void Bot::buyStuff () {
case BuyState::NightVision:
if (teamHasGoodEconomics && m_moneyAmount > 2500 && !m_hasNVG && rg.chance (30) && m_path) {
float skyColor = illum.getSkyColor ();
float lightLevel = m_path->light;
const float skyColor = illum.getSkyColor ();
const float lightLevel = m_path->light;
// if it's somewhat darkm do buy nightvision goggles
if ((skyColor >= 50.0f && lightLevel <= 15.0f) || (skyColor < 50.0f && lightLevel < 40.0f)) {
@ -2026,7 +2026,7 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
clearSearchNodes ();
ignoreCollision ();
const int tid = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
// leader bot?
if (m_isLeader && tid == Task::SeekCover) {
@ -2226,9 +2226,9 @@ void Bot::checkRadioQueue () {
m_targetEntity = m_radioEntity;
// don't pause/camp/follow anymore
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (taskID == Task::Pause || taskID == Task::Camp) {
if (tid == Task::Pause || tid == Task::Camp) {
getTask ()->time = game.time ();
}
startTask (Task::FollowUser, TaskPri::FollowUser, kInvalidNodeIndex, 0.0f, true);
@ -2344,9 +2344,9 @@ void Bot::checkRadioQueue () {
}
}
else if ((game.isNullEntity (m_enemy) && seesEntity (m_radioEntity->v.origin)) || distanceSq < cr::sqrf (2048.0f)) {
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (taskID == Task::Pause || taskID == Task::Camp) {
if (tid == Task::Pause || tid == Task::Camp) {
m_fearLevel -= 0.2f;
if (m_fearLevel < 0.0f) {
@ -2406,9 +2406,9 @@ void Bot::checkRadioQueue () {
pushRadioMessage (Radio::RogerThat);
// don't pause/camp anymore
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (taskID == Task::Pause || taskID == Task::Camp) {
if (tid == Task::Pause || tid == Task::Camp) {
getTask ()->time = game.time ();
}
m_targetEntity = nullptr;
@ -2447,9 +2447,9 @@ void Bot::checkRadioQueue () {
}
else {
// don't pause/camp anymore
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (taskID == Task::Pause) {
if (tid == Task::Pause) {
getTask ()->time = game.time ();
}
m_targetEntity = nullptr;
@ -2601,9 +2601,9 @@ void Bot::checkRadioQueue () {
}
else {
// don't pause anymore
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (taskID == Task::Pause) {
if (tid == Task::Pause) {
getTask ()->time = game.time ();
}
@ -2621,10 +2621,10 @@ void Bot::checkRadioQueue () {
}
auto enemy = client.ent;
const float distanceSq = m_radioEntity->v.origin.distanceSq (enemy->v.origin);
const float enemyDistanceSq = m_radioEntity->v.origin.distanceSq (enemy->v.origin);
if (distanceSq < nearestDistanceSq) {
nearestDistanceSq = distanceSq;
if (enemyDistanceSq < nearestDistanceSq) {
nearestDistanceSq = enemyDistanceSq;
m_lastEnemy = enemy;
m_lastEnemyOrigin = enemy->v.origin;
@ -2633,7 +2633,7 @@ void Bot::checkRadioQueue () {
}
clearSearchNodes ();
int index = findDefendNode (m_radioEntity->v.origin);
const int index = findDefendNode (m_radioEntity->v.origin);
// push camp task on to stack
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, game.time () + rg.get (30.0f, 60.0f), true);
@ -2651,7 +2651,7 @@ void Bot::checkRadioQueue () {
}
void Bot::tryHeadTowardRadioMessage () {
const int tid = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (tid == Task::MoveToPosition || m_headedTime + 15.0f < game.time () || !util.isAlive (m_radioEntity) || m_hasC4) {
return;
@ -3098,7 +3098,7 @@ void Bot::showDebugOverlay () {
return;
}
static float timeDebugUpdate = 0.0f;
static int index = kInvalidNodeIndex, goal = kInvalidNodeIndex, taskID = 0;
static int index = kInvalidNodeIndex, goal = kInvalidNodeIndex, tid = 0;
static HashMap <int32_t, StringRef> tasks {
{ Task::Normal, "Normal" },
@ -3149,8 +3149,8 @@ void Bot::showDebugOverlay () {
return;
}
if (taskID != getCurrentTaskId () || index != m_currentNodeIndex || goal != getTask ()->data || timeDebugUpdate < game.time ()) {
taskID = getCurrentTaskId ();
if (tid != getCurrentTaskId () || index != m_currentNodeIndex || goal != getTask ()->data || timeDebugUpdate < game.time ()) {
tid = getCurrentTaskId ();
index = m_currentNodeIndex;
goal = getTask ()->data;
@ -3179,7 +3179,7 @@ void Bot::showDebugOverlay () {
auto weapon = util.weaponIdToAlias (m_currentWeapon);
String debugData;
debugData.assignf ("\n\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%s Pickup=%s Type=%s Terrain=%s Stuck=%s\n", pev->netname.str (), m_healthValue, pev->armorvalue, taskID, tasks[taskID], getTask ()->desire, weapon, getAmmoInClip (), getAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags.trim (), m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - game.time (), pev->movetype, enemy, pickup, personalities[m_personality], boolValue (m_checkTerrain), boolValue (m_isStuck));
debugData.assignf ("\n\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%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 (), pev->movetype, enemy, pickup, personalities[m_personality], boolValue (m_checkTerrain), boolValue (m_isStuck));
MessageWriter (MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, nullptr, overlayEntity)
.writeByte (TE_TEXTMESSAGE)

View file

@ -457,11 +457,11 @@ Vector Bot::getBodyOffsetError (float distance) {
if (m_aimErrorTime < game.time ()) {
const float hitError = distance / (cr::clamp (static_cast <float> (m_difficulty), 1.0f, 4.0f) * 1000.0f);
auto &maxs = m_enemy->v.maxs, &mins = m_enemy->v.mins;
const auto &maxs = m_enemy->v.maxs, &mins = m_enemy->v.mins;
m_aimLastError = Vector (rg.get (mins.x * hitError, maxs.x * hitError), rg.get (mins.y * hitError, maxs.y * hitError), rg.get (mins.z * hitError, maxs.z * hitError));
auto &aimError = conf.getDifficultyTweaks (m_difficulty) ->aimError;
const auto &aimError = conf.getDifficultyTweaks (m_difficulty) ->aimError;
m_aimLastError += Vector (rg.get (-aimError.x, aimError.x), rg.get (-aimError.y, aimError.y), rg.get (-aimError.z, aimError.z));
m_aimErrorTime = game.time () + rg.get (1.5f, 2.0f);
@ -656,7 +656,7 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
obstacleDistanceSq = tr.vecEndPos.distanceSq (source);
}
}
const float kMaxDistanceSq = cr::sqrf (75.0f);
constexpr float kMaxDistanceSq = cr::sqrf (75.0f);
if (obstacleDistanceSq > 0.0f) {
while (power > 0) {
@ -1031,7 +1031,7 @@ bool Bot::isWeaponBadAtDistance (int weaponIndex, float distance) {
if (m_difficulty < Difficulty::Normal || !hasSecondaryWeapon ()) {
return false;
}
auto weaponType = info[weaponIndex].type;
const auto weaponType = info[weaponIndex].type;
if (weaponType == WeaponType::Melee) {
return false;
@ -1358,48 +1358,6 @@ bool Bot::isEnemyBehindShield (edict_t *enemy) {
return false;
}
bool Bot::usesSniper () {
// this function returns true, if returns if bot is using a sniper rifle
return m_weaponType == WeaponType::Sniper;
}
bool Bot::usesRifle () {
return usesZoomableRifle () || m_weaponType == WeaponType::Rifle;
}
bool Bot::usesZoomableRifle () {
return m_weaponType == WeaponType::ZoomRifle;
}
bool Bot::usesPistol () {
return m_weaponType == WeaponType::Pistol;
}
bool Bot::usesSubmachine () {
return m_weaponType == WeaponType::SMG;
}
bool Bot::usesShotgun () {
return m_weaponType == WeaponType::Shotgun;
}
bool Bot::usesHeavy () {
return m_weaponType == WeaponType::Heavy;
}
bool Bot::usesBadWeapon () {
return usesShotgun () || m_currentWeapon == Weapon::UMP45 || m_currentWeapon == Weapon::MAC10 || m_currentWeapon == Weapon::TMP;
}
bool Bot::usesCampGun () {
return usesSubmachine () || usesRifle () || usesSniper () || usesHeavy ();
}
bool Bot::usesKnife () {
return m_weaponType == WeaponType::Melee;
}
int Bot::bestPrimaryCarried () {
// this function returns the best weapon of this bot (based on personality prefs)
@ -1673,10 +1631,10 @@ bool Bot::isGroupOfEnemies (const Vector &location, int numEnemies, float radius
void Bot::checkReload () {
// check the reload state
const auto task = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
// we're should not reload, while doing next tasks
const bool uninterruptibleTask = (task == Task::PlantBomb || task == Task::DefuseBomb || task == Task::PickupItem || task == Task::ThrowExplosive || task == Task::ThrowFlashbang || task == Task::ThrowSmoke);
const bool uninterruptibleTask = (tid == Task::PlantBomb || tid == Task::DefuseBomb || tid == Task::PickupItem || tid == Task::ThrowExplosive || tid == Task::ThrowFlashbang || tid == Task::ThrowSmoke);
// do not check for reload
if (uninterruptibleTask || m_isUsingGrenade || usesKnife ()) {
@ -1939,7 +1897,7 @@ void Bot::checkGrenadesThrow () {
allowThrowing = false;
}
else {
float radius = cr::max (192.0f, m_lastEnemy->v.velocity.length2d ());
const float radius = cr::max (192.0f, m_lastEnemy->v.velocity.length2d ());
const Vector &pos = m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin;
auto predicted = graph.getNarestInRadius (radius, pos, 12);

View file

@ -1745,7 +1745,7 @@ bool BotControl::executeCommands () {
if (prefix != product.cmdPri && prefix != product.cmdSec) {
return false;
}
auto &client = util.getClient (game.indexOfPlayer (m_ent));
const auto &client = util.getClient (game.indexOfPlayer (m_ent));
// do not allow to execute stuff for non admins
if (m_ent != game.getLocalEntity () && !(client.flags & ClientFlags::Admin)) {
@ -1853,7 +1853,7 @@ bool BotControl::executeMenus () {
if (!util.isPlayer (m_ent) || game.isBotCmd ()) {
return false;
}
auto &issuer = util.getClient (game.indexOfPlayer (m_ent));
const auto &issuer = util.getClient (game.indexOfPlayer (m_ent));
// check if it's menu select, and some key pressed
if (strValue (0) != "menuselect" || strValue (1).empty () || issuer.menu == Menu::None) {

View file

@ -1188,7 +1188,7 @@ template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const
const float front = (start | plane->normal) - plane->dist;
const float back = (end | plane->normal) - plane->dist;
int side = front < 0.0f;
const int side = front < 0.0f;
// if they're both on the same side of the plane, don't bother to split just check the appropriate child
if ((back < 0.0f) == side) {
@ -1221,8 +1221,8 @@ template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const
auto tex = surf->texinfo;
// see where in lightmap space our intersection point is
int s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
int t = static_cast <int> ((mid | Vector (tex->vecs[1])) + tex->vecs[1][3]);
const int s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
const int t = static_cast <int> ((mid | Vector (tex->vecs[1])) + tex->vecs[1][3]);
// not in the bounds of our lightmap? punt...
if (s < surf->texturemins[0] || t < surf->texturemins[1]) {
@ -1253,7 +1253,7 @@ template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const
// compute the lightmap color at a particular point
for (int maps = 0u; maps < MAX_LIGHTMAPS && surf->styles[maps] != 255u; ++maps) {
uint32_t scale = m_lightstyleValue[surf->styles[maps]];
const uint32_t scale = m_lightstyleValue[surf->styles[maps]];
m_point.red += lightmap->r * scale;
m_point.green += lightmap->g * scale;
@ -1272,11 +1272,11 @@ template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const
float LightMeasure::getLightLevel (const Vector &point) {
if (game.is (GameFlags::Legacy)) {
return 0.0f;
return kInvalidLightLevel;
}
if (!m_worldModel) {
return 0.0f;
return kInvalidLightLevel;
}
if (!m_worldModel->lightdata) {
@ -1293,7 +1293,7 @@ float LightMeasure::getLightLevel (const Vector &point) {
}
return recursiveLightPoint <msurface_t, mnode_t> (m_worldModel->nodes, point, endPoint);
};
return !recursiveCheck () ? 0.0f : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f);
return !recursiveCheck () ? kInvalidLightLevel : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f);
}
float LightMeasure::getSkyColor () {

View file

@ -701,7 +701,7 @@ void BotGraph::add (int type, const Vector &pos) {
path->end = nullptr;
path->display = 0.0f;
path->light = 0.0f;
path->light = kInvalidLightLevel;
for (auto &link : path->links) {
link.index = kInvalidNodeIndex;
@ -1331,11 +1331,11 @@ void BotGraph::calculatePathRadius (int index) {
}
}
void BotGraph::initLightLevels () {
void BotGraph::syncInitLightLevels () {
// this function get's the light level for each waypoin on the map
// no nodes ? no light levels, and only one-time init
if (m_paths.empty () || !cr::fzero (m_paths[0].light)) {
if (m_paths.empty () || !cr::fequal (m_paths[0].light, kInvalidLightLevel)) {
return;
}
@ -1347,6 +1347,14 @@ void BotGraph::initLightLevels () {
illum.enableAnimation (false);
}
void BotGraph::initLightLevels () {
// this function get's the light level for each waypoin on the map
worker.enqueue ([this] () {
syncInitLightLevels ();
});
}
void BotGraph::initNarrowPlaces () {
// this function checks all nodes if they are inside narrow places. this is used to prevent
// bots to track hidden enemies in narrow places and prevent bots from throwing flashbangs or
@ -2142,9 +2150,9 @@ void BotGraph::frame () {
// show the information about that point
message.assignf (" %s node:\n"
" Node %d of %d, Radius: %.1f, Light: %.1f\n"
" Node %d of %d, Radius: %.1f, Light: %s\n"
" Flags: %s\n"
" Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, p.radius, p.light, flags, p.origin.x, p.origin.y, p.origin.z);
" Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, p.radius, p.light == kInvalidLightLevel ? "Invalid" : strings.format ("%1.f", p.light), flags, p.origin.x, p.origin.y, p.origin.z);
return message;
};
@ -2630,7 +2638,7 @@ void BotGraph::convertFromPOD (Path &path, const PODPath &pod) {
convertCampDirection (path);
}
path.radius = pod.radius;
path.light = 0.0f;
path.light = kInvalidLightLevel;
path.display = 0.0f;
for (int i = 0; i < kMaxNodeLinks; ++i) {

View file

@ -2206,7 +2206,7 @@ bool Bot::advanceMovement () {
// helper to change bot's goal
auto changeNextGoal = [&] {
int newGoal = findBestGoal ();
const int newGoal = findBestGoal ();
m_prevGoalIndex = newGoal;
m_chosenGoalIndex = newGoal;
@ -2227,10 +2227,10 @@ bool Bot::advanceMovement () {
selectBestNextNode ();
m_minSpeed = pev->maxspeed;
Task taskID = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
// only if we in normal task and bomb is not planted
if (taskID == Task::Normal && bots.getRoundMidTime () + 5.0f < game.time () && m_timeCamping + 5.0f < game.time () && !bots.isBombPlanted () && m_personality != Personality::Rusher && !m_hasC4 && !m_isVIP && m_loosedBombNodeIndex == kInvalidNodeIndex && !m_hasHostage && !m_isCreature) {
if (tid == Task::Normal && bots.getRoundMidTime () + 5.0f < game.time () && m_timeCamping + 5.0f < game.time () && !bots.isBombPlanted () && m_personality != Personality::Rusher && !m_hasC4 && !m_isVIP && m_loosedBombNodeIndex == kInvalidNodeIndex && !m_hasHostage && !m_isCreature) {
m_campButtons = 0;
const int nextIndex = m_pathWalk.next ();

View file

@ -243,20 +243,21 @@ void Bot::checkDarkness () {
}
// do not check every frame
if (m_checkDarkTime > game.time () || cr::fzero (m_path->light)) {
if (m_checkDarkTime > game.time () || cr::fequal (m_path->light, kInvalidLightLevel)) {
return;
}
const auto lightLevel = m_path->light;
const auto skyColor = illum.getSkyColor ();
const auto flashOn = (pev->effects & EF_DIMLIGHT);
if (mp_flashlight.bool_ () && !m_hasNVG) {
const auto task = getCurrentTaskId ();
const auto tid = getCurrentTaskId ();
if (!flashOn && task != Task::Camp && task != Task::Attack && m_heardSoundTime + 3.0f < game.time () && m_flashLevel > 30 && ((skyColor > 50.0f && m_path->light < 10.0f) || (skyColor <= 50.0f && m_path->light < 40.0f))) {
if (!flashOn && tid != Task::Camp && tid != Task::Attack && m_heardSoundTime + 3.0f < game.time () && m_flashLevel > 30 && ((skyColor > 50.0f && lightLevel < 10.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) {
pev->impulse = 100;
}
else if (flashOn && (((m_path->light > 15.0f && skyColor > 50.0f) || (m_path->light > 45.0f && skyColor <= 50.0f)) || task == Task::Camp || task == Task::Attack || m_flashLevel <= 0 || m_heardSoundTime + 3.0f >= game.time ())) {
else if (flashOn && (((lightLevel > 15.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f)) || tid == Task::Camp || tid == Task::Attack || m_flashLevel <= 0 || m_heardSoundTime + 3.0f >= game.time ())) {
pev->impulse = 100;
}
}
@ -264,10 +265,10 @@ void Bot::checkDarkness () {
if (flashOn) {
pev->impulse = 100;
}
else if (!m_usesNVG && ((skyColor > 50.0f && m_path->light < 15.0f) || (skyColor <= 50.0f && m_path->light < 40.0f))) {
else if (!m_usesNVG && ((skyColor > 50.0f && lightLevel < 15.0f) || (skyColor <= 50.0f && lightLevel < 40.0f))) {
issueCommand ("nightvision");
}
else if (m_usesNVG && ((m_path->light > 20.0f && skyColor > 50.0f) || (m_path->light > 45.0f && skyColor <= 50.0f))) {
else if (m_usesNVG && ((lightLevel > 20.0f && skyColor > 50.0f) || (lightLevel > 45.0f && skyColor <= 50.0f))) {
issueCommand ("nightvision");
}
}