]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/gamemodes/gamemode/mmm/sv_mmm.qc
Fix visualization if server admin uses 'sv_ready_restart_after_countdown 1'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / gamemodes / gamemode / mmm / sv_mmm.qc
index 525fc21a171e6ec1b51b5862e550b335a473639a..c2931f967f86c5f745f5fae200213ce8f1249b15 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_mmm.qh"
 
 //set g_mmm_sleuth_count 0.125 "number of players who will become sleuths, set between 0 and 0.9 to use a multiplier of the current players, or 1 and above to specify an exact number of players"
-//float autocvar_g_mmm_sleuth_count = 0.125; //I don't think that it won't be used...
+//float autocvar_g_mmm_sleuth_count = 0.125; //I don't think that it'll be used...
 float autocvar_g_mmm_civilian_count = 0.625;
 //float autocvar_g_mmm_murderer_count = 0.25;
 float autocvar_g_mmm_round_timelimit = 180;
@@ -11,11 +11,11 @@ bool autocvar_g_mmm_reward_civilian = true;
 bool autocvar_g_mmm_reward_sleuth = true; //sleuth reward if investigated corpses
 float autocvar_g_mmm_max_karma_points = 1000; //LegendGuard sets Karma points 21-02-2021
 float autocvar_g_mmm_min_karma_points = 400;
-int autocvar_g_mmm_karma_bankick_tool = 0; //LegendGuard sets a ban tool for server admins 11-03-2021
+int autocvar_g_mmm_karma_bankick_tool = 1; //LegendGuard sets a ban tool for server admins 11-03-2021
 float autocvar_g_mmm_karma_bantime = 1800; //karma ban seconds
 bool autocvar_g_mmm_karma_damageactive = true; //LegendGuard sets Karma damage setting if active 20-03-2021
 float autocvar_g_mmm_karma_severity = 0.25;
-
+float autocvar_g_mmm_karma_damagepunishmentdeal = 20; //LegendGuard sets Karma punishment damage setting if player kills an ally 28-03-2021
 // Sleuth is a created team, this team is added inside Civilians team
 
 void mmm_FakeTimeLimit(entity e, float t)
@@ -52,13 +52,14 @@ void karma_Control(entity it)
        {
                switch (autocvar_g_mmm_karma_bankick_tool)
                {
+                       //do nothing
+                       case 0: return;
                        //force to spec
-                       case 0: PutObserverInServer(it); return;
+                       case 1: PutObserverInServer(it); return;
                        //kick
-                       case 1: dropclient(it); return;
+                       case 2: dropclient(it); return;
                        //ban and kick
-                       case 2: Ban_KickBanClient(it, bantime, masksize, "Too low karma"); return;
-                       //force to spec
+                       case 3: Ban_KickBanClient(it, bantime, masksize, "Too low karma"); return;
                        default: PutObserverInServer(it); return;
                }
        }
@@ -66,14 +67,14 @@ void karma_Control(entity it)
 
 void karmaLoseDifference(entity attacker, entity target)
 {
-       if (autocvar_g_mmm_karma_severity <= 0)
+       if (autocvar_g_mmm_karma_severity <= 0.09)
                autocvar_g_mmm_karma_severity = 0.1;
        else if (autocvar_g_mmm_karma_severity > 1)
                autocvar_g_mmm_karma_severity = 1;
        
        //BASIC MATH THEORY: example: 1000 * 0.3 * (0.1 + 0.4) * 0.25 // karma points reduce when player attacked to other player
        if (target.karmapoints < attacker.karmapoints)
-       {       
+       {
                float decreasekarma = - ( target.karmapoints * random() * ( 0.1 + random() ) * autocvar_g_mmm_karma_severity );
                GameRules_scoring_add(attacker, MMM_KARMA, decreasekarma);
                attacker.karmapoints = attacker.karmapoints + decreasekarma;
@@ -98,6 +99,7 @@ void karmaWinDifference(entity it)
        float increasekarma = ( autocvar_g_mmm_min_karma_points * random() * ( 0.1 + random() ) * 0.12 );
        GameRules_scoring_add(it, MMM_KARMA, increasekarma);
        it.karmapoints = it.karmapoints + increasekarma;
+       karma_Control(it);
 }
 
 void mmm_UpdateScores(bool timed_out)
@@ -119,7 +121,6 @@ void mmm_UpdateScores(bool timed_out)
                        {
                                karmaWinDifference(it);
                                //PrintToChatAll(sprintf("^2REWARD ^7it.karmapoints: ^1%f", it.karmapoints));
-                               karma_Control(it);
                        }
 
                        //Sleuth reward after investigated a corpse
@@ -131,20 +132,12 @@ void mmm_UpdateScores(bool timed_out)
                                        karmaWinDifference(it);
                                        it.investigated = false;
                                }
-                               karma_Control(it);
                        }
 
-                       if(it.mmm_status == MMM_STATUS_CIVILIAN)
-                       {
-                               karmaWinDifference(it);
-                               //PrintToChatAll(sprintf("^2CIVILIAN ^7it.karmapoints: ^1%f", it.karmapoints));
-                               karma_Control(it);
-                       }
-                       else if(it.mmm_status == MMM_STATUS_MURDERER)
+                       if(it.mmm_status == MMM_STATUS_MURDERER)
                        {
                                karmaWinDifference(it);
                                //PrintToChatAll(sprintf("^1MURDERER ^7it.karmapoints: ^1%f", it.karmapoints));
-                               karma_Control(it);
                        }
                }
        });
@@ -162,6 +155,7 @@ float mmm_CheckWinner()
                        if(IS_PLAYER(it))
                                nades_Clear(it);
                        mmm_FakeTimeLimit(it, -1);
+                       karma_Control(it);
                });
 
                mmm_UpdateScores(true);
@@ -222,16 +216,28 @@ float mmm_CheckWinner()
                        nades_Clear(it);
                }
                mmm_FakeTimeLimit(it, -1);
+               karma_Control(it);
        });
 
        return 1;
 }
 
+void Karma_WarningCheck(entity it)
+{
+       float totalmeankarma = ((autocvar_g_mmm_max_karma_points + autocvar_g_mmm_min_karma_points + it.karmapoints) / 3);
+       if (it.karmapoints <= totalmeankarma)
+       {
+               Send_Notification(NOTIF_ONE_ONLY, it, MSG_INFO, INFO_MMM_KARMAWARNING);
+               //centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
+               GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
+       }
+}
+
 void mmm_RoundStart()
 {
        allowed_to_spawn = boolean(warmup_stage);
        int playercount = 0;
-       
+
        FOREACH_CLIENT(true,
        {
                if(IS_PLAYER(it) && !IS_DEAD(it))
@@ -335,21 +341,12 @@ void mmm_RoundStart()
 
        FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
        {
-               float totalmeankarma = ((autocvar_g_mmm_max_karma_points + autocvar_g_mmm_min_karma_points + it.karmapoints) / 3);
                karma_Control(it);
                it.activekillerrole = false;
 
                if(it.mmm_status == MMM_STATUS_CIVILIAN)
                {
-                       SetResource(it, RES_SHELLS, 10);
-                       SetResource(it, RES_BULLETS, 20);
-                       SetResource(it, RES_ROCKETS, 10);
-                       SetResource(it, RES_CELLS, 10);
-                       if (it.karmapoints <= totalmeankarma)
-                       {
-                               centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
-                               GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
-                       }
+                       Karma_WarningCheck(it);
                        //Gives Mine Layer weapon to the player
                        GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
                        Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_CIVILIAN);
@@ -358,15 +355,7 @@ void mmm_RoundStart()
                }
                else if(it.mmm_status == MMM_STATUS_MURDERER)
                {
-                       SetResource(it, RES_SHELLS, 10);
-                       SetResource(it, RES_BULLETS, 20);
-                       SetResource(it, RES_ROCKETS, 10);
-                       SetResource(it, RES_CELLS, 10);
-                       if (it.karmapoints <= totalmeankarma)
-                       {
-                               centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
-                               GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
-                       }
+                       Karma_WarningCheck(it);
                        //Gives Mine Layer weapon to the player
                        GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
                        Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_MURDERER);
@@ -375,18 +364,13 @@ void mmm_RoundStart()
                }
                else if(it.mmm_status == MMM_STATUS_SLEUTH)
                {
-                       SetResource(it, RES_ROCKETS, 10);
-                       if (it.karmapoints <= totalmeankarma)
-                       {
-                               centerprint(it, strcat(BOLD_OPERATOR, "^1KARMA WARNING!\n^3Here, have the Rifle!"));
-                               GiveWeapon(it, WEP_RIFLE.m_id, OP_PLUS, 1);
-                       }
+                       Karma_WarningCheck(it);
                        //Gives Shockwave and Mine Layer weapon to the player
                        GiveWeapon(it, WEP_SHOCKWAVE.m_id, OP_PLUS, 1);
                        GiveWeapon(it, WEP_MINE_LAYER.m_id, OP_PLUS, 1);
                        Send_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CENTER_MMM_SLEUTH);
                        Send_Notification(NOTIF_ONE_ONLY, it, MSG_INFO, INFO_MMM_SLEUTH);
-                       PrintToChatAll(sprintf("%s is ^4Sleuth^7!", it.netname));
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MMM_WHOISSLEUTH, it.netname);
                }
                mmm_FakeTimeLimit(it, round_handler_GetEndTime());
        });
@@ -399,15 +383,8 @@ bool mmm_CheckPlayers()
        int playercount = 0;
 
        FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
-       {       
+       {
                //PrintToChatAll(sprintf("it.karmapoints ^5begin: ^3%f",it.karmapoints));
-               //Karma points start
-               if (it.karmastarted != true)
-               {
-                       GameRules_scoring_add(it, MMM_KARMA, autocvar_g_mmm_max_karma_points - it.karmapoints);
-                       it.karmapoints = autocvar_g_mmm_max_karma_points;
-                       it.karmastarted = true;
-               }
                karma_Control(it);
                ++playercount;
                //PrintToChatAll(sprintf("it.karmapoints ^6end: ^3%f",it.karmapoints));
@@ -503,7 +480,6 @@ void ReduceKarmaPointsandFrags(entity frag_attacker, entity frag_target, float f
 {
        karmaLoseDifference(frag_attacker, frag_target);
        GiveFrags(frag_attacker, frag_target, ((autocvar_g_mmm_punish_teamkill) ? -1 : -2), frag_deathtype, wep_ent.weaponentity_fld);
-       karma_Control(frag_attacker);
        frag_target.whokilled = frag_attacker.netname;
 }
 
@@ -598,7 +574,6 @@ MUTATOR_HOOKFUNCTION(mmm, ClientObituary)
                checkWeaponDeathtype(frag_target, frag_deathtype);
        }
 
-       //TODO: try to do a "find out" if a sleuth can see who fragged to who if possible 21-02-2021
        M_ARGV(5, bool) = true; // anonymous attacker
 }
 
@@ -611,6 +586,7 @@ MUTATOR_HOOKFUNCTION(mmm, Damage_Calculate)
        float damage = M_ARGV(4, float);
        vector force = M_ARGV(6, vector);
        string corpsemessagestrcat = "";
+       string corpsemsginfo = "";
 
        if (autocvar_g_mmm_karma_damageactive != false)
        {
@@ -634,52 +610,58 @@ MUTATOR_HOOKFUNCTION(mmm, Damage_Calculate)
                }
        }
 
-       //SLEUTH CORPSE DETECTION SKILL 21-03-2021
-       if (attacker.mmm_status == MMM_STATUS_SLEUTH)
+       //CORPSE DETECTION SKILL 21-03-2021
+       if(IS_DEAD(target))
        {
-               if(IS_DEAD(target))
+               //Shockwave weapon as radar gun to check the corpses 22-03-2021
+               if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE))
                {
-                       //Shockwave weapon as radar gun to check the corpses 22-03-2021
-                       if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE))
+                       if (target.killedwithweapon == "")
+                               target.killedwithweapon = "UNKNOWN CAUSE";
+                       
+                       if (target.activekillerrole != true)
                        {
-                               if (target.killedwithweapon == "")
-                                       target.killedwithweapon = "UNKNOWN CAUSE";
-                               
-                               if (target.activekillerrole != true)
-                               {
-                                       target.killerrole = "";
-                                       target.activekillerrole = false;
-                               }
+                               target.killerrole = "";
+                               target.activekillerrole = false;
+                       }
 
-                               string killedbyphrase = strcat("\n^3Killed by:^7 ", target.whokilled, target.killerrole); 
-                               string wepkilledphrase = strcat("\n^3Cause:^7 ", target.killedwithweapon);
-                               if (target.whokilled == "")
-                               {
-                                       killedbyphrase = "";
-                                       if (target.killedwithweapon == "")
-                                               wepkilledphrase = "\n^3Cause:^7 UNKNOWN CAUSE";
-                               }
+                       string killedbyphrase = strcat("^3Killed by:^7 ", target.whokilled, target.killerrole); 
+                       string wepkilledphrase = strcat("^3Cause:^7 ", target.killedwithweapon);
+                       if (target.whokilled == "")
+                       {
+                               killedbyphrase = "";
+                               if (target.killedwithweapon == "")
+                                       wepkilledphrase = "^3Cause:^7 UNKNOWN CAUSE";
+                       }
 
-                               damage = 0;
-                               force = '0 0 0';
-                               if (target.mmm_status == MMM_STATUS_CIVILIAN)
-                               {
-                                       //try to add centerprint message for chat privately if possible
-                                       corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^2Civilian", killedbyphrase, wepkilledphrase);
-                                       centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^2Civilian\n", "^1Killed by^3:^7 ", target.whokilled)));
-                               }
-                               else if (target.mmm_status == MMM_STATUS_MURDERER)
-                               {
-                                       corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^1Murderer", killedbyphrase, wepkilledphrase);
-                                       centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^1Murderer\n", "^1Killed by^3:^7 ", target.whokilled)));
-                               }
-                               else if (target.mmm_status == MMM_STATUS_SLEUTH)
-                               {
-                                       corpsemessagestrcat = strcat("\n^3Name:^7 ", target.netname, "\n^3Role: ^4Sleuth", killedbyphrase, wepkilledphrase);
-                                       centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));//("\n^6Name^3:^7 ", target.netname, "\n^5Role^3: ^4Sleuth\n", "^1Killed by^3:^7 ", target.whokilled)));
-                               }
-                               attacker.investigated = true;
+                       damage = 0;
+                       force = '0 0 0';
+                       if (target.mmm_status == MMM_STATUS_CIVILIAN)
+                       {
+                               //try to add centerprint message for chat privately if possible
+                               corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^2Civilian", "\n", killedbyphrase, "\n", wepkilledphrase);
+                               corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, "   ^3Role: ^2Civilian", "   ", killedbyphrase, "   ", wepkilledphrase);
+                               //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
                        }
+                       else if (target.mmm_status == MMM_STATUS_MURDERER)
+                       {
+                               corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^1Murderer", "\n", killedbyphrase, "\n", wepkilledphrase);
+                               corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, "   ^3Role: ^1Murderer", "   ", killedbyphrase, "   ", wepkilledphrase);
+                               //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
+                       }
+                       else if (target.mmm_status == MMM_STATUS_SLEUTH)
+                       {
+                               corpsemessagestrcat = strcat("^5DEAD PLAYER DETAILS^7: \n^3Name:^7 ", target.netname, "\n^3Role: ^4Sleuth", "\n", killedbyphrase, "\n", wepkilledphrase);
+                               corpsemsginfo = strcat("^5DEAD PLAYER DETAILS^7: ^3Name:^7 ", target.netname, "   ^3Role: ^4Sleuth", "   ", killedbyphrase, "   ", wepkilledphrase);
+                               //centerprint(attacker, strcat(BOLD_OPERATOR, corpsemessagestrcat));
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_CENTER, CENTER_MMM_CORPSEDETECTION, corpsemessagestrcat);
+                               Send_Notification(NOTIF_ONE_ONLY, attacker, MSG_INFO, INFO_MMM_CORPSEDETECTION, corpsemsginfo);
+                       }
+                       attacker.investigated = true;
                }
        }
 
@@ -690,9 +672,39 @@ MUTATOR_HOOKFUNCTION(mmm, Damage_Calculate)
 MUTATOR_HOOKFUNCTION(mmm, PlayerPreThink)
 {
        entity player = M_ARGV(0, entity);
-       
+       int playercount = 0;
+       bool playercheck = false;
+
+       if (playercheck != true)
+       {
+               FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+               {
+                       ++playercount;
+               });
+               playercheck = true;
+       }
+
+       //if the murderer is still here around, then avoid illogical winning
+       if (playercheck == true)
+       {
+               FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+               {
+                       if (playercount == 3)
+                       {
+                               if (it.mmm_status == MMM_STATUS_SLEUTH)
+                                       it.mmm_status = MMM_STATUS_CIVILIAN;
+                       }
+               });
+       }
+
        if(IS_PLAYER(player) || player.caplayer)
        {
+               if (player.karmaspectated != true)
+               {
+                       if (CS(player).scorekeeper.(scores(SP_MMM_KARMA)) <= 0) //wtf? Visualization works 100% correct?
+                               GameRules_scoring_add(player, MMM_KARMA, player.karmapoints);
+                       player.karmaspectated = true;
+               }
                // update the scoreboard colour display to out the real killer at the end of the round
                // running this every frame to avoid cheats
                int plcolor = MMM_COLOR_CIVILIAN;
@@ -705,6 +717,8 @@ MUTATOR_HOOKFUNCTION(mmm, PlayerPreThink)
                        plcolor = MMM_COLOR_SLEUTH;
                setcolor(player, plcolor);
        }
+       if(warmup_stage)
+               player.karmastarted = false;
 
        //CORPSE FEATURE 10-03-2021
        if (IS_DEAD(player))
@@ -719,6 +733,15 @@ MUTATOR_HOOKFUNCTION(mmm, PlayerPreThink)
 MUTATOR_HOOKFUNCTION(mmm, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
+       
+       //Karma points start
+       if (player.karmastarted != true)
+       {
+               CS(player).scorekeeper.(scores(SP_MMM_KARMA)) = 0; //full karma reset lol
+               player.karmapoints = autocvar_g_mmm_max_karma_points;
+               GameRules_scoring_add(player, MMM_KARMA, player.karmapoints);
+               player.karmastarted = true;
+       }
 
        player.mmm_status = 0;
        player.mmm_validkills = 0;
@@ -825,11 +848,7 @@ MUTATOR_HOOKFUNCTION(mmm, PlayerDies)
        frag_target.health = 0;
        
        if (!warmup_stage)
-       {
                eliminatedPlayers.SendFlags |= 1;
-               if (IS_BOT_CLIENT(frag_target))
-                       bot_clear(frag_target);
-       }
        
        //if(frag_attacker.mmm_status == frag_target.mmm_status)
        // killed an ally! punishment is sentenced
@@ -838,8 +857,7 @@ MUTATOR_HOOKFUNCTION(mmm, PlayerDies)
                if (frag_target.mmm_status == MMM_STATUS_CIVILIAN)
                {
                        //PrintToChatAll("^1DEBUG^7: ^4SLEUTH ^1DAMAGE/DEAD^7 HAS TAKEN!");
-                       //30 damage points deal
-                       Damage(frag_attacker, frag_attacker, frag_attacker, 30, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+                       Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
                }
        }
        if (frag_attacker.mmm_status == MMM_STATUS_CIVILIAN)
@@ -847,8 +865,15 @@ MUTATOR_HOOKFUNCTION(mmm, PlayerDies)
                if (frag_target.mmm_status == MMM_STATUS_SLEUTH)
                {
                        //PrintToChatAll("^1DEBUG^7: ^2CIVILIAN ^1DAMAGE/DEAD^7 HAS TAKEN!");
-                       //30 damage points deal
-                       Damage(frag_attacker, frag_attacker, frag_attacker, 30, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+                       Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
+               }
+       }
+       if (frag_attacker.mmm_status == MMM_STATUS_MURDERER)
+       {
+               if (frag_target.mmm_status == MMM_STATUS_MURDERER)
+               {
+                       //PrintToChatAll("^1DEBUG^7: ^1MURDERER ^1DAMAGE/DEAD^7 HAS TAKEN!");
+                       Damage(frag_attacker, frag_attacker, frag_attacker, autocvar_g_mmm_karma_damagepunishmentdeal, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
                }
        }
        return true;
@@ -865,11 +890,12 @@ MUTATOR_HOOKFUNCTION(mmm, ClientDisconnect)
 
 MUTATOR_HOOKFUNCTION(mmm, MakePlayerObserver)
 {
-       // LegendGuard, here is where spectators shouldn't talk to any players to say the hints or who is who 21-10-2021
        entity player = M_ARGV(0, entity);
 
        if (IS_PLAYER(player) && !IS_DEAD(player))
                mmm_LastPlayerForTeam_Notify(player);
+       if (player.karmaspectated == true)
+               player.karmaspectated = false;
        if (player.killindicator_teamchange == -2) // player wants to spectate
                player.caplayer = 0;
        if (player.caplayer)
@@ -895,7 +921,7 @@ MUTATOR_HOOKFUNCTION(mmm, Scores_CountFragsRemaining)
 MUTATOR_HOOKFUNCTION(mmm, GiveFragsForKill, CBC_ORDER_FIRST)
 {
        entity frag_attacker = M_ARGV(0, entity);
-       if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted())
+       if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted()) 
                frag_attacker.mmm_validkills += M_ARGV(2, float);
        M_ARGV(2, float) = 0; // score will be given to the winner when the round ends
        return true;
@@ -915,6 +941,12 @@ MUTATOR_HOOKFUNCTION(mmm, CalculateRespawnTime)
        return true;
 }
 
+//if server admin sets "sv_ready_restart_after_countdown 1", will avoid possible visual failure for karma in the scoreboard
+MUTATOR_HOOKFUNCTION(mmm, ReadLevelCvars)
+{
+       sv_ready_restart_after_countdown = 0;
+}
+
 MUTATOR_HOOKFUNCTION(mmm, Bot_FixCount, CBC_ORDER_EXCLUSIVE)
 {
        FOREACH_CLIENT(IS_REAL_CLIENT(it), {