]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'terencehill/lms_spec' into 'master'
authorterencehill <piuntn@gmail.com>
Thu, 25 May 2023 16:35:55 +0000 (16:35 +0000)
committerterencehill <piuntn@gmail.com>
Thu, 25 May 2023 16:35:55 +0000 (16:35 +0000)
LMS: allow players to get back into the game if they spectated

See merge request xonotic/xonotic-data.pk3dir!1051

notifications.cfg
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qh
qcsrc/common/notifications/all.inc

index b38304dbe88d72fa9bb766eab7ba0e5c8334a191..22a4e70a31403caeaef852e66b96d1c74ae9f011 100644 (file)
@@ -242,7 +242,6 @@ seta notification_INFO_KEYHUNT_DROP "1" "0 = off, 1 = print to console, 2 = prin
 seta notification_INFO_KEYHUNT_LOST "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_KEYHUNT_PICKUP "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_KEYHUNT_PUSHED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-seta notification_INFO_LMS_FORFEIT "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_LMS_NOLIVES "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_MINIGAME_INVITE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_MONSTERS_DISABLED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
@@ -495,7 +494,6 @@ seta notification_CENTER_KEYHUNT_ROUNDSTART "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_KEYHUNT_SCAN "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_KEYHUNT_START "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_LMS_NOLIVES "1" "0 = off, 1 = centerprint"
-seta notification_CENTER_LMS_SPECWARN "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_LMS_VISIBLE_LEADER "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_LMS_VISIBLE_OTHER "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_MISSING_PLAYERS "1" "0 = off, 1 = centerprint"
index d53b213492d81e5140c14be648defa93c2fbefba..348262e76c231cd7d60d1ebe68bc3b8edd8e68ed 100644 (file)
@@ -223,17 +223,11 @@ MUTATOR_HOOKFUNCTION(lms, reset_map_players)
 {
        FOREACH_CLIENT(true, {
                if (it.frags == FRAGS_PLAYER_OUT_OF_GAME)
-               {
-                       // players who forfeited (rank >= 256) become spectators
-                       if (it.lms_spectate_warning == 2)
-                               it.frags = FRAGS_SPECTATOR;
-                       else
-                               it.frags = FRAGS_PLAYER;
-               }
+                       it.frags = FRAGS_PLAYER;
 
                CS(it).killcount = 0;
                INGAME_STATUS_CLEAR(it);
-               it.lms_spectate_warning = 0;
+               it.lms_spectate = false;
                GameRules_scoring_add(it, LMS_RANK, -GameRules_scoring_add(it, LMS_RANK, 0));
                GameRules_scoring_add(it, LMS_LIVES, -GameRules_scoring_add(it, LMS_LIVES, 0));
 
@@ -271,14 +265,11 @@ bool lms_AddPlayer(entity player)
        }
        if (warmup_stage || time <= game_starttime)
        {
-               if(player.lms_spectate_warning)
-               {
-                       player.lms_spectate_warning = 0;
-                       GameRules_scoring_add(player, LMS_RANK, -GameRules_scoring_add(player, LMS_RANK, 0));
-                       int lives = GameRules_scoring_add(player, LMS_LIVES, 0);
-                       if(lives <= 0)
-                               GameRules_scoring_add(player, LMS_LIVES, LMS_NewPlayerLives());
-               }
+               player.lms_spectate = false;
+               GameRules_scoring_add(player, LMS_RANK, -GameRules_scoring_add(player, LMS_RANK, 0));
+               int lives = GameRules_scoring_add(player, LMS_LIVES, 0);
+               if(lives <= 0)
+                       GameRules_scoring_add(player, LMS_LIVES, LMS_NewPlayerLives());
        }
        else
        {
@@ -301,6 +292,9 @@ MUTATOR_HOOKFUNCTION(lms, PutClientInServer)
        }
 }
 
+int last_forfeiter_lives;
+float last_forfeiter_health;
+float last_forfeiter_armorvalue;
 MUTATOR_HOOKFUNCTION(lms, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
@@ -315,6 +309,11 @@ MUTATOR_HOOKFUNCTION(lms, PlayerSpawn)
                int pl_lives = GameRules_scoring_add(player, LMS_LIVES, 0);
                float min_health = start_health;
                float min_armorvalue = start_armorvalue;
+               if (last_forfeiter_lives == pl_lives)
+               {
+                       min_health = last_forfeiter_health;
+                       min_armorvalue = last_forfeiter_armorvalue;
+               }
                FOREACH_CLIENT(it != player && IS_PLAYER(it) && !IS_DEAD(it) && GameRules_scoring_add(it, LMS_LIVES, 0) == pl_lives, {
                        if (GetResource(it, RES_HEALTH) < min_health)
                                min_health = GetResource(it, RES_HEALTH);
@@ -347,7 +346,7 @@ void lms_RemovePlayer(entity player)
        float player_rank = GameRules_scoring_add(player, LMS_RANK, 0);
        if (!player_rank)
        {
-               if (player.lms_spectate_warning < 2)
+               if (!player.lms_spectate)
                {
                        player.frags = FRAGS_PLAYER_OUT_OF_GAME;
                        int pl_cnt = 0;
@@ -358,40 +357,46 @@ void lms_RemovePlayer(entity player)
                }
                else if (INGAME(player))
                {
-                       int min_forfeiter_rank = 665; // different from 666
                        FOREACH_CLIENT(it != player, {
-                               // update rank of other players that were eliminated
+                               // update rank of other players
                                if (it.frags == FRAGS_PLAYER_OUT_OF_GAME)
+                                       GameRules_scoring_add(it, LMS_RANK, -1);
+                       });
+                       int rank = GameRules_scoring_add(player, LMS_RANK, 0);
+                       GameRules_scoring_add(player, LMS_RANK, -rank);
+                       if(!warmup_stage)
+                       {
+                               int pl_lives = GameRules_scoring_add(player, LMS_LIVES, 0);
+                               float pl_health = IS_DEAD(player) ? start_health : GetResource(player, RES_HEALTH);
+                               float pl_armor = IS_DEAD(player) ? start_armorvalue : GetResource(player, RES_ARMOR);
+                               if (!last_forfeiter_lives || pl_lives < last_forfeiter_lives)
                                {
-                                       float it_rank = GameRules_scoring_add(it, LMS_RANK, 0);
-                                       if (it_rank > player_rank && it_rank <= 256)
-                                               GameRules_scoring_add(it, LMS_RANK, -1);
-                                       if (it_rank > 256 && it_rank <= min_forfeiter_rank)
-                                               min_forfeiter_rank = it_rank - 1;
+                                       last_forfeiter_lives = pl_lives;
+                                       last_forfeiter_health = pl_health;
+                                       last_forfeiter_armorvalue = pl_armor;
                                }
-                               else if (it.frags != FRAGS_SPECTATOR)
+                               else if (pl_lives == last_forfeiter_lives)
                                {
-                                       float tl = GameRules_scoring_add(it, LMS_LIVES, 0);
-                                       if(tl < lms_lowest_lives)
-                                               lms_lowest_lives = tl;
+                                       // these values actually can belong to a different forfeiter
+                                       last_forfeiter_health = min(last_forfeiter_health, pl_health);
+                                       last_forfeiter_armorvalue = min(last_forfeiter_armorvalue, pl_armor);
                                }
-                       });
-                       GameRules_scoring_add(player, LMS_RANK, min_forfeiter_rank);
-                       if(!warmup_stage)
-                               GameRules_scoring_add(player, LMS_LIVES, -GameRules_scoring_add(player, LMS_LIVES, 0));
-                       player.frags = FRAGS_PLAYER_OUT_OF_GAME;
+                               GameRules_scoring_add(player, LMS_LIVES, -pl_lives);
+                       }
+                       player.frags = FRAGS_SPECTATOR;
                        TRANSMUTE(Observer, player);
+                       INGAME_STATUS_CLEAR(player);
+                       player.lms_spectate = false;
+                       CS(player).killcount = FRAGS_SPECTATOR;
                }
                if (autocvar_g_lms_leader_lives_diff > 0)
                        lms_UpdateLeaders();
        }
 
-       if (CS(player).killcount != FRAGS_SPECTATOR && player.lms_spectate_warning < 3)
+       if (CS(player).killcount != FRAGS_SPECTATOR)
        {
-               if (GameRules_scoring_add(player, LMS_RANK, 0) > 0 && player.lms_spectate_warning < 2)
+               if (GameRules_scoring_add(player, LMS_RANK, 0) > 0)
                        Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_LMS_NOLIVES, player.netname);
-               else
-                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_LMS_FORFEIT, player.netname);
        }
 }
 
@@ -399,8 +404,7 @@ MUTATOR_HOOKFUNCTION(lms, ClientDisconnect)
 {
        entity player = M_ARGV(0, entity);
 
-       // no further message other than the disconnect message
-       player.lms_spectate_warning = 3;
+       player.lms_spectate = true;
 
        lms_RemovePlayer(player);
        INGAME_STATUS_CLEAR(player);
@@ -423,8 +427,8 @@ MUTATOR_HOOKFUNCTION(lms, MakePlayerObserver)
        }
        else
        {
-               if (is_forced)
-                       player.lms_spectate_warning = 2;
+               if (is_forced || player.killindicator_teamchange == -2) // player is forced or wants to spectate
+                       player.lms_spectate = true;
                if (!GameRules_scoring_add(player, LMS_RANK, 0))
                        lms_RemovePlayer(player);
        }
@@ -696,7 +700,7 @@ MUTATOR_HOOKFUNCTION(lms, ItemTouch)
 MUTATOR_HOOKFUNCTION(lms, Bot_FixCount, CBC_ORDER_EXCLUSIVE)
 {
        FOREACH_CLIENT(IS_REAL_CLIENT(it), {
-               if (INGAME(it) && it.lms_spectate_warning < 2)
+               if (INGAME(it))
                        ++M_ARGV(0, int); // activerealplayers
                ++M_ARGV(1, int); // realplayers
        });
@@ -707,23 +711,10 @@ MUTATOR_HOOKFUNCTION(lms, Bot_FixCount, CBC_ORDER_EXCLUSIVE)
 MUTATOR_HOOKFUNCTION(lms, ClientCommand_Spectate)
 {
        entity player = M_ARGV(0, entity);
-
-       if(warmup_stage || time < game_starttime || player.lms_spectate_warning)
-       {
-               // for the forfeit message...
-               player.lms_spectate_warning = 2;
-       }
-       else
-       {
-               if(player.frags != FRAGS_SPECTATOR && player.frags != FRAGS_PLAYER_OUT_OF_GAME)
-               {
-                       player.lms_spectate_warning = 1;
-                       sprint(player, "^1WARNING:^7 you can't rejoin this match after spectating. Use the same command again to spectate anyway.\n");
-                       Send_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CENTER_LMS_SPECWARN);
-               }
-               return MUT_SPECCMD_RETURN;
-       }
-       return MUT_SPECCMD_CONTINUE;
+       if(player.frags != FRAGS_SPECTATOR && player.frags != FRAGS_PLAYER_OUT_OF_GAME)
+               return MUT_SPECCMD_CONTINUE;
+       // ranked players (out of game) can no longer become real spectators
+       return MUT_SPECCMD_RETURN;
 }
 
 MUTATOR_HOOKFUNCTION(lms, CheckRules_World)
index bf02920d2c1616207ac54545d3b331a617de90e6..8019c76ddb62c2ae5a002f4d61b58c03a53c2b4b 100644 (file)
@@ -3,10 +3,9 @@
 #include <common/mutators/base.qh>
 #include <common/scores.qh>
 
-// 1 when player presses F3 to spectate for the first time (he only gets a warning)
-// 2 when player goes spectator (presses F3 to spectate for the second time)
-// 3 when player disconnects
-.int lms_spectate_warning;
+// set before a lms_RemovePlayer call, if true player becomes a real spectator
+// otherwise it gets eliminated becoming spectator but as player out of game with a rank
+.bool lms_spectate;
 
 #define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
 string autocvar_g_lms_weaponarena = "most_available";
index 061d951a66015b6752470980a649bbf427d7a54a..effed26d98f90084dd53d1afb8da23e5db5664a5 100644 (file)
@@ -403,7 +403,6 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MULTITEAM_INFO(KEYHUNT_DESTROYED,                       N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG destroyed the ^TC^TT Key"), "", KEY)
     MULTITEAM_INFO(KEYHUNT_PICKUP,                          N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG picked up the ^TC^TT Key"), "", KEY)
 
-    MSG_INFO_NOTIF(LMS_FORFEIT,                             N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 forfeited"), "")
     MSG_INFO_NOTIF(LMS_NOLIVES,                             N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^F3 has no more lives left"), "")
 
     MSG_INFO_NOTIF(MONSTERS_DISABLED,                       N_CONSOLE,  0, 0, "", "",           "",     _("^BGMonsters are currently disabled"), "")
@@ -729,7 +728,6 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MULTITEAM_CENTER(KEYHUNT_START,                     N_ENABLE,    0, 0, "",               CPID_KEYHUNT,           "0 0",  _("^BGYou are starting with the ^TC^TT Key"), "", KEY)
 
     MSG_CENTER_NOTIF(LMS_NOLIVES,                       N_ENABLE,    0, 0, "",               CPID_LMS,               "0 0",  _("^BGYou have no lives left, you must wait until the next match"), "")
-    MSG_CENTER_NOTIF(LMS_SPECWARN,                      N_ENABLE,    0, 0, "",               CPID_LMS,               "0 0",  _("^F4WARNING:^BG you can't rejoin this match after spectating.\nUse the same command again to spectate anyway."), "")
     MSG_CENTER_NOTIF(LMS_VISIBLE_LEADER,                N_ENABLE,    0, 0, "",               CPID_LMS,               "0 0",  _("^BGEnemies can now see you on radar!"), "")
     MSG_CENTER_NOTIF(LMS_VISIBLE_OTHER,                 N_ENABLE,    0, 0, "",               CPID_LMS,               "0 0",  _("^BGLeaders can now be seen by enemies on radar!"), "")