control: add g path_clean to remove all links from node (#475)
refactor: small cosmetic changes
This commit is contained in:
parent
fe5c8ef053
commit
fb301b7b19
23 changed files with 205 additions and 132 deletions
|
|
@ -447,3 +447,8 @@ constexpr auto kSecondaryWeaponMask = (cr::bit (Weapon::P228) | cr::bit (Weapon:
|
||||||
|
|
||||||
// weapons < 7 are secondary
|
// weapons < 7 are secondary
|
||||||
constexpr auto kPrimaryWeaponMinIndex = 7;
|
constexpr auto kPrimaryWeaponMinIndex = 7;
|
||||||
|
|
||||||
|
// grenade model names
|
||||||
|
static constexpr StringRef kExplosiveModelName = "hegrenade.mdl";
|
||||||
|
static constexpr StringRef kFlashbangModelName = "flashbang.mdl";
|
||||||
|
static constexpr StringRef kSmokeModelName = "smokegrenade.mdl";
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ private:
|
||||||
int cmdNodePathCreate ();
|
int cmdNodePathCreate ();
|
||||||
int cmdNodePathDelete ();
|
int cmdNodePathDelete ();
|
||||||
int cmdNodePathSetAutoDistance ();
|
int cmdNodePathSetAutoDistance ();
|
||||||
|
int cmdNodePathCleanAll ();
|
||||||
int cmdNodeAcquireEditor ();
|
int cmdNodeAcquireEditor ();
|
||||||
int cmdNodeReleaseEditor ();
|
int cmdNodeReleaseEditor ();
|
||||||
int cmdNodeUpload ();
|
int cmdNodeUpload ();
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ public:
|
||||||
// provides utility functions to not call original engine (less call-cost)
|
// provides utility functions to not call original engine (less call-cost)
|
||||||
class Game final : public Singleton <Game> {
|
class Game final : public Singleton <Game> {
|
||||||
public:
|
public:
|
||||||
using EntitySearch = Lambda <EntitySearchResult (edict_t *)>;
|
using EntitySearch = const Lambda <EntitySearchResult (edict_t *)> &;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_drawModels[DrawLine::Count] {};
|
int m_drawModels[DrawLine::Count] {};
|
||||||
|
|
@ -227,12 +227,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// get "maxplayers" limit on server
|
// get "maxplayers" limit on server
|
||||||
int maxClients () const {
|
int maxClients () const {
|
||||||
return globals->maxClients;
|
return globals->maxClients;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the fakeclient command interface
|
// get the fakeclient command interface
|
||||||
bool isBotCmd () const {
|
bool isBotCmd () const {
|
||||||
return !m_botArgs.empty ();
|
return !m_botArgs.empty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ public:
|
||||||
void setRadius (int index, float radius);
|
void setRadius (int index, float radius);
|
||||||
void pathCreate (char dir);
|
void pathCreate (char dir);
|
||||||
void erasePath ();
|
void erasePath ();
|
||||||
|
void resetPath (int index);
|
||||||
void cachePoint (int index);
|
void cachePoint (int index);
|
||||||
void calculatePathRadius (int index);
|
void calculatePathRadius (int index);
|
||||||
void addBasic ();
|
void addBasic ();
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ struct BotRequest {
|
||||||
// manager class
|
// manager class
|
||||||
class BotManager final : public Singleton <BotManager> {
|
class BotManager final : public Singleton <BotManager> {
|
||||||
public:
|
public:
|
||||||
using ForEachBot = Lambda <bool (Bot *)>;
|
using ForEachBot = const Lambda <bool (Bot *)> &;
|
||||||
using UniqueBot = UniquePtr <Bot>;
|
using UniqueBot = UniquePtr <Bot>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ CR_DECLARE_SCOPED_ENUM (AStarResult,
|
||||||
)
|
)
|
||||||
|
|
||||||
// node added
|
// node added
|
||||||
using NodeAdderFn = Lambda <bool (int)>;
|
using NodeAdderFn = const Lambda <bool (int)> &;
|
||||||
|
|
||||||
// route twin node
|
// route twin node
|
||||||
template <typename HT> struct RouteTwin final {
|
template <typename HT> struct RouteTwin final {
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public:
|
||||||
// check if entity is a hostage entity
|
// check if entity is a hostage entity
|
||||||
bool isHostageEntity (edict_t *ent);
|
bool isHostageEntity (edict_t *ent);
|
||||||
|
|
||||||
// check if entity is a door enitty
|
// check if entity is a door entity
|
||||||
bool isDoorEntity (edict_t *ent);
|
bool isDoorEntity (edict_t *ent);
|
||||||
|
|
||||||
// this function is checking that pointed by ent pointer obstacle, can be destroyed
|
// this function is checking that pointed by ent pointer obstacle, can be destroyed
|
||||||
|
|
@ -133,13 +133,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the shooting cone deviation
|
// gets the shooting cone deviation
|
||||||
float getShootingCone (edict_t *ent, const Vector &position) {
|
float getShootingCone (edict_t *ent, const Vector &pos) {
|
||||||
return ent->v.v_angle.forward () | (position - (ent->v.origin + ent->v.view_ofs)).normalize (); // he's facing it, he meant it
|
return ent->v.v_angle.forward () | (pos - (ent->v.origin + ent->v.view_ofs)).normalize (); // he's facing it, he meant it
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if origin is inside view cone of entity
|
// check if position is inside view cone of entity
|
||||||
bool isInViewCone (const Vector &origin, edict_t *ent) {
|
bool isInViewCone (const Vector &pos, edict_t *ent) {
|
||||||
return getShootingCone (ent, origin) >= cr::cosf (cr::deg2rad ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
return getShootingCone (ent, pos) >= cr::cosf (cr::deg2rad ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -366,6 +366,7 @@ private:
|
||||||
Vector m_lookAtPredict {}; // aiming vector when predicting
|
Vector m_lookAtPredict {}; // aiming vector when predicting
|
||||||
Vector m_desiredVelocity {}; // desired velocity for jump nodes
|
Vector m_desiredVelocity {}; // desired velocity for jump nodes
|
||||||
Vector m_breakableOrigin {}; // origin of breakable
|
Vector m_breakableOrigin {}; // origin of breakable
|
||||||
|
Vector m_rightRef {}; // right referential vector
|
||||||
|
|
||||||
Array <edict_t *> m_ignoredBreakable {}; // list of ignored breakables
|
Array <edict_t *> m_ignoredBreakable {}; // list of ignored breakables
|
||||||
Array <edict_t *> m_hostages {}; // pointer to used hostage entities
|
Array <edict_t *> m_hostages {}; // pointer to used hostage entities
|
||||||
|
|
@ -485,7 +486,7 @@ private:
|
||||||
void findShortestPath (int srcIndex, int destIndex);
|
void findShortestPath (int srcIndex, int destIndex);
|
||||||
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
|
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
|
||||||
void syncFindPath (int srcIndex, int destIndex, FindPath pathType);
|
void syncFindPath (int srcIndex, int destIndex, FindPath pathType);
|
||||||
void debugMsgInternal (const char *str);
|
void debugMsgInternal (StringRef str);
|
||||||
void frame ();
|
void frame ();
|
||||||
void resetCollision ();
|
void resetCollision ();
|
||||||
void ignoreCollision ();
|
void ignoreCollision ();
|
||||||
|
|
@ -509,6 +510,7 @@ private:
|
||||||
void syncUpdatePredictedIndex ();
|
void syncUpdatePredictedIndex ();
|
||||||
void updatePredictedIndex ();
|
void updatePredictedIndex ();
|
||||||
void refreshModelName (char *infobuffer);
|
void refreshModelName (char *infobuffer);
|
||||||
|
void updateRightRef ();
|
||||||
|
|
||||||
void completeTask ();
|
void completeTask ();
|
||||||
void executeTasks ();
|
void executeTasks ();
|
||||||
|
|
@ -540,9 +542,9 @@ private:
|
||||||
void pickupItem_ ();
|
void pickupItem_ ();
|
||||||
void shootBreakable_ ();
|
void shootBreakable_ ();
|
||||||
|
|
||||||
edict_t *lookupButton (const char *target);
|
edict_t *lookupButton (StringRef target);
|
||||||
edict_t *lookupBreakable ();
|
edict_t *lookupBreakable ();
|
||||||
edict_t *setCorrectGrenadeVelocity (const char *model);
|
edict_t *setCorrectGrenadeVelocity (StringRef model);
|
||||||
|
|
||||||
Vector getEnemyBodyOffset ();
|
Vector getEnemyBodyOffset ();
|
||||||
Vector calcThrow (const Vector &start, const Vector &stop);
|
Vector calcThrow (const Vector &start, const Vector &stop);
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ void Bot::pushMsgQueue (int message) {
|
||||||
|
|
||||||
if (message == BotMsg::Say) {
|
if (message == BotMsg::Say) {
|
||||||
// notify other bots of the spoken text otherwise, bots won't respond to other bots (network messages aren't sent from bots)
|
// notify other bots of the spoken text otherwise, bots won't respond to other bots (network messages aren't sent from bots)
|
||||||
int entityIndex = index ();
|
const int entityIndex = index ();
|
||||||
|
|
||||||
for (const auto &other : bots) {
|
for (const auto &other : bots) {
|
||||||
if (other->pev != pev) {
|
if (other->pev != pev) {
|
||||||
|
|
@ -96,7 +96,7 @@ void Bot::avoidGrenades () {
|
||||||
}
|
}
|
||||||
auto model = pent->v.model.str (9);
|
auto model = pent->v.model.str (9);
|
||||||
|
|
||||||
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == Difficulty::Expert && model == "flashbang.mdl") {
|
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == Difficulty::Expert && model == kFlashbangModelName) {
|
||||||
// don't look at flash bang
|
// don't look at flash bang
|
||||||
if (!(m_states & Sense::SeeingEnemy)) {
|
if (!(m_states & Sense::SeeingEnemy)) {
|
||||||
m_lookAt.y = cr::wrapAngle ((game.getEntityOrigin (pent) - getEyesPos ()).angles ().y + 180.0f);
|
m_lookAt.y = cr::wrapAngle ((game.getEntityOrigin (pent) - getEyesPos ()).angles ().y + 180.0f);
|
||||||
|
|
@ -105,7 +105,7 @@ void Bot::avoidGrenades () {
|
||||||
m_preventFlashing = game.time () + rg.get (1.0f, 2.0f);
|
m_preventFlashing = game.time () + rg.get (1.0f, 2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (game.isNullEntity (m_avoidGrenade) && model == "hegrenade.mdl") {
|
else if (game.isNullEntity (m_avoidGrenade) && model == kExplosiveModelName) {
|
||||||
if (game.getTeam (pent->v.owner) == m_team || pent->v.owner == ent ()) {
|
if (game.getTeam (pent->v.owner) == m_team || pent->v.owner == ent ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,7 @@ void Bot::avoidGrenades () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((pent->v.flags & FL_ONGROUND) && model == "smokegrenade.mdl") {
|
else if ((pent->v.flags & FL_ONGROUND) && model == kSmokeModelName) {
|
||||||
if (isInFOV (pent->v.origin - getEyesPos ()) < pev->fov / 3.0f) {
|
if (isInFOV (pent->v.origin - getEyesPos ()) < pev->fov / 3.0f) {
|
||||||
const auto &entOrigin = game.getEntityOrigin (pent);
|
const auto &entOrigin = game.getEntityOrigin (pent);
|
||||||
const auto &betweenUs = (entOrigin - pev->origin).normalize_apx ();
|
const auto &betweenUs = (entOrigin - pev->origin).normalize_apx ();
|
||||||
|
|
@ -403,8 +403,8 @@ void Bot::updatePickups () {
|
||||||
pickupType = Pickup::Weapon;
|
pickupType = Pickup::Weapon;
|
||||||
|
|
||||||
if (cv_pickup_ammo_and_kits.bool_ ()) {
|
if (cv_pickup_ammo_and_kits.bool_ ()) {
|
||||||
int primaryWeaponCarried = bestPrimaryCarried ();
|
const int primaryWeaponCarried = bestPrimaryCarried ();
|
||||||
int secondaryWeaponCarried = bestSecondaryCarried ();
|
const int secondaryWeaponCarried = bestSecondaryCarried ();
|
||||||
|
|
||||||
const auto &config = conf.getWeapons ();
|
const auto &config = conf.getWeapons ();
|
||||||
const auto &primary = config[primaryWeaponCarried];
|
const auto &primary = config[primaryWeaponCarried];
|
||||||
|
|
@ -493,13 +493,13 @@ void Bot::updatePickups () {
|
||||||
else if (!rateGroundWeapon (ent)) {
|
else if (!rateGroundWeapon (ent)) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
else if ((pev->weapons & cr::bit (Weapon::Flashbang)) && model == "flashbang.mdl") {
|
else if ((pev->weapons & cr::bit (Weapon::Flashbang)) && model == kFlashbangModelName) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
else if ((pev->weapons & cr::bit (Weapon::Explosive)) && model == "hegrenade.mdl") {
|
else if ((pev->weapons & cr::bit (Weapon::Explosive)) && model == kExplosiveModelName) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
else if ((pev->weapons & cr::bit (Weapon::Smoke)) && model == "smokegrenade.mdl") {
|
else if ((pev->weapons & cr::bit (Weapon::Smoke)) && model == kSmokeModelName) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -637,7 +637,6 @@ void Bot::updatePickups () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pev->origin.distanceSq (origin) > cr::sqrf (60.0f)) {
|
if (pev->origin.distanceSq (origin) > cr::sqrf (60.0f)) {
|
||||||
|
|
||||||
if (!graph.isNodeReacheable (pev->origin, origin)) {
|
if (!graph.isNodeReacheable (pev->origin, origin)) {
|
||||||
allowPickup = false;
|
allowPickup = false;
|
||||||
}
|
}
|
||||||
|
|
@ -840,7 +839,7 @@ void Bot::instantChatter (int type) {
|
||||||
const int ownIndex = index ();
|
const int ownIndex = index ();
|
||||||
|
|
||||||
auto writeChatterSound = [&msg] (ChatterItem item) {
|
auto writeChatterSound = [&msg] (ChatterItem item) {
|
||||||
msg.writeString (strings.format ("%s%s%s.wav", cv_chatter_path.str (), PATH_SEP, item.name));
|
msg.writeString (strings.format ("%s%s%s.wav", cv_chatter_path.str (), kPathSeparator, item.name));
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto &client : util.getClients ()) {
|
for (auto &client : util.getClients ()) {
|
||||||
|
|
@ -3483,7 +3482,7 @@ void Bot::resetDoubleJump () {
|
||||||
m_jumpReady = false;
|
m_jumpReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::debugMsgInternal (const char *str) {
|
void Bot::debugMsgInternal (StringRef str) {
|
||||||
if (game.isDedicated ()) {
|
if (game.isDedicated ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ void BotSupport::addChatErrors (String &line) {
|
||||||
if (rg.chance (8) && cv_language.str () == "en") {
|
if (rg.chance (8) && cv_language.str () == "en") {
|
||||||
line.lowercase ();
|
line.lowercase ();
|
||||||
}
|
}
|
||||||
auto length = static_cast <int32_t> (line.length ());
|
const auto length = static_cast <int32_t> (line.length ());
|
||||||
|
|
||||||
if (length > 15) {
|
if (length > 15) {
|
||||||
const auto percentile = length / 2;
|
const auto percentile = length / 2;
|
||||||
|
|
@ -106,6 +106,7 @@ bool BotSupport::checkKeywords (StringRef line, String &reply) {
|
||||||
if (!replyUsed) {
|
if (!replyUsed) {
|
||||||
reply.assign (choosenReply); // update final buffer
|
reply.assign (choosenReply); // update final buffer
|
||||||
usedReplies.push (choosenReply); // add to ignore list
|
usedReplies.push (choosenReply); // add to ignore list
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +169,7 @@ void Bot::prepareChatMessage (StringRef message) {
|
||||||
if (!(client.flags & ClientFlags::Used) || client.ent == ent ()) {
|
if (!(client.flags & ClientFlags::Used) || client.ent == ent ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int frags = static_cast <int> (client.ent->v.frags);
|
const auto frags = static_cast <int> (client.ent->v.frags);
|
||||||
|
|
||||||
if (frags > highestFrags) {
|
if (frags > highestFrags) {
|
||||||
highestFrags = frags;
|
highestFrags = frags;
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ bool Bot::isEnemyHidden (edict_t *enemy) {
|
||||||
if (!cv_check_enemy_rendering.bool_ () || game.isNullEntity (enemy)) {
|
if (!cv_check_enemy_rendering.bool_ () || game.isNullEntity (enemy)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
entvars_t &v = enemy->v;
|
const auto &v = enemy->v;
|
||||||
|
|
||||||
const bool enemyHasGun = (v.weapons & kPrimaryWeaponMask) || (v.weapons & kSecondaryWeaponMask);
|
const bool enemyHasGun = (v.weapons & kPrimaryWeaponMask) || (v.weapons & kSecondaryWeaponMask);
|
||||||
const bool enemyGunfire = (v.button & IN_ATTACK) || (v.oldbuttons & IN_ATTACK);
|
const bool enemyGunfire = (v.button & IN_ATTACK) || (v.oldbuttons & IN_ATTACK);
|
||||||
|
|
@ -94,7 +94,7 @@ bool Bot::isEnemyInvincible (edict_t *enemy) {
|
||||||
if (!cv_check_enemy_invincibility.bool_ () || game.isNullEntity (enemy)) {
|
if (!cv_check_enemy_invincibility.bool_ () || game.isNullEntity (enemy)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const entvars_t &v = enemy->v;
|
const auto &v = enemy->v;
|
||||||
|
|
||||||
if (v.solid < SOLID_BBOX) {
|
if (v.solid < SOLID_BBOX) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -162,14 +162,15 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto standFeet = 34.0f;
|
constexpr auto kStandFeet = 34.0f;
|
||||||
constexpr auto crouchFeet = 14.0f;
|
constexpr auto kCrouchFeet = 14.0f;
|
||||||
|
constexpr auto kEdgeOffset = 13.0f;
|
||||||
|
|
||||||
if (target->v.flags & FL_DUCKING) {
|
if (target->v.flags & FL_DUCKING) {
|
||||||
spot.z = target->v.origin.z - crouchFeet;
|
spot.z = target->v.origin.z - kCrouchFeet;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spot.z = target->v.origin.z - standFeet;
|
spot.z = target->v.origin.z - kStandFeet;
|
||||||
}
|
}
|
||||||
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
||||||
|
|
||||||
|
|
@ -179,12 +180,10 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float edgeOffset = 13.0f;
|
|
||||||
Vector dir = (target->v.origin - pev->origin).normalize2d ();
|
Vector dir = (target->v.origin - pev->origin).normalize2d ();
|
||||||
|
|
||||||
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 * kEdgeOffset, perp.y * kEdgeOffset, 0);
|
||||||
|
|
||||||
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
||||||
|
|
||||||
|
|
@ -194,7 +193,7 @@ bool Bot::checkBodyParts (edict_t *target) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
spot = target->v.origin - Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
spot = target->v.origin - Vector (perp.x * kEdgeOffset, perp.y * kEdgeOffset, 0);
|
||||||
|
|
||||||
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
game.testLine (eyes, spot, ignoreFlags, self, &result);
|
||||||
|
|
||||||
|
|
@ -554,7 +553,7 @@ Vector Bot::getCustomHeight (float distance) {
|
||||||
constexpr float offsetRanges[9][3] = {
|
constexpr float offsetRanges[9][3] = {
|
||||||
{ 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
|
||||||
{ 0.5f, -3.0f, -4.5f }, // pistol
|
{ 0.5f, -0.1f, -1.5f }, // pistol
|
||||||
{ 6.5f, 6.0f, -2.0f }, // shotgun
|
{ 6.5f, 6.0f, -2.0f }, // shotgun
|
||||||
{ 0.5f -7.5f, -9.5f }, // zoomrifle
|
{ 0.5f -7.5f, -9.5f }, // zoomrifle
|
||||||
{ 0.5f, -7.5f, -9.5f }, // rifle
|
{ 0.5f, -7.5f, -9.5f }, // rifle
|
||||||
|
|
@ -771,6 +770,9 @@ bool Bot::needToPauseFiring (float distance) {
|
||||||
else if (distance < kDoubleSprayDistance) {
|
else if (distance < kDoubleSprayDistance) {
|
||||||
offset = 2.75f;
|
offset = 2.75f;
|
||||||
}
|
}
|
||||||
|
else if ((m_states & Sense::SuspectEnemy) && distance < kDoubleSprayDistance) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const float xPunch = cr::sqrf (cr::deg2rad (pev->punchangle.x));
|
const float xPunch = cr::sqrf (cr::deg2rad (pev->punchangle.x));
|
||||||
const float yPunch = cr::sqrf (cr::deg2rad (pev->punchangle.y));
|
const float yPunch = cr::sqrf (cr::deg2rad (pev->punchangle.y));
|
||||||
|
|
||||||
|
|
@ -931,12 +933,12 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
|
||||||
pev->button |= IN_ATTACK;
|
pev->button |= IN_ATTACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr float minDelay[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f };
|
constexpr float kMinFireDelay[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f };
|
||||||
constexpr float maxDelay[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f };
|
constexpr float kMaxFireDelay[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f };
|
||||||
|
|
||||||
const int offset = cr::abs <int> (m_difficulty * 25 / 20 - 5);
|
const int offset = cr::abs <int> (m_difficulty * 25 / 20 - 5);
|
||||||
|
|
||||||
m_shootTime = game.time () + 0.1f + rg.get (minDelay[offset], maxDelay[offset]);
|
m_shootTime = game.time () + 0.1f + rg.get (kMinFireDelay[offset], kMaxFireDelay[offset]);
|
||||||
m_zoomCheckTime = game.time ();
|
m_zoomCheckTime = game.time ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -944,8 +946,8 @@ 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
|
||||||
//
|
|
||||||
// do not handle this if with grenade, as it's done it throw grendate task
|
// do not handle this if with grenade, as it's done it throw grenade task
|
||||||
if (m_isUsingGrenade) {
|
if (m_isUsingGrenade) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -963,7 +965,7 @@ void Bot::fireWeapons () {
|
||||||
const auto tab = conf.getRawWeapons ();
|
const auto tab = conf.getRawWeapons ();
|
||||||
const auto weapons = pev->weapons;
|
const auto weapons = pev->weapons;
|
||||||
|
|
||||||
// if jason mode use knife only
|
// if knife mode use knife only
|
||||||
if (isKnifeMode ()) {
|
if (isKnifeMode ()) {
|
||||||
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
|
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1707,10 +1709,10 @@ void Bot::checkReload () {
|
||||||
|
|
||||||
float Bot::calculateScaleFactor (edict_t *ent) {
|
float Bot::calculateScaleFactor (edict_t *ent) {
|
||||||
Vector entSize = ent->v.maxs - ent->v.mins;
|
Vector entSize = ent->v.maxs - ent->v.mins;
|
||||||
float entArea = 2.0f * (entSize.x * entSize.y + entSize.y * entSize.z + entSize.x * entSize.z);
|
const float entArea = 2.0f * (entSize.x * entSize.y + entSize.y * entSize.z + entSize.x * entSize.z);
|
||||||
|
|
||||||
Vector botSize = pev->maxs - pev->mins;
|
Vector botSize = pev->maxs - pev->mins;
|
||||||
float botArea = 2.0f * (botSize.x * botSize.y + botSize.y * botSize.z + botSize.x * botSize.z);
|
const float botArea = 2.0f * (botSize.x * botSize.y + botSize.y * botSize.z + botSize.x * botSize.z);
|
||||||
|
|
||||||
return entArea / botArea;
|
return entArea / botArea;
|
||||||
}
|
}
|
||||||
|
|
@ -1809,7 +1811,7 @@ Vector Bot::calcThrow (const Vector &start, const Vector &stop) {
|
||||||
return velocity * 0.7793f;
|
return velocity * 0.7793f;
|
||||||
}
|
}
|
||||||
|
|
||||||
edict_t *Bot::setCorrectGrenadeVelocity (const char *model) {
|
edict_t *Bot::setCorrectGrenadeVelocity (StringRef model) {
|
||||||
edict_t *result = nullptr;
|
edict_t *result = nullptr;
|
||||||
|
|
||||||
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
||||||
|
|
@ -1856,11 +1858,11 @@ void Bot::checkGrenadesThrow () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we have grenades to throw
|
// check if we have grenades to throw
|
||||||
int grenadeToThrow = bestGrenadeCarried ();
|
const auto grenadeToThrow = bestGrenadeCarried ();
|
||||||
|
|
||||||
// if we don't have grenades no need to check it this round again
|
// if we don't have grenades no need to check it this round again
|
||||||
if (grenadeToThrow == -1) {
|
if (grenadeToThrow == -1) {
|
||||||
m_grenadeCheckTime = game.time () + 15.0f; // changed since, conzero can drop grens from dead players
|
m_grenadeCheckTime = game.time () + 15.0f; // changed since, czero can drop grenades from dead players
|
||||||
|
|
||||||
clearThrowStates (m_states);
|
clearThrowStates (m_states);
|
||||||
return;
|
return;
|
||||||
|
|
@ -2051,18 +2053,18 @@ bool Bot::isEnemyNoticeable (float range) {
|
||||||
if (m_enemyParts & Visibility::Other) {
|
if (m_enemyParts & Visibility::Other) {
|
||||||
coverRatio += rg.get (10.0f, 25.0f);
|
coverRatio += rg.get (10.0f, 25.0f);
|
||||||
}
|
}
|
||||||
constexpr float closeRange = 300.0f;
|
constexpr float kCloseRange = 300.0f;
|
||||||
constexpr float farRange = 1000.0f;
|
constexpr float kFarRange = 1000.0f;
|
||||||
|
|
||||||
float rangeModifier;
|
float rangeModifier;
|
||||||
if (range < closeRange) {
|
if (range < kCloseRange) {
|
||||||
rangeModifier = 0.0f;
|
rangeModifier = 0.0f;
|
||||||
}
|
}
|
||||||
else if (range > farRange) {
|
else if (range > kFarRange) {
|
||||||
rangeModifier = 1.0f;
|
rangeModifier = 1.0f;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rangeModifier = (range - closeRange) / (farRange - closeRange);
|
rangeModifier = (range - kCloseRange) / (kFarRange - kCloseRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// harder to notice when crouched
|
// harder to notice when crouched
|
||||||
|
|
@ -2072,13 +2074,13 @@ bool Bot::isEnemyNoticeable (float range) {
|
||||||
float playerSpeedSq = m_enemy->v.velocity.lengthSq ();
|
float playerSpeedSq = m_enemy->v.velocity.lengthSq ();
|
||||||
float farChance, closeChance;
|
float farChance, closeChance;
|
||||||
|
|
||||||
constexpr float runSpeed = cr::sqrf (200.0f);
|
constexpr float kRunSpeed = cr::sqrf (200.0f);
|
||||||
constexpr float walkSpeed = cr::sqrf (30.0f);
|
constexpr float kWalkSpeed = cr::sqrf (30.0f);
|
||||||
|
|
||||||
if (playerSpeedSq > runSpeed) {
|
if (playerSpeedSq > kRunSpeed) {
|
||||||
return true; // running players are always easy to spot (must be standing to run)
|
return true; // running players are always easy to spot (must be standing to run)
|
||||||
}
|
}
|
||||||
else if (playerSpeedSq > walkSpeed) {
|
else if (playerSpeedSq > kWalkSpeed) {
|
||||||
// walking players are less noticeable far away
|
// walking players are less noticeable far away
|
||||||
if (isCrouching) {
|
if (isCrouching) {
|
||||||
closeChance = 90.0f;
|
closeChance = 90.0f;
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,8 @@ void BotConfig::loadNamesConfig () {
|
||||||
String line;
|
String line;
|
||||||
MemFile file;
|
MemFile file;
|
||||||
|
|
||||||
|
constexpr auto kMaxNameLen = 32;
|
||||||
|
|
||||||
// naming initialization
|
// naming initialization
|
||||||
if (openConfig ("names", "Name configuration file not found.", &file, true)) {
|
if (openConfig ("names", "Name configuration file not found.", &file, true)) {
|
||||||
m_botNames.clear ();
|
m_botNames.clear ();
|
||||||
|
|
@ -135,8 +137,8 @@ void BotConfig::loadNamesConfig () {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// max botname is 32 characters
|
// max botname is 32 characters
|
||||||
if (line.length () > 32) {
|
if (line.length () > kMaxNameLen - 1) {
|
||||||
line[32] = kNullChar;
|
line[kMaxNameLen - 1] = kNullChar;
|
||||||
}
|
}
|
||||||
m_botNames.emplace (line, -1);
|
m_botNames.emplace (line, -1);
|
||||||
}
|
}
|
||||||
|
|
@ -583,7 +585,7 @@ void BotConfig::loadDifficultyConfig () {
|
||||||
diff->aimError.z = values[8].float_ ();
|
diff->aimError.z = values[8].float_ ();
|
||||||
};
|
};
|
||||||
|
|
||||||
// avatars initialization
|
// difficulty initialization
|
||||||
if (openConfig ("difficulty", "Difficulty config file not found. Loading defaults.", &file)) {
|
if (openConfig ("difficulty", "Difficulty config file not found. Loading defaults.", &file)) {
|
||||||
|
|
||||||
while (file.getLine (line)) {
|
while (file.getLine (line)) {
|
||||||
|
|
@ -706,20 +708,20 @@ BotName *BotConfig::pickBotName () {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_botNames.length () * 2; ++i) {
|
for (size_t i = 0; i < m_botNames.length () * 2; ++i) {
|
||||||
auto botName = &m_botNames.random ();
|
auto bn = &m_botNames.random ();
|
||||||
|
|
||||||
if (botName->name.length () < 3 || botName->usedBy != -1) {
|
if (bn->name.length () < 3 || bn->usedBy != -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return botName;
|
return bn;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotConfig::clearUsedName (Bot *bot) {
|
void BotConfig::clearUsedName (Bot *bot) {
|
||||||
for (auto &name : m_botNames) {
|
for (auto &bn : m_botNames) {
|
||||||
if (name.usedBy == bot->index ()) {
|
if (bn.usedBy == bot->index ()) {
|
||||||
name.usedBy = -1;
|
bn.usedBy = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ int BotControl::cmdCvars () {
|
||||||
|
|
||||||
if (isSave) {
|
if (isSave) {
|
||||||
if (!cfg) {
|
if (!cfg) {
|
||||||
msg ("Unable to write cvars to config file. File not accesssible");
|
msg ("Unable to write cvars to config file. File not accessible");
|
||||||
return BotCommandResult::Handled;
|
return BotCommandResult::Handled;
|
||||||
}
|
}
|
||||||
msg ("Bots cvars has been written to file.");
|
msg ("Bots cvars has been written to file.");
|
||||||
|
|
@ -368,6 +368,7 @@ int BotControl::cmdNode () {
|
||||||
addGraphCmd ("path_create_jump", "path_create_jump [noarguments]", "Creates jumping path connection from nearest to faced node.", &BotControl::cmdNodePathCreate);
|
addGraphCmd ("path_create_jump", "path_create_jump [noarguments]", "Creates jumping path connection from nearest to faced node.", &BotControl::cmdNodePathCreate);
|
||||||
addGraphCmd ("path_delete", "path_delete [noarguments]", "Deletes path from nearest to faced node.", &BotControl::cmdNodePathDelete);
|
addGraphCmd ("path_delete", "path_delete [noarguments]", "Deletes path from nearest to faced node.", &BotControl::cmdNodePathDelete);
|
||||||
addGraphCmd ("path_set_autopath", "path_set_autopath [max_distance]", "Opens menu for setting autopath maximum distance.", &BotControl::cmdNodePathSetAutoDistance);
|
addGraphCmd ("path_set_autopath", "path_set_autopath [max_distance]", "Opens menu for setting autopath maximum distance.", &BotControl::cmdNodePathSetAutoDistance);
|
||||||
|
addGraphCmd ("path_clean", "path_clean [index]", "Clean's up all types of connections from the node.", &BotControl::cmdNodePathCleanAll);
|
||||||
|
|
||||||
// camp points iterator
|
// camp points iterator
|
||||||
addGraphCmd ("iterate_camp", "iterate_camp [begin|end|next]", "Allows to go through all camp points on map.", &BotControl::cmdNodeIterateCamp);
|
addGraphCmd ("iterate_camp", "iterate_camp [begin|end|next]", "Allows to go through all camp points on map.", &BotControl::cmdNodeIterateCamp);
|
||||||
|
|
@ -756,6 +757,19 @@ int BotControl::cmdNodePathSetAutoDistance () {
|
||||||
return BotCommandResult::Handled;
|
return BotCommandResult::Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BotControl::cmdNodePathCleanAll () {
|
||||||
|
enum args { graph_cmd = 1, cmd, index };
|
||||||
|
|
||||||
|
auto requestedNode = kInvalidNodeIndex;
|
||||||
|
|
||||||
|
if (hasArg (index)) {
|
||||||
|
requestedNode = intValue (index);
|
||||||
|
}
|
||||||
|
graph.resetPath (requestedNode);
|
||||||
|
|
||||||
|
return BotCommandResult::Handled;
|
||||||
|
}
|
||||||
|
|
||||||
int BotControl::cmdNodeAcquireEditor () {
|
int BotControl::cmdNodeAcquireEditor () {
|
||||||
enum args { graph_cmd = 1 };
|
enum args { graph_cmd = 1 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -803,7 +803,7 @@ bool Game::loadCSBinary () {
|
||||||
|
|
||||||
// search the libraries inside game dlls directory
|
// search the libraries inside game dlls directory
|
||||||
for (const auto &lib : libs) {
|
for (const auto &lib : libs) {
|
||||||
auto path = strings.joinPath (modname, "dlls", lib) + DLL_SUFFIX;
|
auto path = strings.joinPath (modname, "dlls", lib) + kLibrarySuffix;
|
||||||
|
|
||||||
// if we can't read file, skip it
|
// if we can't read file, skip it
|
||||||
if (!plat.fileExists (path.chars ())) {
|
if (!plat.fileExists (path.chars ())) {
|
||||||
|
|
@ -1136,7 +1136,7 @@ void LightMeasure::initializeLightstyles () {
|
||||||
// reset all light styles
|
// reset all light styles
|
||||||
for (auto &ls : m_lightstyle) {
|
for (auto &ls : m_lightstyle) {
|
||||||
ls.length = 0;
|
ls.length = 0;
|
||||||
ls.map[0] = 0;
|
ls.map[0] = kNullChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &lsv : m_lightstyleValue) {
|
for (auto &lsv : m_lightstyleValue) {
|
||||||
|
|
@ -1226,7 +1226,7 @@ template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const
|
||||||
if (surf->flags & SURF_DRAWTILED) {
|
if (surf->flags & SURF_DRAWTILED) {
|
||||||
continue; // no lightmaps
|
continue; // no lightmaps
|
||||||
}
|
}
|
||||||
auto tex = surf->texinfo;
|
const auto tex = surf->texinfo;
|
||||||
|
|
||||||
// see where in lightmap space our intersection point is
|
// see where in lightmap space our intersection point is
|
||||||
const int s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
|
const int s = static_cast <int> ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]);
|
||||||
|
|
|
||||||
|
|
@ -1135,6 +1135,45 @@ void BotGraph::erasePath () {
|
||||||
msg ("There is already no path on this node.");
|
msg ("There is already no path on this node.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BotGraph::resetPath (int index) {
|
||||||
|
int node = index;
|
||||||
|
|
||||||
|
if (!exists (node)) {
|
||||||
|
node = getEditorNearest ();
|
||||||
|
|
||||||
|
if (!exists (node)) {
|
||||||
|
msg ("Unable to find nearest node in 50 units.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper
|
||||||
|
auto destroy = [] (PathLink &link) -> void {
|
||||||
|
link.index = kInvalidNodeIndex;
|
||||||
|
link.distance = 0;
|
||||||
|
link.flags = 0;
|
||||||
|
link.velocity = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// clean all incoming
|
||||||
|
for (auto &connected : m_paths) {
|
||||||
|
for (auto &link : connected.links) {
|
||||||
|
if (link.index == node) {
|
||||||
|
destroy (link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean all outgoing connections
|
||||||
|
for (auto &link : m_paths[node].links) {
|
||||||
|
destroy (link);
|
||||||
|
}
|
||||||
|
emitNotify (NotifySound::Change);
|
||||||
|
|
||||||
|
// notify use something evil happened
|
||||||
|
msg ("All paths for node #%d has been reset.", node);
|
||||||
|
}
|
||||||
|
|
||||||
void BotGraph::cachePoint (int index) {
|
void BotGraph::cachePoint (int index) {
|
||||||
const int node = exists (index) ? index : getEditorNearest ();
|
const int node = exists (index) ? index : getEditorNearest ();
|
||||||
|
|
||||||
|
|
@ -1579,7 +1618,7 @@ bool BotGraph::loadGraphData () {
|
||||||
reset ();
|
reset ();
|
||||||
|
|
||||||
// check if loaded
|
// check if loaded
|
||||||
bool dataLoaded = bstor.load <Path> (m_paths, &exten, &outOptions);
|
const bool dataLoaded = bstor.load <Path> (m_paths, &exten, &outOptions);
|
||||||
|
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
initBuckets ();
|
initBuckets ();
|
||||||
|
|
@ -1898,7 +1937,7 @@ void BotGraph::frame () {
|
||||||
for (auto &path : m_paths) {
|
for (auto &path : m_paths) {
|
||||||
const float distanceSq = path.origin.distanceSq (m_editor->v.origin);
|
const float distanceSq = path.origin.distanceSq (m_editor->v.origin);
|
||||||
|
|
||||||
// check if node is whitin a distance, and is visible
|
// check if node is within a distance, and is visible
|
||||||
if (distanceSq < cr::sqrf (cv_graph_draw_distance.float_ ()) && ((util.isVisible (path.origin, m_editor) && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distanceSq < cr::sqrf (64.0f))) {
|
if (distanceSq < cr::sqrf (cv_graph_draw_distance.float_ ()) && ((util.isVisible (path.origin, m_editor) && util.isInViewCone (path.origin, m_editor)) || !util.isAlive (m_editor) || distanceSq < cr::sqrf (64.0f))) {
|
||||||
// check the distance
|
// check the distance
|
||||||
if (distanceSq < nearestDistanceSq) {
|
if (distanceSq < nearestDistanceSq) {
|
||||||
|
|
@ -2128,7 +2167,7 @@ void BotGraph::frame () {
|
||||||
};
|
};
|
||||||
|
|
||||||
// very helpful stuff..
|
// very helpful stuff..
|
||||||
auto getNodeData = [&] (StringRef type, int node) -> String {
|
auto getNodeData = [this] (StringRef type, int node) -> String {
|
||||||
String message, flags;
|
String message, flags;
|
||||||
|
|
||||||
const auto &p = m_paths[node];
|
const auto &p = m_paths[node];
|
||||||
|
|
|
||||||
|
|
@ -992,7 +992,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
|
||||||
// this function does core operation of creating bot, it's called by addbot (),
|
// this function does core operation of creating bot, it's called by addbot (),
|
||||||
// when bot setup completed, (this is a bot class constructor)
|
// when bot setup completed, (this is a bot class constructor)
|
||||||
|
|
||||||
int clientIndex = game.indexOfEntity (bot);
|
const int clientIndex = game.indexOfEntity (bot);
|
||||||
pev = &bot->v;
|
pev = &bot->v;
|
||||||
|
|
||||||
if (bot->pvPrivateData != nullptr) {
|
if (bot->pvPrivateData != nullptr) {
|
||||||
|
|
@ -1176,25 +1176,25 @@ int BotManager::getAliveHumansCount () {
|
||||||
}
|
}
|
||||||
|
|
||||||
int BotManager::getPlayerPriority (edict_t *ent) {
|
int BotManager::getPlayerPriority (edict_t *ent) {
|
||||||
constexpr auto highPrio = 512;
|
constexpr auto kHighPriority = 512;
|
||||||
|
|
||||||
// always check for only our own bots
|
// always check for only our own bots
|
||||||
auto bot = bots[ent];
|
auto bot = bots[ent];
|
||||||
|
|
||||||
// if player just return high prio
|
// if player just return high prio
|
||||||
if (!bot) {
|
if (!bot) {
|
||||||
return game.indexOfEntity (ent) + highPrio;
|
return game.indexOfEntity (ent) + kHighPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
// give bots some priority
|
// give bots some priority
|
||||||
if (bot->m_hasC4 || bot->m_isVIP || bot->m_hasHostage || bot->m_healthValue < ent->v.health) {
|
if (bot->m_hasC4 || bot->m_isVIP || bot->m_hasHostage || bot->m_healthValue < ent->v.health) {
|
||||||
return bot->entindex () + highPrio;
|
return bot->entindex () + kHighPriority;
|
||||||
}
|
}
|
||||||
auto task = bot->getCurrentTaskId ();
|
auto task = bot->getCurrentTaskId ();
|
||||||
|
|
||||||
// higher priority if camping or hiding
|
// higher priority if camping or hiding
|
||||||
if (task == Task::Camp || task == Task::Hide) {
|
if (task == Task::Camp || task == Task::Hide) {
|
||||||
return bot->entindex () + highPrio;
|
return bot->entindex () + kHighPriority;
|
||||||
}
|
}
|
||||||
return bot->entindex ();
|
return bot->entindex ();
|
||||||
}
|
}
|
||||||
|
|
@ -1229,7 +1229,7 @@ void BotManager::erase (Bot *bot) {
|
||||||
}
|
}
|
||||||
bot->markStale ();
|
bot->markStale ();
|
||||||
|
|
||||||
auto index = m_bots.index (e);
|
const auto index = m_bots.index (e);
|
||||||
e.reset ();
|
e.reset ();
|
||||||
|
|
||||||
m_bots.erase (index, 1); // remove from bots array
|
m_bots.erase (index, 1); // remove from bots array
|
||||||
|
|
@ -1291,6 +1291,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
|
||||||
if (victimBot != nullptr) {
|
if (victimBot != nullptr) {
|
||||||
if (killerTeam == victimBot->m_team) {
|
if (killerTeam == victimBot->m_team) {
|
||||||
victimBot->m_voteKickIndex = game.indexOfEntity (killer);
|
victimBot->m_voteKickIndex = game.indexOfEntity (killer);
|
||||||
|
|
||||||
for (const auto ¬ify : bots) {
|
for (const auto ¬ify : bots) {
|
||||||
if (notify->seesEntity (victim->v.origin)) {
|
if (notify->seesEntity (victim->v.origin)) {
|
||||||
notify->pushChatterMessage (Chatter::TeamKill);
|
notify->pushChatterMessage (Chatter::TeamKill);
|
||||||
|
|
@ -1502,6 +1503,9 @@ void Bot::newRound () {
|
||||||
m_goalHist.clear ();
|
m_goalHist.clear ();
|
||||||
m_ignoredBreakable.clear ();
|
m_ignoredBreakable.clear ();
|
||||||
|
|
||||||
|
// update refvec for blocked movement
|
||||||
|
updateRightRef ();
|
||||||
|
|
||||||
// and put buying into its message queue
|
// and put buying into its message queue
|
||||||
pushMsgQueue (BotMsg::Buy);
|
pushMsgQueue (BotMsg::Buy);
|
||||||
startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
|
startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
|
||||||
|
|
@ -1618,7 +1622,7 @@ void Bot::updateTeamJoin () {
|
||||||
m_startAction = BotMsg::TeamSelect;
|
m_startAction = BotMsg::TeamSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if bot was unable to join team, and no menus popups, check for stacked team
|
// if bot was unable to join team, and no menus pop-ups, check for stacked team
|
||||||
if (m_startAction == BotMsg::None) {
|
if (m_startAction == BotMsg::None) {
|
||||||
if (++m_retryJoin > 3 && bots.isTeamStacked (m_wantedTeam - 1)) {
|
if (++m_retryJoin > 3 && bots.isTeamStacked (m_wantedTeam - 1)) {
|
||||||
m_retryJoin = 0;
|
m_retryJoin = 0;
|
||||||
|
|
@ -1710,7 +1714,7 @@ void BotManager::captureChatRadio (StringRef cmd, StringRef arg, edict_t *ent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd.startsWith ("say")) {
|
if (cmd.startsWith ("say")) {
|
||||||
const bool alive = util.isAlive (ent);
|
const bool alive = util.isAlive (ent);
|
||||||
int team = -1;
|
int team = -1;
|
||||||
|
|
||||||
if (cmd == "say_team") {
|
if (cmd == "say_team") {
|
||||||
|
|
@ -1768,7 +1772,7 @@ void BotManager::notifyBombDefuse () {
|
||||||
const auto &bombPos = graph.getBombOrigin ();
|
const auto &bombPos = graph.getBombOrigin ();
|
||||||
|
|
||||||
for (const auto &bot : bots) {
|
for (const auto &bot : bots) {
|
||||||
auto task = bot->getCurrentTaskId ();
|
const auto task = bot->getCurrentTaskId ();
|
||||||
|
|
||||||
if (!bot->m_defuseNotified && bot->m_notKilled && task != Task::MoveToPosition && task != Task::DefuseBomb && task != Task::EscapeFromBomb) {
|
if (!bot->m_defuseNotified && bot->m_notKilled && task != Task::MoveToPosition && task != Task::DefuseBomb && task != Task::EscapeFromBomb) {
|
||||||
if (bot->m_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (384.0f)) {
|
if (bot->m_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (384.0f)) {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ void MessageDispatcher::netMsgVGUIMenu () {
|
||||||
|
|
||||||
enum args { menu = 0, min = 1 };
|
enum args { menu = 0, min = 1 };
|
||||||
|
|
||||||
// check the minimum states or existance of bot
|
// check the minimum states or existence of bot
|
||||||
if (m_args.length () < min || !m_bot) {
|
if (m_args.length () < min || !m_bot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ void MessageDispatcher::netMsgShowMenu () {
|
||||||
|
|
||||||
enum args { menu = 3, min = 4 };
|
enum args { menu = 3, min = 4 };
|
||||||
|
|
||||||
// check the minimum states or existance of bot
|
// check the minimum states or existence of bot
|
||||||
if (m_args.length () < min || !m_bot) {
|
if (m_args.length () < min || !m_bot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +144,7 @@ void MessageDispatcher::netMsgWeaponList () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageDispatcher::netMsgCurWeapon () {
|
void MessageDispatcher::netMsgCurWeapon () {
|
||||||
// this message is sent when a weapon is selected (either by the bot chosing a weapon or by the server auto assigning the bot a weapon). In CS it's also called when Ammo is increased/decreased
|
// this message is sent when a weapon is selected (either by the bot choosing a weapon or by the server auto assigning the bot a weapon). In CS it's also called when Ammo is increased/decreased
|
||||||
|
|
||||||
enum args { state = 0, id = 1, clip = 2, min = 3 };
|
enum args { state = 0, id = 1, clip = 2, min = 3 };
|
||||||
|
|
||||||
|
|
@ -524,7 +524,7 @@ void MessageDispatcher::start (edict_t *ent, int32_t type) {
|
||||||
m_current = m_handlers[msg] ? msg : NetMsg::None;
|
m_current = m_handlers[msg] ? msg : NetMsg::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no messagem no processing
|
// no message no processing
|
||||||
if (m_current == NetMsg::None) {
|
if (m_current == NetMsg::None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -571,6 +571,6 @@ int32_t MessageDispatcher::id (NetMsg msg) {
|
||||||
Bot *MessageDispatcher::pickBot (int32_t index) {
|
Bot *MessageDispatcher::pickBot (int32_t index) {
|
||||||
const auto &client = util.getClient (m_args[index].long_ - 1);
|
const auto &client = util.getClient (m_args[index].long_ - 1);
|
||||||
|
|
||||||
// get the bot in this msg
|
// get the bot in this message
|
||||||
return bots[client.ent];
|
return bots[client.ent];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -661,7 +661,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seesEntity (m_destOrigin)) {
|
if (seesEntity (m_destOrigin)) {
|
||||||
auto right = m_moveAngles.right ();
|
const auto &right = m_moveAngles.right ();
|
||||||
|
|
||||||
src = getEyesPos ();
|
src = getEyesPos ();
|
||||||
src = src + right * 15.0f;
|
src = src + right * 15.0f;
|
||||||
|
|
@ -910,7 +910,7 @@ bool Bot::updateNavigation () {
|
||||||
if (feet.z > pev->origin.z) {
|
if (feet.z > pev->origin.z) {
|
||||||
feet = pev->origin + pev->maxs;
|
feet = pev->origin + pev->maxs;
|
||||||
}
|
}
|
||||||
feet = { pev->origin.x, pev->origin.y, feet.z };
|
feet = { pev->origin.x, pev->origin.y, feet.z };
|
||||||
|
|
||||||
// calculate like we do with grenades
|
// calculate like we do with grenades
|
||||||
auto velocity = calcThrow (feet, node);
|
auto velocity = calcThrow (feet, node);
|
||||||
|
|
@ -949,9 +949,8 @@ bool Bot::updateNavigation () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_pathFlags & NodeFlag::Ladder) || isOnLadder ()) {
|
if ((m_pathFlags & NodeFlag::Ladder) || isOnLadder ()) {
|
||||||
constexpr auto kLadderOffset = Vector (0.0f, 0.0f, 16.0f);
|
|
||||||
|
|
||||||
if (m_pathOrigin.z >= (pev->origin.z + 16.0f)) {
|
if (m_pathOrigin.z >= (pev->origin.z + 16.0f)) {
|
||||||
|
constexpr auto kLadderOffset = Vector (0.0f, 0.0f, 16.0f);
|
||||||
m_pathOrigin = m_path->origin + kLadderOffset;
|
m_pathOrigin = m_path->origin + kLadderOffset;
|
||||||
}
|
}
|
||||||
else if (m_pathOrigin.z < pev->origin.z + 16.0f && !isOnLadder () && isOnFloor () && !(pev->flags & FL_DUCKING)) {
|
else if (m_pathOrigin.z < pev->origin.z + 16.0f && !isOnLadder () && isOnFloor () && !(pev->flags & FL_DUCKING)) {
|
||||||
|
|
@ -1059,7 +1058,7 @@ bool Bot::updateNavigation () {
|
||||||
ignoreCollision (); // don't consider being stuck
|
ignoreCollision (); // don't consider being stuck
|
||||||
|
|
||||||
if (rg.chance (50)) {
|
if (rg.chance (50)) {
|
||||||
// do not use door directrly under xash, or we will get failed assert in gamedll code
|
// do not use door directly under xash, or we will get failed assert in gamedll code
|
||||||
if (game.is (GameFlags::Xash3D)) {
|
if (game.is (GameFlags::Xash3D)) {
|
||||||
pev->button |= IN_USE;
|
pev->button |= IN_USE;
|
||||||
}
|
}
|
||||||
|
|
@ -1357,7 +1356,7 @@ bool Bot::updateLiftHandling () {
|
||||||
|
|
||||||
// bot is trying to find button inside a lift
|
// bot is trying to find button inside a lift
|
||||||
if (m_liftState == LiftState::LookingButtonInside) {
|
if (m_liftState == LiftState::LookingButtonInside) {
|
||||||
auto button = lookupButton (m_liftEntity->v.targetname.chars ());
|
auto button = lookupButton (m_liftEntity->v.targetname.str ());
|
||||||
|
|
||||||
// got a valid button entity ?
|
// got a valid button entity ?
|
||||||
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && cr::fzero (m_liftEntity->v.velocity.z) && isOnFloor ()) {
|
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && cr::fzero (m_liftEntity->v.velocity.z) && isOnFloor ()) {
|
||||||
|
|
@ -1406,7 +1405,7 @@ bool Bot::updateLiftHandling () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!game.isNullEntity (m_liftEntity)) {
|
else if (!game.isNullEntity (m_liftEntity)) {
|
||||||
auto button = lookupButton (m_liftEntity->v.targetname.chars ());
|
auto button = lookupButton (m_liftEntity->v.targetname.str ());
|
||||||
|
|
||||||
// if we got a valid button entity
|
// if we got a valid button entity
|
||||||
if (!game.isNullEntity (button)) {
|
if (!game.isNullEntity (button)) {
|
||||||
|
|
@ -1702,18 +1701,18 @@ void Bot::findValidNode () {
|
||||||
findNextBestNode ();
|
findNextBestNode ();
|
||||||
}
|
}
|
||||||
else if (m_navTimeset + getEstimatedNodeReachTime () < game.time ()) {
|
else if (m_navTimeset + getEstimatedNodeReachTime () < game.time ()) {
|
||||||
constexpr int maxDamageValue = PracticeLimit::Damage;
|
constexpr int kMaxDamageValue = PracticeLimit::Damage;
|
||||||
|
|
||||||
// increase danger for both teams
|
// increase danger for both teams
|
||||||
for (int team = Team::Terrorist; team < kGameTeamNum; ++team) {
|
for (int team = Team::Terrorist; team < kGameTeamNum; ++team) {
|
||||||
int damageValue = practice.getDamage (team, m_currentNodeIndex, m_currentNodeIndex);
|
int damageValue = practice.getDamage (team, m_currentNodeIndex, m_currentNodeIndex);
|
||||||
damageValue = cr::clamp (damageValue + 100, 0, maxDamageValue);
|
damageValue = cr::clamp (damageValue + 100, 0, kMaxDamageValue);
|
||||||
|
|
||||||
// affect nearby connected with victim nodes
|
// affect nearby connected with victim nodes
|
||||||
for (auto &neighbour : m_path->links) {
|
for (auto &neighbour : m_path->links) {
|
||||||
if (graph.exists (neighbour.index)) {
|
if (graph.exists (neighbour.index)) {
|
||||||
int neighbourValue = practice.getDamage (team, neighbour.index, neighbour.index);
|
int neighbourValue = practice.getDamage (team, neighbour.index, neighbour.index);
|
||||||
neighbourValue = cr::clamp (neighbourValue + 100, 0, maxDamageValue);
|
neighbourValue = cr::clamp (neighbourValue + 100, 0, kMaxDamageValue);
|
||||||
|
|
||||||
practice.setDamage (m_team, neighbour.index, neighbour.index, neighbourValue);
|
practice.setDamage (m_team, neighbour.index, neighbour.index, neighbourValue);
|
||||||
}
|
}
|
||||||
|
|
@ -2062,8 +2061,8 @@ int Bot::findCoverNode (float maxDistance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the 'real' pathfinding distances
|
// use the 'real' pathfinding distances
|
||||||
float distance = planner.dist (srcIndex, path.number);
|
const float distance = planner.dist (srcIndex, path.number);
|
||||||
float enemyDistance = planner.dist (enemyIndex, path.number);
|
const float enemyDistance = planner.dist (enemyIndex, path.number);
|
||||||
|
|
||||||
if (distance >= enemyDistance) {
|
if (distance >= enemyDistance) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -2408,6 +2407,10 @@ void Bot::setPathOrigin () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::updateRightRef () {
|
||||||
|
m_rightRef = Vector { 0.0f, pev->angles.y, 0.0f }.right (); // convert current view angle to vectors for traceline math...
|
||||||
|
}
|
||||||
|
|
||||||
bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
// checks if bot is blocked in his movement direction (excluding doors)
|
// checks if bot is blocked in his movement direction (excluding doors)
|
||||||
|
|
||||||
|
|
@ -2416,7 +2419,6 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
// first do a trace from the bot's eyes forward...
|
// first do a trace from the bot's eyes forward...
|
||||||
auto src = getEyesPos ();
|
auto src = getEyesPos ();
|
||||||
auto forward = src + normal * 24.0f;
|
auto forward = src + normal * 24.0f;
|
||||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
|
||||||
|
|
||||||
auto checkDoor = [] (TraceResult *result) {
|
auto checkDoor = [] (TraceResult *result) {
|
||||||
if (!game.mapIs (MapFlags::HasDoors)) {
|
if (!game.mapIs (MapFlags::HasDoors)) {
|
||||||
|
|
@ -2437,10 +2439,13 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
}
|
}
|
||||||
constexpr auto kVec00N16 = Vector (0.0f, 0.0f, -16.0f);
|
constexpr auto kVec00N16 = Vector (0.0f, 0.0f, -16.0f);
|
||||||
|
|
||||||
|
// right referential vector
|
||||||
|
updateRightRef ();
|
||||||
|
|
||||||
// bot's head is clear, check at shoulder level...
|
// bot's head is clear, check at shoulder level...
|
||||||
// trace from the bot's shoulder left diagonal forward to the right shoulder...
|
// trace from the bot's shoulder left diagonal forward to the right shoulder...
|
||||||
src = getEyesPos () + kVec00N16 - right * -16.0f;
|
src = getEyesPos () + kVec00N16 - m_rightRef * -16.0f;
|
||||||
forward = getEyesPos () + kVec00N16 + right * 16.0f + normal * 24.0f;
|
forward = getEyesPos () + kVec00N16 + m_rightRef * 16.0f + normal * 24.0f;
|
||||||
|
|
||||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||||
|
|
||||||
|
|
@ -2451,8 +2456,8 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
|
|
||||||
// bot's head is clear, check at shoulder level...
|
// bot's head is clear, check at shoulder level...
|
||||||
// trace from the bot's shoulder right diagonal forward to the left shoulder...
|
// trace from the bot's shoulder right diagonal forward to the left shoulder...
|
||||||
src = getEyesPos () + kVec00N16 + right * 16.0f;
|
src = getEyesPos () + kVec00N16 + m_rightRef * 16.0f;
|
||||||
forward = getEyesPos () + kVec00N16 - right * -16.0f + normal * 24.0f;
|
forward = getEyesPos () + kVec00N16 - m_rightRef * -16.0f + normal * 24.0f;
|
||||||
|
|
||||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||||
|
|
||||||
|
|
@ -2487,8 +2492,8 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
constexpr auto kVec00N24 = Vector (0.0f, 0.0f, -24.0f);
|
constexpr auto kVec00N24 = Vector (0.0f, 0.0f, -24.0f);
|
||||||
|
|
||||||
// trace from the left waist to the right forward waist pos
|
// trace from the left waist to the right forward waist pos
|
||||||
src = pev->origin + kVec00N17 - right * -16.0f;
|
src = pev->origin + kVec00N17 - m_rightRef * -16.0f;
|
||||||
forward = pev->origin + kVec00N17 + right * 16.0f + normal * 24.0f;
|
forward = pev->origin + kVec00N17 + m_rightRef * 16.0f + normal * 24.0f;
|
||||||
|
|
||||||
// trace from the bot's waist straight forward...
|
// trace from the bot's waist straight forward...
|
||||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||||
|
|
@ -2499,8 +2504,8 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// trace from the left waist to the right forward waist pos
|
// trace from the left waist to the right forward waist pos
|
||||||
src = pev->origin + kVec00N24 + right * 16.0f;
|
src = pev->origin + kVec00N24 + m_rightRef * 16.0f;
|
||||||
forward = pev->origin + kVec00N24 - right * -16.0f + normal * 24.0f;
|
forward = pev->origin + kVec00N24 - m_rightRef * -16.0f + normal * 24.0f;
|
||||||
|
|
||||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||||
|
|
||||||
|
|
@ -2580,7 +2585,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
if (!isOnFloor () && (isOnLadder () || !isInWater ())) {
|
if (!isOnFloor () && (isOnLadder () || !isInWater ())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right (); // convert current view angle to vectors for traceline math...
|
updateRightRef ();
|
||||||
|
|
||||||
// check for normal jump height first...
|
// check for normal jump height first...
|
||||||
auto src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
auto src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
||||||
|
|
@ -2590,7 +2595,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
return doneCanJumpUp (normal, right);
|
return doneCanJumpUp (normal, m_rightRef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// now trace from jump height upward to check for obstructions...
|
// now trace from jump height upward to check for obstructions...
|
||||||
|
|
@ -2605,7 +2610,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check same height to one side of the bot...
|
// now check same height to one side of the bot...
|
||||||
src = pev->origin + right * 16.0f + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
src = pev->origin + m_rightRef * 16.0f + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
||||||
dest = src + normal * 32.0f;
|
dest = src + normal * 32.0f;
|
||||||
|
|
||||||
// trace a line forward at maximum jump height...
|
// trace a line forward at maximum jump height...
|
||||||
|
|
@ -2613,7 +2618,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
|
|
||||||
// if trace hit something, return false
|
// if trace hit something, return false
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
return doneCanJumpUp (normal, right);
|
return doneCanJumpUp (normal, m_rightRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now trace from jump height upward to check for obstructions...
|
// now trace from jump height upward to check for obstructions...
|
||||||
|
|
@ -2628,7 +2633,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check same height on the other side of the bot...
|
// now check same height on the other side of the bot...
|
||||||
src = pev->origin + (-right * 16.0f) + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
src = pev->origin + (-m_rightRef * 16.0f) + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
||||||
dest = src + normal * 32.0f;
|
dest = src + normal * 32.0f;
|
||||||
|
|
||||||
// trace a line forward at maximum jump height...
|
// trace a line forward at maximum jump height...
|
||||||
|
|
@ -2636,7 +2641,7 @@ bool Bot::canJumpUp (const Vector &normal) {
|
||||||
|
|
||||||
// if trace hit something, return false
|
// if trace hit something, return false
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
return doneCanJumpUp (normal, right);
|
return doneCanJumpUp (normal, m_rightRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now trace from jump height upward to check for obstructions...
|
// now trace from jump height upward to check for obstructions...
|
||||||
|
|
@ -2744,12 +2749,10 @@ bool Bot::canDuckUnder (const Vector &normal) {
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
updateRightRef ();
|
||||||
// convert current view angle to vectors for TraceLine math...
|
|
||||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
|
||||||
|
|
||||||
// now check same height to one side of the bot...
|
// now check same height to one side of the bot...
|
||||||
src = baseHeight + right * 16.0f;
|
src = baseHeight + m_rightRef * 16.0f;
|
||||||
dest = src + normal * 32.0f;
|
dest = src + normal * 32.0f;
|
||||||
|
|
||||||
// trace a line forward at duck height...
|
// trace a line forward at duck height...
|
||||||
|
|
@ -2761,7 +2764,7 @@ bool Bot::canDuckUnder (const Vector &normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check same height on the other side of the bot...
|
// now check same height on the other side of the bot...
|
||||||
src = baseHeight + (-right * 16.0f);
|
src = baseHeight + (-m_rightRef * 16.0f);
|
||||||
dest = src + normal * 32.0f;
|
dest = src + normal * 32.0f;
|
||||||
|
|
||||||
// trace a line forward at duck height...
|
// trace a line forward at duck height...
|
||||||
|
|
@ -3057,11 +3060,11 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edict_t *Bot::lookupButton (const char *target) {
|
edict_t *Bot::lookupButton (StringRef target) {
|
||||||
// this function tries to find nearest to current bot button, and returns pointer to
|
// this function tries to find nearest to current bot button, and returns pointer to
|
||||||
// it's entity, also here must be specified the target, that button must open.
|
// it's entity, also here must be specified the target, that button must open.
|
||||||
|
|
||||||
if (strings.isEmpty (target)) {
|
if (target.empty ()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
float nearestDistanceSq = kInfiniteDistance;
|
float nearestDistanceSq = kInfiniteDistance;
|
||||||
|
|
|
||||||
|
|
@ -373,7 +373,7 @@ bool FloydWarshallAlgo::load () {
|
||||||
if (!m_length) {
|
if (!m_length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool dataLoaded = bstor.load <Matrix> (m_matrix);
|
const bool dataLoaded = bstor.load <Matrix> (m_matrix);
|
||||||
|
|
||||||
// do not rebuild if loaded
|
// do not rebuild if loaded
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
|
|
@ -451,7 +451,7 @@ bool DijkstraAlgo::find (int srcIndex, int destIndex, NodeAdderFn onAddedNode, i
|
||||||
|
|
||||||
for (const auto &link : graph[current].links) {
|
for (const auto &link : graph[current].links) {
|
||||||
if (link.index != kInvalidNodeIndex) {
|
if (link.index != kInvalidNodeIndex) {
|
||||||
auto dlink = m_distance[current] + link.distance;
|
const auto dlink = m_distance[current] + link.distance;
|
||||||
|
|
||||||
if (dlink < m_distance[link.index]) {
|
if (dlink < m_distance[link.index]) {
|
||||||
m_distance[link.index] = dlink;
|
m_distance[link.index] = dlink;
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ void BotPractice::load () {
|
||||||
SmallArray <DangerSaveRestore> data;
|
SmallArray <DangerSaveRestore> data;
|
||||||
m_data.clear ();
|
m_data.clear ();
|
||||||
|
|
||||||
bool dataLoaded = bstor.load <DangerSaveRestore> (data);
|
const bool dataLoaded = bstor.load <DangerSaveRestore> (data);
|
||||||
|
|
||||||
// copy back to hash table
|
// copy back to hash table
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ template <typename U> bool BotStorage::save (const SmallArray <U> &data, ExtenHe
|
||||||
SmallArray <uint8_t> compressed (rawLength + sizeof (uint8_t) * ULZ::Excess);
|
SmallArray <uint8_t> compressed (rawLength + sizeof (uint8_t) * ULZ::Excess);
|
||||||
|
|
||||||
// try to compress
|
// try to compress
|
||||||
auto compressedLength = static_cast <size_t> (ulz.compress (reinterpret_cast <uint8_t *> (data.data ()), static_cast <int32_t> (rawLength), reinterpret_cast <uint8_t *> (compressed.data ())));
|
const auto compressedLength = static_cast <size_t> (ulz.compress (reinterpret_cast <uint8_t *> (data.data ()), static_cast <int32_t> (rawLength), reinterpret_cast <uint8_t *> (compressed.data ())));
|
||||||
|
|
||||||
if (compressedLength > 0) {
|
if (compressedLength > 0) {
|
||||||
StorageHeader hdr {};
|
StorageHeader hdr {};
|
||||||
|
|
@ -349,7 +349,7 @@ String BotStorage::buildPath (int32_t file, bool isMemoryLoad) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally use correct path separators for us
|
// finally use correct path separators for us
|
||||||
return String::join (path, PATH_SEP);
|
return String::join (path, kPathSeparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t BotStorage::storageToBotFile (int32_t options) {
|
int32_t BotStorage::storageToBotFile (int32_t options) {
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ bool BotSupport::isDoorEntity (edict_t *ent) {
|
||||||
if (game.isNullEntity (ent)) {
|
if (game.isNullEntity (ent)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ent->v.classname.str ().startsWith ("func_door");;
|
return ent->v.classname.str ().startsWith ("func_door");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BotSupport::isHostageEntity (edict_t *ent) {
|
bool BotSupport::isHostageEntity (edict_t *ent) {
|
||||||
|
|
|
||||||
|
|
@ -1097,7 +1097,7 @@ void Bot::throwExplosive_ () {
|
||||||
else {
|
else {
|
||||||
m_aimFlags |= AimFlags::Grenade;
|
m_aimFlags |= AimFlags::Grenade;
|
||||||
|
|
||||||
auto grenade = setCorrectGrenadeVelocity ("hegrenade.mdl");
|
auto grenade = setCorrectGrenadeVelocity (kExplosiveModelName);
|
||||||
|
|
||||||
if (game.isNullEntity (grenade)) {
|
if (game.isNullEntity (grenade)) {
|
||||||
if (m_currentWeapon != Weapon::Explosive && !m_grenadeRequested) {
|
if (m_currentWeapon != Weapon::Explosive && !m_grenadeRequested) {
|
||||||
|
|
@ -1163,7 +1163,7 @@ void Bot::throwFlashbang_ () {
|
||||||
else {
|
else {
|
||||||
m_aimFlags |= AimFlags::Grenade;
|
m_aimFlags |= AimFlags::Grenade;
|
||||||
|
|
||||||
auto grenade = setCorrectGrenadeVelocity ("flashbang.mdl");
|
auto grenade = setCorrectGrenadeVelocity (kFlashbangModelName);
|
||||||
|
|
||||||
if (game.isNullEntity (grenade)) {
|
if (game.isNullEntity (grenade)) {
|
||||||
if (m_currentWeapon != Weapon::Flashbang && !m_grenadeRequested) {
|
if (m_currentWeapon != Weapon::Flashbang && !m_grenadeRequested) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue