Xonotic
teamplay.qh File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  { TEAM_CHANGE_AUTO = 2, TEAM_CHANGE_MANUAL = 3, TEAM_CHANGE_SPECTATOR = 4 }
 
enum  { TEAM_FORCE_SPECTATOR = -1, TEAM_FORCE_DEFAULT = 0 }
 
enum  { TEAMS_COMPARE_INVALID, TEAMS_COMPARE_LESS, TEAMS_COMPARE_EQUAL, TEAMS_COMPARE_GREATER }
 Describes the result of comparing teams. More...
 

Functions

entity Entity_GetTeam (entity this)
 Returns the team entity of the given entity. More...
 
int Entity_GetTeamIndex (entity this)
 Returns the team index of the given entity. More...
 
bool Entity_HasValidTeam (entity this)
 Returns whether the given entity belongs to a valid team. More...
 
void KillPlayerForTeamChange (entity player)
 Kills player as a result of team change. More...
 
void LogTeamChange (float player_id, float team_number, int type)
 
bool MoveToTeam (entity client, int team_index, int type)
 Moves player to the specified team. More...
 
void Player_DetermineForcedTeam (entity player)
 Determines the forced team of the player using current global config. More...
 
int Player_GetForcedTeamIndex (entity player)
 Returns the index of the forced team of the given player. More...
 
bool Player_HasRealForcedTeam (entity player)
 Returns whether player has real forced team. More...
 
void Player_SetForcedTeamIndex (entity player, int team_index)
 Sets the index of the forced team of the given player. More...
 
bool Player_SetTeamIndex (entity player, int index)
 Sets the team of the player using its index. More...
 
void Player_SetTeamIndexChecked (entity player, int team_index)
 Sets the team of the player with all sanity checks. More...
 
void setcolor (entity this, int clr)
 
void SetPlayerColors (entity player, float _color)
 
bool SetPlayerTeam (entity player, int team_index, int type)
 Sets the team of the player. More...
 
void SV_ChangeTeam (entity player, int new_color)
 Called when the player changes color with the "color" command. More...
 
int Team_GetNumberOfAlivePlayers (entity team_ent)
 Returns the number of alive players in a team. More...
 
int Team_GetNumberOfAliveTeams ()
 Returns the number of alive teams. More...
 
int Team_GetNumberOfOwnedItems (entity team_ent)
 Returns the number of items owned by a team. More...
 
int Team_GetNumberOfTeamsWithOwnedItems ()
 Returns the number of teams that own items. More...
 
entity Team_GetTeam (int team_num)
 Returns the global team entity that corresponds to the given TEAM_NUM value. More...
 
entity Team_GetTeamFromIndex (int index)
 Returns the global team entity at the given index. More...
 
float Team_GetTeamScore (entity team_ent)
 Returns the score of the team. More...
 
int Team_GetWinnerAliveTeam ()
 Returns the winner team. More...
 
int Team_GetWinnerTeam_WithOwnedItems (int min_owned_items)
 Returns the winner team. More...
 
void Team_InitTeams ()
 
void Team_SetNumberOfAlivePlayers (entity team_ent, int number)
 Sets the number of alive players in a team. More...
 
void Team_SetNumberOfOwnedItems (entity team_ent, int number)
 Sets the number of items owned by a team. More...
 
void Team_SetTeamScore (entity team_ent, float score)
 Sets the score of the team. More...
 
void TeamBalance_AutoBalanceBots ()
 Switches a bot from one team to another if teams are not balanced. More...
 
void TeamBalance_BanTeamsExcept (entity balance, int index)
 Bans team change to all teams except the given one. More...
 
entity TeamBalance_CheckAllowedTeams (entity for_whom)
 Checks whether the player can join teams according to global configuration and mutator settings. More...
 
int TeamBalance_CompareTeams (entity balance, int team_index_a, int team_index_b, entity player, bool use_score)
 Compares two teams for the purposes of game balance. More...
 
int TeamBalance_CompareTeamsInternal (entity team_a, entity team_index_b, entity player, bool use_score)
 Compares two teams for the purposes of game balance. More...
 
void TeamBalance_Destroy (entity balance)
 Destroy the team balance entity. More...
 
int TeamBalance_FindBestTeam (entity balance, entity player, bool ignore_player)
 Finds the team that will make the game most balanced if the player joins it. More...
 
int TeamBalance_FindBestTeams (entity balance, entity player, bool use_score)
 Returns the bitmask of the teams that will make the game most balanced if the player joins any of them. More...
 
int TeamBalance_GetAllowedTeams (entity balance)
 Returns the bitmask of allowed teams. More...
 
int TeamBalance_GetLargestTeamIndex (entity balance, int teams)
 Returns the index of the team with most players that is contained in the given bitmask of teams. More...
 
int TeamBalance_GetNumberOfPlayers (entity balance, int index)
 Returns the number of players (both humans and bots) in a team. More...
 
entity TeamBalance_GetPlayerForTeamSwitch (int source_team_index, int destination_team_index, bool is_bot)
 Returns the player who is the most suitable for switching between the given teams. More...
 
entity TeamBalance_GetTeam (entity balance, int team_num)
 Returns the team entity of the team balance entity that corresponds to the given TEAM_NUM value. More...
 
void TeamBalance_GetTeamCounts (entity balance, entity ignore)
 Counts the number of players and various other information about each team. More...
 
entity TeamBalance_GetTeamFromIndex (entity balance, int index)
 Returns the team entity of the team balance entity at the given index. More...
 
bool TeamBalance_IsTeamAllowed (entity balance, int index)
 Returns whether the team change to the specified team is allowed. More...
 
bool TeamBalance_IsTeamAllowedInternal (entity balance, int index)
 Returns whether the team change to the specified team is allowed. More...
 
void TeamBalance_JoinBestTeam (entity player)
 Assigns the given player to a team that will make the game most balanced. More...
 
int TeamBalanceTeam_GetNumberOfBots (entity team_ent)
 Returns the number of bots in a team. More...
 
int TeamBalanceTeam_GetNumberOfPlayers (entity team_ent)
 Returns the number of players (both humans and bots) in a team. More...
 
bool TeamBalanceTeam_IsAllowed (entity team_ent)
 Returns whether the team is allowed. More...
 

Variables

bool autocvar_g_balance_teams
 
bool autocvar_g_balance_teams_prevent_imbalance
 
bool autocvar_g_changeteam_banned
 
string autocvar_g_forced_team_otherwise
 
bool autocvar_teamplay_lockonrestart
 
int autocvar_teamplay_mode
 
bool lockteams
 
int team_forced
 

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
TEAM_CHANGE_AUTO 

The team was selected by autobalance.

TEAM_CHANGE_MANUAL 

Player has manually selected their team.

TEAM_CHANGE_SPECTATOR 

Player is joining spectators. //TODO: Remove?

Definition at line 109 of file teamplay.qh.

110 {
111  TEAM_CHANGE_AUTO = 2,
112  TEAM_CHANGE_MANUAL = 3,
114 };
The team was selected by autobalance.
Definition: teamplay.qh:111
Player has manually selected their team.
Definition: teamplay.qh:112
Player is joining spectators. //TODO: Remove?
Definition: teamplay.qh:113

◆ anonymous enum

anonymous enum
Enumerator
TEAM_FORCE_SPECTATOR 

Force the player to spectator team.

TEAM_FORCE_DEFAULT 

Don't force any team.

Definition at line 135 of file teamplay.qh.

136 {
137  TEAM_FORCE_SPECTATOR = -1,
138  TEAM_FORCE_DEFAULT = 0
139 };
Force the player to spectator team.
Definition: teamplay.qh:137
Don't force any team.
Definition: teamplay.qh:138

◆ anonymous enum

anonymous enum

Describes the result of comparing teams.

Enumerator
TEAMS_COMPARE_INVALID 

One or both teams are invalid.

TEAMS_COMPARE_LESS 

First team is less than the second one.

TEAMS_COMPARE_EQUAL 

Both teams are equal.

TEAMS_COMPARE_GREATER 

First team the greater than the second one.

Definition at line 231 of file teamplay.qh.

232 {
237 };
One or both teams are invalid.
Definition: teamplay.qh:233
First team is less than the second one.
Definition: teamplay.qh:234
First team the greater than the second one.
Definition: teamplay.qh:236
Both teams are equal.
Definition: teamplay.qh:235

Function Documentation

◆ Entity_GetTeam()

entity Entity_GetTeam ( entity  this)

Returns the team entity of the given entity.

Parameters
[in]thisEntity to check.
Returns
Team entity of the given entity or NULL if the entity doesn't belong to any team.

Definition at line 181 of file teamplay.qc.

References Entity_GetTeamIndex(), NULL, Team_GetTeamFromIndex(), and Team_IsValidIndex().

Referenced by CA_count_alive_players(), Domination_count_controlpoints(), freezetag_count_alive_players(), MUTATOR_HOOKFUNCTION(), and Onslaught_count_generators().

182 {
183  int index = Entity_GetTeamIndex(this);
184  if (!Team_IsValidIndex(index))
185  {
186  return NULL;
187  }
188  return Team_GetTeamFromIndex(index);
189 }
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
int Entity_GetTeamIndex(entity this)
Returns the team index of the given entity.
Definition: teamplay.qc:176
#define NULL
Definition: post.qh:17
entity Team_GetTeamFromIndex(int index)
Returns the global team entity at the given index.
Definition: teamplay.qc:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Entity_GetTeamIndex()

int Entity_GetTeamIndex ( entity  this)

Returns the team index of the given entity.

Parameters
[in]thisEntity to check.
Returns
Team index of the entity.

Definition at line 176 of file teamplay.qc.

References team, and Team_TeamToIndex().

Referenced by Entity_GetTeam(), SetPlayerTeam(), shuffleteams(), and TeamBalance_GetPlayerForTeamSwitch().

177 {
178  return Team_TeamToIndex(this.team);
179 }
int team
Definition: main.qh:157
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition: teams.qh:184
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Entity_HasValidTeam()

bool Entity_HasValidTeam ( entity  this)

Returns whether the given entity belongs to a valid team.

Parameters
[in]thisEntity to check.
Returns
True if entity belongs to a valid team, false otherwise.

Definition at line 171 of file teamplay.qc.

References team, and Team_IsValidTeam().

Referenced by CA_count_alive_players(), Domination_count_controlpoints(), and freezetag_count_alive_players().

172 {
173  return Team_IsValidTeam(this.team);
174 }
int team
Definition: main.qh:157
bool Team_IsValidTeam(int team_num)
Returns whether team value is valid.
Definition: teams.qh:133
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ KillPlayerForTeamChange()

void KillPlayerForTeamChange ( entity  player)

Kills player as a result of team change.

Parameters
[in,out]playerPlayer to kill.

Definition at line 1049 of file teamplay.qc.

References Damage(), DMG_NOWEP, IS_DEAD, and MUTATOR_CALLHOOK.

Referenced by SetPlayerTeam().

1050 {
1051  if (IS_DEAD(player))
1052  {
1053  return;
1054  }
1055  if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true)
1056  {
1057  return;
1058  }
1059  Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP,
1060  player.origin, '0 0 0');
1061 }
#define DMG_NOWEP
Definition: damage.qh:126
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
#define IS_DEAD(s)
Definition: utils.qh:26
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ LogTeamChange()

void LogTeamChange ( float  player_id,
float  team_number,
int  type 
)

Definition at line 1036 of file teamplay.qc.

References autocvar_sv_eventlog, and GameLogEcho().

Referenced by SetPlayerTeam().

1037 {
1038  if (!autocvar_sv_eventlog)
1039  {
1040  return;
1041  }
1042  if (player_id < 1)
1043  {
1044  return;
1045  }
1046  GameLogEcho(sprintf(":team:%d:%d:%d", player_id, team_number, type));
1047 }
void GameLogEcho(string s)
Definition: gamelog.qc:12
bool autocvar_sv_eventlog
Definition: gamelog.qh:3
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MoveToTeam()

bool MoveToTeam ( entity  client,
int  team_index,
int  type 
)

Moves player to the specified team.

Parameters
[in,out]clientClient to move.
[in]team_indexIndex of the team.
[in]type???
Returns
True on success, false otherwise.

Definition at line 327 of file teamplay.qc.

References lockteams, and SetPlayerTeam().

Referenced by GameCommand_moveplayer(), and shuffleteams().

328 {
329  //PrintToChatAll(sprintf("MoveToTeam: %s, %f", client.netname, team_index));
330  int lockteams_backup = lockteams; // backup any team lock
331  lockteams = 0; // disable locked teams
332  if (!SetPlayerTeam(client, team_index, type))
333  {
334  lockteams = lockteams_backup; // restore the team lock
335  return false;
336  }
337  lockteams = lockteams_backup; // restore the team lock
338  return true;
339 }
bool SetPlayerTeam(entity player, int team_index, int type)
Sets the team of the player.
Definition: teamplay.qc:237
bool lockteams
Definition: teamplay.qh:13
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Player_DetermineForcedTeam()

void Player_DetermineForcedTeam ( entity  player)

Determines the forced team of the player using current global config.

Parameters
[in,out]playerPlayer to adjust.

Definition at line 376 of file teamplay.qc.

References autocvar_g_campaign, autocvar_g_campaign_forceteam, autocvar_g_forced_team_blue, autocvar_g_forced_team_otherwise, autocvar_g_forced_team_pink, autocvar_g_forced_team_red, autocvar_g_forced_team_yellow, IS_REAL_CLIENT, Player_HasRealForcedTeam(), PlayerInList(), TEAM_FORCE_DEFAULT, TEAM_FORCE_SPECTATOR, Team_IsValidIndex(), and teamplay.

Referenced by ClientConnect().

377 {
379  {
380  if (IS_REAL_CLIENT(player)) // only players, not bots
381  {
383  {
384  player.team_forced = autocvar_g_campaign_forceteam;
385  }
386  else
387  {
388  player.team_forced = TEAM_FORCE_DEFAULT;
389  }
390  }
391  }
392  else if (PlayerInList(player, autocvar_g_forced_team_red))
393  {
394  player.team_forced = 1;
395  }
396  else if (PlayerInList(player, autocvar_g_forced_team_blue))
397  {
398  player.team_forced = 2;
399  }
401  {
402  player.team_forced = 3;
403  }
404  else if (PlayerInList(player, autocvar_g_forced_team_pink))
405  {
406  player.team_forced = 4;
407  }
408  else
409  {
411  {
412  case "red":
413  {
414  player.team_forced = 1;
415  break;
416  }
417  case "blue":
418  {
419  player.team_forced = 2;
420  break;
421  }
422  case "yellow":
423  {
424  player.team_forced = 3;
425  break;
426  }
427  case "pink":
428  {
429  player.team_forced = 4;
430  break;
431  }
432  case "spectate":
433  case "spectator":
434  {
435  player.team_forced = TEAM_FORCE_SPECTATOR;
436  break;
437  }
438  default:
439  {
440  player.team_forced = TEAM_FORCE_DEFAULT;
441  break;
442  }
443  }
444  }
445  if (!teamplay && Player_HasRealForcedTeam(player))
446  {
447  player.team_forced = TEAM_FORCE_DEFAULT;
448  }
449 }
string autocvar_g_forced_team_otherwise
Definition: teamplay.qh:11
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
string autocvar_g_forced_team_red
Definition: teamplay.qc:40
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
float autocvar_g_campaign_forceteam
Definition: campaign.qh:7
string autocvar_g_forced_team_blue
Definition: teamplay.qc:41
Force the player to spectator team.
Definition: teamplay.qh:137
float teamplay
Definition: progsdefs.qc:31
string autocvar_g_forced_team_pink
Definition: teamplay.qc:43
string autocvar_g_forced_team_yellow
Definition: teamplay.qc:42
Don&#39;t force any team.
Definition: teamplay.qh:138
bool Player_HasRealForcedTeam(entity player)
Returns whether player has real forced team.
Definition: teamplay.qc:341
bool autocvar_g_campaign
Definition: campaign.qh:6
bool PlayerInList(entity player, string list)
Definition: client.qc:995
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Player_GetForcedTeamIndex()

int Player_GetForcedTeamIndex ( entity  player)

Returns the index of the forced team of the given player.

Parameters
[in]playerPlayer to check.
Returns
Index of the forced team.

Definition at line 346 of file teamplay.qc.

Referenced by ClientCommand_clientversion(), ClientCommand_selectteam(), GameCommand_moveplayer(), nJoinAllowed(), and PlayerPreThink().

347 {
348  return player.team_forced;
349 }
+ Here is the caller graph for this function:

◆ Player_HasRealForcedTeam()

bool Player_HasRealForcedTeam ( entity  player)

Returns whether player has real forced team.

Spectator team is ignored.

Parameters
[in]playerPlayer to check.
Returns
True if player has real forced team, false otherwise.

Definition at line 341 of file teamplay.qc.

References TEAM_FORCE_DEFAULT.

Referenced by Player_DetermineForcedTeam(), ShowTeamSelection(), shuffleteams(), TeamBalance_GetTeamCounts(), and TeamBalance_JoinBestTeam().

342 {
343  return player.team_forced > TEAM_FORCE_DEFAULT;
344 }
Don&#39;t force any team.
Definition: teamplay.qh:138
+ Here is the caller graph for this function:

◆ Player_SetForcedTeamIndex()

void Player_SetForcedTeamIndex ( entity  player,
int  team_index 
)

Sets the index of the forced team of the given player.

Parameters
[in,out]playerPlayer to adjust.
[in]team_indexIndex of the team to set.

Definition at line 351 of file teamplay.qc.

References LOG_FATAL, TEAM_FORCE_DEFAULT, TEAM_FORCE_SPECTATOR, and Team_IsValidIndex().

Referenced by GameCommand_moveplayer(), minigame_addplayer(), and player_clear_minigame().

352 {
353  switch (team_index)
354  {
356  case TEAM_FORCE_DEFAULT:
357  {
358  player.team_forced = team_index;
359  break;
360  }
361  default:
362  {
363  if (!Team_IsValidIndex(team_index))
364  {
365  LOG_FATAL("Player_SetForcedTeamIndex: Invalid team index.");
366  }
367  else
368  {
369  player.team_forced = team_index;
370  break;
371  }
372  }
373  }
374 }
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
Force the player to spectator team.
Definition: teamplay.qh:137
Don&#39;t force any team.
Definition: teamplay.qh:138
#define LOG_FATAL(...)
Definition: log.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Player_SetTeamIndex()

bool Player_SetTeamIndex ( entity  player,
int  index 
)

Sets the team of the player using its index.

Parameters
[in,out]playerPlayer to adjust.
[in]indexIndex of the team to set.
Returns
True if team switch was successful, false otherwise.

Definition at line 205 of file teamplay.qc.

References MUTATOR_CALLHOOK, SetPlayerColors(), Team_IndexToTeam(), and Team_TeamToIndex().

Referenced by SetPlayerTeam().

206 {
207  int new_team = Team_IndexToTeam(index);
208  if (player.team == new_team)
209  {
210  if (new_team != -1)
211  {
212  // This is important when players join the game and one of their
213  // color matches the team color while other doesn't. For example
214  // [BOT]Lion: color 0 4.
215  SetPlayerColors(player, new_team - 1);
216  }
217  return true;
218  }
219  int old_index = Team_TeamToIndex(player.team);
220  if (MUTATOR_CALLHOOK(Player_ChangeTeam, player, old_index, index) == true)
221  {
222  // Mutator has blocked team change.
223  return false;
224  }
225  if (new_team == -1)
226  {
227  player.team = -1;
228  }
229  else
230  {
231  SetPlayerColors(player, new_team - 1);
232  }
233  MUTATOR_CALLHOOK(Player_ChangedTeam, player, old_index, index);
234  return true;
235 }
void SetPlayerColors(entity player, float _color)
Definition: teamplay.qc:191
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition: teams.qh:184
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition: teams.qh:169
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Player_SetTeamIndexChecked()

void Player_SetTeamIndexChecked ( entity  player,
int  team_index 
)

Sets the team of the player with all sanity checks.

Parameters
[in,out]playerPlayer to adjust.
[in]team_indexIndex of the team to set.

Definition at line 276 of file teamplay.qc.

References autocvar_g_balance_teams, autocvar_g_balance_teams_prevent_imbalance, autocvar_g_campaign, autocvar_g_changeteam_banned, CS(), entity(), SetPlayerTeam(), TEAM_CHANGE_MANUAL, Team_IndexToBit(), Team_IsValidIndex(), TeamBalance_CheckAllowedTeams(), TeamBalance_Destroy(), TeamBalance_FindBestTeams(), TeamBalance_GetTeamCounts(), TeamBalance_IsTeamAllowedInternal(), teamplay, and wasplayer.

Referenced by ClientKill_Now_TeamChange(), and SV_ChangeTeam().

277 {
278  if (!teamplay)
279  {
280  return;
281  }
282  if (!Team_IsValidIndex(team_index))
283  {
284  return;
285  }
287  CS(player).wasplayer))
288  {
289  Send_Notification(NOTIF_ONE, player, MSG_INFO,
290  INFO_TEAMCHANGE_NOTALLOWED);
291  return;
292  }
293  entity balance = TeamBalance_CheckAllowedTeams(player);
294  if (team_index == 1 && !TeamBalance_IsTeamAllowedInternal(balance, 1))
295  {
296  team_index = 4;
297  }
298  if (team_index == 4 && !TeamBalance_IsTeamAllowedInternal(balance, 4))
299  {
300  team_index = 3;
301  }
302  if (team_index == 3 && !TeamBalance_IsTeamAllowedInternal(balance, 3))
303  {
304  team_index = 2;
305  }
306  if (team_index == 2 && !TeamBalance_IsTeamAllowedInternal(balance, 2))
307  {
308  team_index = 1;
309  }
310  // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
312  {
313  TeamBalance_GetTeamCounts(balance, player);
314  if ((Team_IndexToBit(team_index) & TeamBalance_FindBestTeams(balance,
315  player, false)) == 0)
316  {
317  Send_Notification(NOTIF_ONE, player, MSG_INFO,
318  INFO_TEAMCHANGE_LARGERTEAM);
319  TeamBalance_Destroy(balance);
320  return;
321  }
322  }
323  TeamBalance_Destroy(balance);
324  SetPlayerTeam(player, team_index, TEAM_CHANGE_MANUAL);
325 }
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
bool SetPlayerTeam(entity player, int team_index, int type)
Sets the team of the player.
Definition: teamplay.qc:237
bool wasplayer
Definition: client.qh:69
int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score)
Returns the bitmask of the teams that will make the game most balanced if the player joins any of the...
Definition: teamplay.qc:820
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition: teamplay.qc:627
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
bool autocvar_g_changeteam_banned
Definition: teamplay.qh:5
Player has manually selected their team.
Definition: teamplay.qh:112
bool autocvar_g_balance_teams_prevent_imbalance
Definition: teamplay.qh:9
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
Definition: teamplay.qc:681
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
float teamplay
Definition: progsdefs.qc:31
bool autocvar_g_balance_teams
Definition: teamplay.qh:8
bool autocvar_g_campaign
Definition: campaign.qh:6
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setcolor()

void setcolor ( entity  this,
int  clr 
)

Definition at line 161 of file teamplay.qc.

References clientcolors, and team.

Referenced by SetPlayerColors().

162 {
163 #if 0
164  this.clientcolors = clr;
165  this.team = (clr & 15) + 1;
166 #else
167  builtin_setcolor(this, clr);
168 #endif
169 }
int team
Definition: main.qh:157
float clientcolors
+ Here is the caller graph for this function:

◆ SetPlayerColors()

void SetPlayerColors ( entity  player,
float  _color 
)

Definition at line 191 of file teamplay.qc.

References setcolor(), and teamplay.

Referenced by Player_SetTeamIndex(), and SV_ChangeTeam().

192 {
193  float pants = _color & 0x0F;
194  float shirt = _color & 0xF0;
195  if (teamplay)
196  {
197  setcolor(player, 16 * pants + pants);
198  }
199  else
200  {
201  setcolor(player, shirt + pants);
202  }
203 }
void setcolor(entity this, int clr)
Definition: teamplay.qc:161
float teamplay
Definition: progsdefs.qc:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SetPlayerTeam()

bool SetPlayerTeam ( entity  player,
int  team_index,
int  type 
)

Sets the team of the player.

Parameters
[in,out]playerPlayer to adjust.
[in]team_indexIndex of the team to set.
[in]typeType of the team change. See TEAM_CHANGE constants.
Returns
True if team switch was successful, false otherwise.

Definition at line 237 of file teamplay.qc.

References APP_TEAM_NUM, autocvar_sv_maxidle_playertospectator, CPID_IDLING, CS(), Entity_GetTeamIndex(), FRAGS_SPECTATOR, IS_BOT_CLIENT, just_joined, KillPlayerForTeamChange(), LogTeamChange(), NULL, Player_SetTeamIndex(), PlayerScore_Clear(), TeamBalance_AutoBalanceBots(), and time.

Referenced by bot_clientconnect(), MoveToTeam(), Player_SetTeamIndexChecked(), PutObserverInServer(), TeamBalance_AutoBalanceBots(), and TeamBalance_JoinBestTeam().

238 {
239  int old_team_index = Entity_GetTeamIndex(player);
240 
241  if (!Player_SetTeamIndex(player, team_index))
242  return false;
243 
244  LogTeamChange(player.playerid, player.team, type);
245 
246  if (team_index != old_team_index)
247  {
248  KillPlayerForTeamChange(player);
249  PlayerScore_Clear(player);
250  CS(player).parm_idlesince = time;
251 
252  if (!IS_BOT_CLIENT(player))
254 
255  if (team_index != -1)
256  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, INFO_JOIN_PLAY_TEAM), player.netname);
257  }
258 
259  if (team_index == -1)
260  {
261  if (autocvar_sv_maxidle_playertospectator > 0 && CS(player).idlekick_lasttimeleft)
262  {
263  // this done here so it happens even when manually speccing during the countdown
264  Kill_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CPID_IDLING);
265  CS(player).idlekick_lasttimeleft = 0;
266  }
267  else if (!CS(player).just_joined && player.frags != FRAGS_SPECTATOR)
268  {
269  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, player.netname);
270  }
271  }
272 
273  return true;
274 }
#define APP_TEAM_NUM(num, prefix)
Definition: all.qh:85
void TeamBalance_AutoBalanceBots()
Switches a bot from one team to another if teams are not balanced.
Definition: teamplay.qc:897
ClientState CS(Client this)
Definition: state.qh:47
int Entity_GetTeamIndex(entity this)
Returns the team index of the given entity.
Definition: teamplay.qc:176
void KillPlayerForTeamChange(entity player)
Kills player as a result of team change.
Definition: teamplay.qc:1049
bool just_joined
Definition: client.qh:74
float autocvar_sv_maxidle_playertospectator
Definition: client.qh:38
#define NULL
Definition: post.qh:17
float PlayerScore_Clear(entity player)
Initialize the score of this player if needed.
Definition: scores.qc:267
bool Player_SetTeamIndex(entity player, int index)
Sets the team of the player using its index.
Definition: teamplay.qc:205
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 CPID_IDLING
Definition: all.inc:654
const int FRAGS_SPECTATOR
Definition: constants.qh:4
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition: utils.qh:15
float time
Definition: csprogsdefs.qc:16
void LogTeamChange(float player_id, float team_number, int type)
Definition: teamplay.qc:1036
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SV_ChangeTeam()

void SV_ChangeTeam ( entity  player,
int  new_color 
)

Called when the player changes color with the "color" command.

Note that the "color" command is always called early on player connection

Parameters
[in,out]playerPlayer that requested a new color.
[in]new_colorRequested color.

Definition at line 1151 of file teamplay.qc.

References IS_CLIENT, Player_SetTeamIndexChecked(), SetPlayerColors(), Team_TeamToIndex(), and teamplay.

1152 {
1153  if (!teamplay)
1154  {
1155  SetPlayerColors(player, new_color);
1156  }
1157  if(!IS_CLIENT(player))
1158  {
1159  return;
1160  }
1161  if (!teamplay)
1162  {
1163  return;
1164  }
1165  Player_SetTeamIndexChecked(player, Team_TeamToIndex((new_color & 0x0F) + 1));
1166 }
#define IS_CLIENT(v)
Definition: utils.qh:13
void SetPlayerColors(entity player, float _color)
Definition: teamplay.qc:191
void Player_SetTeamIndexChecked(entity player, int team_index)
Sets the team of the player with all sanity checks.
Definition: teamplay.qc:276
float teamplay
Definition: progsdefs.qc:31
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition: teams.qh:184
+ Here is the call graph for this function:

◆ Team_GetNumberOfAlivePlayers()

int Team_GetNumberOfAlivePlayers ( entity  team_ent)

Returns the number of alive players in a team.

Parameters
[in]team_entTeam entity.
Returns
Number of alive players in a team.

Definition at line 85 of file teamplay.qc.

Referenced by CA_CheckTeams(), CA_count_alive_players(), freezetag_CheckTeams(), freezetag_count_alive_players(), and MUTATOR_HOOKFUNCTION().

86 {
87  return team_ent.m_num_players_alive;
88 }
+ Here is the caller graph for this function:

◆ Team_GetNumberOfAliveTeams()

int Team_GetNumberOfAliveTeams ( )

Returns the number of alive teams.

Returns
Number of alive teams.

Definition at line 110 of file teamplay.qc.

References g_team_entities, m_num_players_alive, NUM_TEAMS, and result.

Referenced by CA_CheckTeams(), and freezetag_CheckTeams().

111 {
112  int result = 0;
113  for (int i = 0; i < NUM_TEAMS; ++i)
114  {
116  {
117  ++result;
118  }
119  }
120  return result;
121 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
entity result
Definition: promise.qc:43
int m_num_players_alive
Number of alive players in a team.
Definition: teamplay.qc:37
+ Here is the caller graph for this function:

◆ Team_GetNumberOfOwnedItems()

int Team_GetNumberOfOwnedItems ( entity  team_ent)

Returns the number of items owned by a team.

Parameters
[in]team_entTeam entity.
Returns
Number of items owned by a team.

Definition at line 138 of file teamplay.qc.

Referenced by Domination_count_controlpoints(), and Onslaught_count_generators().

139 {
140  return team_ent.m_num_owned_items;
141 }
+ Here is the caller graph for this function:

◆ Team_GetNumberOfTeamsWithOwnedItems()

int Team_GetNumberOfTeamsWithOwnedItems ( )

Returns the number of teams that own items.

Returns
Number of teams that own items.

Definition at line 148 of file teamplay.qc.

References g_team_entities, m_num_owned_items, NUM_TEAMS, and result.

149 {
150  int result = 0;
151  for (int i = 0; i < NUM_TEAMS; ++i)
152  {
154  {
155  ++result;
156  }
157  }
158  return result;
159 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
entity result
Definition: promise.qc:43
int m_num_owned_items
Number of items owned by a team.
Definition: teamplay.qc:38

◆ Team_GetTeam()

entity Team_GetTeam ( int  team_num)

Returns the global team entity that corresponds to the given TEAM_NUM value.

Parameters
[in]team_numTeam value. See TEAM_NUM constants.
Returns
Global team entity that corresponds to the given TEAM_NUM value.

Definition at line 66 of file teamplay.qc.

References g_team_entities, LOG_FATALF, Team_IsValidTeam(), and Team_TeamToIndex().

67 {
68  if (!Team_IsValidTeam(team_num))
69  {
70  LOG_FATALF("Team_GetTeam: Value is invalid: %f", team_num);
71  }
72  return g_team_entities[Team_TeamToIndex(team_num) - 1];
73 }
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition: teams.qh:184
#define LOG_FATALF(...)
Definition: log.qh:59
bool Team_IsValidTeam(int team_num)
Returns whether team value is valid.
Definition: teams.qh:133
+ Here is the call graph for this function:

◆ Team_GetTeamFromIndex()

entity Team_GetTeamFromIndex ( int  index)

Returns the global team entity at the given index.

Parameters
[in]indexIndex of the team.
Returns
Global team entity at the given index.

Definition at line 57 of file teamplay.qc.

References g_team_entities, LOG_FATALF, and Team_IsValidIndex().

Referenced by CA_CheckTeams(), CA_count_alive_players(), Domination_count_controlpoints(), Entity_GetTeam(), freezetag_CheckTeams(), freezetag_count_alive_players(), Onslaught_count_generators(), WinningCondition_RanOutOfSpawns(), and WinningCondition_Scores().

58 {
59  if (!Team_IsValidIndex(index))
60  {
61  LOG_FATALF("Team_GetTeamFromIndex: Index is invalid: %f", index);
62  }
63  return g_team_entities[index - 1];
64 }
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
#define LOG_FATALF(...)
Definition: log.qh:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Team_GetTeamScore()

float Team_GetTeamScore ( entity  team_ent)

Returns the score of the team.

Parameters
[in]team_entTeam entity.
Returns
Score of the team.

Definition at line 75 of file teamplay.qc.

Referenced by WinningCondition_RanOutOfSpawns().

76 {
77  return team_ent.m_team_score;
78 }
+ Here is the caller graph for this function:

◆ Team_GetWinnerAliveTeam()

int Team_GetWinnerAliveTeam ( )

Returns the winner team.

Returns
Winner team or 0 if 2 or more teams have alive players or -1 if no team has any alive players.

Definition at line 95 of file teamplay.qc.

References g_team_entities, m_num_players_alive, NUM_TEAMS, and Team_IndexToTeam().

Referenced by CA_CheckWinner(), and freezetag_CheckWinner().

96 {
97  int winner = 0;
98  for (int i = 0; i < NUM_TEAMS; ++i)
99  {
101  {
102  if (winner)
103  return 0;
104  winner = Team_IndexToTeam(i + 1);
105  }
106  }
107  return (winner ? winner : -1);
108 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition: teams.qh:169
int m_num_players_alive
Number of alive players in a team.
Definition: teamplay.qc:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Team_GetWinnerTeam_WithOwnedItems()

int Team_GetWinnerTeam_WithOwnedItems ( int  min_owned_items)

Returns the winner team.

Parameters
[in]min_owned_itemsMinimum number of items the winner team must have.
Returns
Winner team or 0 if 2 or more teams own items or -1 if no team own any items.

Definition at line 123 of file teamplay.qc.

References g_team_entities, m_num_owned_items, NUM_TEAMS, and Team_IndexToTeam().

Referenced by Domination_CheckWinner(), and Onslaught_CheckWinner().

124 {
125  int winner = 0;
126  for (int i = 0; i < NUM_TEAMS; ++i)
127  {
128  if (g_team_entities[i].m_num_owned_items >= min_control_points)
129  {
130  if (winner)
131  return 0;
132  winner = Team_IndexToTeam(i + 1);
133  }
134  }
135  return (winner ? winner : -1);
136 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition: teams.qh:169
int m_num_owned_items
Number of items owned by a team.
Definition: teamplay.qc:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Team_InitTeams()

void Team_InitTeams ( )

Definition at line 47 of file teamplay.qc.

References g_team_entities, new_pure, and NUM_TEAMS.

Referenced by GameRules_teams().

48 {
49  if (g_team_entities[0])
50  return;
51  for (int i = 0; i < NUM_TEAMS; ++i)
52  {
53  g_team_entities[i] = new_pure(team_entity);
54  }
55 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
+ Here is the caller graph for this function:

◆ Team_SetNumberOfAlivePlayers()

void Team_SetNumberOfAlivePlayers ( entity  team_ent,
int  number 
)

Sets the number of alive players in a team.

Parameters
[in,out]team_entTeam entity.
[in]numberNumber of players to set.

Definition at line 90 of file teamplay.qc.

References number.

Referenced by CA_count_alive_players(), and freezetag_count_alive_players().

91 {
92  team_ent.m_num_players_alive = number;
93 }
int int number
Definition: impulse.qc:89
+ Here is the caller graph for this function:

◆ Team_SetNumberOfOwnedItems()

void Team_SetNumberOfOwnedItems ( entity  team_ent,
int  number 
)

Sets the number of items owned by a team.

Parameters
[in,out]team_entTeam entity.
[in]numberNumber of items to set.

Definition at line 143 of file teamplay.qc.

References number.

Referenced by Domination_count_controlpoints(), and Onslaught_count_generators().

144 {
145  team_ent.m_num_owned_items = number;
146 }
int int number
Definition: impulse.qc:89
+ Here is the caller graph for this function:

◆ Team_SetTeamScore()

void Team_SetTeamScore ( entity  team_ent,
float  score 
)

Sets the score of the team.

Parameters
[in,out]team_entTeam entity.
[in]scoreScore to set.

Definition at line 80 of file teamplay.qc.

Referenced by WinningCondition_RanOutOfSpawns(), and WinningCondition_Scores().

81 {
82  team_ent.m_team_score = score;
83 }
+ Here is the caller graph for this function:

◆ TeamBalance_AutoBalanceBots()

void TeamBalance_AutoBalanceBots ( )

Switches a bot from one team to another if teams are not balanced.

Definition at line 897 of file teamplay.qc.

References BITS, entity(), NULL, NUM_TEAMS, SetPlayerTeam(), TEAM_CHANGE_AUTO, Team_IndexToBit(), TeamBalance_CheckAllowedTeams(), TeamBalance_Destroy(), TeamBalance_GetLargestTeamIndex(), TeamBalance_GetPlayerForTeamSwitch(), TeamBalance_GetTeamCounts(), TeamBalance_GetTeamFromIndex(), TeamBalanceTeam_GetNumberOfPlayers(), TeamBalanceTeam_IsAllowed(), and teams.

Referenced by SetPlayerTeam().

898 {
899  // checks disabled because we always want auto-balanced bots
900  //if (!(autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance))
901  // return;
902 
905  int smallest_team_index = 0;
906  int smallest_team_player_count = 0;
907  for (int i = 1; i <= NUM_TEAMS; ++i)
908  {
909  entity team_ = TeamBalance_GetTeamFromIndex(balance, i);
910  if (!TeamBalanceTeam_IsAllowed(team_))
911  {
912  continue;
913  }
914  int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
915  if (smallest_team_index == 0)
916  {
917  smallest_team_index = i;
918  smallest_team_player_count = playercount;
919  }
920  else if (playercount < smallest_team_player_count)
921  {
922  smallest_team_index = i;
923  smallest_team_player_count = playercount;
924  }
925  }
926  //PrintToChatAll(sprintf("Smallest team: %f", smallest_team_index));
927  //PrintToChatAll(sprintf("Smallest team players: %f", smallest_team_player_count));
928  entity switchable_bot = NULL;
929  int teams = BITS(NUM_TEAMS);
930  while (teams != 0)
931  {
932  int largest_team_index = TeamBalance_GetLargestTeamIndex(balance,
933  teams);
934  if (smallest_team_index == largest_team_index)
935  {
936  TeamBalance_Destroy(balance);
937  return;
938  }
939  entity largest_team = TeamBalance_GetTeamFromIndex(balance,
940  largest_team_index);
941  int largest_team_player_count = TeamBalanceTeam_GetNumberOfPlayers(
942  largest_team);
943  if (largest_team_player_count - smallest_team_player_count < 2)
944  {
945  TeamBalance_Destroy(balance);
946  return;
947  }
948  //PrintToChatAll(sprintf("Largest team: %f", largest_team_index));
949  //PrintToChatAll(sprintf("Largest team players: %f", largest_team_player_count));
950  switchable_bot = TeamBalance_GetPlayerForTeamSwitch(largest_team_index,
951  smallest_team_index, true);
952  if (switchable_bot != NULL)
953  {
954  break;
955  }
956  teams &= ~Team_IndexToBit(largest_team_index);
957  }
958  TeamBalance_Destroy(balance);
959  if (switchable_bot == NULL)
960  {
961  //PrintToChatAll("No bot found after searching through all the teams");
962  return;
963  }
964  SetPlayerTeam(switchable_bot, smallest_team_index, TEAM_CHANGE_AUTO);
965 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
bool SetPlayerTeam(entity player, int team_index, int type)
Sets the team of the player.
Definition: teamplay.qc:237
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition: teamplay.qc:627
entity() spawn
The team was selected by autobalance.
Definition: teamplay.qh:111
bool TeamBalanceTeam_IsAllowed(entity team_ent)
Returns whether the team is allowed.
Definition: teamplay.qc:1094
entity teams
Definition: main.qh:44
int TeamBalance_GetLargestTeamIndex(entity balance, int teams)
Returns the index of the team with most players that is contained in the given bitmask of teams...
Definition: teamplay.qc:967
entity TeamBalance_GetTeamFromIndex(entity balance, int index)
Returns the team entity of the team balance entity at the given index.
Definition: teamplay.qc:1080
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
Definition: teamplay.qc:681
#define NULL
Definition: post.qh:17
int TeamBalanceTeam_GetNumberOfPlayers(entity team_ent)
Returns the number of players (both humans and bots) in a team.
Definition: teamplay.qc:1099
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
#define BITS(n)
Definition: bits.qh:9
entity TeamBalance_GetPlayerForTeamSwitch(int source_team_index, int destination_team_index, bool is_bot)
Returns the player who is the most suitable for switching between the given teams.
Definition: teamplay.qc:997
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_BanTeamsExcept()

void TeamBalance_BanTeamsExcept ( entity  balance,
int  index 
)

Bans team change to all teams except the given one.

Parameters
[in,out]balanceTeam balance entity.
[in]indexIndex of the team.

Definition at line 1069 of file teamplay.qc.

References NUM_TEAMS, and TEAM_NOT_ALLOWED.

Referenced by TeamBalance_CheckAllowedTeams().

1070 {
1071  for (int i = 1; i <= NUM_TEAMS; ++i)
1072  {
1073  if (i != index)
1074  {
1075  balance.m_team_balance_team[i - 1].m_num_players = TEAM_NOT_ALLOWED;
1076  }
1077  }
1078 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
const int TEAM_NOT_ALLOWED
Indicates that the player is not allowed to join a team.
Definition: teamplay.qc:29
+ Here is the caller graph for this function:

◆ TeamBalance_CheckAllowedTeams()

entity TeamBalance_CheckAllowedTeams ( entity  for_whom)

Checks whether the player can join teams according to global configuration and mutator settings.

Parameters
[in]for_whomPlayer to check for. Pass NULL for global rules.
Returns
Team balance entity that holds information about teams. This entity will be automatically destroyed on the next frame but you are encouraged to manually destroy it by calling TeamBalance_Destroy for performance reasons.

Definition at line 487 of file teamplay.qc.

References autocvar_bot_vs_human, AvailableTeams(), BIT, classname, entity(), find(), g_team_entities, IS_BOT_CLIENT, M_ARGV, MUTATOR_CALLHOOK, NULL, NUM_TEAMS, setthink, spawn(), string_null, TEAM_BALANCE_TEAMS_CHECKED, Team_IsValidTeam(), TEAM_NOT_ALLOWED, TeamBalance_BanTeamsExcept(), TeamBalance_CheckAllowedTeams(), TeamBalance_Destroy(), TeamBalance_GetTeam(), TeamBalance_IsTeamAllowedInternal(), and time.

Referenced by adjust_respawntime(), bot_removefromlargestteam(), bot_setnameandstuff(), ClientCommand_selectteam(), ClientConnect(), dom_DelayedInit(), GameCommand_moveplayer(), ons_ScoreRules(), Player_SetTeamIndexChecked(), ScoreRules_generic(), shuffleteams(), TeamBalance_AutoBalanceBots(), TeamBalance_CheckAllowedTeams(), TeamBalance_GetPlayerForTeamSwitch(), TeamBalance_JoinBestTeam(), and WinningCondition_RanOutOfSpawns().

488 {
489  entity balance = spawn();
490  for (int i = 0; i < NUM_TEAMS; ++i)
491  {
492  entity team_ent = balance.m_team_balance_team[i] = spawn();
493  team_ent.m_team_score = g_team_entities[i].m_team_score;
494  team_ent.m_num_players = TEAM_NOT_ALLOWED;
495  team_ent.m_num_bots = 0;
496  }
497  setthink(balance, TeamBalance_Destroy);
498  balance.nextthink = time;
499 
500  int teams_mask = 0;
501  string teament_name = string_null;
502  bool mutator_returnvalue = MUTATOR_CALLHOOK(TeamBalance_CheckAllowedTeams,
503  teams_mask, teament_name, for_whom);
504  teams_mask = M_ARGV(0, float);
505  teament_name = M_ARGV(1, string);
506  if (mutator_returnvalue)
507  {
508  for (int i = 0; i < NUM_TEAMS; ++i)
509  {
510  if (teams_mask & BIT(i))
511  {
512  balance.m_team_balance_team[i].m_num_players = 0;
513  }
514  }
515  }
516 
517  if (teament_name)
518  {
519  entity head = find(NULL, classname, teament_name);
520  while (head)
521  {
522  if (Team_IsValidTeam(head.team))
523  {
524  TeamBalance_GetTeam(balance, head.team).m_num_players = 0;
525  }
526  head = find(head, classname, teament_name);
527  }
528  }
529 
530  // TODO: Balance quantity of bots across > 2 teams when bot_vs_human is set (and remove next line)
531  if (autocvar_bot_vs_human && AvailableTeams() == 2 && for_whom)
532  {
533  if (autocvar_bot_vs_human > 0)
534  {
535  // find last team available
536  if (IS_BOT_CLIENT(for_whom))
537  {
538  if (TeamBalance_IsTeamAllowedInternal(balance, 4))
539  {
540  TeamBalance_BanTeamsExcept(balance, 4);
541  }
542  else if (TeamBalance_IsTeamAllowedInternal(balance, 3))
543  {
544  TeamBalance_BanTeamsExcept(balance, 3);
545  }
546  else
547  {
548  TeamBalance_BanTeamsExcept(balance, 2);
549  }
550  // no further cases, we know at least 2 teams exist
551  }
552  else
553  {
554  if (TeamBalance_IsTeamAllowedInternal(balance, 1))
555  {
556  TeamBalance_BanTeamsExcept(balance, 1);
557  }
558  else if (TeamBalance_IsTeamAllowedInternal(balance, 2))
559  {
560  TeamBalance_BanTeamsExcept(balance, 2);
561  }
562  else
563  {
564  TeamBalance_BanTeamsExcept(balance, 3);
565  }
566  // no further cases, bots have one of the teams
567  }
568  }
569  else
570  {
571  // find first team available
572  if (IS_BOT_CLIENT(for_whom))
573  {
574  if (TeamBalance_IsTeamAllowedInternal(balance, 1))
575  {
576  TeamBalance_BanTeamsExcept(balance, 1);
577  }
578  else if (TeamBalance_IsTeamAllowedInternal(balance, 2))
579  {
580  TeamBalance_BanTeamsExcept(balance, 2);
581  }
582  else
583  {
584  TeamBalance_BanTeamsExcept(balance, 3);
585  }
586  // no further cases, we know at least 2 teams exist
587  }
588  else
589  {
590  if (TeamBalance_IsTeamAllowedInternal(balance, 4))
591  {
592  TeamBalance_BanTeamsExcept(balance, 4);
593  }
594  else if (TeamBalance_IsTeamAllowedInternal(balance, 3))
595  {
596  TeamBalance_BanTeamsExcept(balance, 3);
597  }
598  else
599  {
600  TeamBalance_BanTeamsExcept(balance, 2);
601  }
602  // no further cases, bots have one of the teams
603  }
604  }
605  }
606 
607  if (!for_whom)
608  {
609  balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
610  return balance;
611  }
612 
613  // if player has a forced team, ONLY allow that one
614  for (int i = 1; i <= NUM_TEAMS; ++i)
615  {
616  if (for_whom.team_forced == i &&
618  {
619  TeamBalance_BanTeamsExcept(balance, i);
620  break;
621  }
622  }
623  balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
624  return balance;
625 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
string string_null
Definition: nil.qh:9
entity g_team_entities[NUM_TEAMS]
Holds global team entities.
Definition: teamplay.qc:45
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition: teamplay.qc:627
TeamBalance_CheckAllowedTeams has been called.
Definition: teamplay.qc:23
entity() spawn
string classname
Definition: csprogsdefs.qc:107
int autocvar_bot_vs_human
Definition: cvars.qh:70
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
entity TeamBalance_GetTeam(entity balance, int team_num)
Returns the team entity of the team balance entity that corresponds to the given TEAM_NUM value...
Definition: teamplay.qc:1089
const int TEAM_NOT_ALLOWED
Indicates that the player is not allowed to join a team.
Definition: teamplay.qc:29
#define NULL
Definition: post.qh:17
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
void TeamBalance_BanTeamsExcept(entity balance, int index)
Bans team change to all teams except the given one.
Definition: teamplay.qc:1069
int AvailableTeams()
Definition: scores_rules.qc:22
#define M_ARGV(x, type)
Definition: events.qh:17
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition: utils.qh:15
#define setthink(e, f)
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
float time
Definition: csprogsdefs.qc:16
bool Team_IsValidTeam(int team_num)
Returns whether team value is valid.
Definition: teams.qh:133
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_CompareTeams()

int TeamBalance_CompareTeams ( entity  balance,
int  team_index_a,
int  team_index_b,
entity  player,
bool  use_score 
)

Compares two teams for the purposes of game balance.

Parameters
[in]balanceTeam balance entity.
[in]team_index_aIndex of the first team.
[in]team_index_bIndex of the second team.
[in]playerPlayer to check.
[in]use_scoreWhether to take into account team scores.
Returns
TEAMS_COMPARE value. See above.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 866 of file teamplay.qc.

References entity(), LOG_FATAL, LOG_FATALF, NULL, TEAM_BALANCE_TEAM_COUNTS_FILLED, Team_IsValidIndex(), TeamBalance_CompareTeamsInternal(), TeamBalance_GetTeamFromIndex(), and TEAMS_COMPARE_EQUAL.

Referenced by TeamBalance_FindBestTeams().

868 {
869  if (balance == NULL)
870  {
871  LOG_FATAL("TeamBalance_CompareTeams: Team balance entity is NULL.");
872  }
873  if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
874  {
875  LOG_FATAL("TeamBalance_CompareTeams: "
876  "TeamBalance_GetTeamCounts has not been called.");
877  }
878  if (!Team_IsValidIndex(team_index_a))
879  {
880  LOG_FATALF("TeamBalance_CompareTeams: team_index_a is invalid: %f",
881  team_index_a);
882  }
883  if (!Team_IsValidIndex(team_index_b))
884  {
885  LOG_FATALF("TeamBalance_CompareTeams: team_index_b is invalid: %f",
886  team_index_b);
887  }
888  if (team_index_a == team_index_b)
889  {
890  return TEAMS_COMPARE_EQUAL;
891  }
892  entity team_a = TeamBalance_GetTeamFromIndex(balance, team_index_a);
893  entity team_b = TeamBalance_GetTeamFromIndex(balance, team_index_b);
894  return TeamBalance_CompareTeamsInternal(team_a, team_b, player, use_score);
895 }
int TeamBalance_CompareTeamsInternal(entity team_a, entity team_b, entity player, bool use_score)
Compares two teams for the purposes of game balance.
Definition: teamplay.qc:1109
entity() spawn
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
entity TeamBalance_GetTeamFromIndex(entity balance, int index)
Returns the team entity of the team balance entity at the given index.
Definition: teamplay.qc:1080
#define NULL
Definition: post.qh:17
#define LOG_FATALF(...)
Definition: log.qh:59
#define LOG_FATAL(...)
Definition: log.qh:58
TeamBalance_GetTeamCounts has been called.
Definition: teamplay.qc:25
Both teams are equal.
Definition: teamplay.qh:235
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_CompareTeamsInternal()

int TeamBalance_CompareTeamsInternal ( entity  team_a,
entity  team_index_b,
entity  player,
bool  use_score 
)

Compares two teams for the purposes of game balance.

Parameters
[in]team_aFirst team.
[in]team_bSecond team.
[in]playerPlayer to check.
[in]use_scoreWhether to take into account team scores.
Returns
TEAMS_COMPARE value. See above.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 1109 of file teamplay.qc.

References bots_would_leave, IS_REAL_CLIENT, TeamBalanceTeam_IsAllowed(), TEAMS_COMPARE_EQUAL, TEAMS_COMPARE_GREATER, TEAMS_COMPARE_INVALID, and TEAMS_COMPARE_LESS.

Referenced by TeamBalance_CompareTeams().

1111 {
1112  if (team_a == team_b)
1113  {
1114  return TEAMS_COMPARE_EQUAL;
1115  }
1116  if (!TeamBalanceTeam_IsAllowed(team_a) ||
1117  !TeamBalanceTeam_IsAllowed(team_b))
1118  {
1119  return TEAMS_COMPARE_INVALID;
1120  }
1121  int num_players_team_a = team_a.m_num_players;
1122  int num_players_team_b = team_b.m_num_players;
1123  if (IS_REAL_CLIENT(player) && bots_would_leave)
1124  {
1125  num_players_team_a -= team_a.m_num_bots;
1126  num_players_team_b -= team_b.m_num_bots;
1127  }
1128  if (num_players_team_a < num_players_team_b)
1129  {
1130  return TEAMS_COMPARE_LESS;
1131  }
1132  if (num_players_team_a > num_players_team_b)
1133  {
1134  return TEAMS_COMPARE_GREATER;
1135  }
1136  if (!use_score)
1137  {
1138  return TEAMS_COMPARE_EQUAL;
1139  }
1140  if (team_a.m_team_score < team_b.m_team_score)
1141  {
1142  return TEAMS_COMPARE_LESS;
1143  }
1144  if (team_a.m_team_score > team_b.m_team_score)
1145  {
1146  return TEAMS_COMPARE_GREATER;
1147  }
1148  return TEAMS_COMPARE_EQUAL;
1149 }
One or both teams are invalid.
Definition: teamplay.qh:233
bool TeamBalanceTeam_IsAllowed(entity team_ent)
Returns whether the team is allowed.
Definition: teamplay.qc:1094
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
bool bots_would_leave
Definition: api.qh:101
First team is less than the second one.
Definition: teamplay.qh:234
First team the greater than the second one.
Definition: teamplay.qh:236
Both teams are equal.
Definition: teamplay.qh:235
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_Destroy()

void TeamBalance_Destroy ( entity  balance)

Destroy the team balance entity.

Parameters
[in,out]balanceTeam balance entity to destroy.
Note
Team balance entity is allowed to be NULL.

Definition at line 627 of file teamplay.qc.

References NULL, and NUM_TEAMS.

Referenced by adjust_respawntime(), bot_setnameandstuff(), ClientCommand_selectteam(), ClientConnect(), dom_DelayedInit(), GameCommand_moveplayer(), ons_ScoreRules(), Player_SetTeamIndexChecked(), ScoreRules_generic(), shuffleteams(), TeamBalance_AutoBalanceBots(), TeamBalance_CheckAllowedTeams(), TeamBalance_GetPlayerForTeamSwitch(), and TeamBalance_JoinBestTeam().

628 {
629  if (balance == NULL)
630  {
631  return;
632  }
633  for (int i = 0; i < NUM_TEAMS; ++i)
634  {
635  delete(balance.(m_team_balance_team[i]));
636  }
637  delete(balance);
638 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
#define NULL
Definition: post.qh:17
+ Here is the caller graph for this function:

◆ TeamBalance_FindBestTeam()

int TeamBalance_FindBestTeam ( entity  balance,
entity  player,
bool  ignore_player 
)

Finds the team that will make the game most balanced if the player joins it.

Parameters
[in]balanceTeam balance entity.
[in]playerPlayer to check.
[in]ignore_player???
Returns
Index of the team that will make the game most balanced if the player joins it. If there are several equally good teams available, the function will pick a random one.

Definition at line 783 of file teamplay.qc.

References LOG_FATAL, LOG_FATALF, MapInfo_CurrentGametype(), MapInfo_Type_ToString(), NULL, NUM_TEAMS, RandomSelection_AddFloat, RandomSelection_chosen_float, RandomSelection_Init(), TEAM_BALANCE_UNINITIALIZED, Team_IndexToBit(), TeamBalance_FindBestTeams(), and TeamBalance_GetTeamCounts().

Referenced by GameCommand_moveplayer(), and TeamBalance_JoinBestTeam().

784 {
785  if (balance == NULL)
786  {
787  LOG_FATAL("TeamBalance_FindBestTeam: Team balance entity is NULL.");
788  }
789  if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
790  {
791  LOG_FATAL("TeamBalance_FindBestTeam: "
792  "Team balance entity is not initialized.");
793  }
794  // count how many players are in each team
795  if (ignore_player)
796  {
797  TeamBalance_GetTeamCounts(balance, player);
798  }
799  else
800  {
802  }
803  int team_bits = TeamBalance_FindBestTeams(balance, player, true);
804  if (team_bits == 0)
805  {
806  LOG_FATALF("TeamBalance_FindBestTeam: No teams available for %s\n",
808  }
810  for (int i = 1; i <= NUM_TEAMS; ++i)
811  {
812  if (team_bits & Team_IndexToBit(i))
813  {
814  RandomSelection_AddFloat(i, 1, 1);
815  }
816  }
818 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
string MapInfo_Type_ToString(Gametype t)
Definition: mapinfo.qc:616
ERASEABLE void RandomSelection_Init()
Definition: random.qc:4
int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score)
Returns the bitmask of the teams that will make the game most balanced if the player joins any of the...
Definition: teamplay.qc:820
float RandomSelection_chosen_float
Definition: random.qh:6
Gametype MapInfo_CurrentGametype()
Definition: mapinfo.qc:1150
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
Definition: teamplay.qc:681
#define NULL
Definition: post.qh:17
#define RandomSelection_AddFloat(f, weight, priority)
Definition: random.qh:15
The team balance has not been initialized.
Definition: teamplay.qc:21
#define LOG_FATALF(...)
Definition: log.qh:59
#define LOG_FATAL(...)
Definition: log.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_FindBestTeams()

int TeamBalance_FindBestTeams ( entity  balance,
entity  player,
bool  use_score 
)

Returns the bitmask of the teams that will make the game most balanced if the player joins any of them.

Parameters
[in]balanceTeam balance entity.
[in]playerPlayer to check.
[in]use_scoreWhether to take into account team scores.
Returns
Bitmask of the teams that will make the game most balanced if the player joins any of them.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 820 of file teamplay.qc.

References LOG_FATAL, M_ARGV, MUTATOR_CALLHOOK, NULL, NUM_TEAMS, TEAM_BALANCE_TEAM_COUNTS_FILLED, Team_IndexToBit(), TeamBalance_CompareTeams(), TeamBalance_FindBestTeams(), TeamBalance_IsTeamAllowedInternal(), TEAMS_COMPARE_EQUAL, and TEAMS_COMPARE_LESS.

Referenced by ClientCommand_selectteam(), Player_SetTeamIndexChecked(), TeamBalance_FindBestTeam(), and TeamBalance_FindBestTeams().

821 {
822  if (balance == NULL)
823  {
824  LOG_FATAL("TeamBalance_FindBestTeams: Team balance entity is NULL.");
825  }
826  if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
827  {
828  LOG_FATAL("TeamBalance_FindBestTeams: "
829  "TeamBalance_GetTeamCounts has not been called.");
830  }
831  if (MUTATOR_CALLHOOK(TeamBalance_FindBestTeams, player) == true)
832  {
833  return M_ARGV(1, float);
834  }
835  int team_bits = 0;
836  int previous_team = 0;
837  for (int i = 1; i <= NUM_TEAMS; ++i)
838  {
839  if (!TeamBalance_IsTeamAllowedInternal(balance, i))
840  {
841  continue;
842  }
843  if (previous_team == 0)
844  {
845  team_bits = Team_IndexToBit(i);
846  previous_team = i;
847  continue;
848  }
849  int compare = TeamBalance_CompareTeams(balance, i, previous_team,
850  player, use_score);
851  if (compare == TEAMS_COMPARE_LESS)
852  {
853  team_bits = Team_IndexToBit(i);
854  previous_team = i;
855  continue;
856  }
857  if (compare == TEAMS_COMPARE_EQUAL)
858  {
859  team_bits |= Team_IndexToBit(i);
860  previous_team = i;
861  }
862  }
863  return team_bits;
864 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b, entity player, bool use_score)
Compares two teams for the purposes of game balance.
Definition: teamplay.qc:866
int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score)
Returns the bitmask of the teams that will make the game most balanced if the player joins any of the...
Definition: teamplay.qc:820
#define NULL
Definition: post.qh:17
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
#define M_ARGV(x, type)
Definition: events.qh:17
First team is less than the second one.
Definition: teamplay.qh:234
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
#define LOG_FATAL(...)
Definition: log.qh:58
TeamBalance_GetTeamCounts has been called.
Definition: teamplay.qc:25
Both teams are equal.
Definition: teamplay.qh:235
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetAllowedTeams()

int TeamBalance_GetAllowedTeams ( entity  balance)

Returns the bitmask of allowed teams.

Parameters
[in]balanceTeam balance entity.
Returns
Bitmask of allowed teams.

Definition at line 640 of file teamplay.qc.

References LOG_FATAL, NULL, NUM_TEAMS, result, TEAM_BALANCE_UNINITIALIZED, Team_IndexToBit(), and TeamBalance_IsTeamAllowedInternal().

Referenced by ClientConnect(), dom_DelayedInit(), ons_ScoreRules(), and ScoreRules_generic().

641 {
642  if (balance == NULL)
643  {
644  LOG_FATAL("TeamBalance_GetAllowedTeams: Team balance entity is NULL.");
645  }
646  if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
647  {
648  LOG_FATAL("TeamBalance_GetAllowedTeams: "
649  "Team balance entity is not initialized.");
650  }
651  int result = 0;
652  for (int i = 1; i <= NUM_TEAMS; ++i)
653  {
654  if (TeamBalance_IsTeamAllowedInternal(balance, i))
655  {
656  result |= Team_IndexToBit(i);
657  }
658  }
659  return result;
660 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
entity result
Definition: promise.qc:43
#define NULL
Definition: post.qh:17
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
The team balance has not been initialized.
Definition: teamplay.qc:21
#define LOG_FATAL(...)
Definition: log.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetLargestTeamIndex()

int TeamBalance_GetLargestTeamIndex ( entity  balance,
int  teams 
)

Returns the index of the team with most players that is contained in the given bitmask of teams.

Parameters
[in]balanceTeam balance entity.
[in]teamsBitmask of teams to search in.
Returns
Index of the team with most players.

Definition at line 967 of file teamplay.qc.

References entity(), NUM_TEAMS, Team_IndexToBit(), TeamBalance_GetTeamFromIndex(), TeamBalanceTeam_GetNumberOfPlayers(), and TeamBalanceTeam_IsAllowed().

Referenced by TeamBalance_AutoBalanceBots().

968 {
969  int largest_team_index = 0;
970  int largest_team_player_count = 0;
971  for (int i = 1; i <= NUM_TEAMS; ++i)
972  {
973  if (!(Team_IndexToBit(i) & teams))
974  {
975  continue;
976  }
977  entity team_ = TeamBalance_GetTeamFromIndex(balance, i);
978  if (!TeamBalanceTeam_IsAllowed(team_))
979  {
980  continue;
981  }
982  int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
983  if (largest_team_index == 0)
984  {
985  largest_team_index = i;
986  largest_team_player_count = playercount;
987  }
988  else if (playercount > largest_team_player_count)
989  {
990  largest_team_index = i;
991  largest_team_player_count = playercount;
992  }
993  }
994  return largest_team_index;
995 }
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition: teams.qh:211
entity() spawn
bool TeamBalanceTeam_IsAllowed(entity team_ent)
Returns whether the team is allowed.
Definition: teamplay.qc:1094
entity teams
Definition: main.qh:44
entity TeamBalance_GetTeamFromIndex(entity balance, int index)
Returns the team entity of the team balance entity at the given index.
Definition: teamplay.qc:1080
int TeamBalanceTeam_GetNumberOfPlayers(entity team_ent)
Returns the number of players (both humans and bots) in a team.
Definition: teamplay.qc:1099
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetNumberOfPlayers()

int TeamBalance_GetNumberOfPlayers ( entity  balance,
int  index 
)

Returns the number of players (both humans and bots) in a team.

Parameters
[in]balanceTeam balance entity.
[in]indexIndex of the team.
Returns
Number of player (both humans and bots) in a team.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 763 of file teamplay.qc.

References LOG_FATAL, LOG_FATALF, NULL, TEAM_BALANCE_TEAM_COUNTS_FILLED, and Team_IsValidIndex().

Referenced by adjust_respawntime(), and bot_setnameandstuff().

764 {
765  if (balance == NULL)
766  {
767  LOG_FATAL("TeamBalance_GetNumberOfPlayers: "
768  "Team balance entity is NULL.");
769  }
770  if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
771  {
772  LOG_FATAL("TeamBalance_GetNumberOfPlayers: "
773  "TeamBalance_GetTeamCounts has not been called.");
774  }
775  if (!Team_IsValidIndex(index))
776  {
777  LOG_FATALF("TeamBalance_GetNumberOfPlayers: Team index is invalid: %f",
778  index);
779  }
780  return balance.m_team_balance_team[index - 1].m_num_players;
781 }
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
#define NULL
Definition: post.qh:17
#define LOG_FATALF(...)
Definition: log.qh:59
#define LOG_FATAL(...)
Definition: log.qh:58
TeamBalance_GetTeamCounts has been called.
Definition: teamplay.qc:25
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetPlayerForTeamSwitch()

entity TeamBalance_GetPlayerForTeamSwitch ( int  source_team_index,
int  destination_team_index,
bool  is_bot 
)

Returns the player who is the most suitable for switching between the given teams.

Parameters
[in]source_team_indexIndex of the team to search in.
[in]destination_team_indexIndex of the team to switch to.
[in]is_botTrue to search for bot, false for human.
Returns
Player who is the most suitable for switching between the given teams or NULL if not found.

Definition at line 997 of file teamplay.qc.

References entity(), Entity_GetTeamIndex(), FLOAT_MAX, FOREACH_CLIENT, IS_BOT_CLIENT, M_ARGV, MUTATOR_CALLHOOK, NULL, PlayerScore_Get, TeamBalance_CheckAllowedTeams(), TeamBalance_Destroy(), TeamBalance_GetPlayerForTeamSwitch(), and TeamBalance_IsTeamAllowed().

Referenced by TeamBalance_AutoBalanceBots(), and TeamBalance_GetPlayerForTeamSwitch().

999 {
1001  destination_team_index, is_bot))
1002  {
1003  return M_ARGV(3, entity);
1004  }
1005  entity lowest_player = NULL;
1006  float lowest_score = FLOAT_MAX;
1007  FOREACH_CLIENT(Entity_GetTeamIndex(it) == source_team_index,
1008  {
1009  if (IS_BOT_CLIENT(it) != is_bot)
1010  {
1011  continue;
1012  }
1013  float temp_score = PlayerScore_Get(it, SP_SCORE);
1014  if (temp_score >= lowest_score)
1015  {
1016  continue;
1017  }
1018  //PrintToChatAll(sprintf(
1019  // "Found %s with lowest score, checking allowed teams", it.netname));
1020  entity balance = TeamBalance_CheckAllowedTeams(it);
1021  if (TeamBalance_IsTeamAllowed(balance, source_team_index))
1022  {
1023  //PrintToChatAll("Allowed");
1024  lowest_player = it;
1025  lowest_score = temp_score;
1026  }
1027  else
1028  {
1029  //PrintToChatAll("Not allowed");
1030  }
1031  TeamBalance_Destroy(balance);
1032  });
1033  return lowest_player;
1034 }
#define PlayerScore_Get(player, scorefield)
Returns the player&#39;s score.
Definition: scores.qh:43
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition: teamplay.qc:627
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
int Entity_GetTeamIndex(entity this)
Returns the team index of the given entity.
Definition: teamplay.qc:176
#define NULL
Definition: post.qh:17
#define M_ARGV(x, type)
Definition: events.qh:17
bool TeamBalance_IsTeamAllowed(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:662
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition: utils.qh:15
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
entity TeamBalance_GetPlayerForTeamSwitch(int source_team_index, int destination_team_index, bool is_bot)
Returns the player who is the most suitable for switching between the given teams.
Definition: teamplay.qc:997
const float FLOAT_MAX
Definition: float.qh:3
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetTeam()

entity TeamBalance_GetTeam ( entity  balance,
int  team_num 
)

Returns the team entity of the team balance entity that corresponds to the given TEAM_NUM value.

Parameters
[in]balanceTeam balance entity.
[in]team_numTeam value. See TEAM_NUM constants.
Returns
Team entity of the team balance entity that corresponds to the given TEAM_NUM value.

Definition at line 1089 of file teamplay.qc.

References Team_TeamToIndex(), and TeamBalance_GetTeamFromIndex().

Referenced by TeamBalance_CheckAllowedTeams(), and TeamBalance_GetTeamCounts().

1090 {
1091  return TeamBalance_GetTeamFromIndex(balance, Team_TeamToIndex(team_num));
1092 }
entity TeamBalance_GetTeamFromIndex(entity balance, int index)
Returns the team entity of the team balance entity at the given index.
Definition: teamplay.qc:1080
int Team_TeamToIndex(int team_num)
Converts team value into team index.
Definition: teams.qh:184
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetTeamCounts()

void TeamBalance_GetTeamCounts ( entity  balance,
entity  ignore 
)

Counts the number of players and various other information about each team.

Parameters
[in,out]balanceTeam balance entity.
[in]ignorePlayer to ignore. This is useful if you plan to switch the player's team. Pass NULL for global information.
Note
This function updates the internal state of the team balance entity.

Definition at line 681 of file teamplay.qc.

References autocvar_g_campaign, autocvar_g_campaign_forceteam, entity(), FOREACH_CLIENT, INGAME, IS_BOT_CLIENT, IS_CLIENT, LOG_FATAL, M_ARGV, MUTATOR_CALLHOOK, NULL, NUM_TEAMS, Player_HasRealForcedTeam(), TEAM_BALANCE_TEAM_COUNTS_FILLED, TEAM_BALANCE_UNINITIALIZED, Team_IndexToTeam(), Team_IsValidIndex(), Team_IsValidTeam(), TeamBalance_GetTeam(), TeamBalance_GetTeamCounts(), TeamBalance_GetTeamFromIndex(), and TeamBalanceTeam_IsAllowed().

Referenced by adjust_respawntime(), bot_removefromlargestteam(), bot_setnameandstuff(), ClientCommand_selectteam(), Player_SetTeamIndexChecked(), TeamBalance_AutoBalanceBots(), TeamBalance_FindBestTeam(), and TeamBalance_GetTeamCounts().

682 {
683  if (balance == NULL)
684  {
685  LOG_FATAL("TeamBalance_GetTeamCounts: Team balance entity is NULL.");
686  }
687  if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
688  {
689  LOG_FATAL("TeamBalance_GetTeamCounts: "
690  "Team balance entity is not initialized.");
691  }
693  {
694  // Mutator has overriden the configuration.
695  for (int i = 1; i <= NUM_TEAMS; ++i)
696  {
697  entity team_ent = TeamBalance_GetTeamFromIndex(balance, i);
698  if (TeamBalanceTeam_IsAllowed(team_ent))
699  {
700  MUTATOR_CALLHOOK(TeamBalance_GetTeamCount, i, ignore);
701  team_ent.m_num_players = M_ARGV(2, float);
702  team_ent.m_num_bots = M_ARGV(3, float);
703  }
704  }
705  }
706  else
707  {
708  // Manually count all players.
709  FOREACH_CLIENT(true,
710  {
711  if (it == ignore)
712  {
713  continue;
714  }
715  int team_num;
716  // TODO: Reconsider when the player is truly on the team.
717  if (IS_CLIENT(it) || INGAME(it))
718  {
719  team_num = it.team;
720  }
721  else if (Player_HasRealForcedTeam(it))
722  {
723  // Do we really need this? Probably not.
724  team_num = Team_IndexToTeam(it.team_forced); // reserve the spot
725  }
726  else
727  {
728  continue;
729  }
730  if (!Team_IsValidTeam(team_num))
731  {
732  continue;
733  }
734  entity team_ent = TeamBalance_GetTeam(balance, team_num);
735  if (!TeamBalanceTeam_IsAllowed(team_ent))
736  {
737  continue;
738  }
739  ++team_ent.m_num_players;
740  if (IS_BOT_CLIENT(it))
741  {
742  ++team_ent.m_num_bots;
743  }
744  });
745  }
746 
747  // if the player who has a forced team has not joined yet, reserve the spot
749  {
751  {
752  entity team_ent = TeamBalance_GetTeamFromIndex(balance,
754  if (team_ent.m_num_players == team_ent.m_num_bots)
755  {
756  ++team_ent.m_num_players;
757  }
758  }
759  }
760  balance.m_team_balance_state = TEAM_BALANCE_TEAM_COUNTS_FILLED;
761 }
#define INGAME(it)
Definition: sv_rules.qh:20
const int NUM_TEAMS
Number of teams in the game.
Definition: teams.qh:3
#define IS_CLIENT(v)
Definition: utils.qh:13
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
bool TeamBalanceTeam_IsAllowed(entity team_ent)
Returns whether the team is allowed.
Definition: teamplay.qc:1094
float autocvar_g_campaign_forceteam
Definition: campaign.qh:7
entity TeamBalance_GetTeam(entity balance, int team_num)
Returns the team entity of the team balance entity that corresponds to the given TEAM_NUM value...
Definition: teamplay.qc:1089
entity TeamBalance_GetTeamFromIndex(entity balance, int index)
Returns the team entity of the team balance entity at the given index.
Definition: teamplay.qc:1080
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
Definition: teamplay.qc:681
#define NULL
Definition: post.qh:17
#define M_ARGV(x, type)
Definition: events.qh:17
The team balance has not been initialized.
Definition: teamplay.qc:21
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition: utils.qh:15
bool Player_HasRealForcedTeam(entity player)
Returns whether player has real forced team.
Definition: teamplay.qc:341
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition: teams.qh:169
bool autocvar_g_campaign
Definition: campaign.qh:6
#define LOG_FATAL(...)
Definition: log.qh:58
TeamBalance_GetTeamCounts has been called.
Definition: teamplay.qc:25
bool Team_IsValidTeam(int team_num)
Returns whether team value is valid.
Definition: teams.qh:133
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_GetTeamFromIndex()

entity TeamBalance_GetTeamFromIndex ( entity  balance,
int  index 
)

Returns the team entity of the team balance entity at the given index.

Parameters
[in]balanceTeam balance entity.
[in]indexIndex of the team.
Returns
Team entity of the team balance entity at the given index.

Definition at line 1080 of file teamplay.qc.

References LOG_FATALF, and Team_IsValidIndex().

Referenced by TeamBalance_AutoBalanceBots(), TeamBalance_CompareTeams(), TeamBalance_GetLargestTeamIndex(), TeamBalance_GetTeam(), and TeamBalance_GetTeamCounts().

1081 {
1082  if (!Team_IsValidIndex(index))
1083  {
1084  LOG_FATALF("TeamBalance_GetTeamFromIndex: Index is invalid: %f", index);
1085  }
1086  return balance.m_team_balance_team[index - 1];
1087 }
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
#define LOG_FATALF(...)
Definition: log.qh:59
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_IsTeamAllowed()

bool TeamBalance_IsTeamAllowed ( entity  balance,
int  index 
)

Returns whether the team change to the specified team is allowed.

Parameters
[in]balanceTeam balance entity.
[in]indexIndex of the team.
Returns
True if team change to the specified team is allowed, false otherwise.

Definition at line 662 of file teamplay.qc.

References LOG_FATAL, LOG_FATALF, NULL, TEAM_BALANCE_UNINITIALIZED, Team_IsValidIndex(), and TeamBalance_IsTeamAllowedInternal().

Referenced by adjust_respawntime(), GameCommand_moveplayer(), shuffleteams(), TeamBalance_GetPlayerForTeamSwitch(), and WinningCondition_RanOutOfSpawns().

663 {
664  if (balance == NULL)
665  {
666  LOG_FATAL("TeamBalance_IsTeamAllowed: Team balance entity is NULL.");
667  }
668  if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
669  {
670  LOG_FATAL("TeamBalance_IsTeamAllowed: "
671  "Team balance entity is not initialized.");
672  }
673  if (!Team_IsValidIndex(index))
674  {
675  LOG_FATALF("TeamBalance_IsTeamAllowed: Team index is invalid: %f",
676  index);
677  }
678  return TeamBalance_IsTeamAllowedInternal(balance, index);
679 }
bool Team_IsValidIndex(int index)
Returns whether the team index is valid.
Definition: teams.qh:151
#define NULL
Definition: post.qh:17
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
The team balance has not been initialized.
Definition: teamplay.qc:21
#define LOG_FATALF(...)
Definition: log.qh:59
#define LOG_FATAL(...)
Definition: log.qh:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalance_IsTeamAllowedInternal()

bool TeamBalance_IsTeamAllowedInternal ( entity  balance,
int  index 
)

Returns whether the team change to the specified team is allowed.

Parameters
[in]balanceTeam balance entity.
[in]indexIndex of the team.
Returns
True if team change to the specified team is allowed, false otherwise.
Note
This function bypasses all the sanity checks.

Definition at line 1063 of file teamplay.qc.

References TEAM_NOT_ALLOWED.

Referenced by Player_SetTeamIndexChecked(), TeamBalance_CheckAllowedTeams(), TeamBalance_FindBestTeams(), TeamBalance_GetAllowedTeams(), TeamBalance_IsTeamAllowed(), and TeamBalance_JoinBestTeam().

1064 {
1065  return balance.m_team_balance_team[index - 1].m_num_players !=
1067 }
const int TEAM_NOT_ALLOWED
Indicates that the player is not allowed to join a team.
Definition: teamplay.qc:29
+ Here is the caller graph for this function:

◆ TeamBalance_JoinBestTeam()

void TeamBalance_JoinBestTeam ( entity  player)

Assigns the given player to a team that will make the game most balanced.

Parameters
[in,out]playerPlayer to assign.

Definition at line 451 of file teamplay.qc.

References entity(), Player_HasRealForcedTeam(), SetPlayerTeam(), TEAM_CHANGE_AUTO, TeamBalance_CheckAllowedTeams(), TeamBalance_Destroy(), TeamBalance_FindBestTeam(), TeamBalance_IsTeamAllowedInternal(), and teamplay.

Referenced by bot_clientconnect(), ClientKill_Now_TeamChange(), Join(), and PutPlayerInServer().

452 {
453  //PrintToChatAll(sprintf("TeamBalance_JoinBestTeam: %s", player.netname));
454  if (!teamplay)
455  {
456  return;
457  }
458  if (player.bot_forced_team)
459  {
460  return;
461  }
462  entity balance = TeamBalance_CheckAllowedTeams(player);
463  if (Player_HasRealForcedTeam(player))
464  {
465  int forced_team_index = player.team_forced;
466  bool is_team_allowed = TeamBalance_IsTeamAllowedInternal(balance,
467  forced_team_index);
468  TeamBalance_Destroy(balance);
469  if (!is_team_allowed)
470  {
471  return;
472  }
473  if (!SetPlayerTeam(player, forced_team_index, TEAM_CHANGE_AUTO))
474  {
475  return;
476  }
477  return;
478  }
479  int best_team_index = TeamBalance_FindBestTeam(balance, player, true);
480  TeamBalance_Destroy(balance);
481  if (!SetPlayerTeam(player, best_team_index, TEAM_CHANGE_AUTO))
482  {
483  return;
484  }
485 }
bool SetPlayerTeam(entity player, int team_index, int type)
Sets the team of the player.
Definition: teamplay.qc:237
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition: teamplay.qc:627
entity() spawn
The team was selected by autobalance.
Definition: teamplay.qh:111
int TeamBalance_FindBestTeam(entity balance, entity player, bool ignore_player)
Finds the team that will make the game most balanced if the player joins it.
Definition: teamplay.qc:783
bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition: teamplay.qc:1063
float teamplay
Definition: progsdefs.qc:31
bool Player_HasRealForcedTeam(entity player)
Returns whether player has real forced team.
Definition: teamplay.qc:341
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamBalanceTeam_GetNumberOfBots()

int TeamBalanceTeam_GetNumberOfBots ( entity  team_ent)

Returns the number of bots in a team.

Parameters
[in]team_entTeam entity.
Returns
Number of bots in a team.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 1104 of file teamplay.qc.

1105 {
1106  return team_ent.m_num_bots;
1107 }

◆ TeamBalanceTeam_GetNumberOfPlayers()

int TeamBalanceTeam_GetNumberOfPlayers ( entity  team_ent)

Returns the number of players (both humans and bots) in a team.

Parameters
[in]team_entTeam entity.
Returns
Number of player (both humans and bots) in a team.
Note
You need to call TeamBalance_GetTeamCounts before calling this function.

Definition at line 1099 of file teamplay.qc.

Referenced by TeamBalance_AutoBalanceBots(), and TeamBalance_GetLargestTeamIndex().

1100 {
1101  return team_ent.m_num_players;
1102 }
+ Here is the caller graph for this function:

◆ TeamBalanceTeam_IsAllowed()

bool TeamBalanceTeam_IsAllowed ( entity  team_ent)

Returns whether the team is allowed.

Parameters
[in]team_entTeam entity.
Returns
True if team is allowed, false otherwise.

Definition at line 1094 of file teamplay.qc.

References TEAM_NOT_ALLOWED.

Referenced by TeamBalance_AutoBalanceBots(), TeamBalance_CompareTeamsInternal(), TeamBalance_GetLargestTeamIndex(), and TeamBalance_GetTeamCounts().

1095 {
1096  return team_ent.m_num_players != TEAM_NOT_ALLOWED;
1097 }
const int TEAM_NOT_ALLOWED
Indicates that the player is not allowed to join a team.
Definition: teamplay.qc:29
+ Here is the caller graph for this function:

Variable Documentation

◆ autocvar_g_balance_teams

◆ autocvar_g_balance_teams_prevent_imbalance

bool autocvar_g_balance_teams_prevent_imbalance

Definition at line 9 of file teamplay.qh.

Referenced by ClientCommand_selectteam(), and Player_SetTeamIndexChecked().

◆ autocvar_g_changeteam_banned

bool autocvar_g_changeteam_banned

◆ autocvar_g_forced_team_otherwise

string autocvar_g_forced_team_otherwise

Definition at line 11 of file teamplay.qh.

Referenced by nJoinAllowed(), and Player_DetermineForcedTeam().

◆ autocvar_teamplay_lockonrestart

bool autocvar_teamplay_lockonrestart

Definition at line 6 of file teamplay.qh.

Referenced by ReadyRestart_force().

◆ autocvar_teamplay_mode

int autocvar_teamplay_mode

Definition at line 3 of file teamplay.qh.

Referenced by Damage().

◆ lockteams

◆ team_forced

int team_forced

Definition at line 15 of file teamplay.qh.

Referenced by buff_Customize(), buff_Think(), buff_Touch(), and STATIC_INIT().