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:
parent
4a35a87b25
commit
3d2579c7ea
11 changed files with 121 additions and 111 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit c4815b7445ae0fc509cba511deee0f2c67834704
|
||||
Subproject commit 60e0b07a5f4cf630cd2ad49112129ac3e5859b5d
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
63
inc/yapb.h
63
inc/yapb.h
|
|
@ -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 ();
|
||||
|
|
@ -778,7 +768,7 @@ public:
|
|||
return pev->origin + pev->view_ofs;
|
||||
};
|
||||
|
||||
Task getCurrentTaskId () {
|
||||
Task getCurrentTaskId () {
|
||||
return getTask ()->id;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 () {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue