From d6d76e136d067362297d1bfedcd7c0f1e0068b2c Mon Sep 17 00:00:00 2001 From: jeefo Date: Thu, 3 Apr 2025 15:12:06 +0300 Subject: [PATCH] fix: problems with breakable on cs_mari (ref #686) fix: goal selection on some zombie maps (ref #684) --- cfg/addons/yapb/conf/lang/chs_lang.cfg | 6 +-- cfg/addons/yapb/conf/lang/ru_lang.cfg | 6 +-- inc/graph.h | 21 ++++++-- inc/message.h | 2 +- inc/yapb.h | 1 + src/botlib.cpp | 66 ++++++++++++++------------ src/config.cpp | 35 +++++++------- src/graph.cpp | 20 ++------ src/linkage.cpp | 2 +- src/message.cpp | 5 +- src/navigate.cpp | 9 ++-- src/tasks.cpp | 8 ++-- 12 files changed, 95 insertions(+), 86 deletions(-) diff --git a/cfg/addons/yapb/conf/lang/chs_lang.cfg b/cfg/addons/yapb/conf/lang/chs_lang.cfg index 4f1cd88..4cbd8ee 100644 --- a/cfg/addons/yapb/conf/lang/chs_lang.cfg +++ b/cfg/addons/yapb/conf/lang/chs_lang.cfg @@ -2651,7 +2651,7 @@ Weapon configuration file not found. Loading defaults. 未找到武器配置文件。加载默认值。 [ORIGINAL] -Couldn't open chatter system configuration +Couldn't open chatter configuration. [TRANSLATED] 无法打开聊天系统配置 @@ -2669,7 +2669,7 @@ Bots chatter communication disabled. 已禁用人机聊天通信。 [ORIGINAL] -Chat file not found. +Couldn't open chat configuration. [TRANSLATED] 未找到聊天文件。 @@ -2687,7 +2687,7 @@ Specified language not found. 未找到指定语言。 [ORIGINAL] -Couldn't load language configuration +Couldn't load language configuration. [TRANSLATED] 无法加载语言配置 diff --git a/cfg/addons/yapb/conf/lang/ru_lang.cfg b/cfg/addons/yapb/conf/lang/ru_lang.cfg index 39104b3..830a5d6 100644 --- a/cfg/addons/yapb/conf/lang/ru_lang.cfg +++ b/cfg/addons/yapb/conf/lang/ru_lang.cfg @@ -2650,10 +2650,10 @@ Weapon configuration file not found. Loading defaults. Оружейный конфигурационный файл не найден. Загружаем стандартные значения. [ORIGINAL] -Couldn't open chatter system configuration +Couldn't open chat configuration. [TRANSLATED] -Не удалось открыть конфигурацию системы переговоров +Не удалось открыть конфигурацию переговоров. [ORIGINAL] Error in chatter config file syntax... Please correct all errors. @@ -2686,7 +2686,7 @@ Specified language not found. Указанный язык не найден. [ORIGINAL] -Couldn't load language configuration +Couldn't load language configuration. [TRANSLATED] Не удалось загрузить языковую конфигурацию diff --git a/inc/graph.h b/inc/graph.h index 4d2f283..1978a89 100644 --- a/inc/graph.h +++ b/inc/graph.h @@ -223,11 +223,11 @@ public: bool isNodeReacheableWithJump (const Vector &src, const Vector &destination); bool checkNodes (bool teleportPlayer, bool onlyPaths = false); bool isVisited (int index); - bool isAnalyzed () const; bool saveGraphData (); bool loadGraphData (); bool canDownload (); + bool isAnalyzed () const; void saveOldFormat (); void reset (); @@ -251,8 +251,7 @@ public: void startLearnJump (); void setVisited (int index); void clearVisited (); - void initBuckets (); - void addToBucket (const Vector &pos, int index); + void eraseFromBucket (const Vector &pos, int index); void setBombOrigin (bool reset = false, const Vector &pos = nullptr); void unassignPath (int from, int to); @@ -267,7 +266,6 @@ public: void collectOnline (); IntArray getNearestInRadius (float radius, const Vector &origin, int maxCount = -1); - const IntArray &getNodesInBucket (const Vector &pos); public: StringRef getAuthor () const { @@ -353,6 +351,21 @@ public: return m_nodeNumbers; } + // reinitialize buckets + void initBuckets () { + m_hashTable.clear (); + } + + // get the bucket of nodes near position + const IntArray &getNodesInBucket (const Vector &pos) { + return m_hashTable[locateBucket (pos)]; + } + + // add a node to position bucket + void addToBucket (const Vector &pos, int index) { + m_hashTable[locateBucket (pos)].emplace (index); + } + public: // graph helper for sending message to correct channel template void msg (const char *fmt, Args &&...args); diff --git a/inc/message.h b/inc/message.h index 73acaae..b6556d4 100644 --- a/inc/message.h +++ b/inc/message.h @@ -154,7 +154,7 @@ public: private: void reset () { - m_current = NetMsg::None; + stopCollection (); m_bot = nullptr; } }; diff --git a/inc/yapb.h b/inc/yapb.h index 43b9290..2235a2c 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -520,6 +520,7 @@ private: void updateRightRef (); void donateC4ToHuman (); void clearAmmoInfo (); + void handleChatterTaskChange (Task tid); void completeTask (); void executeTasks (); diff --git a/src/botlib.cpp b/src/botlib.cpp index 0fa0e9b..0de00df 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -2146,6 +2146,7 @@ void Bot::filterTasks () { // zombie bots has more hunt desire if (m_isCreature && huntEnemyDesire > 16.0f) { huntEnemyDesire = TaskPri::Attack; + seekCoverDesire = 0.0f; } // blinded behavior @@ -2250,37 +2251,9 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) { selectBestWeapon (); } - // this is best place to handle some voice commands report team some info + // this is best place to handle some chatter commands report team some info if (cv_radio_mode.as () > 1) { - if (rg.chance (90)) { - if (tid == Task::Blind) { - pushChatterMessage (Chatter::Blind); - } - else if (tid == Task::PlantBomb) { - pushChatterMessage (Chatter::PlantingBomb); - } - } - - if (rg.chance (25) && tid == Task::Camp) { - if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) { - pushChatterMessage (Chatter::GuardingPlantedC4); - } - else { - pushChatterMessage (Chatter::GoingToCamp); - } - } - - if (rg.chance (75) && tid == Task::Camp && m_team == Team::CT && m_inEscapeZone) { - pushChatterMessage (Chatter::GoingToGuardEscapeZone); - } - - if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inRescueZone) { - pushChatterMessage (Chatter::GoingToGuardRescueZone); - } - - if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) { - pushChatterMessage (Chatter::GoingToGuardVIPSafety); - } + handleChatterTaskChange (tid); } if (cv_debug_goal.as () != kInvalidNodeIndex) { @@ -2419,10 +2392,41 @@ bool Bot::lastEnemyShootable () { return util.getConeDeviation (ent (), m_lastEnemyOrigin) >= 0.90f && isPenetrableObstacle (m_lastEnemyOrigin); } +void Bot::handleChatterTaskChange (Task tid) { + if (rg.chance (90)) { + if (tid == Task::Blind) { + pushChatterMessage (Chatter::Blind); + } + else if (tid == Task::PlantBomb) { + pushChatterMessage (Chatter::PlantingBomb); + } + } + + if (rg.chance (25) && tid == Task::Camp) { + if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) { + pushChatterMessage (Chatter::GuardingPlantedC4); + } + else { + pushChatterMessage (Chatter::GoingToCamp); + } + } + + if (rg.chance (75) && tid == Task::Camp && m_team == Team::CT && m_inEscapeZone) { + pushChatterMessage (Chatter::GoingToGuardEscapeZone); + } + + if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inRescueZone) { + pushChatterMessage (Chatter::GoingToGuardRescueZone); + } + + if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) { + pushChatterMessage (Chatter::GoingToGuardVIPSafety); + } +} + void Bot::checkRadioQueue () { // this function handling radio and reacting to it - // don't allow bot listen you if bot is busy if (m_radioOrder != Radio::ReportInTeam && (getCurrentTaskId () == Task::DefuseBomb diff --git a/src/config.cpp b/src/config.cpp index 1520923..a4f3da9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -208,28 +208,29 @@ void BotConfig::loadWeaponsConfig () { trim.trim (); } auto splitted = pair[1].split (","); + auto key = pair[0]; - if (pair[0].startsWith ("MapStandard")) { - addWeaponEntries (m_weapons, false, pair[0], splitted); + if (key.startsWith ("MapStandard")) { + addWeaponEntries (m_weapons, false, key, splitted); } - else if (pair[0].startsWith ("MapAS")) { - addWeaponEntries (m_weapons, true, pair[0], splitted); + else if (key.startsWith ("MapAS")) { + addWeaponEntries (m_weapons, true, key, splitted); } - else if (pair[0].startsWith ("GrenadePercent")) { - addIntEntries (m_grenadeBuyPrecent, pair[0], splitted); + else if (key.startsWith ("GrenadePercent")) { + addIntEntries (m_grenadeBuyPrecent, key, splitted); } - else if (pair[0].startsWith ("Economics")) { - addIntEntries (m_botBuyEconomyTable, pair[0], splitted); + else if (key.startsWith ("Economics")) { + addIntEntries (m_botBuyEconomyTable, key, splitted); } - else if (pair[0].startsWith ("PersonalityNormal")) { - addIntEntries (m_normalWeaponPrefs, pair[0], splitted); + else if (key.startsWith ("PersonalityNormal")) { + addIntEntries (m_normalWeaponPrefs, key, splitted); } - else if (pair[0].startsWith ("PersonalityRusher")) { - addIntEntries (m_rusherWeaponPrefs, pair[0], splitted); + else if (key.startsWith ("PersonalityRusher")) { + addIntEntries (m_rusherWeaponPrefs, key, splitted); } - else if (pair[0].startsWith ("PersonalityCareful")) { - addIntEntries (m_carefulWeaponPrefs, pair[0], splitted); + else if (key.startsWith ("PersonalityCareful")) { + addIntEntries (m_carefulWeaponPrefs, key, splitted); } } file.close (); @@ -244,7 +245,7 @@ void BotConfig::loadChatterConfig () { // chatter initialization if (game.is (GameFlags::HasBotVoice) && cv_radio_mode.as () == 2 - && openConfig ("chatter", "Couldn't open chatter system configuration", &file)) { + && openConfig ("chatter", "Couldn't open chatter configuration.", &file)) { m_chatter.clear (); @@ -402,7 +403,7 @@ void BotConfig::loadChatConfig () { MemFile file {}; // chat config initialization - if (openConfig ("chat", "Chat file not found.", &file, true)) { + if (openConfig ("chat", "Couldn't open chat configuration.", &file, true)) { StringArray *chat = nullptr; StringArray keywords {}; @@ -549,7 +550,7 @@ void BotConfig::loadLanguageConfig () { file.close (); } else if (cv_language.as () != "en") { - logger.error ("Couldn't load language configuration"); + logger.error ("Couldn't load language configuration."); } } diff --git a/src/graph.cpp b/src/graph.cpp index ef3b202..d2aa97d 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -599,6 +599,10 @@ IntArray BotGraph::getNearestInRadius (float radius, const Vector &origin, int m return result; } +bool BotGraph::isAnalyzed () const { + return (m_info.header.options & StorageOption::Analyzed); +} + void BotGraph::add (int type, const Vector &pos) { if (!hasEditor () && !analyzer.isAnalyzing ()) { return; @@ -2836,22 +2840,6 @@ BotGraph::BotGraph () { m_editor = nullptr; } -void BotGraph::initBuckets () { - m_hashTable.clear (); -} - -void BotGraph::addToBucket (const Vector &pos, int index) { - m_hashTable[locateBucket (pos)].emplace (index); -} - -const Array &BotGraph::getNodesInBucket (const Vector &pos) { - return m_hashTable[locateBucket (pos)]; -} - -bool BotGraph::isAnalyzed () const { - return (m_info.header.options & StorageOption::Analyzed); -} - void BotGraph::eraseFromBucket (const Vector &pos, int index) { auto &data = m_hashTable[locateBucket (pos)]; diff --git a/src/linkage.cpp b/src/linkage.cpp index d912cbd..6bed47c 100644 --- a/src/linkage.cpp +++ b/src/linkage.cpp @@ -459,7 +459,7 @@ CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int interfaceVersion) { // would all have the dull "models/player.mdl" one). The entity for which the keyvalue data // pointer is requested is pentKeyvalue, the pointer to the keyvalue data structure pkvd. - if (game.isNullEntity (ent) && strcmp (ent->v.classname.chars (), "func_breakable") == 0) { + if (!game.isNullEntity (ent) && strcmp (ent->v.classname.chars (), "func_breakable") == 0) { if (kvd && kvd->szKeyName && strcmp (kvd->szKeyName, "material") == 0) { if (atoi (kvd->szValue) == 7) { game.markBreakableAsInvalid (ent); diff --git a/src/message.cpp b/src/message.cpp index 552704a..538d778 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -549,7 +549,7 @@ void MessageDispatcher::start (edict_t *ent, int32_t type) { m_bot = bots[ent]; if (!m_bot) { - m_current = NetMsg::None; + stopCollection (); return; } } @@ -561,7 +561,8 @@ void MessageDispatcher::stop () { return; } (this->*m_handlers[m_current]) (); - m_current = NetMsg::None; + + stopCollection (); } void MessageDispatcher::ensureMessages () { diff --git a/src/navigate.cpp b/src/navigate.cpp index a20c132..d633d22 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -11,12 +11,13 @@ ConVar cv_has_team_semiclip ("has_team_semiclip", "0", "When enabled, bots will ConVar cv_graph_slope_height ("graph_slope_height", "24.0", "Determines the maximum slope height change between the current and next node to consider the current link as a jump link. Only for generated graphs.", true, 12.0f, 48.0f); int Bot::findBestGoal () { - if (m_isCreature) { - if (!graph.m_terrorPoints.empty ()) { + if (game.is (GameFlags::ZombieMod) && m_isCreature) { + const auto &players = bots.countTeamPlayers (); + + if (players.first < graph.m_terrorPoints.length ()) { return graph.m_terrorPoints.random (); } - - if (!graph.m_goalPoints.empty ()) { + else if (players.first < graph.m_goalPoints.length ()) { return graph.m_goalPoints.random (); } return graph.random (); diff --git a/src/tasks.cpp b/src/tasks.cpp index f71c8b9..d2454d7 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -1473,9 +1473,9 @@ void Bot::shootBreakable_ () { } else { TraceResult tr {}; - game.testLine (pev->origin, m_breakableOrigin, TraceIgnore::None, ent (), &tr); + game.testLine (pev->origin, m_breakableOrigin, TraceIgnore::Monsters , ent (), &tr); - if (tr.pHit != m_breakableEntity || !util.isVisible (tr.vecEndPos, ent ())) { + if (tr.pHit != m_breakableEntity && !cr::fequal (tr.flFraction, 1.0f)) { m_ignoredBreakable.push (tr.pHit); m_breakableEntity = nullptr; @@ -1494,8 +1494,6 @@ void Bot::shootBreakable_ () { m_navTimeset = game.time (); m_lookAtSafe = m_breakableOrigin; - const float distToObstacle = pev->origin.distanceSq (m_lookAtSafe); - // is bot facing the breakable? if (util.getConeDeviation (ent (), m_lookAtSafe) >= 0.90f) { m_moveSpeed = 0.0f; @@ -1510,6 +1508,7 @@ void Bot::shootBreakable_ () { pev->button |= IN_ATTACK; } } + const float distToObstacle = pev->origin.distanceSq (m_lookAtSafe); // if with knife with no ammo, recompute breakable distance if (!hasAnyAmmoInClip () @@ -1703,6 +1702,7 @@ void Bot::pickupItem_ () { for (const auto &client : util.getClients ()) { if ((client.flags & ClientFlags::Used) && !(client.ent->v.flags & FL_FAKECLIENT) && (client.flags & ClientFlags::Alive) && client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::sqrf (240.0f)) { + return EntitySearchResult::Continue; } }