/// \brief Indicates that the player is not allowed to join a team.
const int TEAM_NOT_ALLOWED = -1;
+.float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
+
.int m_team_balance_state; ///< Holds the state of the team balance entity.
.entity m_team_balance_team[NUM_TEAMS]; ///< ???
.int m_num_players_alive; ///< Number of alive players in a team.
.int m_num_control_points; ///< Number of control points owned by a team.
+string autocvar_g_forced_team_red;
+string autocvar_g_forced_team_blue;
+string autocvar_g_forced_team_yellow;
+string autocvar_g_forced_team_pink;
+
entity g_team_entities[NUM_TEAMS]; ///< Holds global team entities.
STATIC_INIT(g_team_entities)
GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type)));
}
+bool Player_HasRealForcedTeam(entity player)
+{
+ return player.team_forced > TEAM_FORCE_DEFAULT;
+}
+
+int Player_GetForcedTeamIndex(entity player)
+{
+ return player.team_forced;
+}
+
+void Player_SetForcedTeamIndex(entity player, int team_index)
+{
+ switch (team_index)
+ {
+ case TEAM_FORCE_SPECTATOR:
+ case TEAM_FORCE_DEFAULT:
+ {
+ player.team_forced = team_index;
+ break;
+ }
+ default:
+ {
+ if (!Team_IsValidIndex(team_index))
+ {
+ LOG_FATAL("Player_SetForcedTeamIndex: Invalid team index.");
+ }
+ else
+ {
+ player.team_forced = team_index;
+ break;
+ }
+ }
+ }
+}
+
+void Player_DetermineForcedTeam(entity player)
+{
+ if (autocvar_g_campaign)
+ {
+ if (IS_REAL_CLIENT(player)) // only players, not bots
+ {
+ if (Team_IsValidIndex(autocvar_g_campaign_forceteam))
+ {
+ player.team_forced = autocvar_g_campaign_forceteam;
+ }
+ else
+ {
+ player.team_forced = TEAM_FORCE_DEFAULT;
+ }
+ }
+ }
+ else if (PlayerInList(player, autocvar_g_forced_team_red))
+ {
+ player.team_forced = 1;
+ }
+ else if (PlayerInList(player, autocvar_g_forced_team_blue))
+ {
+ player.team_forced = 2;
+ }
+ else if (PlayerInList(player, autocvar_g_forced_team_yellow))
+ {
+ player.team_forced = 3;
+ }
+ else if (PlayerInList(player, autocvar_g_forced_team_pink))
+ {
+ player.team_forced = 4;
+ }
+ else
+ {
+ switch (autocvar_g_forced_team_otherwise)
+ {
+ case "red":
+ {
+ player.team_forced = 1;
+ break;
+ }
+ case "blue":
+ {
+ player.team_forced = 2;
+ break;
+ }
+ case "yellow":
+ {
+ player.team_forced = 3;
+ break;
+ }
+ case "pink":
+ {
+ player.team_forced = 4;
+ break;
+ }
+ case "spectate":
+ case "spectator":
+ {
+ player.team_forced = TEAM_FORCE_SPECTATOR;
+ break;
+ }
+ default:
+ {
+ player.team_forced = TEAM_FORCE_DEFAULT;
+ break;
+ }
+ }
+ }
+ if (!teamplay && Player_HasRealForcedTeam(player))
+ {
+ player.team_forced = TEAM_FORCE_DEFAULT;
+ }
+}
+
entity TeamBalance_CheckAllowedTeams(entity for_whom)
{
entity balance = spawn();
team_ent.m_num_players = TEAM_NOT_ALLOWED;
team_ent.m_num_bots = 0;
}
+ setthink(balance, TeamBalance_Destroy);
int teams_mask = 0;
string teament_name = string_null;
// if player has a forced team, ONLY allow that one
for (int i = 1; i <= NUM_TEAMS; ++i)
{
- if (for_whom.team_forced == Team_IndexToTeam(i) &&
+ if (for_whom.team_forced == i &&
TeamBalance_IsTeamAllowedInternal(balance, i))
{
TeamBalance_BanTeamsExcept(balance, i);
{
team_num = it.team;
}
- else if (it.team_forced > 0)
+ else if (Player_HasRealForcedTeam(it))
{
- team_num = it.team_forced; // reserve the spot
+ team_num = Team_IndexToTeam(it.team_forced); // reserve the spot
}
else
{
return team_bits;
}
-void TeamBalance_JoinBestTeam(entity this, bool force_best_team)
+void TeamBalance_JoinBestTeam(entity this)
{
- //PrintToChatAll(sprintf("JoinBestTeam: %s, %f", this.netname, force_best_team));
- // don't join a team if we're not playing a team game
+ //PrintToChatAll(sprintf("JoinBestTeam: %s", this.netname));
if (!teamplay)
{
return;
}
-
- // find out what teams are available
+ if (this.bot_forced_team)
+ {
+ return;
+ }
+ int old_team_index = Team_TeamToIndex(this.team);
entity balance = TeamBalance_CheckAllowedTeams(this);
-
- // if we don't care what team they end up on, put them on whatever team they entered as.
- // if they're not on a valid team, then let other code put them on the smallest team
- if (!force_best_team)
+ if (Player_HasRealForcedTeam(this))
{
- int selected_team_index = -1;
- for (int i = 1; i <= NUM_TEAMS; ++i)
+ int forced_team_index = this.team_forced;
+ bool is_team_allowed = TeamBalance_IsTeamAllowedInternal(balance,
+ forced_team_index);
+ TeamBalance_Destroy(balance);
+ if (!is_team_allowed)
{
- if (TeamBalance_IsTeamAllowedInternal(balance, i) &&
- (Team_TeamToIndex(this.team) == i))
- {
- selected_team_index = i;
- break;
- }
+ return;
}
-
- if (Team_IsValidIndex(selected_team_index))
+ if (!SetPlayerTeam(this, forced_team_index, TEAM_CHANGE_AUTO))
{
- SetPlayerTeam(this, selected_team_index, TEAM_CHANGE_AUTO_RELAXED);
- TeamBalance_Destroy(balance);
return;
}
- }
- // otherwise end up on the smallest team (handled below)
- if (this.bot_forced_team)
- {
- TeamBalance_Destroy(balance);
+ if ((old_team_index != -1) && !IS_BOT_CLIENT(this))
+ {
+ TeamBalance_AutoBalanceBots(forced_team_index, old_team_index);
+ }
return;
}
int best_team_index = TeamBalance_FindBestTeam(balance, this, true);
- int old_team_index = Team_TeamToIndex(this.team);
TeamBalance_Destroy(balance);
PlayerScore_Clear(this);
if (!SetPlayerTeam(this, best_team_index, TEAM_CHANGE_AUTO))
{
return;
}
+ if (source_team_index == -1)
+ {
+ return;
+ }
TeamBalance_AutoBalanceBots(destination_team_index, source_team_index);
}