diff --git a/include/core.h b/include/core.h
index 01075e6..745a516 100644
--- a/include/core.h
+++ b/include/core.h
@@ -157,7 +157,8 @@ enum BotCreationResult
{
BOT_RESULT_CREATED,
BOT_RESULT_MAX_PLAYERS_REACHED,
- BOT_RESULT_NAV_ERROR
+ BOT_RESULT_NAV_ERROR,
+ BOT_RESULT_TEAM_STACKED
};
// radio messages
@@ -1098,7 +1099,9 @@ public:
int m_numEnemiesLeft; // number of enemies alive left on map
int m_numFriendsLeft; // number of friend alive left on map
+ int m_retryJoin; // retry count for chosing team/class
int m_startAction; // team/class selection state
+
bool m_notKilled; // has the player been killed or has he just respawned
bool m_notStarted; // team/class not chosen yet
@@ -1294,6 +1297,7 @@ public:
~BotManager (void);
bool IsEcoValid (int team) { return m_economicsGood[team]; }
+ bool IsTeamStacked (int team);
int GetLastWinner (void) const { return m_lastWinner; }
void SetLastWinner (int winner) { m_lastWinner = winner; }
diff --git a/project/yapb.vcxproj b/project/yapb.vcxproj
index b8162b2..d3ba282 100644
--- a/project/yapb.vcxproj
+++ b/project/yapb.vcxproj
@@ -193,7 +193,7 @@
.\release\inf\
Level4
true
- None
+ ProgramDatabase
CompileAsCpp
SingleFile
true
@@ -225,7 +225,7 @@
.\release\yapb.dll
true
user32.dll;ws2_32.dll;%(DelayLoadDLLs)
- No
+ true
false
Windows
false
diff --git a/source/interface.cpp b/source/interface.cpp
index f3c8efa..a707cd6 100644
--- a/source/interface.cpp
+++ b/source/interface.cpp
@@ -1548,7 +1548,6 @@ void ClientCommand (edict_t *ent)
case 4:
bots.RemoveAll ();
- DisplayMenuToClient (ent, BOT_MENU_CONTROL);
break;
case 5:
diff --git a/source/manager.cpp b/source/manager.cpp
index 6ff1d79..1859895 100644
--- a/source/manager.cpp
+++ b/source/manager.cpp
@@ -24,6 +24,8 @@ ConVar yb_difficulty ("yb_difficulty", "4");
ConVar yb_latency_display ("yb_latency_display", "2");
ConVar yb_avatar_display ("yb_avatar_display", "1");
+ConVar mp_limitteams ("mp_limitteams", nullptr, VT_NOREGISTER);
+
BotManager::BotManager (void)
{
// this is a bot manager class constructor
@@ -128,17 +130,24 @@ BotCreationResult BotManager::CreateBot (const String &name, int difficulty, int
engine.CenterPrintf ("Waypoints have been changed. Load waypoints again...");
return BOT_RESULT_NAV_ERROR;
}
-
- if (difficulty < 0 || difficulty > 4)
- difficulty = yb_difficulty.GetInt ();
+ else if (team != -1 && IsTeamStacked (team - 1))
+ {
+ engine.CenterPrintf ("Desired team is stacked. Unable to proceed with bot creation");
+ return BOT_RESULT_TEAM_STACKED;
+ }
if (difficulty < 0 || difficulty > 4)
{
- difficulty = Random.Int (3, 4);
- yb_difficulty.SetInt (difficulty);
+ difficulty = yb_difficulty.GetInt ();
+
+ if (difficulty < 0 || difficulty > 4)
+ {
+ difficulty = Random.Int (3, 4);
+ yb_difficulty.SetInt (difficulty);
+ }
}
- if (personality < 0 || personality > 2)
+ if (personality < PERSONALITY_NORMAL || personality > PERSONALITY_CAREFUL)
{
if (Random.Int (0, 100) < 50)
personality = PERSONALITY_NORMAL;
@@ -438,6 +447,10 @@ void BotManager::MaintainBotQuota (void)
m_creationTab.RemoveAll (); // maximum players reached, so set quota to maximum players
yb_quota.SetInt (GetBotsNum ());
}
+ else if (callResult == BOT_RESULT_TEAM_STACKED)
+ {
+ engine.Printf ("Could not add bot to the game: Team is stacked (to disable this check, set mp_limitteams and mp_autoteambalance to zero and restart the round)");
+ }
m_maintainTime = engine.Time () + 0.20f;
}
@@ -934,6 +947,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member, c
m_forceRadio = false;
m_startAction = GSM_IDLE;
+ m_retryJoin = 0;
m_moneyAmount = 0;
m_logotypeIndex = Random.Int (0, 9);
@@ -1069,6 +1083,26 @@ int BotManager::GetHumansJoinedTeam (void)
return count;
}
+bool BotManager::IsTeamStacked (int team)
+{
+ int teamLimit = mp_limitteams.GetInt ();
+
+ if (!teamLimit)
+ return false;
+
+ int teamCount[SPECTATOR] = { 0, };
+
+ for (int i = 0; i < engine.MaxClients (); i++)
+ {
+ const Client &client = g_clients[i];
+
+ if ((client.flags & CF_USED) && ((client.team == TERRORIST) || client.team == CT))
+ teamCount[client.team]++;
+ }
+ return teamCount[team] + 1 > teamCount[team == CT ? TERRORIST : CT] + teamLimit;
+}
+
+
void Bot::NewRound (void)
{
// this function initializes a bot after creation & at the start of each round
@@ -1326,6 +1360,24 @@ void Bot::StartGame (void)
if (g_gameFlags & GAME_LEGACY)
pev->button |= IN_ATTACK;
+ // check if something has assigned team to us
+ else if (m_team == TERRORIST || m_team == CT)
+ m_notStarted = false;
+
+ // if bot was unable to join team, and no menus popups, check for stacked team
+ if (m_startAction == GSM_IDLE && ++m_retryJoin > 2)
+ {
+ if (bots.IsTeamStacked (m_wantedTeam - 1))
+ {
+ m_retryJoin = 0;
+
+ engine.Printf ("Could not add bot to the game: Team is stacked (to disable this check, set mp_limitteams and mp_autoteambalance to zero and restart the round).");
+ Kick ();
+
+ return;
+ }
+ }
+
// handle counter-strike stuff here...
if (m_startAction == GSM_TEAM_SELECT)
{
@@ -1348,16 +1400,11 @@ void Bot::StartGame (void)
{
m_startAction = GSM_IDLE; // switch back to idle
- if (g_gameFlags & GAME_CZERO) // czero has spetsnaz and militia skins
- {
- if (m_wantedClass < 1 || m_wantedClass > 5)
- m_wantedClass = Random.Int (1, 5); // use random if invalid
- }
- else
- {
- if (m_wantedClass < 1 || m_wantedClass > 4)
- m_wantedClass = Random.Int (1, 4); // use random if invalid
- }
+ // czero has additional models
+ int maxChoice = (g_gameFlags & GAME_CZERO) ? 5 : 4;
+
+ if (m_wantedClass < 1 || m_wantedClass > maxChoice)
+ m_wantedClass = Random.Int (1, maxChoice); // use random if invalid
// select the class the bot wishes to use...
engine.IssueBotCommand (GetEntity (), "menuselect %d", m_wantedClass);