diff --git a/inc/yapb.h b/inc/yapb.h index 6414fa2..016c3f5 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -819,7 +819,7 @@ private: int findDefendNode (const Vector &origin); int findBestGoal (); int findBestGoalWhenBombAction (); - int findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive); + int findGoalPost (int tactic, IntArray *defensive, IntArray *offensive); int bestPrimaryCarried (); int bestSecondaryCarried (); int bestGrenadeCarried (); @@ -1122,12 +1122,13 @@ public: Vector m_position {}; // position to move to in move to position task Vector m_doubleJumpOrigin {}; // origin of double jump Vector m_lastEnemyOrigin {}; // vector to last enemy origin - + ChatCollection m_sayTextBuffer {}; // holds the index & the actual message of the last unprocessed text message of a player BurstMode m_weaponBurstMode {}; // bot using burst mode? (famas/glock18, but also silencer mode) Personality m_personality {}; // bots type Array m_tasks {}; Deque m_msgQueue {}; + Array m_goalHist {}; public: Bot (edict_t *bot, int difficulty, int personality, int team, int skin); diff --git a/src/control.cpp b/src/control.cpp index 6ae9c35..10ce606 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -211,7 +211,7 @@ int BotControl::cmdCvars () { } for (const auto &cvar : game.getCvars ()) { - if (cvar.info.empty ()) { + if (cvar.info.empty () || !cvar.self || !cvar.self->ptr) { continue; } diff --git a/src/engine.cpp b/src/engine.cpp index 7cf7bc2..d0773c6 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -678,6 +678,9 @@ void ConVar::revert () { void Game::checkCvarsBounds () { for (const auto &var : m_cvars) { + if (!var.self->ptr) { + continue; + } // read only cvar is not changeable if (var.type == Var::ReadOnly && !var.init.empty ()) { diff --git a/src/manager.cpp b/src/manager.cpp index b800ba7..b0d1835 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1481,6 +1481,7 @@ void Bot::newRound () { m_heardSoundTime = game.time (); m_msgQueue.clear (); + m_goalHist.clear (); m_ignoredBreakable.clear (); // and put buying into its message queue diff --git a/src/navigate.cpp b/src/navigate.cpp index 449f0fe..1e09681 100644 --- a/src/navigate.cpp +++ b/src/navigate.cpp @@ -206,7 +206,7 @@ int Bot::findBestGoalWhenBombAction () { return result; } -int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) { +int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) { int goalChoices[4] = { kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex }; if (tactic == 0 && !(*defensive).empty ()) { // careful goal @@ -222,8 +222,8 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) { postprocessGoals (graph.m_campPoints, goalChoices); } } - else if (tactic == 2 && !(*offsensive).empty ()) { // offensive goal - postprocessGoals (*offsensive, goalChoices); + else if (tactic == 2 && !(*offensive).empty ()) { // offensive goal + postprocessGoals (*offensive, goalChoices); } else if (tactic == 3 && !graph.m_goalPoints.empty ()) // map goal node { @@ -282,15 +282,11 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) { } } } - - if (!graph.exists (m_currentNodeIndex)) { - changeNodeIndex (findNearestNode ()); - } + ensureCurrentNodeIndex (); if (goalChoices[0] == kInvalidNodeIndex) { return m_chosenGoalIndex = graph.random (); } - bool sorting = false; do { @@ -313,16 +309,41 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) { void Bot::postprocessGoals (const IntArray &goals, int result[]) { // this function filters the goals, so new goal is not bot's old goal, and array of goals doesn't contains duplicate goals - int searchCount = 0; + int recurseCount = 0; + + auto isRecentOrHistorical = [&] (int index) -> bool { + if (m_prevGoalIndex == index || m_previousNodes[0] == index) { + return true; + } + + // too less to choice from just return all the goals + if (goals.length () < 4) { + return false; + } + + // check if historical goal + for (const auto &hg : m_goalHist) { + if (hg == index) { + return true; + } + } + + for (size_t i = 0; i < 4; ++i) { + if (result[i] == index) { + return true; + } + } + return isOccupiedNode (index); + }; for (int index = 0; index < 4; ++index) { auto goal = goals.random (); - if (searchCount <= 8 && (m_prevGoalIndex == goal || ((result[0] == goal || result[1] == goal || result[2] == goal || result[3] == goal) && goals.length () > 4)) && !isOccupiedNode (goal)) { + if (recurseCount <= cr::max (4, goals.length ()) && isRecentOrHistorical (goal)) { if (index > 0) { index--; } - ++searchCount; + ++recurseCount; continue; } result[index] = goal; @@ -336,6 +357,7 @@ bool Bot::hasActiveGoal () { return false; } else if (goal == m_currentNodeIndex) { // no nodes needed + m_goalHist.push (goal); return true; } else if (m_pathWalk.empty ()) { // no path calculated diff --git a/src/tasks.cpp b/src/tasks.cpp index 9142d7a..c88abf0 100644 --- a/src/tasks.cpp +++ b/src/tasks.cpp @@ -67,7 +67,7 @@ void Bot::normal_ () { // reached node is a camp node if ((m_pathFlags & NodeFlag::Camp) && !game.is (GameFlags::CSDM) && cv_camping_allowed.bool_ () && !isKnifeMode ()) { - const bool allowedCampWeapon = hasPrimaryWeapon () || (hasSecondaryWeapon () && m_numFriendsLeft > game.maxClients () / 4); + const bool allowedCampWeapon = hasPrimaryWeapon () || (hasSecondaryWeapon () && !hasPrimaryWeapon () && m_numFriendsLeft > game.maxClients () / 6); // check if bot has got a primary weapon and hasn't camped before if (allowedCampWeapon && m_timeCamping + 10.0f < game.time () && !m_hasHostage) {