From fb301b7b19d20d5f7207bfa6be4666c97565f4de Mon Sep 17 00:00:00 2001 From: jeefo Date: Tue, 8 Aug 2023 11:48:37 +0300 Subject: [PATCH] control: add g path_clean to remove all links from node (#475) refactor: small cosmetic changes --- inc/constant.h | 5 ++++ inc/control.h | 1 + inc/engine.h | 6 ++-- inc/graph.h | 1 + inc/manager.h | 2 +- inc/planner.h | 2 +- inc/support.h | 12 ++++---- inc/yapb.h | 8 ++++-- src/botlib.cpp | 23 ++++++++------- src/chatlib.cpp | 5 ++-- src/combat.cpp | 64 ++++++++++++++++++++++-------------------- src/config.cpp | 20 +++++++------ src/control.cpp | 16 ++++++++++- src/engine.cpp | 6 ++-- src/graph.cpp | 45 +++++++++++++++++++++++++++-- src/manager.cpp | 22 +++++++++------ src/message.cpp | 10 +++---- src/navigate.cpp | 73 +++++++++++++++++++++++++----------------------- src/planner.cpp | 4 +-- src/practice.cpp | 2 +- src/storage.cpp | 4 +-- src/support.cpp | 2 +- src/tasks.cpp | 4 +-- 23 files changed, 205 insertions(+), 132 deletions(-) diff --git a/inc/constant.h b/inc/constant.h index 17e1a45..79dfd60 100644 --- a/inc/constant.h +++ b/inc/constant.h @@ -447,3 +447,8 @@ constexpr auto kSecondaryWeaponMask = (cr::bit (Weapon::P228) | cr::bit (Weapon: // weapons < 7 are secondary 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"; diff --git a/inc/control.h b/inc/control.h index dfe4e82..d4048a5 100644 --- a/inc/control.h +++ b/inc/control.h @@ -118,6 +118,7 @@ private: int cmdNodePathCreate (); int cmdNodePathDelete (); int cmdNodePathSetAutoDistance (); + int cmdNodePathCleanAll (); int cmdNodeAcquireEditor (); int cmdNodeReleaseEditor (); int cmdNodeUpload (); diff --git a/inc/engine.h b/inc/engine.h index 44cab7f..b9c80e9 100644 --- a/inc/engine.h +++ b/inc/engine.h @@ -111,7 +111,7 @@ public: // provides utility functions to not call original engine (less call-cost) class Game final : public Singleton { public: - using EntitySearch = Lambda ; + using EntitySearch = const Lambda &; private: int m_drawModels[DrawLine::Count] {}; @@ -227,12 +227,12 @@ public: } // get "maxplayers" limit on server - int maxClients () const { + int maxClients () const { return globals->maxClients; } // get the fakeclient command interface - bool isBotCmd () const { + bool isBotCmd () const { return !m_botArgs.empty (); } diff --git a/inc/graph.h b/inc/graph.h index e043a0e..e8d04be 100644 --- a/inc/graph.h +++ b/inc/graph.h @@ -239,6 +239,7 @@ public: void setRadius (int index, float radius); void pathCreate (char dir); void erasePath (); + void resetPath (int index); void cachePoint (int index); void calculatePathRadius (int index); void addBasic (); diff --git a/inc/manager.h b/inc/manager.h index 0c368e7..2e00f81 100644 --- a/inc/manager.h +++ b/inc/manager.h @@ -20,7 +20,7 @@ struct BotRequest { // manager class class BotManager final : public Singleton { public: - using ForEachBot = Lambda ; + using ForEachBot = const Lambda &; using UniqueBot = UniquePtr ; private: diff --git a/inc/planner.h b/inc/planner.h index f8351b6..1c8d0c2 100644 --- a/inc/planner.h +++ b/inc/planner.h @@ -24,7 +24,7 @@ CR_DECLARE_SCOPED_ENUM (AStarResult, ) // node added -using NodeAdderFn = Lambda ; +using NodeAdderFn = const Lambda &; // route twin node template struct RouteTwin final { diff --git a/inc/support.h b/inc/support.h index 8c8cc89..b0c4aa0 100644 --- a/inc/support.h +++ b/inc/support.h @@ -57,7 +57,7 @@ public: // check if entity is a hostage entity bool isHostageEntity (edict_t *ent); - // check if entity is a door enitty + // check if entity is a door entity bool isDoorEntity (edict_t *ent); // this function is checking that pointed by ent pointer obstacle, can be destroyed @@ -133,13 +133,13 @@ public: } // gets the shooting cone deviation - float getShootingCone (edict_t *ent, const Vector &position) { - return ent->v.v_angle.forward () | (position - (ent->v.origin + ent->v.view_ofs)).normalize (); // he's facing it, he meant it + float getShootingCone (edict_t *ent, const Vector &pos) { + 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 - bool isInViewCone (const Vector &origin, edict_t *ent) { - return getShootingCone (ent, origin) >= cr::cosf (cr::deg2rad ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f)); + // check if position is inside view cone of entity + bool isInViewCone (const Vector &pos, edict_t *ent) { + return getShootingCone (ent, pos) >= cr::cosf (cr::deg2rad ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f)); } public: diff --git a/inc/yapb.h b/inc/yapb.h index 887f0cb..3063aaa 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -366,6 +366,7 @@ private: Vector m_lookAtPredict {}; // aiming vector when predicting Vector m_desiredVelocity {}; // desired velocity for jump nodes Vector m_breakableOrigin {}; // origin of breakable + Vector m_rightRef {}; // right referential vector Array m_ignoredBreakable {}; // list of ignored breakables Array m_hostages {}; // pointer to used hostage entities @@ -485,7 +486,7 @@ private: void findShortestPath (int srcIndex, int destIndex); void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast); void syncFindPath (int srcIndex, int destIndex, FindPath pathType); - void debugMsgInternal (const char *str); + void debugMsgInternal (StringRef str); void frame (); void resetCollision (); void ignoreCollision (); @@ -509,6 +510,7 @@ private: void syncUpdatePredictedIndex (); void updatePredictedIndex (); void refreshModelName (char *infobuffer); + void updateRightRef (); void completeTask (); void executeTasks (); @@ -540,9 +542,9 @@ private: void pickupItem_ (); void shootBreakable_ (); - edict_t *lookupButton (const char *target); + edict_t *lookupButton (StringRef target); edict_t *lookupBreakable (); - edict_t *setCorrectGrenadeVelocity (const char *model); + edict_t *setCorrectGrenadeVelocity (StringRef model); Vector getEnemyBodyOffset (); Vector calcThrow (const Vector &start, const Vector &stop); diff --git a/src/botlib.cpp b/src/botlib.cpp index 17ac677..b34d123 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -51,7 +51,7 @@ void Bot::pushMsgQueue (int message) { 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) - int entityIndex = index (); + const int entityIndex = index (); for (const auto &other : bots) { if (other->pev != pev) { @@ -96,7 +96,7 @@ void Bot::avoidGrenades () { } 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 if (!(m_states & Sense::SeeingEnemy)) { 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); } } - 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 ()) { 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) { const auto &entOrigin = game.getEntityOrigin (pent); const auto &betweenUs = (entOrigin - pev->origin).normalize_apx (); @@ -403,8 +403,8 @@ void Bot::updatePickups () { pickupType = Pickup::Weapon; if (cv_pickup_ammo_and_kits.bool_ ()) { - int primaryWeaponCarried = bestPrimaryCarried (); - int secondaryWeaponCarried = bestSecondaryCarried (); + const int primaryWeaponCarried = bestPrimaryCarried (); + const int secondaryWeaponCarried = bestSecondaryCarried (); const auto &config = conf.getWeapons (); const auto &primary = config[primaryWeaponCarried]; @@ -493,13 +493,13 @@ void Bot::updatePickups () { else if (!rateGroundWeapon (ent)) { 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; } - else if ((pev->weapons & cr::bit (Weapon::Explosive)) && model == "hegrenade.mdl") { + else if ((pev->weapons & cr::bit (Weapon::Explosive)) && model == kExplosiveModelName) { 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; } } @@ -637,7 +637,6 @@ void Bot::updatePickups () { } if (pev->origin.distanceSq (origin) > cr::sqrf (60.0f)) { - if (!graph.isNodeReacheable (pev->origin, origin)) { allowPickup = false; } @@ -840,7 +839,7 @@ void Bot::instantChatter (int type) { const int ownIndex = index (); 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 ()) { @@ -3483,7 +3482,7 @@ void Bot::resetDoubleJump () { m_jumpReady = false; } -void Bot::debugMsgInternal (const char *str) { +void Bot::debugMsgInternal (StringRef str) { if (game.isDedicated ()) { return; } diff --git a/src/chatlib.cpp b/src/chatlib.cpp index 8cadb10..da66897 100644 --- a/src/chatlib.cpp +++ b/src/chatlib.cpp @@ -54,7 +54,7 @@ void BotSupport::addChatErrors (String &line) { if (rg.chance (8) && cv_language.str () == "en") { line.lowercase (); } - auto length = static_cast (line.length ()); + const auto length = static_cast (line.length ()); if (length > 15) { const auto percentile = length / 2; @@ -106,6 +106,7 @@ bool BotSupport::checkKeywords (StringRef line, String &reply) { if (!replyUsed) { reply.assign (choosenReply); // update final buffer usedReplies.push (choosenReply); // add to ignore list + return true; } } @@ -168,7 +169,7 @@ void Bot::prepareChatMessage (StringRef message) { if (!(client.flags & ClientFlags::Used) || client.ent == ent ()) { continue; } - int frags = static_cast (client.ent->v.frags); + const auto frags = static_cast (client.ent->v.frags); if (frags > highestFrags) { highestFrags = frags; diff --git a/src/combat.cpp b/src/combat.cpp index 34bdb46..414b6e5 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -52,7 +52,7 @@ bool Bot::isEnemyHidden (edict_t *enemy) { if (!cv_check_enemy_rendering.bool_ () || game.isNullEntity (enemy)) { return false; } - entvars_t &v = enemy->v; + const auto &v = enemy->v; const bool enemyHasGun = (v.weapons & kPrimaryWeaponMask) || (v.weapons & kSecondaryWeaponMask); 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)) { return false; } - const entvars_t &v = enemy->v; + const auto &v = enemy->v; if (v.solid < SOLID_BBOX) { return true; @@ -162,14 +162,15 @@ bool Bot::checkBodyParts (edict_t *target) { return true; } - constexpr auto standFeet = 34.0f; - constexpr auto crouchFeet = 14.0f; + constexpr auto kStandFeet = 34.0f; + constexpr auto kCrouchFeet = 14.0f; + constexpr auto kEdgeOffset = 13.0f; if (target->v.flags & FL_DUCKING) { - spot.z = target->v.origin.z - crouchFeet; + spot.z = target->v.origin.z - kCrouchFeet; } else { - spot.z = target->v.origin.z - standFeet; + spot.z = target->v.origin.z - kStandFeet; } game.testLine (eyes, spot, ignoreFlags, self, &result); @@ -179,12 +180,10 @@ bool Bot::checkBodyParts (edict_t *target) { return true; } - - const float edgeOffset = 13.0f; Vector dir = (target->v.origin - pev->origin).normalize2d (); 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); @@ -194,7 +193,7 @@ bool Bot::checkBodyParts (edict_t *target) { 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); @@ -554,7 +553,7 @@ Vector Bot::getCustomHeight (float distance) { constexpr float offsetRanges[9][3] = { { 0.0f, 0.0f, 0.0f }, // none { 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 { 0.5f -7.5f, -9.5f }, // zoomrifle { 0.5f, -7.5f, -9.5f }, // rifle @@ -771,6 +770,9 @@ bool Bot::needToPauseFiring (float distance) { else if (distance < kDoubleSprayDistance) { 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 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; } - constexpr float minDelay[] = { 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 kMinFireDelay[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f }; + constexpr float kMaxFireDelay[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }; const int offset = cr::abs (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 (); } } @@ -944,8 +946,8 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) { void Bot::fireWeapons () { // 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) { return; } @@ -963,7 +965,7 @@ void Bot::fireWeapons () { const auto tab = conf.getRawWeapons (); const auto weapons = pev->weapons; - // if jason mode use knife only + // if knife mode use knife only if (isKnifeMode ()) { selectWeapons (distance, selectIndex, selectId, choosenWeapon); return; @@ -1707,10 +1709,10 @@ void Bot::checkReload () { float Bot::calculateScaleFactor (edict_t *ent) { 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; - 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; } @@ -1809,7 +1811,7 @@ Vector Bot::calcThrow (const Vector &start, const Vector &stop) { return velocity * 0.7793f; } -edict_t *Bot::setCorrectGrenadeVelocity (const char *model) { +edict_t *Bot::setCorrectGrenadeVelocity (StringRef model) { edict_t *result = nullptr; game.searchEntities ("classname", "grenade", [&] (edict_t *ent) { @@ -1856,11 +1858,11 @@ void Bot::checkGrenadesThrow () { } // 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 (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); return; @@ -2051,18 +2053,18 @@ bool Bot::isEnemyNoticeable (float range) { if (m_enemyParts & Visibility::Other) { coverRatio += rg.get (10.0f, 25.0f); } - constexpr float closeRange = 300.0f; - constexpr float farRange = 1000.0f; + constexpr float kCloseRange = 300.0f; + constexpr float kFarRange = 1000.0f; float rangeModifier; - if (range < closeRange) { + if (range < kCloseRange) { rangeModifier = 0.0f; } - else if (range > farRange) { + else if (range > kFarRange) { rangeModifier = 1.0f; } else { - rangeModifier = (range - closeRange) / (farRange - closeRange); + rangeModifier = (range - kCloseRange) / (kFarRange - kCloseRange); } // harder to notice when crouched @@ -2072,13 +2074,13 @@ bool Bot::isEnemyNoticeable (float range) { float playerSpeedSq = m_enemy->v.velocity.lengthSq (); float farChance, closeChance; - constexpr float runSpeed = cr::sqrf (200.0f); - constexpr float walkSpeed = cr::sqrf (30.0f); + constexpr float kRunSpeed = cr::sqrf (200.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) } - else if (playerSpeedSq > walkSpeed) { + else if (playerSpeedSq > kWalkSpeed) { // walking players are less noticeable far away if (isCrouching) { closeChance = 90.0f; diff --git a/src/config.cpp b/src/config.cpp index 6f32fe7..ffd6fce 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -124,6 +124,8 @@ void BotConfig::loadNamesConfig () { String line; MemFile file; + constexpr auto kMaxNameLen = 32; + // naming initialization if (openConfig ("names", "Name configuration file not found.", &file, true)) { m_botNames.clear (); @@ -135,8 +137,8 @@ void BotConfig::loadNamesConfig () { continue; } // max botname is 32 characters - if (line.length () > 32) { - line[32] = kNullChar; + if (line.length () > kMaxNameLen - 1) { + line[kMaxNameLen - 1] = kNullChar; } m_botNames.emplace (line, -1); } @@ -583,7 +585,7 @@ void BotConfig::loadDifficultyConfig () { diff->aimError.z = values[8].float_ (); }; - // avatars initialization + // difficulty initialization if (openConfig ("difficulty", "Difficulty config file not found. Loading defaults.", &file)) { while (file.getLine (line)) { @@ -706,20 +708,20 @@ BotName *BotConfig::pickBotName () { } 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; } - return botName; + return bn; } return nullptr; } void BotConfig::clearUsedName (Bot *bot) { - for (auto &name : m_botNames) { - if (name.usedBy == bot->index ()) { - name.usedBy = -1; + for (auto &bn : m_botNames) { + if (bn.usedBy == bot->index ()) { + bn.usedBy = -1; break; } } diff --git a/src/control.cpp b/src/control.cpp index 5122931..0a17100 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -278,7 +278,7 @@ int BotControl::cmdCvars () { if (isSave) { 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; } 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_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_clean", "path_clean [index]", "Clean's up all types of connections from the node.", &BotControl::cmdNodePathCleanAll); // camp points iterator 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; } +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 () { enum args { graph_cmd = 1 }; diff --git a/src/engine.cpp b/src/engine.cpp index 5c76060..7d4daae 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -803,7 +803,7 @@ bool Game::loadCSBinary () { // search the libraries inside game dlls directory 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 (!plat.fileExists (path.chars ())) { @@ -1136,7 +1136,7 @@ void LightMeasure::initializeLightstyles () { // reset all light styles for (auto &ls : m_lightstyle) { ls.length = 0; - ls.map[0] = 0; + ls.map[0] = kNullChar; } for (auto &lsv : m_lightstyleValue) { @@ -1226,7 +1226,7 @@ template bool LightMeasure::recursiveLightPoint (const if (surf->flags & SURF_DRAWTILED) { continue; // no lightmaps } - auto tex = surf->texinfo; + const auto tex = surf->texinfo; // see where in lightmap space our intersection point is const int s = static_cast ((mid | Vector (tex->vecs[0])) + tex->vecs[0][3]); diff --git a/src/graph.cpp b/src/graph.cpp index b957640..a87c629 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -1135,6 +1135,45 @@ void BotGraph::erasePath () { 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) { const int node = exists (index) ? index : getEditorNearest (); @@ -1579,7 +1618,7 @@ bool BotGraph::loadGraphData () { reset (); // check if loaded - bool dataLoaded = bstor.load (m_paths, &exten, &outOptions); + const bool dataLoaded = bstor.load (m_paths, &exten, &outOptions); if (dataLoaded) { initBuckets (); @@ -1898,7 +1937,7 @@ void BotGraph::frame () { for (auto &path : m_paths) { 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))) { // check the distance if (distanceSq < nearestDistanceSq) { @@ -2128,7 +2167,7 @@ void BotGraph::frame () { }; // very helpful stuff.. - auto getNodeData = [&] (StringRef type, int node) -> String { + auto getNodeData = [this] (StringRef type, int node) -> String { String message, flags; const auto &p = m_paths[node]; diff --git a/src/manager.cpp b/src/manager.cpp index c495baf..7eaa040 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -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 (), // when bot setup completed, (this is a bot class constructor) - int clientIndex = game.indexOfEntity (bot); + const int clientIndex = game.indexOfEntity (bot); pev = &bot->v; if (bot->pvPrivateData != nullptr) { @@ -1176,25 +1176,25 @@ int BotManager::getAliveHumansCount () { } int BotManager::getPlayerPriority (edict_t *ent) { - constexpr auto highPrio = 512; + constexpr auto kHighPriority = 512; // always check for only our own bots auto bot = bots[ent]; // if player just return high prio if (!bot) { - return game.indexOfEntity (ent) + highPrio; + return game.indexOfEntity (ent) + kHighPriority; } // give bots some priority 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 (); // higher priority if camping or hiding if (task == Task::Camp || task == Task::Hide) { - return bot->entindex () + highPrio; + return bot->entindex () + kHighPriority; } return bot->entindex (); } @@ -1229,7 +1229,7 @@ void BotManager::erase (Bot *bot) { } bot->markStale (); - auto index = m_bots.index (e); + const auto index = m_bots.index (e); e.reset (); 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 (killerTeam == victimBot->m_team) { victimBot->m_voteKickIndex = game.indexOfEntity (killer); + for (const auto ¬ify : bots) { if (notify->seesEntity (victim->v.origin)) { notify->pushChatterMessage (Chatter::TeamKill); @@ -1502,6 +1503,9 @@ void Bot::newRound () { m_goalHist.clear (); m_ignoredBreakable.clear (); + // update refvec for blocked movement + updateRightRef (); + // and put buying into its message queue pushMsgQueue (BotMsg::Buy); startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true); @@ -1618,7 +1622,7 @@ void Bot::updateTeamJoin () { 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_retryJoin > 3 && bots.isTeamStacked (m_wantedTeam - 1)) { m_retryJoin = 0; @@ -1710,7 +1714,7 @@ void BotManager::captureChatRadio (StringRef cmd, StringRef arg, edict_t *ent) { } if (cmd.startsWith ("say")) { - const bool alive = util.isAlive (ent); + const bool alive = util.isAlive (ent); int team = -1; if (cmd == "say_team") { @@ -1768,7 +1772,7 @@ void BotManager::notifyBombDefuse () { const auto &bombPos = graph.getBombOrigin (); 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_team == Team::Terrorist && bot->pev->origin.distanceSq (bombPos) < cr::sqrf (384.0f)) { diff --git a/src/message.cpp b/src/message.cpp index 8245e2b..e70b770 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -87,7 +87,7 @@ void MessageDispatcher::netMsgVGUIMenu () { 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) { return; } @@ -109,7 +109,7 @@ void MessageDispatcher::netMsgShowMenu () { 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) { return; } @@ -144,7 +144,7 @@ void MessageDispatcher::netMsgWeaponList () { } 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 }; @@ -524,7 +524,7 @@ void MessageDispatcher::start (edict_t *ent, int32_t type) { m_current = m_handlers[msg] ? msg : NetMsg::None; } - // no messagem no processing + // no message no processing if (m_current == NetMsg::None) { return; } @@ -571,6 +571,6 @@ int32_t MessageDispatcher::id (NetMsg msg) { Bot *MessageDispatcher::pickBot (int32_t index) { 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]; } diff --git a/src/navigate.cpp b/src/navigate.cpp index 4b5c540..4f9c5fe 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -661,7 +661,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { } if (seesEntity (m_destOrigin)) { - auto right = m_moveAngles.right (); + const auto &right = m_moveAngles.right (); src = getEyesPos (); src = src + right * 15.0f; @@ -910,7 +910,7 @@ bool Bot::updateNavigation () { if (feet.z > pev->origin.z) { 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 auto velocity = calcThrow (feet, node); @@ -947,11 +947,10 @@ bool Bot::updateNavigation () { selectBestWeapon (); } } - + 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)) { + constexpr auto kLadderOffset = Vector (0.0f, 0.0f, 16.0f); m_pathOrigin = m_path->origin + kLadderOffset; } 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 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)) { pev->button |= IN_USE; } @@ -1357,7 +1356,7 @@ bool Bot::updateLiftHandling () { // bot is trying to find button inside a lift 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 ? 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)) { - auto button = lookupButton (m_liftEntity->v.targetname.chars ()); + auto button = lookupButton (m_liftEntity->v.targetname.str ()); // if we got a valid button entity if (!game.isNullEntity (button)) { @@ -1702,18 +1701,18 @@ void Bot::findValidNode () { findNextBestNode (); } else if (m_navTimeset + getEstimatedNodeReachTime () < game.time ()) { - constexpr int maxDamageValue = PracticeLimit::Damage; + constexpr int kMaxDamageValue = PracticeLimit::Damage; // increase danger for both teams for (int team = Team::Terrorist; team < kGameTeamNum; ++team) { 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 for (auto &neighbour : m_path->links) { if (graph.exists (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); } @@ -2062,8 +2061,8 @@ int Bot::findCoverNode (float maxDistance) { } // use the 'real' pathfinding distances - float distance = planner.dist (srcIndex, path.number); - float enemyDistance = planner.dist (enemyIndex, path.number); + const float distance = planner.dist (srcIndex, path.number); + const float enemyDistance = planner.dist (enemyIndex, path.number); if (distance >= enemyDistance) { 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) { // 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... auto src = getEyesPos (); auto forward = src + normal * 24.0f; - auto right = Vector (0.0f, pev->angles.y, 0.0f).right (); auto checkDoor = [] (TraceResult *result) { 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); + // right referential vector + updateRightRef (); + // bot's head is clear, check at shoulder level... // trace from the bot's shoulder left diagonal forward to the right shoulder... - src = getEyesPos () + kVec00N16 - right * -16.0f; - forward = getEyesPos () + kVec00N16 + right * 16.0f + normal * 24.0f; + src = getEyesPos () + kVec00N16 - m_rightRef * -16.0f; + forward = getEyesPos () + kVec00N16 + m_rightRef * 16.0f + normal * 24.0f; 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... // trace from the bot's shoulder right diagonal forward to the left shoulder... - src = getEyesPos () + kVec00N16 + right * 16.0f; - forward = getEyesPos () + kVec00N16 - right * -16.0f + normal * 24.0f; + src = getEyesPos () + kVec00N16 + m_rightRef * 16.0f; + forward = getEyesPos () + kVec00N16 - m_rightRef * -16.0f + normal * 24.0f; 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); // trace from the left waist to the right forward waist pos - src = pev->origin + kVec00N17 - right * -16.0f; - forward = pev->origin + kVec00N17 + right * 16.0f + normal * 24.0f; + src = pev->origin + kVec00N17 - m_rightRef * -16.0f; + forward = pev->origin + kVec00N17 + m_rightRef * 16.0f + normal * 24.0f; // trace from the bot's waist straight forward... 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 - src = pev->origin + kVec00N24 + right * 16.0f; - forward = pev->origin + kVec00N24 - right * -16.0f + normal * 24.0f; + src = pev->origin + kVec00N24 + m_rightRef * 16.0f; + forward = pev->origin + kVec00N24 - m_rightRef * -16.0f + normal * 24.0f; game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr); @@ -2580,7 +2585,7 @@ bool Bot::canJumpUp (const Vector &normal) { if (!isOnFloor () && (isOnLadder () || !isInWater ())) { 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... 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); if (tr.flFraction < 1.0f) { - return doneCanJumpUp (normal, right); + return doneCanJumpUp (normal, m_rightRef); } else { // 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... - 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; // 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 (tr.flFraction < 1.0f) { - return doneCanJumpUp (normal, right); + return doneCanJumpUp (normal, m_rightRef); } // 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... - 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; // 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 (tr.flFraction < 1.0f) { - return doneCanJumpUp (normal, right); + return doneCanJumpUp (normal, m_rightRef); } // 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) { return false; } - - // convert current view angle to vectors for TraceLine math... - auto right = Vector (0.0f, pev->angles.y, 0.0f).right (); + updateRightRef (); // 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; // 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... - src = baseHeight + (-right * 16.0f); + src = baseHeight + (-m_rightRef * 16.0f); dest = src + normal * 32.0f; // trace a line forward at duck height... @@ -3057,11 +3060,11 @@ bool Bot::isOccupiedNode (int index, bool needZeroVelocity) { 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 // it's entity, also here must be specified the target, that button must open. - if (strings.isEmpty (target)) { + if (target.empty ()) { return nullptr; } float nearestDistanceSq = kInfiniteDistance; diff --git a/src/planner.cpp b/src/planner.cpp index 6a10bf5..cb25370 100644 --- a/src/planner.cpp +++ b/src/planner.cpp @@ -373,7 +373,7 @@ bool FloydWarshallAlgo::load () { if (!m_length) { return false; } - bool dataLoaded = bstor.load (m_matrix); + const bool dataLoaded = bstor.load (m_matrix); // do not rebuild if loaded if (dataLoaded) { @@ -451,7 +451,7 @@ bool DijkstraAlgo::find (int srcIndex, int destIndex, NodeAdderFn onAddedNode, i for (const auto &link : graph[current].links) { 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]) { m_distance[link.index] = dlink; diff --git a/src/practice.cpp b/src/practice.cpp index 1510b37..e377ef9 100644 --- a/src/practice.cpp +++ b/src/practice.cpp @@ -169,7 +169,7 @@ void BotPractice::load () { SmallArray data; m_data.clear (); - bool dataLoaded = bstor.load (data); + const bool dataLoaded = bstor.load (data); // copy back to hash table if (dataLoaded) { diff --git a/src/storage.cpp b/src/storage.cpp index 67fd415..22809fa 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -233,7 +233,7 @@ template bool BotStorage::save (const SmallArray &data, ExtenHe SmallArray compressed (rawLength + sizeof (uint8_t) * ULZ::Excess); // try to compress - auto compressedLength = static_cast (ulz.compress (reinterpret_cast (data.data ()), static_cast (rawLength), reinterpret_cast (compressed.data ()))); + const auto compressedLength = static_cast (ulz.compress (reinterpret_cast (data.data ()), static_cast (rawLength), reinterpret_cast (compressed.data ()))); if (compressedLength > 0) { StorageHeader hdr {}; @@ -349,7 +349,7 @@ String BotStorage::buildPath (int32_t file, bool isMemoryLoad) { } // 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) { diff --git a/src/support.cpp b/src/support.cpp index 3fdcb39..6728917 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -231,7 +231,7 @@ bool BotSupport::isDoorEntity (edict_t *ent) { if (game.isNullEntity (ent)) { return false; } - return ent->v.classname.str ().startsWith ("func_door");; + return ent->v.classname.str ().startsWith ("func_door"); } bool BotSupport::isHostageEntity (edict_t *ent) { diff --git a/src/tasks.cpp b/src/tasks.cpp index 46c14ae..4f8c9f0 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -1097,7 +1097,7 @@ void Bot::throwExplosive_ () { else { m_aimFlags |= AimFlags::Grenade; - auto grenade = setCorrectGrenadeVelocity ("hegrenade.mdl"); + auto grenade = setCorrectGrenadeVelocity (kExplosiveModelName); if (game.isNullEntity (grenade)) { if (m_currentWeapon != Weapon::Explosive && !m_grenadeRequested) { @@ -1163,7 +1163,7 @@ void Bot::throwFlashbang_ () { else { m_aimFlags |= AimFlags::Grenade; - auto grenade = setCorrectGrenadeVelocity ("flashbang.mdl"); + auto grenade = setCorrectGrenadeVelocity (kFlashbangModelName); if (game.isNullEntity (grenade)) { if (m_currentWeapon != Weapon::Flashbang && !m_grenadeRequested) {