]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/teamplay.qc
Split the gamelog code out of miscfunctions and into its own file
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / teamplay.qc
index 58843299642e2d5578ac2227af2af945e5e1fbeb..83f1d38568b969c75683d730659838f4240ceacc 100644 (file)
@@ -1,6 +1,7 @@
 #include "teamplay.qh"
 
 #include "client.qh"
+#include <server/gamelog.qh>
 #include "race.qh"
 #include "scores.qh"
 #include "scores_rules.qh"
@@ -181,7 +182,7 @@ bool Player_SetTeamIndex(entity player, int index)
                {
                        // This is important when players join the game and one of their
                        // color matches the team color while other doesn't. For example
-                       // [BOT]Lion.
+                       // [BOT]Lion: color 0 4.
                        SetPlayerColors(player, new_team - 1);
                }
                return true;
@@ -222,8 +223,11 @@ bool SetPlayerTeam(entity player, int team_index, int type)
                }
                else
                {
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE,
-                               player.netname);
+                       if (!CS(player).just_joined)
+                       {
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE,
+                                       player.netname);
+                       }
                }
                KillPlayerForTeamChange(player);
                if (!IS_BOT_CLIENT(player))
@@ -231,9 +235,65 @@ bool SetPlayerTeam(entity player, int team_index, int type)
                        TeamBalance_AutoBalanceBots();
                }
        }
+       else if (team_index == -1)
+       {
+               if (!CS(player).just_joined && player.frags != FRAGS_SPECTATOR)
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, player.netname);
+       }
        return true;
 }
 
+void Player_SetTeamIndexChecked(entity player, int team_index)
+{
+       if (!teamplay)
+       {
+               return;
+       }
+       if (!Team_IsValidIndex(team_index))
+       {
+               return;
+       }
+       if ((autocvar_g_campaign) || (autocvar_g_changeteam_banned &&
+               CS(player).wasplayer))
+       {
+               Send_Notification(NOTIF_ONE, player, MSG_INFO,
+                       INFO_TEAMCHANGE_NOTALLOWED);
+               return;
+       }
+       entity balance = TeamBalance_CheckAllowedTeams(player);
+       if (team_index == 1 && !TeamBalance_IsTeamAllowedInternal(balance, 1))
+       {
+               team_index = 4;
+       }
+       if (team_index == 4 && !TeamBalance_IsTeamAllowedInternal(balance, 4))
+       {
+               team_index = 3;
+       }
+       if (team_index == 3 && !TeamBalance_IsTeamAllowedInternal(balance, 3))
+       {
+               team_index = 2;
+       }
+       if (team_index == 2 && !TeamBalance_IsTeamAllowedInternal(balance, 2))
+       {
+               team_index = 1;
+       }
+       // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
+       if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
+       {
+               TeamBalance_GetTeamCounts(balance, player);
+               if ((Team_IndexToBit(team_index) & TeamBalance_FindBestTeams(balance,
+                       player, false)) == 0)
+               {
+                       Send_Notification(NOTIF_ONE, player, MSG_INFO,
+                               INFO_TEAMCHANGE_LARGERTEAM);
+                       TeamBalance_Destroy(balance);
+                       return;
+               }
+       }
+       TeamBalance_Destroy(balance);
+       SetPlayerTeam(player, team_index, TEAM_CHANGE_MANUAL);
+}
+
 bool MoveToTeam(entity client, int team_index, int type)
 {
        //PrintToChatAll(sprintf("MoveToTeam: %s, %f", client.netname, team_index));
@@ -405,8 +465,8 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
                team_ent.m_num_bots = 0;
        }
        setthink(balance, TeamBalance_Destroy);
-       
-       int teams_mask = 0;     
+
+       int teams_mask = 0;
        string teament_name = string_null;
        bool mutator_returnvalue = MUTATOR_CALLHOOK(TeamBalance_CheckAllowedTeams,
                teams_mask, teament_name, for_whom);
@@ -437,8 +497,7 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
        }
 
        // TODO: Balance quantity of bots across > 2 teams when bot_vs_human is set (and remove next line)
-       if (AvailableTeams() == 2)
-       if (autocvar_bot_vs_human && for_whom)
+       if (autocvar_bot_vs_human && AvailableTeams() == 2 && for_whom)
        {
                if (autocvar_bot_vs_human > 0)
                {
@@ -527,8 +586,8 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
                        TeamBalance_IsTeamAllowedInternal(balance, i))
                {
                        TeamBalance_BanTeamsExcept(balance, i);
+                       break;
                }
-               break;
        }
        balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
        return balance;
@@ -806,12 +865,10 @@ int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
 
 void TeamBalance_AutoBalanceBots()
 {
-       if (!autocvar_g_balance_teams ||
-               !autocvar_g_balance_teams_prevent_imbalance)
-       {
-               return;
-       }
-       //PrintToChatAll("TeamBalance_AutoBalanceBots");
+       // checks disabled because we always want auto-balanced bots
+       //if (!(autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance))
+       //      return;
+
        entity balance = TeamBalance_CheckAllowedTeams(NULL);
        TeamBalance_GetTeamCounts(balance, NULL);
        int smallest_team_index = 0;
@@ -823,16 +880,16 @@ void TeamBalance_AutoBalanceBots()
                {
                        continue;
                }
-               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
                if (smallest_team_index == 0)
                {
                        smallest_team_index = i;
-                       smallest_team_player_count = player_count;
+                       smallest_team_player_count = playercount;
                }
-               else if (player_count < smallest_team_player_count)
+               else if (playercount < smallest_team_player_count)
                {
                        smallest_team_index = i;
-                       smallest_team_player_count = player_count;
+                       smallest_team_player_count = playercount;
                }
        }
        //PrintToChatAll(sprintf("Smallest team: %f", smallest_team_index));
@@ -891,16 +948,16 @@ int TeamBalance_GetLargestTeamIndex(entity balance, int teams)
                {
                        continue;
                }
-               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               int playercount = TeamBalanceTeam_GetNumberOfPlayers(team_);
                if (largest_team_index == 0)
                {
                        largest_team_index = i;
-                       largest_team_player_count = player_count;
+                       largest_team_player_count = playercount;
                }
-               else if (player_count > largest_team_player_count)
+               else if (playercount > largest_team_player_count)
                {
                        largest_team_index = i;
-                       largest_team_player_count = player_count;
+                       largest_team_player_count = playercount;
                }
        }
        return largest_team_index;
@@ -955,7 +1012,7 @@ void LogTeamChange(float player_id, float team_number, int type)
        {
                return;
        }
-       GameLogEcho(sprintf(":team:%f:%f:%f", player_id, team_number, type));
+       GameLogEcho(sprintf(":team:%d:%d:%d", player_id, team_number, type));
 }
 
 void KillPlayerForTeamChange(entity player)
@@ -1060,89 +1117,24 @@ int TeamBalance_CompareTeamsInternal(entity team_a, entity team_b,
        return TEAMS_COMPARE_EQUAL;
 }
 
-// Called when the player connects or when they change their color with "color"
-// command.
-void SV_ChangeTeam(entity this, float _color)
+void SV_ChangeTeam(entity player, int new_color)
 {
-       //PrintToChatAll(sprintf("SV_ChangeTeam: %s, %f", this.netname, _color));
-
-       // in normal deathmatch we can just apply the color and we're done
-       if(!teamplay)
-               SetPlayerColors(this, _color);
-
-       if(!IS_CLIENT(this))
+       if (!teamplay)
        {
-               //PrintToChatAll("Not a client yet");
-               // 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, this.netname);
-               return;
+               SetPlayerColors(player, new_color);
        }
-
-       if(!teamplay)
-               return;
-
-       int source_color, destination_color;
-       int source_team_index, destination_team_index;
-
-       source_color = this.clientcolors & 0x0F;
-       destination_color = _color & 0x0F;
-
-       source_team_index = Team_TeamToIndex(source_color + 1);
-       destination_team_index = Team_TeamToIndex(destination_color + 1);
-
-       if (destination_team_index == -1)
+       // 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;
        }
-
-       entity balance = TeamBalance_CheckAllowedTeams(this);
-
-       if (destination_team_index == 1 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 1))
-       {
-               destination_team_index = 4;
-       }
-       if (destination_team_index == 4 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 4))
-       {
-               destination_team_index = 3;
-       }
-       if (destination_team_index == 3 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 3))
-       {
-               destination_team_index = 2;
-       }
-       if (destination_team_index == 2 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 2))
-       {
-               destination_team_index = 1;
-       }
-
-       // not changing teams
-       if (source_color == destination_color)
+       if (!teamplay)
        {
-               SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL);
-               TeamBalance_Destroy(balance);
                return;
        }
-
-       if((autocvar_g_campaign) || (autocvar_g_changeteam_banned && CS(this).wasplayer)) {
-               Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_NOTALLOWED);
-               return; // changing teams is not allowed
-       }
-
-       // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
-       if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
-       {
-               TeamBalance_GetTeamCounts(balance, this);
-               if ((Team_IndexToBit(destination_team_index) &
-                       TeamBalance_FindBestTeams(balance, this, false)) == 0)
-               {
-                       Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM);
-                       TeamBalance_Destroy(balance);
-                       return;
-               }
-       }
-       TeamBalance_Destroy(balance);
-       SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL);
+       Player_SetTeamIndexChecked(player, Team_TeamToIndex((new_color & 0x0F) +
+               1));
 }