Refactoring (#246)
add: yb_chat_percent, yb_camping_time_[min/max], yb_danger_factor[min/max], yb_chat_percent cvars fix: possible crash with difficulty 0 fix: debug_goal should not be used as last history fix: startup on old hlds, because of missing pfnGetFileSize fix: crash with out-bounds read change: again tweaked some aiming code change: player avoidance code so bots will jump less when stuck change: max followers is just /4 of max players refactor: redone distance between vectors refactor: remove magic numbers in graph.add function
This commit is contained in:
parent
6e83258c7d
commit
6f912eb056
10 changed files with 214 additions and 177 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 26c617d0a0cd18238a62f6e829da9161b7d56bd0
|
Subproject commit b5392f30bd5c0f2d0de0c6b3f39104c9aa1b1ee0
|
||||||
20
inc/graph.h
20
inc/graph.h
|
|
@ -43,11 +43,6 @@ CR_DECLARE_SCOPED_ENUM (PathConnection,
|
||||||
Bidirectional
|
Bidirectional
|
||||||
)
|
)
|
||||||
|
|
||||||
// defines node add commands
|
|
||||||
CR_DECLARE_SCOPED_ENUM (GraphAdd,
|
|
||||||
Normal = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// a* route state
|
// a* route state
|
||||||
CR_DECLARE_SCOPED_ENUM (RouteState,
|
CR_DECLARE_SCOPED_ENUM (RouteState,
|
||||||
Open = 0,
|
Open = 0,
|
||||||
|
|
@ -94,6 +89,20 @@ CR_DECLARE_SCOPED_ENUM (LiftState,
|
||||||
Leaving
|
Leaving
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// node add flags
|
||||||
|
CR_DECLARE_SCOPED_ENUM (NodeAddFlag,
|
||||||
|
Normal = 0,
|
||||||
|
TOnly = 1,
|
||||||
|
CTOnly = 2,
|
||||||
|
NoHostage = 3,
|
||||||
|
Rescue = 4,
|
||||||
|
Camp = 5,
|
||||||
|
CampEnd = 6,
|
||||||
|
JumpStart = 9,
|
||||||
|
JumpEnd = 10,
|
||||||
|
Goal = 100
|
||||||
|
)
|
||||||
|
|
||||||
// a* route
|
// a* route
|
||||||
struct Route {
|
struct Route {
|
||||||
float g, f;
|
float g, f;
|
||||||
|
|
@ -312,6 +321,7 @@ public:
|
||||||
int getDangerDamage (int team, int start, int goal);
|
int getDangerDamage (int team, int start, int goal);
|
||||||
int getPathDist (int srcIndex, int destIndex);
|
int getPathDist (int srcIndex, int destIndex);
|
||||||
int clearConnections (int index);
|
int clearConnections (int index);
|
||||||
|
int getBspSize ();
|
||||||
|
|
||||||
float calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin);
|
float calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,17 @@
|
||||||
ConVar cv_debug ("yb_debug", "0", "Enables or disables useful messages about bot states. Not required for end users.", true, 0.0f, 4.0f);
|
ConVar cv_debug ("yb_debug", "0", "Enables or disables useful messages about bot states. Not required for end users.", true, 0.0f, 4.0f);
|
||||||
ConVar cv_debug_goal ("yb_debug_goal", "-1", "Forces all alive bots to build path and go to the specified here graph node.", true, -1.0f, kMaxNodes);
|
ConVar cv_debug_goal ("yb_debug_goal", "-1", "Forces all alive bots to build path and go to the specified here graph node.", true, -1.0f, kMaxNodes);
|
||||||
ConVar cv_user_follow_percent ("yb_user_follow_percent", "20", "Specifies the percent of bots, than can follow leader on each round start.", true, 0.0f, 100.0f);
|
ConVar cv_user_follow_percent ("yb_user_follow_percent", "20", "Specifies the percent of bots, than can follow leader on each round start.", true, 0.0f, 100.0f);
|
||||||
ConVar cv_user_max_followers ("yb_user_max_followers", "1", "Specifies how many bots can follow a single user.", true, 0.0f, static_cast <float> (kGameMaxPlayers / 2));
|
ConVar cv_user_max_followers ("yb_user_max_followers", "1", "Specifies how many bots can follow a single user.", true, 0.0f, static_cast <float> (kGameMaxPlayers / 4));
|
||||||
|
|
||||||
ConVar cv_jasonmode ("yb_jasonmode", "0", "If enabled, all bots will be forced only the knife, skipping weapon buying routines.");
|
ConVar cv_jasonmode ("yb_jasonmode", "0", "If enabled, all bots will be forced only the knife, skipping weapon buying routines.");
|
||||||
ConVar cv_radio_mode ("yb_radio_mode", "2", "Allows bots to use radio or chattter.\nAllowed values: '0', '1', '2'.\nIf '0', radio and chatter is disabled.\nIf '1', only radio allowed.\nIf '2' chatter and radio allowed.", true, 0.0f, 2.0f);
|
ConVar cv_radio_mode ("yb_radio_mode", "2", "Allows bots to use radio or chattter.\nAllowed values: '0', '1', '2'.\nIf '0', radio and chatter is disabled.\nIf '1', only radio allowed.\nIf '2' chatter and radio allowed.", true, 0.0f, 2.0f);
|
||||||
|
|
||||||
ConVar cv_economics_rounds ("yb_economics_rounds", "1", "Specifies whether bots able to use team economics, like do not buy any weapons for whole team to keep money for better guns.");
|
ConVar cv_economics_rounds ("yb_economics_rounds", "1", "Specifies whether bots able to use team economics, like do not buy any weapons for whole team to keep money for better guns.");
|
||||||
ConVar cv_walking_allowed ("yb_walking_allowed", "1", "Specifies whether bots able to use 'shift' if they thinks that enemy is near.");
|
ConVar cv_walking_allowed ("yb_walking_allowed", "1", "Specifies whether bots able to use 'shift' if they thinks that enemy is near.");
|
||||||
ConVar cv_camping_allowed ("yb_camping_allowed", "1", "Allows or disallows bots to camp. Doesn't affects bomb/hostage defending tasks");
|
ConVar cv_camping_allowed ("yb_camping_allowed", "1", "Allows or disallows bots to camp. Doesn't affects bomb/hostage defending tasks.");
|
||||||
|
|
||||||
|
ConVar cv_camping_time_min ("yb_camping_time_min", "15.0", "Lower bound of time from which time for camping is calculated", true, 5.0f, 90.0f);
|
||||||
|
ConVar cv_camping_time_max ("yb_camping_time_max", "45.0", "Upper bound of time from which time for camping is calculated", true, 15.0f, 120.0f);
|
||||||
|
|
||||||
ConVar cv_tkpunish ("yb_tkpunish", "1", "Allows or disallows bots to take revenge of teamkillers / team attacks.");
|
ConVar cv_tkpunish ("yb_tkpunish", "1", "Allows or disallows bots to take revenge of teamkillers / team attacks.");
|
||||||
ConVar cv_freeze_bots ("yb_freeze_bots", "0", "If enabled the bots think function is disabled, so bots will not move anywhere from their spawn spots.");
|
ConVar cv_freeze_bots ("yb_freeze_bots", "0", "If enabled the bots think function is disabled, so bots will not move anywhere from their spawn spots.");
|
||||||
|
|
@ -30,7 +33,7 @@ ConVar cv_restricted_weapons ("yb_restricted_weapons", "", "Specifies semicolon
|
||||||
|
|
||||||
ConVar cv_attack_monsters ("yb_attack_monsters", "0", "Allows or disallows bots to attack monsters.");
|
ConVar cv_attack_monsters ("yb_attack_monsters", "0", "Allows or disallows bots to attack monsters.");
|
||||||
ConVar cv_pickup_custom_items ("yb_pickup_custom_items", "0", "Allows or disallows bots to pickup custom items.");
|
ConVar cv_pickup_custom_items ("yb_pickup_custom_items", "0", "Allows or disallows bots to pickup custom items.");
|
||||||
ConVar cv_ignore_objectives ("yb_ignore_objectives", "0", "Allows or disallows bots to do map objectives, i.e. plant/defuse bombs, and saves hostages");
|
ConVar cv_ignore_objectives ("yb_ignore_objectives", "0", "Allows or disallows bots to do map objectives, i.e. plant/defuse bombs, and saves hostages.");
|
||||||
|
|
||||||
// game console variables
|
// game console variables
|
||||||
ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef);
|
ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef);
|
||||||
|
|
@ -154,7 +157,7 @@ void Bot::checkGrenadesThrow () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float distance = (m_lastEnemyOrigin - pev->origin).length2d ();
|
float distance = m_lastEnemyOrigin.distance2d (pev->origin);
|
||||||
|
|
||||||
// don't throw grenades at anything that isn't on the ground!
|
// don't throw grenades at anything that isn't on the ground!
|
||||||
if (!(m_lastEnemy->v.flags & FL_ONGROUND) && !m_lastEnemy->v.waterlevel && m_lastEnemyOrigin.z > pev->absmax.z) {
|
if (!(m_lastEnemy->v.flags & FL_ONGROUND) && !m_lastEnemy->v.waterlevel && m_lastEnemyOrigin.z > pev->absmax.z) {
|
||||||
|
|
@ -346,8 +349,8 @@ void Bot::avoidGrenades () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pent->v.flags & FL_ONGROUND)) {
|
if (!(pent->v.flags & FL_ONGROUND)) {
|
||||||
float distance = (pent->v.origin - pev->origin).lengthSq ();
|
float distance = pent->v.origin.distanceSq (pev->origin);
|
||||||
float distanceMoved = ((pent->v.origin + pent->v.velocity * getFrameInterval ()) - pev->origin).lengthSq ();
|
float distanceMoved = pev->origin.distance (pent->v.origin + pent->v.velocity * getFrameInterval ());
|
||||||
|
|
||||||
if (distanceMoved < distance && distance < cr::square (500.0f)) {
|
if (distanceMoved < distance && distance < cr::square (500.0f)) {
|
||||||
const auto &dirToPoint = (pev->origin - pent->v.origin).normalize2d ();
|
const auto &dirToPoint = (pev->origin - pent->v.origin).normalize2d ();
|
||||||
|
|
@ -365,7 +368,7 @@ void Bot::avoidGrenades () {
|
||||||
}
|
}
|
||||||
else if ((pent->v.flags & FL_ONGROUND) && strcmp (model, "smokegrenade.mdl") == 0) {
|
else if ((pent->v.flags & FL_ONGROUND) && strcmp (model, "smokegrenade.mdl") == 0) {
|
||||||
if (isInFOV (pent->v.origin - getEyesPos ()) < pev->fov - 7.0f) {
|
if (isInFOV (pent->v.origin - getEyesPos ()) < pev->fov - 7.0f) {
|
||||||
float distance = (pent->v.origin - pev->origin).length ();
|
float distance = pent->v.origin.distance (pev->origin);
|
||||||
|
|
||||||
// shrink bot's viewing distance to smoke grenade's distance
|
// shrink bot's viewing distance to smoke grenade's distance
|
||||||
if (m_viewDistance > distance) {
|
if (m_viewDistance > distance) {
|
||||||
|
|
@ -404,7 +407,7 @@ void Bot::checkBreakablesAround () {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto &origin = game.getEntityOrigin (breakable);
|
const auto &origin = game.getEntityOrigin (breakable);
|
||||||
const auto lengthToObstacle = (origin - pev->origin).lengthSq ();
|
const auto lengthToObstacle = origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
// too far, skip it
|
// too far, skip it
|
||||||
if (lengthToObstacle > cr::square (400.0f)) {
|
if (lengthToObstacle > cr::square (400.0f)) {
|
||||||
|
|
@ -505,7 +508,7 @@ void Bot::updatePickups () {
|
||||||
const Vector &origin = game.getEntityOrigin (ent);
|
const Vector &origin = game.getEntityOrigin (ent);
|
||||||
|
|
||||||
// too far from us ?
|
// too far from us ?
|
||||||
if ((pev->origin - origin).lengthSq () > radius) {
|
if (pev->origin.distanceSq (origin) > radius) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -544,7 +547,7 @@ void Bot::updatePickups () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// too far from us ?
|
// too far from us ?
|
||||||
if ((pev->origin - origin).lengthSq () > radius) {
|
if (pev->origin.distanceSq (origin) > radius) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -776,7 +779,7 @@ void Bot::updatePickups () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pev->origin - origin).lengthSq () > cr::square (60.0f)) {
|
if (pev->origin.distanceSq (origin) > cr::square (60.0f)) {
|
||||||
|
|
||||||
if (!graph.isNodeReacheable (pev->origin, origin)) {
|
if (!graph.isNodeReacheable (pev->origin, origin)) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
|
|
@ -855,7 +858,7 @@ void Bot::getCampDirection (Vector *dest) {
|
||||||
|
|
||||||
// check if the trace hit something...
|
// check if the trace hit something...
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
float length = (tr.vecEndPos - src).lengthSq ();
|
float length = tr.vecEndPos.distanceSq (src);
|
||||||
|
|
||||||
if (length > 10000.0f) {
|
if (length > 10000.0f) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1697,7 +1700,7 @@ void Bot::overrideConditions () {
|
||||||
|
|
||||||
// special handling, if we have a knife in our hands
|
// special handling, if we have a knife in our hands
|
||||||
if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && usesKnife () && (util.isPlayer (m_enemy) || (cv_attack_monsters.bool_ () && util.isMonster (m_enemy)))) {
|
if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && usesKnife () && (util.isPlayer (m_enemy) || (cv_attack_monsters.bool_ () && util.isMonster (m_enemy)))) {
|
||||||
float length = (pev->origin - m_enemy->v.origin).length2d ();
|
float length = pev->origin.distance2d (m_enemy->v.origin);
|
||||||
|
|
||||||
// do waypoint movement if enemy is not reachable with a knife
|
// do waypoint movement if enemy is not reachable with a knife
|
||||||
if (length > 100.0f && (m_states & Sense::SeeingEnemy)) {
|
if (length > 100.0f && (m_states & Sense::SeeingEnemy)) {
|
||||||
|
|
@ -1891,7 +1894,7 @@ void Bot::filterTasks () {
|
||||||
filter[Task::PickupItem].desire = 50.0f; // always pickup button
|
filter[Task::PickupItem].desire = 50.0f; // always pickup button
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float distance = (500.0f - (game.getEntityOrigin (m_pickupItem) - pev->origin).length ()) * 0.2f;
|
float distance = (500.0f - pev->origin.distance (game.getEntityOrigin (m_pickupItem))) * 0.2f;
|
||||||
|
|
||||||
if (distance > 50.0f) {
|
if (distance > 50.0f) {
|
||||||
distance = 50.0f;
|
distance = 50.0f;
|
||||||
|
|
@ -1955,7 +1958,7 @@ void Bot::filterTasks () {
|
||||||
|
|
||||||
// if half of the round is over, allow hunting
|
// if half of the round is over, allow hunting
|
||||||
if (getCurrentTaskId () != Task::EscapeFromBomb && game.isNullEntity (m_enemy) && bots.getRoundMidTime () < game.time () && !m_isUsingGrenade && m_currentNodeIndex != graph.getNearest (m_lastEnemyOrigin) && m_personality != Personality::Careful && !cv_ignore_enemies.bool_ ()) {
|
if (getCurrentTaskId () != Task::EscapeFromBomb && game.isNullEntity (m_enemy) && bots.getRoundMidTime () < game.time () && !m_isUsingGrenade && m_currentNodeIndex != graph.getNearest (m_lastEnemyOrigin) && m_personality != Personality::Careful && !cv_ignore_enemies.bool_ ()) {
|
||||||
float desireLevel = 4096.0f - ((1.0f - tempAgression) * (m_lastEnemyOrigin - pev->origin).length ());
|
float desireLevel = 4096.0f - ((1.0f - tempAgression) * m_lastEnemyOrigin.distance (pev->origin));
|
||||||
|
|
||||||
desireLevel = (100.0f * desireLevel) / 4096.0f;
|
desireLevel = (100.0f * desireLevel) / 4096.0f;
|
||||||
desireLevel -= retreatLevel;
|
desireLevel -= retreatLevel;
|
||||||
|
|
@ -2167,7 +2170,7 @@ bool Bot::isEnemyThreat () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if enemy is near or facing us directly
|
// if enemy is near or facing us directly
|
||||||
if ((m_enemy->v.origin - pev->origin).lengthSq () < cr::square (256.0f) || isInViewCone (m_enemy->v.origin)) {
|
if (m_enemy->v.origin.distanceSq (pev->origin) < cr::square (256.0f) || isInViewCone (m_enemy->v.origin)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2188,7 +2191,7 @@ bool Bot::reactOnEnemy () {
|
||||||
}
|
}
|
||||||
int enemyIndex = graph.getNearest (m_enemy->v.origin);
|
int enemyIndex = graph.getNearest (m_enemy->v.origin);
|
||||||
|
|
||||||
auto lineDist = (m_enemy->v.origin - pev->origin).length ();
|
auto lineDist = m_enemy->v.origin.distance (pev->origin);
|
||||||
auto pathDist = static_cast <float> (graph.getPathDist (ownIndex, enemyIndex));
|
auto pathDist = static_cast <float> (graph.getPathDist (ownIndex, enemyIndex));
|
||||||
|
|
||||||
if (pathDist - lineDist > 112.0f || isOnLadder ()) {
|
if (pathDist - lineDist > 112.0f || isOnLadder ()) {
|
||||||
|
|
@ -2224,7 +2227,7 @@ void Bot::checkRadioQueue () {
|
||||||
m_radioOrder = 0;
|
m_radioOrder = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float distance = (m_radioEntity->v.origin - pev->origin).length ();
|
float distance = m_radioEntity->v.origin.distance (pev->origin);
|
||||||
|
|
||||||
switch (m_radioOrder) {
|
switch (m_radioOrder) {
|
||||||
case Radio::CoverMe:
|
case Radio::CoverMe:
|
||||||
|
|
@ -2497,7 +2500,7 @@ void Bot::checkRadioQueue () {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto enemy = client.ent;
|
auto enemy = client.ent;
|
||||||
float curDist = (m_radioEntity->v.origin - enemy->v.origin).lengthSq ();
|
float curDist = m_radioEntity->v.origin.distanceSq (enemy->v.origin);
|
||||||
|
|
||||||
if (curDist < nearestDistance) {
|
if (curDist < nearestDistance) {
|
||||||
nearestDistance = curDist;
|
nearestDistance = curDist;
|
||||||
|
|
@ -2599,7 +2602,7 @@ void Bot::checkRadioQueue () {
|
||||||
|
|
||||||
// find nearest bomb waypoint to player
|
// find nearest bomb waypoint to player
|
||||||
for (auto &point : graph.m_goalPoints) {
|
for (auto &point : graph.m_goalPoints) {
|
||||||
distance = (graph[point].origin - m_radioEntity->v.origin).lengthSq ();
|
distance = graph[point].origin.distanceSq (m_radioEntity->v.origin);
|
||||||
|
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
minDistance = distance;
|
minDistance = distance;
|
||||||
|
|
@ -2652,7 +2655,7 @@ void Bot::checkRadioQueue () {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto enemy = client.ent;
|
auto enemy = client.ent;
|
||||||
float dist = (m_radioEntity->v.origin - enemy->v.origin).lengthSq ();
|
float dist = m_radioEntity->v.origin.distanceSq (enemy->v.origin);
|
||||||
|
|
||||||
if (dist < nearestDistance) {
|
if (dist < nearestDistance) {
|
||||||
nearestDistance = dist;
|
nearestDistance = dist;
|
||||||
|
|
@ -2723,7 +2726,7 @@ void Bot::updateAimDir () {
|
||||||
else if (flags & AimFlags::Grenade) {
|
else if (flags & AimFlags::Grenade) {
|
||||||
m_lookAt = m_throw;
|
m_lookAt = m_throw;
|
||||||
|
|
||||||
float throwDistance = (m_throw - pev->origin).length ();
|
float throwDistance = m_throw.distance (pev->origin);
|
||||||
float coordCorrection = 0.0f;
|
float coordCorrection = 0.0f;
|
||||||
|
|
||||||
if (throwDistance > 100.0f && throwDistance < 800.0f) {
|
if (throwDistance > 100.0f && throwDistance < 800.0f) {
|
||||||
|
|
@ -2799,7 +2802,7 @@ void Bot::updateAimDir () {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_moveToGoal && !m_isStuck && m_moveSpeed > getShiftSpeed () && !(pev->button & IN_DUCK) && m_currentNodeIndex != kInvalidNodeIndex && !(m_path->flags & (NodeFlag::Ladder | NodeFlag::Crouch)) && m_pathWalk.hasNext () && (pev->origin - m_destOrigin).lengthSq () < cr::square (160.0f)) {
|
if (m_moveToGoal && !m_isStuck && m_moveSpeed > getShiftSpeed () && !(pev->button & IN_DUCK) && m_currentNodeIndex != kInvalidNodeIndex && !(m_path->flags & (NodeFlag::Ladder | NodeFlag::Crouch)) && m_pathWalk.hasNext () && pev->origin.distanceSq (m_destOrigin) < cr::square (160.0f)) {
|
||||||
auto nextPathIndex = m_pathWalk.next ();
|
auto nextPathIndex = m_pathWalk.next ();
|
||||||
|
|
||||||
if (graph.isVisible (m_currentNodeIndex, nextPathIndex)) {
|
if (graph.isVisible (m_currentNodeIndex, nextPathIndex)) {
|
||||||
|
|
@ -2817,7 +2820,7 @@ void Bot::updateAimDir () {
|
||||||
auto dangerIndex = graph.getDangerIndex (m_team, m_currentNodeIndex, m_currentNodeIndex);
|
auto dangerIndex = graph.getDangerIndex (m_team, m_currentNodeIndex, m_currentNodeIndex);
|
||||||
|
|
||||||
if (graph.exists (dangerIndex) && graph.isVisible (m_currentNodeIndex, dangerIndex) && !(graph[dangerIndex].flags & NodeFlag::Crouch)) {
|
if (graph.exists (dangerIndex) && graph.isVisible (m_currentNodeIndex, dangerIndex) && !(graph[dangerIndex].flags & NodeFlag::Crouch)) {
|
||||||
if ((graph[dangerIndex].origin - pev->origin).lengthSq () < cr::square (160.0f)) {
|
if (pev->origin.distanceSq (graph[dangerIndex].origin) < cr::square (160.0f)) {
|
||||||
m_lookAt = m_destOrigin;
|
m_lookAt = m_destOrigin;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -2910,7 +2913,7 @@ void Bot::frame () {
|
||||||
if (bots.isBombPlanted () && m_team == Team::CT && m_notKilled) {
|
if (bots.isBombPlanted () && m_team == Team::CT && m_notKilled) {
|
||||||
const Vector &bombPosition = graph.getBombOrigin ();
|
const Vector &bombPosition = graph.getBombOrigin ();
|
||||||
|
|
||||||
if (!m_hasProgressBar && getCurrentTaskId () != Task::EscapeFromBomb && (pev->origin - bombPosition).lengthSq () < cr::square (1540.0f) && !isBombDefusing (bombPosition)) {
|
if (!m_hasProgressBar && getCurrentTaskId () != Task::EscapeFromBomb && pev->origin.distanceSq (bombPosition) < cr::square (1540.0f) && !isBombDefusing (bombPosition)) {
|
||||||
m_itemIgnore = nullptr;
|
m_itemIgnore = nullptr;
|
||||||
m_itemCheckTime = game.time ();
|
m_itemCheckTime = game.time ();
|
||||||
|
|
||||||
|
|
@ -2927,7 +2930,7 @@ void Bot::frame () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear enemy far away
|
// clear enemy far away
|
||||||
if (!m_lastEnemyOrigin.empty () && !game.isNullEntity (m_lastEnemy) && (pev->origin - m_lastEnemyOrigin).lengthSq () >= cr::square (1600.0f)) {
|
if (!m_lastEnemyOrigin.empty () && !game.isNullEntity (m_lastEnemy) && pev->origin.distanceSq (m_lastEnemyOrigin) >= cr::square (1600.0f)) {
|
||||||
m_lastEnemy = nullptr;
|
m_lastEnemy = nullptr;
|
||||||
m_lastEnemyOrigin = nullptr;
|
m_lastEnemyOrigin = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -3134,7 +3137,7 @@ void Bot::normal_ () {
|
||||||
if (!(m_states & (Sense::SeeingEnemy | Sense::HearingEnemy)) && !m_reloadState) {
|
if (!(m_states & (Sense::SeeingEnemy | Sense::HearingEnemy)) && !m_reloadState) {
|
||||||
m_reloadState = Reload::Primary;
|
m_reloadState = Reload::Primary;
|
||||||
}
|
}
|
||||||
m_timeCamping = game.time () + rg.get (10.0f, 25.0f);
|
m_timeCamping = game.time () + rg.get (cv_camping_time_min.float_ (), cv_camping_time_max.float_ ());
|
||||||
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, m_timeCamping, true);
|
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, m_timeCamping, true);
|
||||||
|
|
||||||
m_camp = m_path->origin + m_path->start.forward () * 500.0f;
|
m_camp = m_path->origin + m_path->start.forward () * 500.0f;
|
||||||
|
|
@ -3239,7 +3242,7 @@ void Bot::normal_ () {
|
||||||
destIndex = graph.getFarest (pev->origin, 512.0f);
|
destIndex = graph.getFarest (pev->origin, 512.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_prevGoalIndex == currIndex && !(graph[currIndex].flags & NodeFlag::Goal)) {
|
if (!graph.exists (cv_debug_goal.int_ ()) && graph.exists (currIndex) && m_prevGoalIndex == currIndex && !(graph[currIndex].flags & NodeFlag::Goal)) {
|
||||||
m_goalHistory.push (currIndex);
|
m_goalHistory.push (currIndex);
|
||||||
}
|
}
|
||||||
m_prevGoalIndex = destIndex;
|
m_prevGoalIndex = destIndex;
|
||||||
|
|
@ -3388,7 +3391,7 @@ void Bot::huntEnemy_ () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_lastEnemyOrigin - pev->origin).lengthSq () < cr::square (512.0f)) {
|
if (m_lastEnemyOrigin.distanceSq (pev->origin) < cr::square (512.0f)) {
|
||||||
m_moveSpeed = getShiftSpeed ();
|
m_moveSpeed = getShiftSpeed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3616,7 +3619,7 @@ void Bot::camp_ () {
|
||||||
const Vector &dotB = (graph[i].origin - pev->origin).normalize2d ();
|
const Vector &dotB = (graph[i].origin - pev->origin).normalize2d ();
|
||||||
|
|
||||||
if ((dotA | dotB) > 0.9f) {
|
if ((dotA | dotB) > 0.9f) {
|
||||||
int distance = static_cast <int> ((pev->origin - graph[i].origin).length ());
|
int distance = static_cast <int> (graph[i].origin.distance (pev->origin));
|
||||||
|
|
||||||
if (numFoundPoints >= 3) {
|
if (numFoundPoints >= 3) {
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
|
@ -3900,7 +3903,7 @@ void Bot::defuseBomb_ () {
|
||||||
m_strafeSpeed = 0.0f;
|
m_strafeSpeed = 0.0f;
|
||||||
|
|
||||||
// bot is reloading and we close enough to start defusing
|
// bot is reloading and we close enough to start defusing
|
||||||
if (m_isReloading && (bombPos - pev->origin).length2d () < 80.0f) {
|
if (m_isReloading && bombPos.distance2d (pev->origin) < 80.0f) {
|
||||||
if (m_numEnemiesLeft == 0 || timeToBlowUp < fullDefuseTime + 7.0f || ((getAmmoInClip () > 8 && m_reloadState == Reload::Primary) || (getAmmoInClip () > 5 && m_reloadState == Reload::Secondary))) {
|
if (m_numEnemiesLeft == 0 || timeToBlowUp < fullDefuseTime + 7.0f || ((getAmmoInClip () > 8 && m_reloadState == Reload::Primary) || (getAmmoInClip () > 5 && m_reloadState == Reload::Secondary))) {
|
||||||
int weaponIndex = bestWeaponCarried ();
|
int weaponIndex = bestWeaponCarried ();
|
||||||
|
|
||||||
|
|
@ -3942,8 +3945,8 @@ void Bot::defuseBomb_ () {
|
||||||
botStandOrigin = pev->origin;
|
botStandOrigin = pev->origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
float duckLength = (m_entity - botDuckOrigin).lengthSq ();
|
float duckLength = m_entity.distanceSq (botDuckOrigin);
|
||||||
float standLength = (m_entity - botStandOrigin).lengthSq ();
|
float standLength = m_entity.distanceSq (botStandOrigin);
|
||||||
|
|
||||||
if (duckLength > 5625.0f || standLength > 5625.0f) {
|
if (duckLength > 5625.0f || standLength > 5625.0f) {
|
||||||
if (standLength < duckLength) {
|
if (standLength < duckLength) {
|
||||||
|
|
@ -4026,7 +4029,7 @@ void Bot::followUser_ () {
|
||||||
m_reloadState = Reload::Primary;
|
m_reloadState = Reload::Primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_targetEntity->v.origin - pev->origin).lengthSq () > cr::square (130.0f)) {
|
if (m_targetEntity->v.origin.distanceSq (pev->origin) > cr::square (130.0f)) {
|
||||||
m_followWaitTime = 0.0f;
|
m_followWaitTime = 0.0f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -4106,7 +4109,7 @@ void Bot::throwExplosive_ () {
|
||||||
|
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
|
|
||||||
if ((pev->origin - dest).lengthSq () < cr::square (400.0f)) {
|
if (pev->origin.distanceSq (dest) < cr::square (400.0f)) {
|
||||||
// heck, I don't wanna blow up myself
|
// heck, I don't wanna blow up myself
|
||||||
m_grenadeCheckTime = game.time () + kGrenadeCheckTime;
|
m_grenadeCheckTime = game.time () + kGrenadeCheckTime;
|
||||||
|
|
||||||
|
|
@ -4173,7 +4176,7 @@ void Bot::throwFlashbang_ () {
|
||||||
|
|
||||||
ignoreCollision ();
|
ignoreCollision ();
|
||||||
|
|
||||||
if ((pev->origin - dest).lengthSq () < cr::square (400.0f)) {
|
if (pev->origin.distanceSq (dest) < cr::square (400.0f)) {
|
||||||
m_grenadeCheckTime = game.time () + kGrenadeCheckTime; // heck, I don't wanna blow up myself
|
m_grenadeCheckTime = game.time () + kGrenadeCheckTime; // heck, I don't wanna blow up myself
|
||||||
|
|
||||||
selectBestWeapon ();
|
selectBestWeapon ();
|
||||||
|
|
@ -4380,7 +4383,7 @@ void Bot::escapeFromBomb_ () {
|
||||||
float safeRadius = rg.get (1513.0f, 2048.0f);
|
float safeRadius = rg.get (1513.0f, 2048.0f);
|
||||||
|
|
||||||
for (int i = 0; i < graph.length (); ++i) {
|
for (int i = 0; i < graph.length (); ++i) {
|
||||||
if ((graph[i].origin - graph.getBombOrigin ()).length () < safeRadius || isOccupiedNode (i)) {
|
if (graph[i].origin.distance (graph.getBombOrigin ()) < safeRadius || isOccupiedNode (i)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int pathDistance = graph.getPathDist (m_currentNodeIndex, i);
|
int pathDistance = graph.getPathDist (m_currentNodeIndex, i);
|
||||||
|
|
@ -4457,7 +4460,7 @@ void Bot::pickupItem_ () {
|
||||||
m_entity = dest;
|
m_entity = dest;
|
||||||
|
|
||||||
// find the distance to the item
|
// find the distance to the item
|
||||||
float itemDistance = (dest - pev->origin).length ();
|
float itemDistance = dest.distance (pev->origin);
|
||||||
|
|
||||||
switch (m_pickupType) {
|
switch (m_pickupType) {
|
||||||
case Pickup::DroppedC4:
|
case Pickup::DroppedC4:
|
||||||
|
|
@ -4730,7 +4733,7 @@ void Bot::logic () {
|
||||||
|
|
||||||
// see how far bot has moved since the previous position...
|
// see how far bot has moved since the previous position...
|
||||||
if (m_checkTerrain) {
|
if (m_checkTerrain) {
|
||||||
movedDistance = (m_prevOrigin - pev->origin).length ();
|
movedDistance = m_prevOrigin.distance (pev->origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save current position as previous
|
// save current position as previous
|
||||||
|
|
@ -5074,7 +5077,7 @@ bool Bot::hasHostage () {
|
||||||
if (!game.isNullEntity (hostage)) {
|
if (!game.isNullEntity (hostage)) {
|
||||||
|
|
||||||
// don't care about dead hostages
|
// don't care about dead hostages
|
||||||
if (hostage->v.health <= 0.0f || (pev->origin - hostage->v.origin).lengthSq () > cr::square (600.0f)) {
|
if (hostage->v.health <= 0.0f || pev->origin.distanceSq (hostage->v.origin) > cr::square (600.0f)) {
|
||||||
hostage = nullptr;
|
hostage = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -5273,7 +5276,7 @@ void Bot::dropWeaponForUser (edict_t *user, bool discardC4) {
|
||||||
// this function, asks bot to discard his current primary weapon (or c4) to the user that requsted it with /drop*
|
// this function, asks bot to discard his current primary weapon (or c4) to the user that requsted it with /drop*
|
||||||
// command, very useful, when i'm don't have money to buy anything... )
|
// command, very useful, when i'm don't have money to buy anything... )
|
||||||
|
|
||||||
if (util.isAlive (user) && m_moneyAmount >= 2000 && hasPrimaryWeapon () && (user->v.origin - pev->origin).length () <= 450.0f) {
|
if (util.isAlive (user) && m_moneyAmount >= 2000 && hasPrimaryWeapon () && user->v.origin.distance (pev->origin) <= 450.0f) {
|
||||||
m_aimFlags |= AimFlags::Entity;
|
m_aimFlags |= AimFlags::Entity;
|
||||||
m_lookAt = user->v.origin;
|
m_lookAt = user->v.origin;
|
||||||
|
|
||||||
|
|
@ -5506,7 +5509,7 @@ Vector Bot::isBombAudible () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we hear bomb if length greater than radius
|
// we hear bomb if length greater than radius
|
||||||
if (desiredRadius < (pev->origin - bombOrigin).length2d ()) {
|
if (desiredRadius < pev->origin.distance2d (bombOrigin)) {
|
||||||
return bombOrigin;
|
return bombOrigin;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -5645,7 +5648,7 @@ bool Bot::isOutOfBombTimer () {
|
||||||
const Vector &bombOrigin = graph.getBombOrigin ();
|
const Vector &bombOrigin = graph.getBombOrigin ();
|
||||||
|
|
||||||
// for terrorist, if timer is lower than 13 seconds, return true
|
// for terrorist, if timer is lower than 13 seconds, return true
|
||||||
if (timeLeft < 13.0f && m_team == Team::Terrorist && (bombOrigin - pev->origin).lengthSq () < cr::square (964.0f)) {
|
if (timeLeft < 13.0f && m_team == Team::Terrorist && bombOrigin.distanceSq (pev->origin) < cr::square (964.0f)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool hasTeammatesWithDefuserKit = false;
|
bool hasTeammatesWithDefuserKit = false;
|
||||||
|
|
@ -5653,7 +5656,7 @@ bool Bot::isOutOfBombTimer () {
|
||||||
// check if our teammates has defusal kit
|
// check if our teammates has defusal kit
|
||||||
for (const auto &bot : bots) {
|
for (const auto &bot : bots) {
|
||||||
// search players with defuse kit
|
// search players with defuse kit
|
||||||
if (bot.get () != this && bot->m_team == Team::CT && bot->m_hasDefuser && (bombOrigin - bot->pev->origin).lengthSq () < cr::square (512.0f)) {
|
if (bot.get () != this && bot->m_team == Team::CT && bot->m_hasDefuser && bombOrigin.distanceSq (bot->pev->origin) < cr::square (512.0f)) {
|
||||||
hasTeammatesWithDefuserKit = true;
|
hasTeammatesWithDefuserKit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -5691,7 +5694,7 @@ void Bot::updateHearing () {
|
||||||
if (!game.checkVisibility (client.ent, set)) {
|
if (!game.checkVisibility (client.ent, set)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float distance = (client.noise.pos - pev->origin).length ();
|
float distance = client.noise.pos.distance (pev->origin);
|
||||||
|
|
||||||
if (distance > client.noise.dist) {
|
if (distance > client.noise.dist) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -5739,9 +5742,9 @@ void Bot::updateHearing () {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if bot had an enemy but the heard one is nearer, take it instead
|
// if bot had an enemy but the heard one is nearer, take it instead
|
||||||
float distance = (m_lastEnemyOrigin - pev->origin).lengthSq ();
|
float distance = m_lastEnemyOrigin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (distance > (player->v.origin - pev->origin).lengthSq () && m_seeEnemyTime + 2.0f < game.time ()) {
|
if (distance > player->v.origin.distanceSq (pev->origin) && m_seeEnemyTime + 2.0f < game.time ()) {
|
||||||
m_lastEnemy = player;
|
m_lastEnemy = player;
|
||||||
m_lastEnemyOrigin = player->v.origin;
|
m_lastEnemyOrigin = player->v.origin;
|
||||||
}
|
}
|
||||||
|
|
@ -5810,7 +5813,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bot = bots[client.ent];
|
auto bot = bots[client.ent];
|
||||||
auto bombDistance = (client.origin - bombOrigin).lengthSq ();
|
auto bombDistance = client.origin.distanceSq (bombOrigin);
|
||||||
|
|
||||||
if (bot && !bot->m_notKilled) {
|
if (bot && !bot->m_notKilled) {
|
||||||
if (m_team != bot->m_team || bot->getCurrentTaskId () == Task::EscapeFromBomb) {
|
if (m_team != bot->m_team || bot->getCurrentTaskId () == Task::EscapeFromBomb) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <yapb.h>
|
#include <yapb.h>
|
||||||
|
|
||||||
ConVar cv_chat ("yb_chat", "1", "Enables or disables bots chat functionality.");
|
ConVar cv_chat ("yb_chat", "1", "Enables or disables bots chat functionality.");
|
||||||
|
ConVar cv_chat_percent ("yb_chat_percent", "30", "Chances bot will send random dead chat when killed.", true, 0.0f, 100.0f);
|
||||||
|
|
||||||
void BotSupport::stripTags (String &line) {
|
void BotSupport::stripTags (String &line) {
|
||||||
if (line.empty ()) {
|
if (line.empty ()) {
|
||||||
|
|
@ -316,7 +317,7 @@ bool Bot::isReplyingToChat () {
|
||||||
void Bot::checkForChat () {
|
void Bot::checkForChat () {
|
||||||
|
|
||||||
// say a text every now and then
|
// say a text every now and then
|
||||||
if (rg.chance (30) || m_notKilled || !cv_chat.bool_ ()) {
|
if (rg.chance (cv_chat_percent.int_ ()) || m_notKilled || !cv_chat.bool_ ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ int Bot::numFriendsNear (const Vector &origin, float radius) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((client.origin - origin).lengthSq () < cr::square (radius)) {
|
if (client.origin.distanceSq (origin) < cr::square (radius)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ int Bot::numEnemiesNear (const Vector &origin, float radius) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((client.origin - origin).lengthSq () < cr::square (radius)) {
|
if (client.origin.distanceSq (origin) < cr::square (radius)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +246,7 @@ bool Bot::lookupEnemies () {
|
||||||
player = m_enemy;
|
player = m_enemy;
|
||||||
|
|
||||||
// is player is alive
|
// is player is alive
|
||||||
if (m_enemyUpdateTime > game.time () && (m_enemy->v.origin - pev->origin).lengthSq () < nearestDistance && util.isAlive (player) && seesEnemy (player)) {
|
if (m_enemyUpdateTime > game.time () && m_enemy->v.origin.distanceSq (pev->origin) < nearestDistance && util.isAlive (player) && seesEnemy (player)) {
|
||||||
newEnemy = player;
|
newEnemy = player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +274,7 @@ bool Bot::lookupEnemies () {
|
||||||
if (seesEnemy (intresting)) {
|
if (seesEnemy (intresting)) {
|
||||||
// higher priority for big monsters
|
// higher priority for big monsters
|
||||||
float scaleFactor = (1.0f / calculateScaleFactor (intresting));
|
float scaleFactor = (1.0f / calculateScaleFactor (intresting));
|
||||||
float distance = (intresting->v.origin - pev->origin).lengthSq () * scaleFactor;
|
float distance = intresting->v.origin.distanceSq (pev->origin) * scaleFactor;
|
||||||
|
|
||||||
if (distance * 0.7f < nearestDistance) {
|
if (distance * 0.7f < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
|
|
@ -307,7 +307,7 @@ bool Bot::lookupEnemies () {
|
||||||
shieldEnemy = player;
|
shieldEnemy = player;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float distance = (player->v.origin - pev->origin).lengthSq ();
|
float distance = player->v.origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (distance * 0.7f < nearestDistance) {
|
if (distance * 0.7f < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
|
|
@ -482,7 +482,7 @@ const Vector &Bot::getEnemyBodyOffset () {
|
||||||
if (!m_enemyParts) {
|
if (!m_enemyParts) {
|
||||||
return m_enemyOrigin;
|
return m_enemyOrigin;
|
||||||
}
|
}
|
||||||
float distance = (m_enemy->v.origin - pev->origin).length ();
|
float distance = m_enemy->v.origin.distance (pev->origin);
|
||||||
|
|
||||||
// do not aim at head, at long distance (only if not using sniper weapon)
|
// do not aim at head, at long distance (only if not using sniper weapon)
|
||||||
if ((m_enemyParts & Visibility::Body) && !usesSniper () && distance > (m_difficulty > Difficulty::Normal ? 2000.0f : 1000.0f)) {
|
if ((m_enemyParts & Visibility::Body) && !usesSniper () && distance > (m_difficulty > Difficulty::Normal ? 2000.0f : 1000.0f)) {
|
||||||
|
|
@ -547,9 +547,9 @@ float Bot::getEnemyBodyOffsetCorrection (float distance) {
|
||||||
{ 0.0f, 0.0f, 0.0f }, // none
|
{ 0.0f, 0.0f, 0.0f }, // none
|
||||||
{ 0.0f, 0.0f, 0.0f }, // melee
|
{ 0.0f, 0.0f, 0.0f }, // melee
|
||||||
{ 2.5f, 1.5f, 0.2f }, // pistol
|
{ 2.5f, 1.5f, 0.2f }, // pistol
|
||||||
{ 6.5f, 2.0f, -9.9f }, // shotgun
|
{ 6.5f, 0.0f, -9.9f }, // shotgun
|
||||||
{ 0.5f, -3.5f, -9.0f }, // zoomrifle
|
{ 0.5f, -6.5f, -9.0f }, // zoomrifle
|
||||||
{ 0.5f, -3.5f, -9.5f }, // rifle
|
{ 0.5f, -6.5f, -9.5f }, // rifle
|
||||||
{ 2.5f, 0.5f, -4.5f }, // smg
|
{ 2.5f, 0.5f, -4.5f }, // smg
|
||||||
{ 0.5f, 0.5f, 1.5f }, // sniper
|
{ 0.5f, 0.5f, 1.5f }, // sniper
|
||||||
{ 1.5f, -2.0f, -9.0f } // heavy
|
{ 1.5f, -2.0f, -9.0f } // heavy
|
||||||
|
|
@ -597,7 +597,7 @@ bool Bot::isFriendInLineOfFire (float distance) {
|
||||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) {
|
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto friendDistance = (client.ent->v.origin - pev->origin).lengthSq ();
|
auto friendDistance = client.ent->v.origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (friendDistance <= distance && util.getShootingCone (ent (), client.ent->v.origin) > friendDistance / (friendDistance + 1089.0f)) {
|
if (friendDistance <= distance && util.getShootingCone (ent (), client.ent->v.origin) > friendDistance / (friendDistance + 1089.0f)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -632,14 +632,14 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
|
||||||
game.testLine (dest, source, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (dest, source, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
||||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||||
if ((tr.vecEndPos - dest).lengthSq () > cr::square (800.0f)) {
|
if (tr.vecEndPos.distanceSq (dest) > cr::square (800.0f)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr.vecEndPos.z >= dest.z + 200.0f) {
|
if (tr.vecEndPos.z >= dest.z + 200.0f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
obstacleDistance = (tr.vecEndPos - source).lengthSq ();
|
obstacleDistance = tr.vecEndPos.distanceSq (source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const float distance = cr::square (75.0f);
|
const float distance = cr::square (75.0f);
|
||||||
|
|
@ -690,7 +690,7 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numHits < 3 && thikness < 98) {
|
if (numHits < 3 && thikness < 98) {
|
||||||
if ((dest - point).lengthSq () < 13143.0f) {
|
if (dest.distanceSq (point) < 13143.0f) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -900,7 +900,7 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
|
||||||
void Bot::fireWeapons () {
|
void Bot::fireWeapons () {
|
||||||
// this function will return true if weapon was fired, false otherwise
|
// this function will return true if weapon was fired, false otherwise
|
||||||
|
|
||||||
float distance = (m_lookAt - getEyesPos ()).length (); // how far away is the enemy?
|
float distance = m_lookAt.distance (getEyesPos ()); // how far away is the enemy?
|
||||||
|
|
||||||
// or if friend in line of fire, stop this too but do not update shoot time
|
// or if friend in line of fire, stop this too but do not update shoot time
|
||||||
if (!game.isNullEntity (m_enemy)) {
|
if (!game.isNullEntity (m_enemy)) {
|
||||||
|
|
@ -1020,7 +1020,7 @@ void Bot::focusEnemy () {
|
||||||
if (m_enemySurpriseTime > game.time ()) {
|
if (m_enemySurpriseTime > game.time ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float distance = (m_lookAt - getEyesPos ()).length2d (); // how far away is the enemy scum?
|
float distance = m_lookAt.distance2d (getEyesPos ()); // how far away is the enemy scum?
|
||||||
|
|
||||||
if (distance < 128.0f && !usesSniper ()) {
|
if (distance < 128.0f && !usesSniper ()) {
|
||||||
if (usesKnife ()) {
|
if (usesKnife ()) {
|
||||||
|
|
@ -1065,7 +1065,7 @@ void Bot::attackMovement () {
|
||||||
if (game.isNullEntity (m_enemy)) {
|
if (game.isNullEntity (m_enemy)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float distance = (m_lookAt - getEyesPos ()).length2d (); // how far away is the enemy scum?
|
float distance = m_lookAt.distance2d (getEyesPos ()); // how far away is the enemy scum?
|
||||||
|
|
||||||
if (m_lastUsedNodesTime + getFrameInterval () + 0.5f < game.time ()) {
|
if (m_lastUsedNodesTime + getFrameInterval () + 0.5f < game.time ()) {
|
||||||
int approach;
|
int approach;
|
||||||
|
|
@ -1570,7 +1570,7 @@ bool Bot::isGroupOfEnemies (const Vector &location, int numEnemies, float radius
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((client.ent->v.origin - location).lengthSq () < cr::square (radius)) {
|
if (client.ent->v.origin.distanceSq (location) < cr::square (radius)) {
|
||||||
// don't target our teammates...
|
// don't target our teammates...
|
||||||
if (client.team == m_team) {
|
if (client.team == m_team) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1351,7 +1351,7 @@ int BotControl::menuGraphType (int item) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
graph.add (100);
|
graph.add (NodeAddFlag::Goal);
|
||||||
showMenu (Menu::NodeType);
|
showMenu (Menu::NodeType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
116
src/graph.cpp
116
src/graph.cpp
|
|
@ -386,6 +386,15 @@ int BotGraph::clearConnections (int index) {
|
||||||
return numFixedLinks;
|
return numFixedLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BotGraph::getBspSize () {
|
||||||
|
MemFile file (strings.format ("maps/%s.bsp", game.getMapName ()));
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
return static_cast <int> (file.length ());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void BotGraph::addPath (int addIndex, int pathIndex, float distance) {
|
void BotGraph::addPath (int addIndex, int pathIndex, float distance) {
|
||||||
if (!exists (addIndex) || !exists (pathIndex)) {
|
if (!exists (addIndex) || !exists (pathIndex)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -437,7 +446,7 @@ int BotGraph::getFarest (const Vector &origin, float maxDistance) {
|
||||||
maxDistance = cr::square (maxDistance);
|
maxDistance = cr::square (maxDistance);
|
||||||
|
|
||||||
for (const auto &path : m_paths) {
|
for (const auto &path : m_paths) {
|
||||||
float distance = (path.origin - origin).lengthSq ();
|
float distance = path.origin.distanceSq (origin);
|
||||||
|
|
||||||
if (distance > maxDistance) {
|
if (distance > maxDistance) {
|
||||||
index = path.number;
|
index = path.number;
|
||||||
|
|
@ -458,7 +467,7 @@ int BotGraph::getNearestNoBuckets (const Vector &origin, float minDistance, int
|
||||||
if (flags != -1 && !(path.flags & flags)) {
|
if (flags != -1 && !(path.flags & flags)) {
|
||||||
continue; // if flag not -1 and node has no this flag, skip node
|
continue; // if flag not -1 and node has no this flag, skip node
|
||||||
}
|
}
|
||||||
float distance = (path.origin - origin).lengthSq ();
|
float distance = path.origin.distanceSq (origin);
|
||||||
|
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
index = path.number;
|
index = path.number;
|
||||||
|
|
@ -491,7 +500,7 @@ int BotGraph::getNearest (const Vector &origin, float minDistance, int flags) {
|
||||||
if (flags != -1 && !(m_paths[at].flags & flags)) {
|
if (flags != -1 && !(m_paths[at].flags & flags)) {
|
||||||
continue; // if flag not -1 and node has no this flag, skip node
|
continue; // if flag not -1 and node has no this flag, skip node
|
||||||
}
|
}
|
||||||
float distance = (m_paths[at].origin - origin).lengthSq ();
|
float distance = origin.distanceSq (m_paths[at].origin);
|
||||||
|
|
||||||
if (distance < minDistanceSq) {
|
if (distance < minDistanceSq) {
|
||||||
index = at;
|
index = at;
|
||||||
|
|
@ -523,7 +532,7 @@ IntArray BotGraph::searchRadius (float radius, const Vector &origin, int maxCoun
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_paths[at].origin - origin).lengthSq () < radius) {
|
if (origin.distanceSq (m_paths[at].origin) < radius) {
|
||||||
result.push (at);
|
result.push (at);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -548,7 +557,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
m_hasChanged = true;
|
m_hasChanged = true;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 5:
|
case NodeAddFlag::Camp:
|
||||||
index = getEditorNeareset ();
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
if (index != kInvalidNodeIndex) {
|
if (index != kInvalidNodeIndex) {
|
||||||
|
|
@ -564,7 +573,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case NodeAddFlag::CampEnd:
|
||||||
index = getEditorNeareset ();
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
if (index != kInvalidNodeIndex) {
|
if (index != kInvalidNodeIndex) {
|
||||||
|
|
@ -581,11 +590,11 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 9:
|
case NodeAddFlag::JumpStart:
|
||||||
index = getEditorNeareset ();
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
if (index != kInvalidNodeIndex && m_paths[index].number >= 0) {
|
if (index != kInvalidNodeIndex && m_paths[index].number >= 0) {
|
||||||
float distance = (m_paths[index].origin - m_editor->v.origin).length ();
|
float distance = m_editor->v.origin.distance (m_paths[index].origin);
|
||||||
|
|
||||||
if (distance < 50.0f) {
|
if (distance < 50.0f) {
|
||||||
addNewNode = false;
|
addNewNode = false;
|
||||||
|
|
@ -599,11 +608,11 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case NodeAddFlag::JumpEnd:
|
||||||
index = getEditorNeareset ();
|
index = getEditorNeareset ();
|
||||||
|
|
||||||
if (index != kInvalidNodeIndex && m_paths[index].number >= 0) {
|
if (index != kInvalidNodeIndex && m_paths[index].number >= 0) {
|
||||||
float distance = (m_paths[index].origin - m_editor->v.origin).length ();
|
float distance = m_editor->v.origin.distance (m_paths[index].origin);
|
||||||
|
|
||||||
if (distance < 50.0f) {
|
if (distance < 50.0f) {
|
||||||
addNewNode = false;
|
addNewNode = false;
|
||||||
|
|
@ -627,7 +636,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
auto nearest = getEditorNeareset ();
|
auto nearest = getEditorNeareset ();
|
||||||
|
|
||||||
// do not allow to place waypoints "inside" waypoints, make at leat 10 units range
|
// do not allow to place waypoints "inside" waypoints, make at leat 10 units range
|
||||||
if (exists (nearest) && (m_paths[nearest].origin - newOrigin).lengthSq () < cr::square (10.0f)) {
|
if (exists (nearest) && newOrigin.distanceSq (m_paths[nearest].origin) < cr::square (10.0f)) {
|
||||||
ctrl.msg ("Can't add node. It's way to near to %d node. Please move some units anywhere.", nearest);
|
ctrl.msg ("Can't add node. It's way to near to %d node. Please move some units anywhere.", nearest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -666,11 +675,11 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
m_lastNode = m_editor->v.origin;
|
m_lastNode = m_editor->v.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 9) {
|
if (type == NodeAddFlag::JumpStart) {
|
||||||
m_lastJumpNode = index;
|
m_lastJumpNode = index;
|
||||||
}
|
}
|
||||||
else if (type == 10) {
|
else if (type == NodeAddFlag::JumpEnd) {
|
||||||
float distance = (m_paths[m_lastJumpNode].origin - m_editor->v.origin).length ();
|
float distance = m_paths[m_lastJumpNode].origin.distance (m_editor->v.origin);
|
||||||
addPath (m_lastJumpNode, index, distance);
|
addPath (m_lastJumpNode, index, distance);
|
||||||
|
|
||||||
for (auto &link : m_paths[m_lastJumpNode].links) {
|
for (auto &link : m_paths[m_lastJumpNode].links) {
|
||||||
|
|
@ -701,32 +710,32 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1:
|
case NodeAddFlag::TOnly:
|
||||||
path->flags |= NodeFlag::Crossing;
|
path->flags |= NodeFlag::Crossing;
|
||||||
path->flags |= NodeFlag::TerroristOnly;
|
path->flags |= NodeFlag::TerroristOnly;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case NodeAddFlag::CTOnly:
|
||||||
path->flags |= NodeFlag::Crossing;
|
path->flags |= NodeFlag::Crossing;
|
||||||
path->flags |= NodeFlag::CTOnly;
|
path->flags |= NodeFlag::CTOnly;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case NodeAddFlag::NoHostage:
|
||||||
path->flags |= NodeFlag::NoHostage;
|
path->flags |= NodeFlag::NoHostage;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case NodeAddFlag::Rescue:
|
||||||
path->flags |= NodeFlag::Rescue;
|
path->flags |= NodeFlag::Rescue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case NodeAddFlag::Camp:
|
||||||
path->flags |= NodeFlag::Crossing;
|
path->flags |= NodeFlag::Crossing;
|
||||||
path->flags |= NodeFlag::Camp;
|
path->flags |= NodeFlag::Camp;
|
||||||
|
|
||||||
path->start = m_editor->v.v_angle;
|
path->start = m_editor->v.v_angle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 100:
|
case NodeAddFlag::Goal:
|
||||||
path->flags |= NodeFlag::Goal;
|
path->flags |= NodeFlag::Goal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -750,7 +759,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
game.testLine (newOrigin, calc.origin, TraceIgnore::Monsters, m_editor, &tr);
|
game.testLine (newOrigin, calc.origin, TraceIgnore::Monsters, m_editor, &tr);
|
||||||
|
|
||||||
if (cr::fequal (tr.flFraction, 1.0f) && cr::abs (newOrigin.x - calc.origin.x) < 64.0f && cr::abs (newOrigin.y - calc.origin.y) < 64.0f && cr::abs (newOrigin.z - calc.origin.z) < m_autoPathDistance) {
|
if (cr::fequal (tr.flFraction, 1.0f) && cr::abs (newOrigin.x - calc.origin.x) < 64.0f && cr::abs (newOrigin.y - calc.origin.y) < 64.0f && cr::abs (newOrigin.z - calc.origin.z) < m_autoPathDistance) {
|
||||||
float distance = (calc.origin - newOrigin).length ();
|
float distance = newOrigin.distance (calc.origin);
|
||||||
|
|
||||||
addPath (index, calc.number, distance);
|
addPath (index, calc.number, distance);
|
||||||
addPath (calc.number, index, distance);
|
addPath (calc.number, index, distance);
|
||||||
|
|
@ -759,7 +768,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
else {
|
else {
|
||||||
// check if the node is reachable from the new one
|
// check if the node is reachable from the new one
|
||||||
if (isNodeReacheable (newOrigin, calc.origin) || isNodeReacheable (calc.origin, newOrigin)) {
|
if (isNodeReacheable (newOrigin, calc.origin) || isNodeReacheable (calc.origin, newOrigin)) {
|
||||||
float distance = (calc.origin - newOrigin).length ();
|
float distance = newOrigin.distance (calc.origin);
|
||||||
|
|
||||||
if (distance < minDistance) {
|
if (distance < minDistance) {
|
||||||
destIndex = calc.number;
|
destIndex = calc.number;
|
||||||
|
|
@ -772,12 +781,12 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
if (exists (destIndex)) {
|
if (exists (destIndex)) {
|
||||||
// check if the node is reachable from the new one (one-way)
|
// check if the node is reachable from the new one (one-way)
|
||||||
if (isNodeReacheable (newOrigin, m_paths[destIndex].origin)) {
|
if (isNodeReacheable (newOrigin, m_paths[destIndex].origin)) {
|
||||||
addPath (index, destIndex, (m_paths[destIndex].origin - newOrigin).length ());
|
addPath (index, destIndex, newOrigin.distance (m_paths[destIndex].origin));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the new one is reachable from the node (other way)
|
// check if the new one is reachable from the node (other way)
|
||||||
if (isNodeReacheable (m_paths[destIndex].origin, newOrigin)) {
|
if (isNodeReacheable (m_paths[destIndex].origin, newOrigin)) {
|
||||||
addPath (destIndex, index, (m_paths[destIndex].origin - newOrigin).length ());
|
addPath (destIndex, index, newOrigin.distance (m_paths[destIndex].origin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -790,12 +799,12 @@ void BotGraph::add (int type, const Vector &pos) {
|
||||||
|
|
||||||
// check if the node is reachable from the new one (one-way)
|
// check if the node is reachable from the new one (one-way)
|
||||||
if (isNodeReacheable (newOrigin, calc.origin)) {
|
if (isNodeReacheable (newOrigin, calc.origin)) {
|
||||||
addPath (index, calc.number, (calc.origin - newOrigin).length ());
|
addPath (index, calc.number, calc.origin.distance (newOrigin));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the new one is reachable from the node (other way)
|
// check if the new one is reachable from the node (other way)
|
||||||
if (isNodeReacheable (calc.origin, newOrigin)) {
|
if (isNodeReacheable (calc.origin, newOrigin)) {
|
||||||
addPath (calc.number, index, (calc.origin - newOrigin).length ());
|
addPath (calc.number, index, calc.origin.distance (newOrigin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearConnections (index);
|
clearConnections (index);
|
||||||
|
|
@ -975,7 +984,7 @@ void BotGraph::pathCreate (char dir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance = (m_paths[nodeTo].origin - m_paths[nodeFrom].origin).length ();
|
float distance = m_paths[nodeFrom].origin.distance (m_paths[nodeTo].origin);
|
||||||
|
|
||||||
if (dir == PathConnection::Outgoing) {
|
if (dir == PathConnection::Outgoing) {
|
||||||
addPath (nodeFrom, nodeTo, distance);
|
addPath (nodeFrom, nodeTo, distance);
|
||||||
|
|
@ -1787,7 +1796,7 @@ bool BotGraph::loadGraphData () {
|
||||||
loadPractice ();
|
loadPractice ();
|
||||||
|
|
||||||
if (exten.mapSize > 0) {
|
if (exten.mapSize > 0) {
|
||||||
int mapSize = engfuncs.pfnGetFileSize (strings.format ("maps/%s.bsp", game.getMapName ()));
|
int mapSize = getBspSize ();
|
||||||
|
|
||||||
if (mapSize != exten.mapSize) {
|
if (mapSize != exten.mapSize) {
|
||||||
ctrl.msg ("Warning: Graph data is probably not for this map. Please check bots behaviour.");
|
ctrl.msg ("Warning: Graph data is probably not for this map. Please check bots behaviour.");
|
||||||
|
|
@ -1829,7 +1838,7 @@ bool BotGraph::saveGraphData () {
|
||||||
|
|
||||||
ExtenHeader exten {};
|
ExtenHeader exten {};
|
||||||
strings.copy (exten.author, author.chars (), cr::bufsize (exten.author));
|
strings.copy (exten.author, author.chars (), cr::bufsize (exten.author));
|
||||||
exten.mapSize = engfuncs.pfnGetFileSize (strings.format ("maps/%s.bsp", game.getMapName ()));
|
exten.mapSize = getBspSize ();
|
||||||
|
|
||||||
// ensure narrow places saved into file
|
// ensure narrow places saved into file
|
||||||
m_narrowChecked = false;
|
m_narrowChecked = false;
|
||||||
|
|
@ -1883,13 +1892,13 @@ const char *BotGraph::getOldFormatGraphName (bool isMemoryFile) {
|
||||||
float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) {
|
float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) {
|
||||||
// this function returns 2D traveltime to a position
|
// this function returns 2D traveltime to a position
|
||||||
|
|
||||||
return (origin - src).length2d () / maxSpeed;
|
return origin.distance2d (src) / maxSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
||||||
TraceResult tr {};
|
TraceResult tr {};
|
||||||
|
|
||||||
float distance = (destination - src).length ();
|
float distance = destination.distance (src);
|
||||||
|
|
||||||
// is the destination not close enough?
|
// is the destination not close enough?
|
||||||
if (distance > m_autoPathDistance) {
|
if (distance > m_autoPathDistance) {
|
||||||
|
|
@ -1945,7 +1954,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
||||||
game.testLine (check, down, TraceIgnore::Monsters, m_editor, &tr);
|
game.testLine (check, down, TraceIgnore::Monsters, m_editor, &tr);
|
||||||
|
|
||||||
float lastHeight = tr.flFraction * 1000.0f; // height from ground
|
float lastHeight = tr.flFraction * 1000.0f; // height from ground
|
||||||
distance = (destination - check).length (); // distance from goal
|
distance = destination.distance (check); // distance from goal
|
||||||
|
|
||||||
while (distance > 10.0f) {
|
while (distance > 10.0f) {
|
||||||
// move 10 units closer to the goal...
|
// move 10 units closer to the goal...
|
||||||
|
|
@ -1963,7 +1972,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
||||||
return false; // can't get there without jumping...
|
return false; // can't get there without jumping...
|
||||||
}
|
}
|
||||||
lastHeight = height;
|
lastHeight = height;
|
||||||
distance = (destination - check).length (); // distance from goal
|
distance = destination.distance (check); // distance from goal
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2115,7 +2124,7 @@ void BotGraph::frame () {
|
||||||
if (m_jumpLearnNode) {
|
if (m_jumpLearnNode) {
|
||||||
if (!m_endJumpPoint) {
|
if (!m_endJumpPoint) {
|
||||||
if (m_editor->v.button & IN_JUMP) {
|
if (m_editor->v.button & IN_JUMP) {
|
||||||
add (9);
|
add (NodeAddFlag::JumpStart);
|
||||||
|
|
||||||
m_timeJumpStarted = game.time ();
|
m_timeJumpStarted = game.time ();
|
||||||
m_endJumpPoint = true;
|
m_endJumpPoint = true;
|
||||||
|
|
@ -2126,7 +2135,7 @@ void BotGraph::frame () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((m_editor->v.flags & FL_ONGROUND) || m_editor->v.movetype == MOVETYPE_FLY) && m_timeJumpStarted + 0.1f < game.time () && m_endJumpPoint) {
|
else if (((m_editor->v.flags & FL_ONGROUND) || m_editor->v.movetype == MOVETYPE_FLY) && m_timeJumpStarted + 0.1f < game.time () && m_endJumpPoint) {
|
||||||
add (10);
|
add (NodeAddFlag::JumpEnd);
|
||||||
|
|
||||||
m_jumpLearnNode = false;
|
m_jumpLearnNode = false;
|
||||||
m_endJumpPoint = false;
|
m_endJumpPoint = false;
|
||||||
|
|
@ -2136,13 +2145,13 @@ void BotGraph::frame () {
|
||||||
// check if it's a auto-add-node mode enabled
|
// check if it's a auto-add-node mode enabled
|
||||||
if (hasEditFlag (GraphEdit::Auto) && (m_editor->v.flags & (FL_ONGROUND | FL_PARTIALGROUND))) {
|
if (hasEditFlag (GraphEdit::Auto) && (m_editor->v.flags & (FL_ONGROUND | FL_PARTIALGROUND))) {
|
||||||
// find the distance from the last used node
|
// find the distance from the last used node
|
||||||
float distance = (m_lastNode - m_editor->v.origin).lengthSq ();
|
float distance = m_lastNode.distanceSq (m_editor->v.origin);
|
||||||
|
|
||||||
if (distance > cr::square (128.0f)) {
|
if (distance > cr::square (128.0f)) {
|
||||||
// check that no other reachable nodes are nearby...
|
// check that no other reachable nodes are nearby...
|
||||||
for (const auto &path : m_paths) {
|
for (const auto &path : m_paths) {
|
||||||
if (isNodeReacheable (m_editor->v.origin, path.origin)) {
|
if (isNodeReacheable (m_editor->v.origin, path.origin)) {
|
||||||
distance = (path.origin - m_editor->v.origin).lengthSq ();
|
distance = path.origin.distanceSq (m_editor->v.origin);
|
||||||
|
|
||||||
if (distance < nearestDistance) {
|
if (distance < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
|
|
@ -2152,7 +2161,7 @@ void BotGraph::frame () {
|
||||||
|
|
||||||
// make sure nearest node is far enough away...
|
// make sure nearest node is far enough away...
|
||||||
if (nearestDistance >= cr::square (128.0f)) {
|
if (nearestDistance >= cr::square (128.0f)) {
|
||||||
add (GraphAdd::Normal); // place a node here
|
add (NodeAddFlag::Normal); // place a node here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2163,7 +2172,7 @@ void BotGraph::frame () {
|
||||||
|
|
||||||
// now iterate through all nodes in a map, and draw required ones
|
// now iterate through all nodes in a map, and draw required ones
|
||||||
for (auto &path : m_paths) {
|
for (auto &path : m_paths) {
|
||||||
float distance = (path.origin - m_editor->v.origin).length ();
|
float distance = path.origin.distance (m_editor->v.origin);
|
||||||
|
|
||||||
// check if node is whitin a distance, and is visible
|
// check if node is whitin a distance, and is visible
|
||||||
if (distance < 512.0f && ((util.isVisible (path.origin, m_editor) && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distance < 128.0f)) {
|
if (distance < 512.0f && ((util.isVisible (path.origin, m_editor) && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distance < 128.0f)) {
|
||||||
|
|
@ -2705,7 +2714,7 @@ void BotGraph::addBasic () {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (getNearestNoBuckets (point, 50.0f) == kInvalidNodeIndex) {
|
if (getNearestNoBuckets (point, 50.0f) == kInvalidNodeIndex) {
|
||||||
add (3, point);
|
add (NodeAddFlag::NoHostage, point);
|
||||||
}
|
}
|
||||||
point.z += 160;
|
point.z += 160;
|
||||||
} while (point.z < down.z - 40.0f);
|
} while (point.z < down.z - 40.0f);
|
||||||
|
|
@ -2713,7 +2722,7 @@ void BotGraph::addBasic () {
|
||||||
point = down + Vector (0.0f, 0.0f, 38.0f);
|
point = down + Vector (0.0f, 0.0f, 38.0f);
|
||||||
|
|
||||||
if (getNearestNoBuckets (point, 50.0f) == kInvalidNodeIndex) {
|
if (getNearestNoBuckets (point, 50.0f) == kInvalidNodeIndex) {
|
||||||
add (3, point);
|
add (NodeAddFlag::NoHostage, point);
|
||||||
}
|
}
|
||||||
m_isOnLadder = false;
|
m_isOnLadder = false;
|
||||||
|
|
||||||
|
|
@ -2731,31 +2740,30 @@ void BotGraph::addBasic () {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
autoCreateForEntity (0, "info_player_deathmatch"); // then terrortist spawnpoints
|
autoCreateForEntity (NodeAddFlag::Normal, "info_player_deathmatch"); // then terrortist spawnpoints
|
||||||
autoCreateForEntity (0, "info_player_start"); // then add ct spawnpoints
|
autoCreateForEntity (NodeAddFlag::Normal, "info_player_start"); // then add ct spawnpoints
|
||||||
autoCreateForEntity (0, "info_vip_start"); // then vip spawnpoint
|
autoCreateForEntity (NodeAddFlag::Normal, "info_vip_start"); // then vip spawnpoint
|
||||||
autoCreateForEntity (0, "armoury_entity"); // weapons on the map ?
|
autoCreateForEntity (NodeAddFlag::Normal, "armoury_entity"); // weapons on the map ?
|
||||||
|
|
||||||
autoCreateForEntity (4, "func_hostage_rescue"); // hostage rescue zone
|
autoCreateForEntity (NodeAddFlag::Rescue, "func_hostage_rescue"); // hostage rescue zone
|
||||||
autoCreateForEntity (4, "info_hostage_rescue"); // hostage rescue zone (same as above)
|
autoCreateForEntity (NodeAddFlag::Rescue, "info_hostage_rescue"); // hostage rescue zone (same as above)
|
||||||
|
|
||||||
autoCreateForEntity (100, "func_bomb_target"); // bombspot zone
|
autoCreateForEntity (NodeAddFlag::Goal, "func_bomb_target"); // bombspot zone
|
||||||
autoCreateForEntity (100, "info_bomb_target"); // bombspot zone (same as above)
|
autoCreateForEntity (NodeAddFlag::Goal, "info_bomb_target"); // bombspot zone (same as above)
|
||||||
autoCreateForEntity (100, "hostage_entity"); // hostage entities
|
autoCreateForEntity (NodeAddFlag::Goal, "hostage_entity"); // hostage entities
|
||||||
autoCreateForEntity (100, "func_vip_safetyzone"); // vip rescue (safety) zone
|
autoCreateForEntity (NodeAddFlag::Goal, "func_vip_safetyzone"); // vip rescue (safety) zone
|
||||||
autoCreateForEntity (100, "func_escapezone"); // terrorist escape zone
|
autoCreateForEntity (NodeAddFlag::Goal, "func_escapezone"); // terrorist escape zone
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::eraseFromDisk () {
|
void BotGraph::eraseFromDisk () {
|
||||||
// this function removes graph file from the hard disk
|
// this function removes graph file from the hard disk
|
||||||
|
|
||||||
StringArray forErase;
|
StringArray forErase;
|
||||||
|
bots.kickEveryone (true);
|
||||||
|
|
||||||
auto map = game.getMapName ();
|
auto map = game.getMapName ();
|
||||||
auto data = getDataDirectory ();
|
auto data = getDataDirectory ();
|
||||||
|
|
||||||
bots.kickEveryone (true);
|
|
||||||
|
|
||||||
// if we're delete graph, delete all corresponding to it files
|
// if we're delete graph, delete all corresponding to it files
|
||||||
forErase.push (strings.format ("%spwf/%s.pwf", data, map)); // graph itself
|
forErase.push (strings.format ("%spwf/%s.pwf", data, map)); // graph itself
|
||||||
forErase.push (strings.format ("%strain/%s.prc", data, map)); // corresponding to practice
|
forErase.push (strings.format ("%strain/%s.prc", data, map)); // corresponding to practice
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ ConVar cv_autovacate ("yb_autovacate", "1", "Kick bots to automatically make roo
|
||||||
ConVar cv_quota ("yb_quota", "9", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
ConVar cv_quota ("yb_quota", "9", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||||
ConVar cv_quota_mode ("yb_quota_mode", "normal", "Specifies the type of quota.\nAllowed values: 'normal', 'fill', and 'match'.\nIf 'fill', the server will adjust bots to keep N players in the game, where N is yb_quota.\nIf 'match', the server will maintain a 1:N ratio of humans to bots, where N is yb_quota_match.", false);
|
ConVar cv_quota_mode ("yb_quota_mode", "normal", "Specifies the type of quota.\nAllowed values: 'normal', 'fill', and 'match'.\nIf 'fill', the server will adjust bots to keep N players in the game, where N is yb_quota.\nIf 'match', the server will maintain a 1:N ratio of humans to bots, where N is yb_quota_match.", false);
|
||||||
ConVar cv_quota_match ("yb_quota_match", "0", "Number of players to match if yb_quota_mode set to 'match'", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
ConVar cv_quota_match ("yb_quota_match", "0", "Number of players to match if yb_quota_mode set to 'match'", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||||
ConVar cv_think_fps ("yb_think_fps", "30.0", "Specifies how many times per second bot code will run.", true, 30.0f, 90.0f);
|
ConVar cv_think_fps ("yb_think_fps", "26.0", "Specifies how many times per second bot code will run.", true, 24.0f, 90.0f);
|
||||||
ConVar cv_autokill_delay ("yb_autokill_delay", "0.0", "Specifies amount of time in seconds when bots will be killed if no humans left alive.", true, 0.0f, 90.0f);
|
ConVar cv_autokill_delay ("yb_autokill_delay", "0.0", "Specifies amount of time in seconds when bots will be killed if no humans left alive.", true, 0.0f, 90.0f);
|
||||||
|
|
||||||
ConVar cv_join_after_player ("yb_join_after_player", "0", "Specifies whether bots should join server, only when at least one human player in game.");
|
ConVar cv_join_after_player ("yb_join_after_player", "0", "Specifies whether bots should join server, only when at least one human player in game.");
|
||||||
|
|
|
||||||
109
src/navigate.cpp
109
src/navigate.cpp
|
|
@ -8,7 +8,10 @@
|
||||||
#include <yapb.h>
|
#include <yapb.h>
|
||||||
|
|
||||||
ConVar cv_whose_your_daddy ("yb_whose_your_daddy", "0", "Enables or disables extra hard difficulty for bots.");
|
ConVar cv_whose_your_daddy ("yb_whose_your_daddy", "0", "Enables or disables extra hard difficulty for bots.");
|
||||||
ConVar cv_debug_heuristic_type ("yb_debug_heuristic_type", "0", "Selects the heuristic function mode. For debug purposes only.", true, 0.0f, 4.0f);
|
ConVar cv_path_heuristic_mode ("yb_path_heuristic_mode", "4", "Selects the heuristic function mode. For debug purposes only.", true, 0.0f, 4.0f);
|
||||||
|
|
||||||
|
ConVar cv_path_danger_factor_min ("yb_path_danger_factor_min", "200", "Lower bound of danger factor that used to add additional danger to path based on practice.", true, 100.0f, 2400.0f);
|
||||||
|
ConVar cv_path_danger_factor_max ("yb_path_danger_factor_max", "400", "Upper bound of danger factor that used to add additional danger to path based on practice.", true, 200.0f, 4800.0f);
|
||||||
|
|
||||||
int Bot::findBestGoal () {
|
int Bot::findBestGoal () {
|
||||||
|
|
||||||
|
|
@ -180,7 +183,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (auto &point : graph.m_goalPoints) {
|
for (auto &point : graph.m_goalPoints) {
|
||||||
float distance = (graph[point].origin - pev->origin).lengthSq ();
|
float distance = graph[point].origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (distance > cr::square (1024.0f)) {
|
if (distance > cr::square (1024.0f)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -295,6 +298,10 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
edict_t *hindrance = nullptr;
|
edict_t *hindrance = nullptr;
|
||||||
float distance = cr::square (300.0f);
|
float distance = cr::square (300.0f);
|
||||||
|
|
||||||
|
if (getCurrentTaskId () == Task::Attack || getCurrentTaskId () == Task::SeekCover || isOnLadder ()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// find nearest player to bot
|
// find nearest player to bot
|
||||||
for (const auto &client : util.getClients ()) {
|
for (const auto &client : util.getClients ()) {
|
||||||
|
|
||||||
|
|
@ -312,7 +319,7 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
if (client.team != m_team || client.ent == ent ()) {
|
if (client.team != m_team || client.ent == ent ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto nearest = (client.ent->v.origin - pev->origin).lengthSq ();
|
auto nearest = client.ent->v.origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (nearest < cr::square (pev->maxspeed) && nearest < distance) {
|
if (nearest < cr::square (pev->maxspeed) && nearest < distance) {
|
||||||
hindrance = client.ent;
|
hindrance = client.ent;
|
||||||
|
|
@ -324,7 +331,7 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
if (!hindrance) {
|
if (!hindrance) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const float interval = getFrameInterval ();
|
const float interval = getFrameInterval () * 4.0f;
|
||||||
|
|
||||||
// use our movement angles, try to predict where we should be next frame
|
// use our movement angles, try to predict where we should be next frame
|
||||||
Vector right, forward;
|
Vector right, forward;
|
||||||
|
|
@ -335,8 +342,8 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
predict += right * m_strafeSpeed * interval;
|
predict += right * m_strafeSpeed * interval;
|
||||||
predict += pev->velocity * interval;
|
predict += pev->velocity * interval;
|
||||||
|
|
||||||
auto movedDistance = (hindrance->v.origin - predict).lengthSq ();
|
auto movedDistance = hindrance->v.origin.distanceSq (predict);
|
||||||
auto nextFrameDistance = ((hindrance->v.origin + hindrance->v.velocity * interval) - pev->origin).lengthSq ();
|
auto nextFrameDistance = pev->origin.distanceSq (hindrance->v.origin + hindrance->v.velocity * interval);
|
||||||
|
|
||||||
// is player that near now or in future that we need to steer away?
|
// is player that near now or in future that we need to steer away?
|
||||||
if (movedDistance <= cr::square (48.0f) || (distance <= cr::square (56.0f) && nextFrameDistance < distance)) {
|
if (movedDistance <= cr::square (48.0f) || (distance <= cr::square (56.0f) && nextFrameDistance < distance)) {
|
||||||
|
|
@ -349,13 +356,11 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
||||||
else {
|
else {
|
||||||
setStrafeSpeed (normal, -pev->maxspeed);
|
setStrafeSpeed (normal, -pev->maxspeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (distance < cr::square (56.0f)) {
|
if (distance < cr::square (56.0f)) {
|
||||||
if ((dir | forward.get2d ()) < 0.0f)
|
if ((dir | forward.get2d ()) < 0.0f) {
|
||||||
m_moveSpeed = -pev->maxspeed;
|
m_moveSpeed = -pev->maxspeed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -365,9 +370,12 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||||
|
|
||||||
// if avoiding someone do not consider stuck
|
// if avoiding someone do not consider stuck
|
||||||
TraceResult tr {};
|
TraceResult tr {};
|
||||||
doPlayerAvoidance (dirNormal);
|
m_isStuck = doPlayerAvoidance (dirNormal);
|
||||||
|
|
||||||
m_isStuck = false;
|
if (m_isStuck) {
|
||||||
|
resetCollision ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Standing still, no need to check?
|
// Standing still, no need to check?
|
||||||
// FIXME: doesn't care for ladder movement (handled separately) should be included in some way
|
// FIXME: doesn't care for ladder movement (handled separately) should be included in some way
|
||||||
|
|
@ -655,7 +663,7 @@ bool Bot::updateNavigation () {
|
||||||
}
|
}
|
||||||
m_destOrigin = m_pathOrigin + pev->view_ofs;
|
m_destOrigin = m_pathOrigin + pev->view_ofs;
|
||||||
|
|
||||||
float nodeDistance = (pev->origin - m_pathOrigin).length ();
|
float nodeDistance = pev->origin.distance (m_pathOrigin);
|
||||||
|
|
||||||
// this node has additional travel flags - care about them
|
// this node has additional travel flags - care about them
|
||||||
if (m_currentTravelFlags & PathFlag::Jump) {
|
if (m_currentTravelFlags & PathFlag::Jump) {
|
||||||
|
|
@ -714,7 +722,7 @@ bool Bot::updateNavigation () {
|
||||||
|
|
||||||
if (!game.isNullEntity (tr.pHit) && game.isNullEntity (m_liftEntity) && strncmp (tr.pHit->v.classname.chars (), "func_door", 9) == 0) {
|
if (!game.isNullEntity (tr.pHit) && game.isNullEntity (m_liftEntity) && strncmp (tr.pHit->v.classname.chars (), "func_door", 9) == 0) {
|
||||||
// if the door is near enough...
|
// if the door is near enough...
|
||||||
if ((game.getEntityOrigin (tr.pHit) - pev->origin).lengthSq () < 2500.0f) {
|
if (pev->origin.distanceSq (game.getEntityOrigin (tr.pHit)) < 2500.0f) {
|
||||||
ignoreCollision (); // don't consider being stuck
|
ignoreCollision (); // don't consider being stuck
|
||||||
|
|
||||||
if (rg.chance (50)) {
|
if (rg.chance (50)) {
|
||||||
|
|
@ -795,7 +803,7 @@ bool Bot::updateNavigation () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// needs precise placement - check if we get past the point
|
// needs precise placement - check if we get past the point
|
||||||
if (desiredDistance < 22.0f && nodeDistance < 30.0f && (pev->origin + (pev->velocity * getFrameInterval ()) - m_pathOrigin).lengthSq () >= cr::square (nodeDistance)) {
|
if (desiredDistance < 22.0f && nodeDistance < 30.0f && m_pathOrigin.distanceSq (pev->origin + pev->velocity * getFrameInterval ()) >= cr::square (nodeDistance)) {
|
||||||
desiredDistance = nodeDistance + 1.0f;
|
desiredDistance = nodeDistance + 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -837,7 +845,7 @@ bool Bot::updateNavigation () {
|
||||||
|
|
||||||
// bot within 'hearable' bomb tick noises?
|
// bot within 'hearable' bomb tick noises?
|
||||||
if (!bombOrigin.empty ()) {
|
if (!bombOrigin.empty ()) {
|
||||||
float distance = (bombOrigin - graph[taskTarget].origin).length ();
|
float distance = bombOrigin.distance (graph[taskTarget].origin);
|
||||||
|
|
||||||
if (distance > 512.0f) {
|
if (distance > 512.0f) {
|
||||||
if (rg.chance (50) && !graph.isVisited (taskTarget)) {
|
if (rg.chance (50) && !graph.isVisited (taskTarget)) {
|
||||||
|
|
@ -930,7 +938,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_destOrigin = m_liftTravelPos;
|
m_destOrigin = m_liftTravelPos;
|
||||||
|
|
||||||
// check if we enough to destination
|
// check if we enough to destination
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
|
|
||||||
// need to wait our following teammate ?
|
// need to wait our following teammate ?
|
||||||
|
|
@ -984,7 +992,7 @@ bool Bot::updateLiftHandling () {
|
||||||
if (needWaitForTeammate) {
|
if (needWaitForTeammate) {
|
||||||
m_destOrigin = m_liftTravelPos;
|
m_destOrigin = m_liftTravelPos;
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1015,7 +1023,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_liftState = LiftState::TravelingBy;
|
m_liftState = LiftState::TravelingBy;
|
||||||
m_liftUsageTime = game.time () + 14.0f;
|
m_liftUsageTime = game.time () + 14.0f;
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1025,7 +1033,7 @@ bool Bot::updateLiftHandling () {
|
||||||
if (m_liftState == LiftState::TravelingBy) {
|
if (m_liftState == LiftState::TravelingBy) {
|
||||||
m_destOrigin = Vector (m_liftTravelPos.x, m_liftTravelPos.y, pev->origin.z);
|
m_destOrigin = Vector (m_liftTravelPos.x, m_liftTravelPos.y, pev->origin.z);
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1042,7 +1050,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_destOrigin = pev->origin;
|
m_destOrigin = pev->origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1075,7 +1083,7 @@ bool Bot::updateLiftHandling () {
|
||||||
m_destOrigin = button->v.origin;
|
m_destOrigin = button->v.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1106,7 +1114,7 @@ bool Bot::updateLiftHandling () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pev->origin - m_destOrigin).lengthSq () < cr::square (20.0f)) {
|
if (pev->origin.distanceSq (m_destOrigin) < cr::square (20.0f)) {
|
||||||
wait ();
|
wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1204,8 +1212,12 @@ void Bot::findShortestPath (int srcIndex, int destIndex) {
|
||||||
void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath::Fast */) {
|
void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath::Fast */) {
|
||||||
// this function finds a path from srcIndex to destIndex
|
// this function finds a path from srcIndex to destIndex
|
||||||
|
|
||||||
|
auto dangerFactor = [&] () -> float {
|
||||||
|
return rg.get (cv_path_danger_factor_min.float_ (), cv_path_danger_factor_max.float_ ()) * 2.0f / cr::clamp (m_difficulty, 1, 3);
|
||||||
|
};
|
||||||
|
|
||||||
// least kills and number of nodes to goal for a team
|
// least kills and number of nodes to goal for a team
|
||||||
auto gfunctionKillsDist = [] (int team, int currentIndex, int parentIndex) -> float {
|
auto gfunctionKillsDist = [&dangerFactor] (int team, int currentIndex, int parentIndex) -> float {
|
||||||
if (parentIndex == kInvalidNodeIndex) {
|
if (parentIndex == kInvalidNodeIndex) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
@ -1221,7 +1233,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
if (current.flags & NodeFlag::Crouch) {
|
if (current.flags & NodeFlag::Crouch) {
|
||||||
cost *= 1.5f;
|
cost *= 1.5f;
|
||||||
}
|
}
|
||||||
return cost;
|
return cost + dangerFactor ();
|
||||||
};
|
};
|
||||||
|
|
||||||
// least kills and number of nodes to goal for a team
|
// least kills and number of nodes to goal for a team
|
||||||
|
|
@ -1238,7 +1250,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
};
|
};
|
||||||
|
|
||||||
// least kills to goal for a team
|
// least kills to goal for a team
|
||||||
auto gfunctionKills = [] (int team, int currentIndex, int) -> float {
|
auto gfunctionKills = [&dangerFactor] (int team, int currentIndex, int) -> float {
|
||||||
auto cost = static_cast <float> (graph.getDangerDamage (team, currentIndex, currentIndex));
|
auto cost = static_cast <float> (graph.getDangerDamage (team, currentIndex, currentIndex));
|
||||||
const auto ¤t = graph[currentIndex];
|
const auto ¤t = graph[currentIndex];
|
||||||
|
|
||||||
|
|
@ -1251,7 +1263,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
if (current.flags & NodeFlag::Crouch) {
|
if (current.flags & NodeFlag::Crouch) {
|
||||||
cost *= 1.5f;
|
cost *= 1.5f;
|
||||||
}
|
}
|
||||||
return cost + 0.5f;
|
return cost + dangerFactor () + 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
// least kills to goal for a team
|
// least kills to goal for a team
|
||||||
|
|
@ -1310,7 +1322,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
float y = cr::abs (start.origin.y - goal.origin.y);
|
float y = cr::abs (start.origin.y - goal.origin.y);
|
||||||
float z = cr::abs (start.origin.z - goal.origin.z);
|
float z = cr::abs (start.origin.z - goal.origin.z);
|
||||||
|
|
||||||
switch (cv_debug_heuristic_type.int_ ()) {
|
switch (cv_path_heuristic_mode.int_ ()) {
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
return cr::max (cr::max (x, y), z); // chebyshev distance
|
return cr::max (cr::max (x, y), z); // chebyshev distance
|
||||||
|
|
@ -1326,7 +1338,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
// euclidean based distance
|
// euclidean based distance
|
||||||
float euclidean = cr::powf (cr::powf (x, 2.0f) + cr::powf (y, 2.0f) + cr::powf (z, 2.0f), 0.5f);
|
float euclidean = cr::powf (cr::powf (x, 2.0f) + cr::powf (y, 2.0f) + cr::powf (z, 2.0f), 0.5f);
|
||||||
|
|
||||||
if (cv_debug_heuristic_type.int_ () == 4) {
|
if (cv_path_heuristic_mode.int_ () == 4) {
|
||||||
return 1000.0f * (cr::ceilf (euclidean) - euclidean);
|
return 1000.0f * (cr::ceilf (euclidean) - euclidean);
|
||||||
}
|
}
|
||||||
return euclidean;
|
return euclidean;
|
||||||
|
|
@ -1343,7 +1355,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
|
|
||||||
// none heuristic
|
// none heuristic
|
||||||
auto hfunctionNone = [&hfunctionPathDist] (int index, int startIndex, int goalIndex) -> float {
|
auto hfunctionNone = [&hfunctionPathDist] (int index, int startIndex, int goalIndex) -> float {
|
||||||
return hfunctionPathDist (index, startIndex, goalIndex) / 128.0f * 10.0f;
|
return hfunctionPathDist (index, startIndex, goalIndex) / (128.0f * 10.0f);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!graph.exists (srcIndex)) {
|
if (!graph.exists (srcIndex)) {
|
||||||
|
|
@ -1578,7 +1590,7 @@ bool Bot::findBestNearestNode () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're still here, find some close nodes
|
// if we're still here, find some close nodes
|
||||||
float distance = (pev->origin - graph[at].origin).lengthSq ();
|
float distance = pev->origin.distanceSq (graph[at].origin);
|
||||||
|
|
||||||
if (distance < lessDist[0]) {
|
if (distance < lessDist[0]) {
|
||||||
lessDist[2] = lessDist[1];
|
lessDist[2] = lessDist[1];
|
||||||
|
|
@ -1650,7 +1662,7 @@ float Bot::getReachTime () {
|
||||||
|
|
||||||
// calculate 'real' time that we need to get from one node to another
|
// calculate 'real' time that we need to get from one node to another
|
||||||
if (graph.exists (m_currentNodeIndex) && graph.exists (m_previousNodes[0])) {
|
if (graph.exists (m_currentNodeIndex) && graph.exists (m_previousNodes[0])) {
|
||||||
float distance = (graph[m_previousNodes[0]].origin - graph[m_currentNodeIndex].origin).length ();
|
float distance = graph[m_previousNodes[0]].origin.distance (graph[m_currentNodeIndex].origin);
|
||||||
|
|
||||||
// caclulate estimated time
|
// caclulate estimated time
|
||||||
if (pev->maxspeed <= 0.0f) {
|
if (pev->maxspeed <= 0.0f) {
|
||||||
|
|
@ -1735,7 +1747,7 @@ int Bot::findNearestNode () {
|
||||||
if (at == m_currentNodeIndex) {
|
if (at == m_currentNodeIndex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float distance = (graph[at].origin - pev->origin).lengthSq ();
|
float distance = graph[at].origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (distance < minimum) {
|
if (distance < minimum) {
|
||||||
|
|
||||||
|
|
@ -1763,7 +1775,7 @@ int Bot::findBombNode () {
|
||||||
const auto &audible = isBombAudible ();
|
const auto &audible = isBombAudible ();
|
||||||
|
|
||||||
// take the nearest to bomb nodes instead of goal if close enough
|
// take the nearest to bomb nodes instead of goal if close enough
|
||||||
if ((pev->origin - bomb).lengthSq () < cr::square (96.0f)) {
|
if (pev->origin.distanceSq (bomb) < cr::square (96.0f)) {
|
||||||
int node = graph.getNearest (bomb, 420.0f);
|
int node = graph.getNearest (bomb, 420.0f);
|
||||||
|
|
||||||
m_bombSearchOverridden = true;
|
m_bombSearchOverridden = true;
|
||||||
|
|
@ -1786,7 +1798,7 @@ int Bot::findBombNode () {
|
||||||
|
|
||||||
// find nearest goal node either to bomb (if "heard" or player)
|
// find nearest goal node either to bomb (if "heard" or player)
|
||||||
for (auto &point : goals) {
|
for (auto &point : goals) {
|
||||||
float distance = (graph[point].origin - bomb).lengthSq ();
|
float distance = bomb.distanceSq (graph[point].origin);
|
||||||
|
|
||||||
// check if we got more close distance
|
// check if we got more close distance
|
||||||
if (distance < lastDistance) {
|
if (distance < lastDistance) {
|
||||||
|
|
@ -1888,7 +1900,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
||||||
IntArray found;
|
IntArray found;
|
||||||
|
|
||||||
for (int i = 0; i < graph.length (); ++i) {
|
for (int i = 0; i < graph.length (); ++i) {
|
||||||
if ((graph[i].origin - origin).lengthSq () <= cr::square (1248.0f) && !graph.isVisible (i, posIndex) && !isOccupiedNode (i)) {
|
if (origin.distanceSq (graph[i].origin) <= cr::square (1248.0f) && !graph.isVisible (i, posIndex) && !isOccupiedNode (i)) {
|
||||||
found.push (i);
|
found.push (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1911,7 +1923,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
||||||
int Bot::findCoverNode (float maxDistance) {
|
int Bot::findCoverNode (float maxDistance) {
|
||||||
// this function tries to find a good cover node if bot wants to hide
|
// this function tries to find a good cover node if bot wants to hide
|
||||||
|
|
||||||
const float enemyMax = (m_lastEnemyOrigin - pev->origin).length ();
|
const float enemyMax = m_lastEnemyOrigin.distance (pev->origin);
|
||||||
|
|
||||||
// do not move to a position near to the enemy
|
// do not move to a position near to the enemy
|
||||||
if (maxDistance > enemyMax) {
|
if (maxDistance > enemyMax) {
|
||||||
|
|
@ -2172,7 +2184,7 @@ bool Bot::advanceMovement () {
|
||||||
src = path.origin;
|
src = path.origin;
|
||||||
dst = next.origin;
|
dst = next.origin;
|
||||||
|
|
||||||
jumpDistance = (path.origin - next.origin).length ();
|
jumpDistance = path.origin.distance (next.origin);
|
||||||
willJump = true;
|
willJump = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -2661,7 +2673,7 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float lastHeight = tr.flFraction * 1000.0f; // height from ground
|
float lastHeight = tr.flFraction * 1000.0f; // height from ground
|
||||||
float distance = (to - check).length (); // distance from goal
|
float distance = to.distance (check); // distance from goal
|
||||||
|
|
||||||
if (distance <= 30.0f && lastHeight > 150.0f) {
|
if (distance <= 30.0f && lastHeight > 150.0f) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2686,7 +2698,7 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
lastHeight = height;
|
lastHeight = height;
|
||||||
distance = (to - check).length (); // distance from goal
|
distance = to.distance (check); // distance from goal
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -2774,13 +2786,13 @@ int Bot::findCampingDirection () {
|
||||||
if (count < 3) {
|
if (count < 3) {
|
||||||
indices[count] = i;
|
indices[count] = i;
|
||||||
|
|
||||||
distTab[count] = (pev->origin - path.origin).lengthSq ();
|
distTab[count] = pev->origin.distanceSq (path.origin);
|
||||||
visibility[count] = path.vis.crouch + path.vis.stand;
|
visibility[count] = path.vis.crouch + path.vis.stand;
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float distance = (pev->origin - path.origin).lengthSq ();
|
float distance = pev->origin.distanceSq (path.origin);
|
||||||
uint16 visBits = path.vis.crouch + path.vis.stand;
|
uint16 visBits = path.vis.crouch + path.vis.stand;
|
||||||
|
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
|
@ -3005,14 +3017,14 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not check clients far away from us
|
// do not check clients far away from us
|
||||||
if ((pev->origin - client.origin).lengthSq () > cr::square (320.0f)) {
|
if (pev->origin.distanceSq (client.origin) > cr::square (320.0f)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needZeroVelocity && client.ent->v.velocity.length2d () > 0.0f) {
|
if (needZeroVelocity && client.ent->v.velocity.length2d () > 0.0f) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto length = (graph[index].origin - client.origin).lengthSq ();
|
auto length = client.origin.distanceSq (graph[index].origin);
|
||||||
|
|
||||||
if (length < cr::clamp (cr::square (graph[index].radius), cr::square (60.0f), cr::square (90.0f))) {
|
if (length < cr::clamp (cr::square (graph[index].radius), cr::square (60.0f), cr::square (90.0f))) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -3049,7 +3061,7 @@ edict_t *Bot::lookupButton (const char *target) {
|
||||||
|
|
||||||
// check if this place safe
|
// check if this place safe
|
||||||
if (!isDeadlyMove (pos)) {
|
if (!isDeadlyMove (pos)) {
|
||||||
float distance = (pev->origin - pos).lengthSq ();
|
float distance = pev->origin.distanceSq (pos);
|
||||||
|
|
||||||
// check if we got more close button
|
// check if we got more close button
|
||||||
if (distance <= nearest) {
|
if (distance <= nearest) {
|
||||||
|
|
@ -3073,7 +3085,7 @@ bool Bot::isReachableNode (int index) {
|
||||||
const Vector &dst = graph[index].origin;
|
const Vector &dst = graph[index].origin;
|
||||||
|
|
||||||
// is the destination close enough?
|
// is the destination close enough?
|
||||||
if ((dst - src).lengthSq () >= cr::square (320.0f)) {
|
if (dst.distanceSq (src) >= cr::square (320.0f)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3081,7 +3093,7 @@ bool Bot::isReachableNode (int index) {
|
||||||
if (isOccupiedNode (index, true)) {
|
if (isOccupiedNode (index, true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
float ladderDist = (dst - src).length2d ();
|
float ladderDist = dst.distance2d (src);
|
||||||
|
|
||||||
TraceResult tr {};
|
TraceResult tr {};
|
||||||
game.testLine (src, dst, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (src, dst, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
@ -3112,6 +3124,9 @@ bool Bot::isReachableNode (int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::isBannedNode (int index) {
|
bool Bot::isBannedNode (int index) {
|
||||||
|
if (graph.exists (cv_debug_goal.int_ ())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (const auto &node : m_goalHistory) {
|
for (const auto &node : m_goalHistory) {
|
||||||
if (node == index) {
|
if (node == index) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ bool BotSupport::findNearestPlayer (void **pvHolder, edict_t *to, float searchDi
|
||||||
if ((sameTeam && client.team != toTeam) || (needAlive && !(client.flags & ClientFlags::Alive)) || (needBot && !isFakeClient (client.ent)) || (needDrawn && (client.ent->v.effects & EF_NODRAW)) || (needBotWithC4 && (client.ent->v.weapons & Weapon::C4))) {
|
if ((sameTeam && client.team != toTeam) || (needAlive && !(client.flags & ClientFlags::Alive)) || (needBot && !isFakeClient (client.ent)) || (needDrawn && (client.ent->v.effects & EF_NODRAW)) || (needBotWithC4 && (client.ent->v.weapons & Weapon::C4))) {
|
||||||
continue; // filter players with parameters
|
continue; // filter players with parameters
|
||||||
}
|
}
|
||||||
float distance = (client.ent->v.origin - to->v.origin).length ();
|
float distance = client.ent->v.origin.distance (to->v.origin);
|
||||||
|
|
||||||
if (distance < nearestPlayer && distance < searchDistance) {
|
if (distance < nearestPlayer && distance < searchDistance) {
|
||||||
nearestPlayer = distance;
|
nearestPlayer = distance;
|
||||||
|
|
@ -398,7 +398,7 @@ void BotSupport::listenNoise (edict_t *ent, StringRef sample, float volume) {
|
||||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive)) {
|
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto distance = (client.origin - origin).lengthSq ();
|
auto distance = client.origin.distanceSq (origin);
|
||||||
|
|
||||||
// now find nearest player
|
// now find nearest player
|
||||||
if (distance < nearest) {
|
if (distance < nearest) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue