]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into z411/bai-server
authorz411 <z411@omaera.org>
Wed, 5 Jan 2022 18:49:38 +0000 (15:49 -0300)
committerz411 <z411@omaera.org>
Wed, 5 Jan 2022 18:49:38 +0000 (15:49 -0300)
20 files changed:
1  2 
commands.cfg
gamemodes-server.cfg
qcsrc/client/hud/panel/timer.qc
qcsrc/common/ent_cs.qc
qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc
qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc
qcsrc/common/replicate.qh
qcsrc/server/chat.qc
qcsrc/server/client.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/command/vote.qh
qcsrc/server/round_handler.qc
qcsrc/server/scores.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/server/world.qc
qcsrc/server/world.qh

diff --cc commands.cfg
Simple merge
Simple merge
index a9512a42fd73be39fbc9f613d09d26c84f3fc698,035d21b60d9c889e00209f19076631aafc5251e5..095e44307ec149b9d9f2b58099e31d3c95022993
@@@ -38,33 -36,14 +38,32 @@@ void HUD_Timer(
                mySize -= '2 2 0' * panel_bg_padding;
        }
  
 -      string timer;
 -      float timelimit, timeleft, minutesLeft;
 +      string timer_sub = "";
 +      float timelimit, timeleft, minutesLeft, overtimes, timeout_last;
  
        timelimit = STAT(TIMELIMIT);
 +      overtimes = STAT(OVERTIMESADDED);
 +      timeout_last = STAT(TIMEOUT_LAST);
  
-       timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time);
-       timeleft = min(timeleft, timelimit * 60);
+       timeleft = bound(0, timelimit * 60 + STAT(GAMESTARTTIME) - time, timelimit * 60);
        timeleft = ceil(timeleft);
  
 +      // countdown sound
 +      // if 3 use server dictated option, otherwise the client's
 +      int countdown_type;
 +      if(autocvar_cl_timer_countdown == 3)
 +              countdown_type = sv_timer_countdown;
 +      else
 +              countdown_type = autocvar_cl_timer_countdown;
 +      
 +      if(countdown_type && !warmup_stage && timeleft > 0 && timeleft != last_timeleft && timeleft <= 10)
 +      {
 +              if(countdown_type == 1 || (countdown_type == 2 && spectatee_status))
 +                      sound(NULL, CH_INFO, SND_ENDCOUNT, VOL_BASE, ATTN_NONE);
 +              
 +              last_timeleft = timeleft;
 +      }
 +
        minutesLeft = floor(timeleft / 60);
  
        float warmup_timeleft = 0;
Simple merge
index 7ee4b4a55b3081a48150fdff11e518d96858f443,866a00419c36c0a2be08367f156c3b4c98d98cca..34e03965494ca3cf615d31e73507b083a958ca49
@@@ -51,49 -40,8 +47,24 @@@ void CA_count_alive_players(
        });
  }
  
- int CA_GetWinnerTeam()
- {
-       int winner_team = 0;
-       if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1)
-       {
-               winner_team = NUM_TEAM_1;
-       }
-       for (int i = 2; i <= NUM_TEAMS; ++i)
-       {
-               if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) >= 1)
-               {
-                       if (winner_team != 0)
-                       {
-                               return 0;
-                       }
-                       winner_team = Team_IndexToTeam(i);
-               }
-       }
-       if (winner_team)
-       {
-               return winner_team;
-       }
-       return -1; // no player left
- }
  void nades_Clear(entity player);
  
 +entity ca_LastPlayer(float tm)
 +{
 +      entity last_pl = NULL;
 +      FOREACH_CLIENT(IS_PLAYER(it) && it.team == tm, {
 +              if (!IS_DEAD(it))
 +              {
 +                      if (!last_pl)
 +                              last_pl = it;
 +                      else
 +                              return NULL;
 +              }
 +      });
 +      return last_pl;
 +}
 +
 +
  float CA_CheckWinner()
  {
        if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
        }
  
        CA_count_alive_players();
-       if (Team_GetNumberOfAliveTeams() > 1)
-       {
+       int winner_team = Team_GetWinnerAliveTeam();
+       if (!winner_team)
                return 0;
-       }
  
-       int winner_team = CA_GetWinnerTeam();
 +      bool perfect = false;
        if(winner_team > 0)
        {
 +              entity tm = Team_GetTeam(winner_team);
 +              entity last_pl = ca_LastPlayer(winner_team);
 +              
 +              if(last_pl && Team_GetNumberOfPlayers(tm) >= 3) {
 +                      Give_Medal(last_pl, DEFENSE);
 +              }
 +              
                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
 +              if(fragsleft > 1) Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, APP_TEAM_NUM(winner_team, ANNCE_ROUND_TEAM_WIN));
                TeamScore_AddToTeam(winner_team, ST_CA_ROUNDS, +1);
 +              
 +              if (Team_GetNumberOfPlayers(tm) >= 3 &&
 +                      Team_GetNumberOfAlivePlayers(tm) == Team_GetNumberOfPlayers(tm))
 +                              perfect = true;
        }
        else if(winner_team == -1)
        {
index 73933c23feef2f930014830690e5d23e08439745,58fd90c897f15213ce6b686e9a5b402df00c19d6..4b01743c21c38caef2d87efa0ef89a3831096bdf
@@@ -149,23 -102,15 +120,21 @@@ bool freezetag_CheckWinner(
                return true;
        }
  
-       if (Team_GetNumberOfAliveTeams() > 1)
-       {
+       int winner_team = Team_GetWinnerAliveTeam();
+       if (!winner_team)
                return false;
-       }
  
-       int winner_team = freezetag_getWinnerTeam();
        if(winner_team > 0)
        {
 -              Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
 -              Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
 +              entity last_pl = freezetag_LastPlayer(winner_team);
 +              if(last_pl) {
 +                      Give_Medal(last_pl, DEFENSE);
 +              }
 +      
 +              Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_SCORES));
 +              Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_SCORES));
                TeamScore_AddToTeam(winner_team, ST_FT_ROUNDS, +1);
 +              if(fragsleft > 1) AnnounceScores(winner_team);
        }
        else if(winner_team == -1)
        {
Simple merge
index 82da61ff2d7a8a5d76fdad2346ba62d51ef0da3d,a73de2a1f6c58f2ed97e4303ae5179a7354b07db..33a2e406f286435fc6cf0997d50f713c36cbc5bd
@@@ -323,12 -315,10 +323,12 @@@ int Say(entity source, int teamsay, ent
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(!(IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                       FOREACH_CLIENT(!(IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
                                sprint(it, msgstr);
                        });
 -                      event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
 +                      
 +                      if(!play_chatsound(source, msgin))
 +                              event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
                }
                else
                {
Simple merge
index 961059738ebbb77c0df20769e5cc1c1dd91541cb,c9ceb31b6dc14cc09d4fe24c4d1a9446ec27cb97..d1ae3c9279914270f4942815d632f6b330d45961
@@@ -372,36 -372,27 +372,27 @@@ void ClientCommand_ready(entity caller
        {
                case CMD_REQUEST_COMMAND:
                {
 -                      if (IS_CLIENT(caller))
 +                      if (IS_CLIENT(caller) && caller.last_ready < time - 3) // anti-spam
                        {
-                               if (warmup_stage || autocvar_sv_ready_restart || g_race_qualifying == 2)
+                               if (warmup_stage || g_race_qualifying == 2)
                                {
-                                       if (!readyrestart_happened || autocvar_sv_ready_restart_repeatable)
+                                       if (time < game_starttime) // game is already restarting
+                                               return;
+                                       if (caller.ready)            // toggle
                                        {
-                                               if (time < game_starttime) // game is already restarting
-                                                       return;
-                                               if (caller.ready)            // toggle
-                                               {
-                                                       caller.ready = false;
-                                                       if(IS_PLAYER(caller) || caller.caplayer == 1)
-                                                               bprint("\{1}", playername(caller.netname, caller.team, false), "^2 is ^1NOT^2 ready\n");
-                                               }
-                                               else
-                                               {
-                                                       caller.ready = true;
-                                                       if(IS_PLAYER(caller) || caller.caplayer == 1)
-                                                               bprint("\{1}", playername(caller.netname, caller.team, false), "^2 is ready\n");
-                                               }
-                                               
-                                               caller.last_ready = time;
-                                               // cannot reset the game while a timeout is active!
-                                               if (!timeout_status) ReadyCount();
+                                               caller.ready = false;
+                                               if (IS_PLAYER(caller) || INGAME_JOINED(caller))
 -                                                      bprint(playername(caller.netname, caller.team, false), "^2 is ^1NOT^2 ready\n");
++                                                      bprint("\{1}", playername(caller.netname, caller.team, false), "^2 is ^1NOT^2 ready\n");
                                        }
                                        else
                                        {
-                                               sprint(caller, "^1Game has already been restarted\n");
+                                               caller.ready = true;
+                                               if (IS_PLAYER(caller) || INGAME_JOINED(caller))
 -                                                      bprint(playername(caller.netname, caller.team, false), "^2 is ready\n");
++                                                      bprint("\{1}", playername(caller.netname, caller.team, false), "^2 is ready\n");
                                        }
+                                       // cannot reset the game while a timeout is active!
+                                       if (!timeout_status) ReadyCount();
                                }
                        }
                        return;  // never fall through to usage
index a0770cab7cc0e8e4c90827e8933f9669a7867d7d,ca6b268e23708a51b5fdb000e295fa4226512657..2112d2f4489a9a8fc2a755464eeff8bb6f2ccb08
@@@ -1809,12 -1675,10 +1804,12 @@@ SERVER_COMMAND(nospectators, "Automatic
  SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
  SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
  SERVER_COMMAND(reducematchtime, "Decrease the timelimit value incrementally") { GameCommand_reducematchtime(request); }
- SERVER_COMMAND(reset, "Soft restart the server and reset the players") { GameCommand_reset(request); }
+ SERVER_COMMAND(resetmatch, "Soft restart the game without changing teams; goes back to warmup if enabled") { GameCommand_resetmatch(request); }
  SERVER_COMMAND(setbots, "Adjust how many bots are in the match") { GameCommand_setbots(request, arguments); }
 +SERVER_COMMAND(setflag, "Set client flag") { GameCommand_setflag(request, arguments); }
  SERVER_COMMAND(shuffleteams, "Randomly move players to different teams") { GameCommand_shuffleteams(request); }
  SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameCommand_stuffto(request, arguments); }
 +SERVER_COMMAND(teamname, "Set team name") { GameCommand_teamname(request, arguments); }
  SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
  SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
  SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
index b98abd921bd41b9c7c5c90e52bee855fec0cc05b,6b39ab7b6d90ffd4d4e8ea90a0dc5962d531af33..4b9429842914b50db70f945c435ca70d73a56289
@@@ -430,10 -414,8 +424,9 @@@ void reset_map(bool dorespawn, bool is_
  // Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown is set)
  void ReadyRestart_think(entity this)
  {
-       restart_mapalreadyrestarted = true;
-       reset_map(true);
+       reset_map(true, false);
        Score_ClearAll();
 +      Inventory_ClearAll();
        delete(this);
  }
  
@@@ -809,18 -760,24 +796,37 @@@ int VoteCommand_parse(entity caller, st
                        break;
                }
  
-               case "restart":
-               case "reset":
 +              case "gg":
 +              case "shuffleteams":
-               case "allready":
 +              case "endmatch":
 +              {
 +                      // add a delay so that vote result can be seen and announcer can be heard
 +                      // if the vote is accepted
 +                      vote_parsed_command = strcat("defer 2 ", vote_command);
 +                      vote_parsed_display = strzone(strcat("^1", vote_command));
++                      
++                      break;
++              }
++
++              case "reset":
+               case "restart":
+               case "resetmatch":  // re-direct all match restarting to resetmatch
+               {
 -                      vote_parsed_command = "resetmatch";
++                      vote_parsed_command = "defer 2 resetmatch";
+                       vote_parsed_display = strzone("^1resetmatch");
+                       break;
+               }
+               case "allready":
+               {
+                       if(!warmup_stage) {
+                               print_to(caller, "Game already started. Use the resetmatch command to restart the match.");
+                               return -1;
+                       }
  
 -                      vote_parsed_command = vote_command;
++                      vote_parsed_command = strcat("defer 2 ", vote_command);
+                       vote_parsed_display = strzone(strcat("^1", vote_command));
                        break;
                }
  
index 156021b8fb9fa87bd63afaa5ec44c64dbd80aab1,63c9e8e453765892bff4823cc41de0e7865e1453..355f241ef1b680f1d71138c0d93127e8b1a723eb
@@@ -70,10 -63,7 +70,8 @@@ void VoteCommand(int request, entity ca
  const float RESTART_COUNTDOWN = 10;
  entity nagger;
  float readycount;                  // amount of players who are ready
- float readyrestart_happened;       // keeps track of whether a restart has already happened
- float restart_mapalreadyrestarted; // bool, indicates whether reset_map() was already executed
  .float ready;                      // flag for if a player is ready
 +.float last_ready;                               // z411 time of the last readyup for anti-spam
  .int team_saved;                   // team number to restore upon map reset
  .void(entity this) reset;            // if set, an entity is reset using this
  .void(entity this) reset2;         // if set, an entity is reset using this (after calling ALL the reset functions for other entities)
Simple merge
Simple merge
index d27be8ad86b65a5d65ea3f0ff0ed6e1ba010be5c,0bc7e7cbb6707956066873d7ea95fdbfdabb7997..d21a33b0cbcfc7e3dae6141a518b6f946f574481
@@@ -103,16 -92,21 +103,31 @@@ void Team_SetNumberOfAlivePlayers(entit
        team_ent.m_num_players_alive = number;
  }
  
 +int Team_GetNumberOfPlayers(entity team_ent)
 +{
 +      return team_ent.m_num_players;
 +}
 +
 +void Team_SetNumberOfPlayers(entity team_ent, int number)
 +{
 +      team_ent.m_num_players = 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;
index c8e6a5d18ae4b5de3cf95d9437c27234caac80d8,a94b247a8a64150d78ba6c1ca52200ff16b70350..8c67bb84fbf2cf05c9b19addc9e30b4290f46fb2
@@@ -51,8 -50,11 +51,12 @@@ int Team_GetNumberOfPlayers(entity team
  /// \param[in,out] team_ent Team entity.
  /// \param[in] number Number of players to set.
  void Team_SetNumberOfAlivePlayers(entity team_ent, int number);
 +void Team_SetNumberOfPlayers(entity team_ent, int number);
  
+ /// \brief Returns the winner team.
+ /// \return Winner team or 0 if 2 or more teams have alive players or -1 if no team has any alive players.
+ int Team_GetWinnerAliveTeam();
  /// \brief Returns the number of alive teams.
  /// \return Number of alive teams.
  int Team_GetNumberOfAliveTeams();
index 2e87471f84f8cbf1d2f78c67409072d1e1774e7c,a438e633f61a71f7f47e89bd95bd6c93fe72f58b..b39b364899b0f093a22f7049a1fd8cdb6b492979
@@@ -1491,52 -1405,10 +1498,52 @@@ void AddWinners(.float field, float val
  // clear the .winning flags
  void ClearWinners()
  {
-       FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; });
+       FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = 0; });
  }
  
 -int fragsleft_last;
 +void AnnounceNewLeader()
 +{
 +      if(teamplay) {
 +              if (WinningConditionHelper_equality)
 +                      Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_TEAM_LEADS_TIED);
 +              else
 +                      FOREACH_CLIENT(IS_PLAYER(it), {
 +                              if(it.team == WinningConditionHelper_winnerteam)
 +                                      Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_TEAM);
 +                              else
 +                                      Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_ENEMY);
 +                      });
 +                      Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(WinningConditionHelper_winnerteam, ANNCE_TEAM_LEADS));
 +      } else {
 +              if (WinningConditionHelper_equality)
 +              {
 +                      Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_one, MSG_ANNCE, ANNCE_LEAD_TIED);
 +                      Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_two, MSG_ANNCE, ANNCE_LEAD_TIED);
 +              }
 +              else
 +              {
 +                      Send_Notification(NOTIF_ONE, WinningConditionHelper_winner, MSG_ANNCE, ANNCE_LEAD_GAINED);
 +                      Send_Notification(NOTIF_ONE, WinningConditionHelper_second, MSG_ANNCE, ANNCE_LEAD_LOST);
 +              }
 +      }
 +}
 +
 +void AnnounceScores(float tm)
 +{
 +      WinningConditionHelper(NULL);
 +      if (Score_NewLeader()) {
 +              AnnounceNewLeader();
 +      } else {
 +              FOREACH_CLIENT(IS_PLAYER(it), {
 +                      if(it.team == tm)
 +                              Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_TEAM);
 +                      else
 +                              Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_ENEMY);
 +              });
 +              Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(tm, ANNCE_TEAM_SCORES));
 +      }
 +}
 +
  float WinningCondition_Scores(float limit, float leadlimit)
  {
        // TODO make everything use THIS winning condition (except LMS)
Simple merge