bot: add basic support to play as zombie bot
aim: check that we're actually hit the target in body checks
This commit is contained in:
parent
70ff2d0ec2
commit
3009b4f50a
8 changed files with 101 additions and 26 deletions
|
|
@ -307,6 +307,11 @@ public:
|
||||||
return m_paths.length <int32_t> ();
|
return m_paths.length <int32_t> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the random node on map
|
||||||
|
int32_t random () const {
|
||||||
|
return rg.get (0, length () - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// check if has editor
|
// check if has editor
|
||||||
bool hasEditor () const {
|
bool hasEditor () const {
|
||||||
return !!m_editor;
|
return !!m_editor;
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ public:
|
||||||
void erase (Bot *bot);
|
void erase (Bot *bot);
|
||||||
void handleDeath (edict_t *killer, edict_t *victim);
|
void handleDeath (edict_t *killer, edict_t *victim);
|
||||||
void setLastWinner (int winner);
|
void setLastWinner (int winner);
|
||||||
|
void checkBotModel (edict_t *ent, char *infobuffer);
|
||||||
|
|
||||||
bool isTeamStacked (int team);
|
bool isTeamStacked (int team);
|
||||||
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);
|
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);
|
||||||
|
|
|
||||||
|
|
@ -771,6 +771,7 @@ private:
|
||||||
bool m_grenadeRequested {}; // bot requested change to grenade
|
bool m_grenadeRequested {}; // bot requested change to grenade
|
||||||
bool m_needToSendWelcomeChat {}; // bot needs to greet people on server?
|
bool m_needToSendWelcomeChat {}; // bot needs to greet people on server?
|
||||||
bool m_switchedToKnifeDuringJump {}; // bot needs to revert weapon after jump?
|
bool m_switchedToKnifeDuringJump {}; // bot needs to revert weapon after jump?
|
||||||
|
bool m_isCreature {}; // bot is not a player, but something else ? zombie ?
|
||||||
|
|
||||||
Pickup m_pickupType {}; // type of entity which needs to be used/picked up
|
Pickup m_pickupType {}; // type of entity which needs to be used/picked up
|
||||||
PathWalk m_pathWalk {}; // pointer to current node from path
|
PathWalk m_pathWalk {}; // pointer to current node from path
|
||||||
|
|
@ -779,6 +780,7 @@ private:
|
||||||
CollisionState m_collisionState {}; // collision State
|
CollisionState m_collisionState {}; // collision State
|
||||||
FindPath m_pathType {}; // which pathfinder to use
|
FindPath m_pathType {}; // which pathfinder to use
|
||||||
uint8_t m_enemyParts {}; // visibility flags
|
uint8_t m_enemyParts {}; // visibility flags
|
||||||
|
uint16_t m_modelMask {}; // model mask bits
|
||||||
TraceResult m_lastTrace[TraceChannel::Num] {}; // last trace result
|
TraceResult m_lastTrace[TraceChannel::Num] {}; // last trace result
|
||||||
UniquePtr <class AStarAlgo> m_planner;
|
UniquePtr <class AStarAlgo> m_planner;
|
||||||
|
|
||||||
|
|
@ -894,6 +896,7 @@ private:
|
||||||
bool canRunHeavyWeight ();
|
bool canRunHeavyWeight ();
|
||||||
bool isEnemyInSight (Vector &endPos);
|
bool isEnemyInSight (Vector &endPos);
|
||||||
bool isEnemyNoticeable (float range);
|
bool isEnemyNoticeable (float range);
|
||||||
|
bool isCreature ();
|
||||||
|
|
||||||
void doPlayerAvoidance (const Vector &normal);
|
void doPlayerAvoidance (const Vector &normal);
|
||||||
void selectCampButtons (int index);
|
void selectCampButtons (int index);
|
||||||
|
|
@ -953,6 +956,7 @@ private:
|
||||||
void refreshEnemyPredict ();
|
void refreshEnemyPredict ();
|
||||||
void syncUpdatePredictedIndex ();
|
void syncUpdatePredictedIndex ();
|
||||||
void updatePredictedIndex ();
|
void updatePredictedIndex ();
|
||||||
|
void refreshModelName (char *infobuffer);
|
||||||
|
|
||||||
void completeTask ();
|
void completeTask ();
|
||||||
void executeTasks ();
|
void executeTasks ();
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,7 @@ void Bot::updatePickups () {
|
||||||
// this function finds Items to collect or use in the near of a bot
|
// this function finds Items to collect or use in the near of a bot
|
||||||
|
|
||||||
// don't try to pickup anything while on ladder or trying to escape from bomb...
|
// don't try to pickup anything while on ladder or trying to escape from bomb...
|
||||||
if ((m_states & Sense::SeeingEnemy) || isOnLadder () || getCurrentTaskId () == Task::EscapeFromBomb || !cv_pickup_best.bool_ () || cv_jasonmode.bool_ () || !bots.hasInterestingEntities ()) {
|
if (m_isCreature || (m_states & Sense::SeeingEnemy) || isOnLadder () || getCurrentTaskId () == Task::EscapeFromBomb || !cv_pickup_best.bool_ () || cv_jasonmode.bool_ () || !bots.hasInterestingEntities ()) {
|
||||||
m_pickupItem = nullptr;
|
m_pickupItem = nullptr;
|
||||||
m_pickupType = Pickup::None;
|
m_pickupType = Pickup::None;
|
||||||
|
|
||||||
|
|
@ -903,7 +903,7 @@ void Bot::checkMsgQueue () {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_inBuyZone || game.is (GameFlags::CSDM)) {
|
if (!m_inBuyZone || game.is (GameFlags::CSDM) || m_isCreature) {
|
||||||
m_buyPending = true;
|
m_buyPending = true;
|
||||||
m_buyingFinished = true;
|
m_buyingFinished = true;
|
||||||
|
|
||||||
|
|
@ -1767,7 +1767,7 @@ void Bot::setConditions () {
|
||||||
refreshEnemyPredict ();
|
refreshEnemyPredict ();
|
||||||
|
|
||||||
// check for grenades depending on difficulty
|
// check for grenades depending on difficulty
|
||||||
if (rg.chance (cr::max (25, m_difficulty * 25))) {
|
if (rg.chance (cr::max (25, m_difficulty * 25)) && !m_isCreature) {
|
||||||
checkGrenadesThrow ();
|
checkGrenadesThrow ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1841,7 +1841,6 @@ void Bot::filterTasks () {
|
||||||
float retreatLevel = (100.0f - (m_healthValue > 70.0f ? 100.0f : m_healthValue)) * tempFear; // retreat level depends on bot health
|
float retreatLevel = (100.0f - (m_healthValue > 70.0f ? 100.0f : m_healthValue)) * tempFear; // retreat level depends on bot health
|
||||||
|
|
||||||
if (m_numEnemiesLeft > m_numFriendsLeft / 2 && m_retreatTime < game.time () && m_seeEnemyTime - rg.get (2.0f, 4.0f) < game.time ()) {
|
if (m_numEnemiesLeft > m_numFriendsLeft / 2 && m_retreatTime < game.time () && m_seeEnemyTime - rg.get (2.0f, 4.0f) < game.time ()) {
|
||||||
|
|
||||||
float timeSeen = m_seeEnemyTime - game.time ();
|
float timeSeen = m_seeEnemyTime - game.time ();
|
||||||
float timeHeard = m_heardSoundTime - game.time ();
|
float timeHeard = m_heardSoundTime - game.time ();
|
||||||
float ratio = 0.0f;
|
float ratio = 0.0f;
|
||||||
|
|
@ -1865,6 +1864,9 @@ void Bot::filterTasks () {
|
||||||
else if (m_isVIP || m_isReloading || (sniping && usesSniper ())) {
|
else if (m_isVIP || m_isReloading || (sniping && usesSniper ())) {
|
||||||
ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading
|
ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading
|
||||||
}
|
}
|
||||||
|
else if (m_isCreature) {
|
||||||
|
ratio = 0.0f;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ratio /= 2.0f; // reduce seek cover otherwise
|
ratio /= 2.0f; // reduce seek cover otherwise
|
||||||
}
|
}
|
||||||
|
|
@ -2553,7 +2555,7 @@ void Bot::checkRadioQueue () {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Radio::GetInPositionAndWaitForGo:
|
case Radio::GetInPositionAndWaitForGo:
|
||||||
if ((game.isNullEntity (m_enemy) && seesEntity (m_radioEntity->v.origin)) || distance < 1024.0f) {
|
if (!m_isCreature && ((game.isNullEntity (m_enemy) && seesEntity (m_radioEntity->v.origin)) || distance < 1024.0f)) {
|
||||||
pushRadioMessage (Radio::RogerThat);
|
pushRadioMessage (Radio::RogerThat);
|
||||||
|
|
||||||
if (getCurrentTaskId () == Task::Camp) {
|
if (getCurrentTaskId () == Task::Camp) {
|
||||||
|
|
@ -2927,6 +2929,7 @@ void Bot::update () {
|
||||||
else if (m_team == Team::CT && game.mapIs (MapFlags::HostageRescue)) {
|
else if (m_team == Team::CT && game.mapIs (MapFlags::HostageRescue)) {
|
||||||
m_hasHostage = hasHostage ();
|
m_hasHostage = hasHostage ();
|
||||||
}
|
}
|
||||||
|
m_isCreature = isCreature ();
|
||||||
|
|
||||||
// is bot movement enabled
|
// is bot movement enabled
|
||||||
bool botMovement = false;
|
bool botMovement = false;
|
||||||
|
|
@ -3537,7 +3540,7 @@ void Bot::blind_ () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::camp_ () {
|
void Bot::camp_ () {
|
||||||
if (!cv_camping_allowed.bool_ ()) {
|
if (!cv_camping_allowed.bool_ () || m_isCreature) {
|
||||||
completeTask ();
|
completeTask ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3627,6 +3630,11 @@ void Bot::camp_ () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::hide_ () {
|
void Bot::hide_ () {
|
||||||
|
if (m_isCreature) {
|
||||||
|
completeTask ();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
m_aimFlags |= AimFlags::Camp;
|
m_aimFlags |= AimFlags::Camp;
|
||||||
m_checkTerrain = false;
|
m_checkTerrain = false;
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
|
|
@ -3747,7 +3755,7 @@ void Bot::plantBomb_ () {
|
||||||
m_aimFlags |= AimFlags::Camp;
|
m_aimFlags |= AimFlags::Camp;
|
||||||
|
|
||||||
// we're still got the C4?
|
// we're still got the C4?
|
||||||
if (m_hasC4) {
|
if (m_hasC4 && !isKnifeMode ()) {
|
||||||
if (m_currentWeapon != Weapon::C4) {
|
if (m_currentWeapon != Weapon::C4) {
|
||||||
selectWeaponById (Weapon::C4);
|
selectWeaponById (Weapon::C4);
|
||||||
}
|
}
|
||||||
|
|
@ -4821,7 +4829,7 @@ void Bot::logic () {
|
||||||
m_wantsToFire = false;
|
m_wantsToFire = false;
|
||||||
|
|
||||||
// avoid flyings grenades, if needed
|
// avoid flyings grenades, if needed
|
||||||
if (cv_avoid_grenades.bool_ ()) {
|
if (cv_avoid_grenades.bool_ () && !m_isCreature) {
|
||||||
avoidGrenades ();
|
avoidGrenades ();
|
||||||
}
|
}
|
||||||
m_isUsingGrenade = false;
|
m_isUsingGrenade = false;
|
||||||
|
|
@ -5660,6 +5668,9 @@ void Bot::updateHearing () {
|
||||||
void Bot::enteredBuyZone (int buyState) {
|
void Bot::enteredBuyZone (int buyState) {
|
||||||
// this function is gets called when bot enters a buyzone, to allow bot to buy some stuff
|
// this function is gets called when bot enters a buyzone, to allow bot to buy some stuff
|
||||||
|
|
||||||
|
if (m_isCreature) {
|
||||||
|
return; // creatures can't buy anything
|
||||||
|
}
|
||||||
const int *econLimit = conf.getEconLimit ();
|
const int *econLimit = conf.getEconLimit ();
|
||||||
|
|
||||||
// if bot is in buy zone, try to buy ammo for this weapon...
|
// if bot is in buy zone, try to buy ammo for this weapon...
|
||||||
|
|
@ -5795,3 +5806,32 @@ bool Bot::isEnemyInFrustum (edict_t *enemy) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::refreshModelName (char *infobuffer) {
|
||||||
|
if (infobuffer == nullptr) {
|
||||||
|
infobuffer = engfuncs.pfnGetInfoKeyBuffer (ent ());
|
||||||
|
}
|
||||||
|
String modelName = engfuncs.pfnInfoKeyValue (infobuffer, "model");
|
||||||
|
|
||||||
|
// need at least two characters to test model mask
|
||||||
|
if (modelName.length () < 2) {
|
||||||
|
m_modelMask = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
union ModelTest {
|
||||||
|
char model[2];
|
||||||
|
uint16_t mask;
|
||||||
|
ModelTest (StringRef m) : model { m[0], m[1] } {};
|
||||||
|
} modelTest { modelName };
|
||||||
|
|
||||||
|
// assign our model mask (tests against model done every bot update)
|
||||||
|
m_modelMask = modelTest.mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bot::isCreature () {
|
||||||
|
// current creature models are: zombie, chicken
|
||||||
|
constexpr auto modelMaskZombie = (('o' << 8) + 'z');
|
||||||
|
constexpr auto modelMaskChicken = (('h' << 8) + 'c');
|
||||||
|
|
||||||
|
return m_modelMask == modelMaskZombie || m_modelMask == modelMaskChicken;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,19 +132,22 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
auto spot = target->v.origin;
|
auto spot = target->v.origin;
|
||||||
auto self = pev->pContainingEntity;
|
auto self = pev->pContainingEntity;
|
||||||
|
|
||||||
m_enemyParts = Visibility::None;
|
// creatures can't hurt behind anything
|
||||||
game.testLine (eyes, spot, TraceIgnore::Everything, self, &result);
|
auto ignoreFlags = m_isCreature ? TraceIgnore::None : TraceIgnore::Everything;
|
||||||
|
|
||||||
if (result.flFraction >= 1.0f) {
|
m_enemyParts = Visibility::None;
|
||||||
|
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
||||||
|
|
||||||
|
if (result.flFraction >= 1.0f && result.pHit == target) {
|
||||||
m_enemyParts |= Visibility::Body;
|
m_enemyParts |= Visibility::Body;
|
||||||
m_enemyOrigin = result.vecEndPos;
|
m_enemyOrigin = result.vecEndPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check top of head
|
// check top of head
|
||||||
spot.z += 25.0f;
|
spot.z += 25.0f;
|
||||||
game.testLine (eyes, spot, TraceIgnore::Everything, self, &result);
|
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
||||||
|
|
||||||
if (result.flFraction >= 1.0f) {
|
if (result.flFraction >= 1.0f && result.pHit == target) {
|
||||||
m_enemyParts |= Visibility::Head;
|
m_enemyParts |= Visibility::Head;
|
||||||
m_enemyOrigin = result.vecEndPos;
|
m_enemyOrigin = result.vecEndPos;
|
||||||
}
|
}
|
||||||
|
|
@ -162,9 +165,9 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
else {
|
else {
|
||||||
spot.z = target->v.origin.z - standFeet;
|
spot.z = target->v.origin.z - standFeet;
|
||||||
}
|
}
|
||||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, result);
|
game.testLineChannel (TraceChannel::Enemy, eyes, spot, ignoreFlags, self, result);
|
||||||
|
|
||||||
if (result.flFraction >= 1.0f) {
|
if (result.flFraction >= 1.0f && result.pHit == target) {
|
||||||
m_enemyParts |= Visibility::Other;
|
m_enemyParts |= Visibility::Other;
|
||||||
m_enemyOrigin = result.vecEndPos;
|
m_enemyOrigin = result.vecEndPos;
|
||||||
|
|
||||||
|
|
@ -177,9 +180,9 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
Vector perp (-dir.y, dir.x, 0.0f);
|
Vector perp (-dir.y, dir.x, 0.0f);
|
||||||
spot = target->v.origin + Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
spot = target->v.origin + Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
||||||
|
|
||||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, result);
|
game.testLineChannel (TraceChannel::Enemy, eyes, spot, ignoreFlags, self, result);
|
||||||
|
|
||||||
if (result.flFraction >= 1.0f) {
|
if (result.flFraction >= 1.0f && result.pHit == target) {
|
||||||
m_enemyParts |= Visibility::Other;
|
m_enemyParts |= Visibility::Other;
|
||||||
m_enemyOrigin = result.vecEndPos;
|
m_enemyOrigin = result.vecEndPos;
|
||||||
|
|
||||||
|
|
@ -187,9 +190,9 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
}
|
}
|
||||||
spot = target->v.origin - Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
spot = target->v.origin - Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
||||||
|
|
||||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, result);
|
game.testLineChannel (TraceChannel::Enemy, eyes, spot, ignoreFlags, self, result);
|
||||||
|
|
||||||
if (result.flFraction >= 1.0f) {
|
if (result.flFraction >= 1.0f && result.pHit == target) {
|
||||||
m_enemyParts |= Visibility::Other;
|
m_enemyParts |= Visibility::Other;
|
||||||
m_enemyOrigin = result.vecEndPos;
|
m_enemyOrigin = result.vecEndPos;
|
||||||
|
|
||||||
|
|
@ -1494,7 +1497,7 @@ bool Bot::hasAnyWeapons () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::isKnifeMode () {
|
bool Bot::isKnifeMode () {
|
||||||
return cv_jasonmode.bool_ () || (usesKnife () && !hasAnyWeapons ());
|
return cv_jasonmode.bool_ () || (usesKnife () && !hasAnyWeapons ()) || m_isCreature;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::selectBestWeapon () {
|
void Bot::selectBestWeapon () {
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int) {
|
||||||
// team changes, recounting the teams population, etc...
|
// team changes, recounting the teams population, etc...
|
||||||
|
|
||||||
ctrl.assignAdminRights (ent, infobuffer);
|
ctrl.assignAdminRights (ent, infobuffer);
|
||||||
|
bots.checkBotModel (ent, infobuffer);
|
||||||
|
|
||||||
if (game.is (GameFlags::Metamod)) {
|
if (game.is (GameFlags::Metamod)) {
|
||||||
RETURN_META (MRES_IGNORED);
|
RETURN_META (MRES_IGNORED);
|
||||||
|
|
|
||||||
|
|
@ -740,6 +740,15 @@ void BotManager::setLastWinner (int winner) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BotManager::checkBotModel (edict_t *ent, char *infobuffer) {
|
||||||
|
for (const auto &bot : bots) {
|
||||||
|
if (bot->ent () == ent) {
|
||||||
|
bot->refreshModelName (infobuffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BotManager::setWeaponMode (int selection) {
|
void BotManager::setWeaponMode (int selection) {
|
||||||
// this function sets bots weapon mode
|
// this function sets bots weapon mode
|
||||||
|
|
||||||
|
|
@ -1367,6 +1376,7 @@ void Bot::newRound () {
|
||||||
for (auto &timer : m_chatterTimes) {
|
for (auto &timer : m_chatterTimes) {
|
||||||
timer = kMaxChatterRepeatInterval;
|
timer = kMaxChatterRepeatInterval;
|
||||||
}
|
}
|
||||||
|
refreshModelName (nullptr);
|
||||||
|
|
||||||
m_isReloading = false;
|
m_isReloading = false;
|
||||||
m_reloadState = Reload::None;
|
m_reloadState = Reload::None;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,17 @@ int Bot::findBestGoal () {
|
||||||
return goal;
|
return goal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (m_isCreature) {
|
||||||
|
if (!graph.m_terrorPoints.empty ()) {
|
||||||
|
return graph.m_terrorPoints.random ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!graph.m_goalPoints.empty ()) {
|
||||||
|
return graph.m_goalPoints.random ();
|
||||||
|
}
|
||||||
|
return graph.random ();
|
||||||
|
}
|
||||||
|
|
||||||
// chooses a destination (goal) node for a bot
|
// chooses a destination (goal) node for a bot
|
||||||
if (m_team == Team::Terrorist && game.mapIs (MapFlags::Demolition)) {
|
if (m_team == Team::Terrorist && game.mapIs (MapFlags::Demolition)) {
|
||||||
auto result = findBestGoalWhenBombAction ();
|
auto result = findBestGoalWhenBombAction ();
|
||||||
|
|
@ -282,7 +293,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (goalChoices[0] == kInvalidNodeIndex) {
|
if (goalChoices[0] == kInvalidNodeIndex) {
|
||||||
return m_chosenGoalIndex = rg.get (0, graph.length () - 1);
|
return m_chosenGoalIndex = graph.random ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sorting = false;
|
bool sorting = false;
|
||||||
|
|
@ -1785,7 +1796,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
||||||
|
|
||||||
// some of points not found, return random one
|
// some of points not found, return random one
|
||||||
if (srcIndex == kInvalidNodeIndex || posIndex == kInvalidNodeIndex) {
|
if (srcIndex == kInvalidNodeIndex || posIndex == kInvalidNodeIndex) {
|
||||||
return rg.get (0, graph.length () - 1);
|
return graph.random ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the best node now
|
// find the best node now
|
||||||
|
|
@ -1885,7 +1896,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found.empty ()) {
|
if (found.empty ()) {
|
||||||
return rg.get (0, graph.length () - 1); // most worst case, since there a evil error in nodes
|
return graph.random (); // most worst case, since there a evil error in nodes
|
||||||
}
|
}
|
||||||
return found.random ();
|
return found.random ();
|
||||||
}
|
}
|
||||||
|
|
@ -2129,7 +2140,7 @@ bool Bot::advanceMovement () {
|
||||||
Task taskID = getCurrentTaskId ();
|
Task taskID = getCurrentTaskId ();
|
||||||
|
|
||||||
// only if we in normal task and bomb is not planted
|
// only if we in normal task and bomb is not planted
|
||||||
if (taskID == Task::Normal && bots.getRoundMidTime () + 5.0f < game.time () && m_timeCamping + 5.0f < game.time () && !bots.isBombPlanted () && m_personality != Personality::Rusher && !m_hasC4 && !m_isVIP && m_loosedBombNodeIndex == kInvalidNodeIndex && !m_hasHostage) {
|
if (taskID == Task::Normal && bots.getRoundMidTime () + 5.0f < game.time () && m_timeCamping + 5.0f < game.time () && !bots.isBombPlanted () && m_personality != Personality::Rusher && !m_hasC4 && !m_isVIP && m_loosedBombNodeIndex == kInvalidNodeIndex && !m_hasHostage && !m_isCreature) {
|
||||||
m_campButtons = 0;
|
m_campButtons = 0;
|
||||||
|
|
||||||
const int nextIndex = m_pathWalk.next ();
|
const int nextIndex = m_pathWalk.next ();
|
||||||
|
|
@ -2861,7 +2872,7 @@ int Bot::getRandomCampDir () {
|
||||||
if (count >= 0) {
|
if (count >= 0) {
|
||||||
return indices[rg.get (0, count)];
|
return indices[rg.get (0, count)];
|
||||||
}
|
}
|
||||||
return rg.get (0, graph.length () - 1);
|
return graph.random ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::updateBodyAngles () {
|
void Bot::updateBodyAngles () {
|
||||||
|
|
@ -3215,7 +3226,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
|
||||||
destIndex = graph.getNearestNoBuckets (pev->origin, kInfiniteDistance, NodeFlag::Goal);
|
destIndex = graph.getNearestNoBuckets (pev->origin, kInfiniteDistance, NodeFlag::Goal);
|
||||||
|
|
||||||
if (!graph.exists (destIndex) || srcIndex == destIndex) {
|
if (!graph.exists (destIndex) || srcIndex == destIndex) {
|
||||||
destIndex = rg.get (0, graph.length () - 1);
|
destIndex = graph.random ();
|
||||||
|
|
||||||
if (!graph.exists (destIndex)) {
|
if (!graph.exists (destIndex)) {
|
||||||
printf ("%s dest path index not valid (%d).", __func__, destIndex);
|
printf ("%s dest path index not valid (%d).", __func__, destIndex);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue