#include "teamplay.qh"
-#include "client.qh"
+#include <common/deathtypes/all.qh>
+#include <common/gamemodes/_mod.qh>
+#include <common/teams.qh>
+#include <server/bot/api.qh>
+#include <server/bot/default/cvars.qh>
+#include <server/campaign.qh>
+#include <server/client.qh>
+#include <server/command/vote.qh>
+#include <server/damage.qh>
#include <server/gamelog.qh>
-#include <server/g_damage.qh>
-#include "race.qh"
-#include "scores.qh"
-#include "scores_rules.qh"
-
-#include "bot/api.qh"
-
-#include "command/vote.qh"
-
#include <server/mutators/_mod.qh>
-
-#include "../common/deathtypes/all.qh"
-#include <common/gamemodes/_mod.qh>
-#include "../common/teams.qh"
+#include <server/race.qh>
+#include <server/scores.qh>
+#include <server/scores_rules.qh>
/// \brief Describes a state of team balance entity.
enum
/// \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; ///< Number of players (both humans and bots) in a team.
.int m_num_bots; ///< Number of bots in a team.
.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.
+.int m_num_owned_items; ///< Number of items owned by a team.
string autocvar_g_forced_team_red;
string autocvar_g_forced_team_blue;
entity g_team_entities[NUM_TEAMS]; ///< Holds global team entities.
-STATIC_INIT(g_team_entities)
+void Team_InitTeams()
{
+ if (g_team_entities[0])
+ return;
for (int i = 0; i < NUM_TEAMS; ++i)
{
- g_team_entities[i] = spawn();
+ g_team_entities[i] = new_pure(team_entity);
}
}
team_ent.m_num_players_alive = number;
}
+int Team_GetWinnerAliveTeam()
+{
+ int winner = 0;
+ for (int i = 0; i < NUM_TEAMS; ++i)
+ {
+ if (g_team_entities[i].m_num_players_alive > 0)
+ {
+ if (winner)
+ return 0;
+ winner = Team_IndexToTeam(i + 1);
+ }
+ }
+ return (winner ? winner : -1);
+}
+
int Team_GetNumberOfAliveTeams()
{
int result = 0;
return result;
}
-int Team_GetNumberOfControlPoints(entity team_ent)
+int Team_GetWinnerTeam_WithOwnedItems(int min_control_points)
+{
+ int winner = 0;
+ for (int i = 0; i < NUM_TEAMS; ++i)
+ {
+ if (g_team_entities[i].m_num_owned_items >= min_control_points)
+ {
+ if (winner)
+ return 0;
+ winner = Team_IndexToTeam(i + 1);
+ }
+ }
+ return (winner ? winner : -1);
+}
+
+int Team_GetNumberOfOwnedItems(entity team_ent)
{
- return team_ent.m_num_control_points;
+ return team_ent.m_num_owned_items;
}
-void Team_SetNumberOfControlPoints(entity team_ent, int number)
+void Team_SetNumberOfOwnedItems(entity team_ent, int number)
{
- team_ent.m_num_control_points = number;
+ team_ent.m_num_owned_items = number;
}
-int Team_GetNumberOfTeamsWithControlPoints()
+int Team_GetNumberOfTeamsWithOwnedItems()
{
int result = 0;
for (int i = 0; i < NUM_TEAMS; ++i)
{
- if (g_team_entities[i].m_num_control_points > 0)
+ if (g_team_entities[i].m_num_owned_items > 0)
{
++result;
}
void setcolor(entity this, int clr)
{
-#if 0
+#if 1
this.clientcolors = clr;
this.team = (clr & 15) + 1;
#else
bool SetPlayerTeam(entity player, int team_index, int type)
{
int old_team_index = Entity_GetTeamIndex(player);
+
if (!Player_SetTeamIndex(player, team_index))
- {
return false;
- }
+
LogTeamChange(player.playerid, player.team, type);
+
if (team_index != old_team_index)
{
- PlayerScore_Clear(player);
- if (team_index != -1)
- {
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(
- player.team, INFO_JOIN_PLAY_TEAM), player.netname);
- }
- else
- {
- if (!CS(player).just_joined)
- {
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE,
- player.netname);
- }
- }
KillPlayerForTeamChange(player);
+ PlayerScore_Clear(player); // works only in game modes without teams
+
if (!IS_BOT_CLIENT(player))
- {
TeamBalance_AutoBalanceBots();
- }
+
+ if (team_index != -1)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, INFO_JOIN_PLAY_TEAM), player.netname);
}
- else if (team_index == -1)
+
+ if (team_index == -1)
{
- if (!CS(player).just_joined && player.frags != FRAGS_SPECTATOR)
+ if (autocvar_sv_maxidle_playertospectator > 0 && CS(player).idlekick_lasttimeleft)
+ {
+ // this done here so it happens even when manually speccing during the countdown
+ Kill_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CPID_IDLING);
+ CS(player).idlekick_lasttimeleft = 0;
+ }
+ else if (!CS(player).just_joined && player.frags != FRAGS_SPECTATOR)
+ {
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, player.netname);
+ }
}
+
return true;
}
}
// TODO: Balance quantity of bots across > 2 teams when bot_vs_human is set (and remove next line)
- if (autocvar_bot_vs_human && AvailableTeams() == 2 && for_whom)
+ if (autocvar_bot_vs_human && AVAILABLE_TEAMS == 2 && for_whom)
{
if (autocvar_bot_vs_human > 0)
{
}
int team_num;
// TODO: Reconsider when the player is truly on the team.
- if (IS_CLIENT(it) || (it.caplayer))
+ if (IS_CLIENT(it) || INGAME(it))
{
team_num = it.team;
}
{
SetPlayerColors(player, new_color);
}
- // TODO: Should we really bother with this?
if(!IS_CLIENT(player))
{
- // since this is an engine function, and gamecode doesn't have any calls earlier than this, do the connecting message here
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_CONNECTING,
- player.netname);
return;
}
if (!teamplay)
{
return;
}
- Player_SetTeamIndexChecked(player, Team_TeamToIndex((new_color & 0x0F) +
- 1));
+ Player_SetTeamIndexChecked(player, Team_TeamToIndex((new_color & 0x0F) + 1));
}