]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
finish refactoring score system
authordrjaska <drjaska83@gmail.com>
Tue, 18 Jan 2022 18:30:51 +0000 (20:30 +0200)
committerdrjaska <drjaska83@gmail.com>
Tue, 18 Jan 2022 18:30:51 +0000 (20:30 +0200)
debug prints are in the code still but disabled, enable to test easily and more accurately

qcsrc/common/gamemodes/gamemode/mayhem/sv_mayhem.qc
qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc

index aeca56e409fd909cfcbe7cea23942fcede89df14..7a8ae68e35507cf0b0e1440397a3155099257d3e 100644 (file)
@@ -130,7 +130,7 @@ MUTATOR_HOOKFUNCTION(mayhem, Damage_Calculate)
        M_ARGV(4, float) = frag_damage;
 }
 
-void CalculatePlayerScore(entity scorer){
+void FFAMayhemCalculatePlayerScore(entity scorer){
        switch (autocvar_g_mayhem_scoringmethod)
        {
                default:
@@ -143,14 +143,14 @@ void CalculatePlayerScore(entity scorer){
 
                        //total damage divided by player start health&armor to get how many lives worth of damage they've dealt, then how much that is out of the fraglimit, then calculate new value affected by weight
                        float playerdamagescore = (((((scorer.total_damage_dealt/(start_health + start_armorvalue)) * 100)/autocvar_g_mayhem_fraglimit) * autocvar_g_mayhem_scoringmethod_1_damage_weight) );
-                                                                                                                                                                                       // * 100 to avoid float inaccuracy at that decimal level
+                                                                                                                                                                                                       //  * 100 to avoid float inaccuracy at that decimal level
 
                        //playerdamagescore rounded
                        float roundedplayerdamagescore = ((rint(playerdamagescore*10))/10);
 
                        //kills minus suicides, total out of fraglimit, calculate weight
                        float playerkillscore = ((((PlayerScore_Get(scorer, SP_KILLS) - (PlayerScore_Get(scorer, SP_SUICIDES) * suicide_weight)) * 100) / autocvar_g_mayhem_fraglimit) * autocvar_g_mayhem_scoringmethod_1_frag_weight);
-                                                                                                                                                                                                                                                                                               // * 100 to avoid float inaccuracy at that decimal level
+                                                                                                                                                                                                                                                               //   * 100 to avoid float inaccuracy at that decimal level
 
                        //only used for debug print, add killscore and damagescore together
                        float playerscore = (roundedplayerdamagescore + playerkillscore);
@@ -161,13 +161,13 @@ void CalculatePlayerScore(entity scorer){
 
                        //calculated how much score the player has and now calculate total of how much they are supposed to have
                        float scoretoadd = (playerscorevisual - (PlayerScore_Get(scorer, SP_SCORE) * 100));
-                                                                                                                                                                                  // * 100 to avoid float inaccuracy at that decimal level
+                                                                                                                                                                  //  * 100 to avoid float inaccuracy at that decimal level
 
                        //adjust total score to be what the player is supposed to have
-                       GameRules_scoring_add_team(scorer, SCORE, (scoretoadd / 100));
-                                                                                                                                       //   / 100 to move back to the decimal level
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd / 100));
+                                                                                                                                       // / 100 to move back to the decimal level
 
-                       if(1){
+                       if(0){
                                //debug printing
                                if(!IS_BOT_CLIENT(scorer)){
                                        print(sprintf("%f", scorer.total_damage_dealt),                 " scorer.total_damage_dealt \n");
@@ -190,9 +190,9 @@ void CalculatePlayerScore(entity scorer){
                        float playerkillscore = (((PlayerScore_Get(scorer, SP_KILLS) - PlayerScore_Get(scorer, SP_SUICIDES)) * 100)/ autocvar_g_mayhem_fraglimit);
                        float playerscorevisual = (playerkillscore * autocvar_g_mayhem_visual_score_limit) / 100;
                        float scoretoadd = (playerscorevisual - PlayerScore_Get(scorer, SP_SCORE));
-                       GameRules_scoring_add_team(scorer, SCORE, scoretoadd);
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd));
 
-                       if(1){
+                       if(0){
                                //debug printing
                                if(!IS_BOT_CLIENT(scorer)){
                                        print(sprintf("%f", playerkillscore),                                   " playerkillscore \n");
@@ -212,9 +212,9 @@ void CalculatePlayerScore(entity scorer){
                        float roundedplayerdamagescore = ((rint(playerdamagescore*10))/10);
                        float playerscorevisual = (roundedplayerdamagescore * autocvar_g_mayhem_visual_score_limit);
                        float scoretoadd = (playerscorevisual - (PlayerScore_Get(scorer, SP_SCORE) * 100));
-                       GameRules_scoring_add_team(scorer, SCORE, (scoretoadd / 100));
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd / 100));
 
-                       if(1){
+                       if(0){
                                //debug printing
                                if(!IS_BOT_CLIENT(scorer)){
                                        print(sprintf("%f", scorer.total_damage_dealt),                 " scorer.total_damage_dealt \n");
@@ -232,7 +232,7 @@ void CalculatePlayerScore(entity scorer){
 
 MUTATOR_HOOKFUNCTION(mayhem, PlayerDamage_SplitHealthArmor)
 {
-       if(autocvar_g_mayhem_scoringmethod==2)return;
+       if (autocvar_g_mayhem_scoringmethod==2) return;
        
        entity frag_target = M_ARGV(2, entity);
 
@@ -285,7 +285,7 @@ MUTATOR_HOOKFUNCTION(mayhem, PlayerDamage_SplitHealthArmor)
                scorer = frag_target;
        }
 
-       CalculatePlayerScore(scorer);
+       FFAMayhemCalculatePlayerScore(scorer);
 }
 
 MUTATOR_HOOKFUNCTION(mayhem, GiveFragsForKill, CBC_ORDER_FIRST)
@@ -293,7 +293,7 @@ MUTATOR_HOOKFUNCTION(mayhem, GiveFragsForKill, CBC_ORDER_FIRST)
        entity frag_attacker = M_ARGV(0, entity);
        M_ARGV(2, float) = 0; //score to give for the frag directly
        
-       if(IS_PLAYER(frag_attacker))CalculatePlayerScore(frag_attacker);
+       if (IS_PLAYER(frag_attacker)) FFAMayhemCalculatePlayerScore(frag_attacker);
        
        return true;
 }
index 41b3ae63345dd509570b529ca91e5ac4be8329ad..4c9e7f85d32a6ac54eaca6cabae56593cd5e2f22 100644 (file)
@@ -31,6 +31,8 @@ float autocvar_g_tmayhem_start_ammo_cells = 180;
 float autocvar_g_tmayhem_start_ammo_plasma = 180;
 float autocvar_g_tmayhem_start_ammo_fuel = 0;
 
+.float total_damage_dealt;
+
 // code from here on is just to support maps that don't have team entities
 void tmayhem_SpawnTeam (string teamname, int teamcolor)
 {
@@ -76,6 +78,7 @@ void tmayhem_Initialize()
 
        InitializeEntity(NULL, tmayhem_DelayedInit, INITPRIO_GAMETYPE);
 }
+// code up to here is just to support maps that don't have team entities
 
 MUTATOR_HOOKFUNCTION(tmayhem, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
@@ -104,7 +107,7 @@ MUTATOR_HOOKFUNCTION(tmayhem, SetStartItems)
        start_ammo_fuel    = warmup_start_ammo_fuel    = autocvar_g_tmayhem_start_ammo_fuel;
 }
 
-//this hook also enables rotting, as players spawn with more hp and armor than what default rot limits are set to this is a bad idea as of now
+//this hook also enables rotting, as players spawn with more hp and armor than what default rot limits are set to this is a bad idea as of now until PlayerRegen is changed
 MUTATOR_HOOKFUNCTION(tmayhem, PlayerRegen)
 {
        if(autocvar_g_tmayhem_regenerate)
@@ -164,164 +167,181 @@ MUTATOR_HOOKFUNCTION(tmayhem, Damage_Calculate)
        float frag_damage = M_ARGV(4, float);
        float frag_mirrordamage = M_ARGV(5, float);
 
-       if (IS_PLAYER(frag_target))
-       if (!IS_DEAD(frag_target))
-       if ((autocvar_g_tmayhem_selfdamage == 0 && frag_target == frag_attacker) || frag_deathtype == DEATH_FALL.m_id)
+       if (IS_PLAYER(frag_target)) //don't ever zero damage to non-players
+       if (!IS_DEAD(frag_target)) //enable anyone to gib corpses
+       if ((autocvar_g_tmayhem_selfdamage == 0 && frag_target == frag_attacker) || frag_deathtype == DEATH_FALL.m_id) //nullify self-damage if self-damage is disabled and always nullify splat
                frag_damage = 0;
 
-       frag_mirrordamage = 0;
+       frag_mirrordamage = 0; //no mirror damaging
 
        M_ARGV(4, float) = frag_damage;
        M_ARGV(5, float) = frag_mirrordamage;
 }
 
-MUTATOR_HOOKFUNCTION(tmayhem, PlayerDamage_SplitHealthArmor)
-{
-       switch(autocvar_g_tmayhem_scoringmethod)
+void TeamMayhemCalculatePlayerScore(entity scorer){
+       switch (autocvar_g_tmayhem_scoringmethod)
        {
-               //frags only
-               case 2:
+               default:
+               case 1:
                {
-                       return;
+                       //calculate how much score the player should have based on their damage dealt and frags gotten and then add the missing score
+
+                       //give a different weight for suicides if scoring method 1 doesn't have selfdamage2score enabled to harshly punish for suicides to avoid exploiting
+                       float suicide_weight = 1 + (autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score * (1/autocvar_g_tmayhem_scoringmethod_1_frag_weight));
+
+                       //total damage divided by player start health&armor to get how many lives worth of damage they've dealt, then how much that is out of the fraglimit, then calculate new value affected by weight
+                       float playerdamagescore = (((((scorer.total_damage_dealt/(start_health + start_armorvalue)) * 100)/autocvar_g_tmayhem_fraglimit) * autocvar_g_tmayhem_scoringmethod_1_damage_weight) );
+                                                                                                                                                                                                       //  * 100 to avoid float inaccuracy at that decimal level
+
+                       //playerdamagescore rounded
+                       float roundedplayerdamagescore = ((rint(playerdamagescore*10))/10);
+
+                       //kills minus suicides, total out of fraglimit, calculate weight
+                       float playerkillscore = ((((PlayerScore_Get(scorer, SP_KILLS) - (PlayerScore_Get(scorer, SP_SUICIDES) * suicide_weight)) * 100) / autocvar_g_tmayhem_fraglimit) * autocvar_g_tmayhem_scoringmethod_1_frag_weight);
+                                                                                                                                                                                                                                                               //   * 100 to avoid float inaccuracy at that decimal level
+
+                       //only used for debug print, add killscore and damagescore together
+                       float playerscore = (roundedplayerdamagescore + playerkillscore);
+
+                       //add killscore and damagescore together to get total score and then adjust it to be total out of the visual score limit
+                       float playerscorevisual = ((roundedplayerdamagescore + playerkillscore) * autocvar_g_tmayhem_visual_score_limit);
+                                                                                                                                                                                                                                               
+
+                       //calculated how much score the player has and now calculate total of how much they are supposed to have
+                       float scoretoadd = (playerscorevisual - (PlayerScore_Get(scorer, SP_SCORE) * 100));
+                                                                                                                                                                  //  * 100 to avoid float inaccuracy at that decimal level
+
+                       //adjust total score to be what the player is supposed to have
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd / 100));
+                                                                                                                                       // / 100 to move back to the decimal level
+
+                       if(0){
+                               //debug printing
+                               if(!IS_BOT_CLIENT(scorer)){
+                                       print(sprintf("%f", scorer.total_damage_dealt),                 " scorer.total_damage_dealt \n");
+                                       print(sprintf("%f", playerdamagescore),                                 " playerdamagescore \n");
+                                       print(sprintf("%f", roundedplayerdamagescore),                  " rounded playerdamagescore \n");
+                                       print(sprintf("%f", playerkillscore),                                   " playerkillscore \n");
+                                       print(sprintf("%f", PlayerScore_Get(scorer, SP_KILLS)), " PlayerScore_Get(scorer, SP_KILLS) \n");
+                                       print(sprintf("%f", playerscore),                                               " playerscore \n");
+                                       print(sprintf("%f", playerscorevisual),                                 " visual playerscore \n");
+                                       print(sprintf("%f", scoretoadd),                                                " scoretoadd \n");
+                                       print(sprintf("%f", PlayerScore_Get(scorer, SP_SCORE)), " PlayerScore_Get(scorer, SP_SCORE) \n \n");
+                               }
+                       }
+               return;
                }
-               
-               //damage only
-               case 3:
+
+               case 2:
                {
-                       entity frag_attacker = M_ARGV(1, entity);
-                       entity frag_target = M_ARGV(2, entity);
-                       float frag_deathtype = M_ARGV(6, float);
-                       float frag_damage = M_ARGV(7, float);
-                       float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH));
-                       float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR));
-
-                       float excess = max(0, frag_damage - damage_take - damage_save);
-
-                       //non-friendly fire
-                       if (IS_PLAYER(frag_attacker) && !SAME_TEAM(frag_target, frag_attacker))
-                               GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-
-                       //friendly fire or self damage
-                       if (frag_target == frag_attacker && IS_PLAYER(frag_attacker) || SAME_TEAM(frag_target, frag_attacker))
-                               GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-
-                       //handle (environmental hazard) suiciding, check first if player has a registered attacker who most likely pushed them there to avoid punishing pushed players as pushers are already rewarded
-                       //deathtypes:
-                       //kill = suicide, drown = drown in water/liquid, hurttrigger = out of the map void or hurt triggers inside maps like electric sparks
-                       //camp = campcheck, lava = lava, slime = slime
-                       //team change / rebalance suicides are currently not included
-                       if (!IS_PLAYER(frag_attacker) && (
-                               frag_deathtype == DEATH_KILL.m_id ||
-                               frag_deathtype == DEATH_DROWN.m_id ||
-                               frag_deathtype == DEATH_HURTTRIGGER.m_id ||
-                               frag_deathtype == DEATH_CAMP.m_id ||
-                               frag_deathtype == DEATH_LAVA.m_id ||
-                               frag_deathtype == DEATH_SLIME.m_id))
-                                       GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-                       return;
+                       //calculate how much score the player should have based on their frags gotten and then add the missing score
+                       float playerkillscore = (((PlayerScore_Get(scorer, SP_KILLS) - PlayerScore_Get(scorer, SP_SUICIDES)) * 100)/ autocvar_g_tmayhem_fraglimit);
+                       float playerscorevisual = (playerkillscore * autocvar_g_tmayhem_visual_score_limit) / 100;
+                       float scoretoadd = (playerscorevisual - PlayerScore_Get(scorer, SP_SCORE));
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd));
+
+                       if(0){
+                               //debug printing
+                               if(!IS_BOT_CLIENT(scorer)){
+                                       print(sprintf("%f", playerkillscore),                                   " playerkillscore \n");
+                                       print(sprintf("%f", PlayerScore_Get(scorer, SP_KILLS)), " PlayerScore_Get(scorer, SP_KILLS) \n");
+                                       print(sprintf("%f", playerscorevisual),                                 " visual playerscore \n");
+                                       print(sprintf("%f", scoretoadd),                                                " scoretoadd \n");
+                                       print(sprintf("%f", PlayerScore_Get(scorer, SP_SCORE)), " PlayerScore_Get(scorer, SP_SCORE) \n \n");
+                               }
+                       }
+               return;
                }
-               
-               //combined damage and frags
-               default:
-               case 1:
+
+               case 3:
                {
-                       entity frag_attacker = M_ARGV(1, entity);
-                       entity frag_target = M_ARGV(2, entity);
-                       float frag_deathtype = M_ARGV(6, float);
-                       float frag_damage = M_ARGV(7, float);
-                       float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH));
-                       float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR));
-
-                       float excess = max(0, frag_damage - damage_take - damage_save);
-
-                       //non-friendly fire
-                       if (IS_PLAYER(frag_attacker) && !SAME_TEAM(frag_target, frag_attacker))
-                               GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * autocvar_g_tmayhem_scoringmethod_1_damage_weight * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-                       
-                       //friendly fire or self damage
-                       if ((SAME_TEAM(frag_target, frag_attacker) && frag_target != frag_attacker) || (frag_target == frag_attacker && IS_PLAYER(frag_attacker) && !autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score))
-                               GameRules_scoring_add_team(frag_attacker, SCORE, (-1 * (frag_damage - excess)) * autocvar_g_tmayhem_scoringmethod_1_damage_weight * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-               
-                       //handle (environmental hazard) suiciding, check first if player has a registered attacker who most likely pushed them there to avoid punishing pushed players as pushers are already rewarded
-                       //deathtypes:
-                       //kill = suicide, drown = drown in water/liquid, hurttrigger = out of the map void or hurt triggers inside maps like electric sparks
-                       //camp = campcheck, lava = lava, slime = slime
-                       //team change / rebalance suicides are currently not included
-                       if (!autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score && !IS_PLAYER(frag_attacker) && (
-                               frag_deathtype == DEATH_KILL.m_id ||
-                               frag_deathtype == DEATH_DROWN.m_id ||
-                               frag_deathtype == DEATH_HURTTRIGGER.m_id ||
-                               frag_deathtype == DEATH_CAMP.m_id ||
-                               frag_deathtype == DEATH_LAVA.m_id ||
-                               frag_deathtype == DEATH_SLIME.m_id))
-                                       GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * autocvar_g_tmayhem_scoringmethod_1_damage_weight * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
-                       return;
+                       //calculate how much score the player should have based on their damage dealt and then add the missing score
+                       float playerdamagescore = (((scorer.total_damage_dealt/(start_health + start_armorvalue)) * 100)/autocvar_g_tmayhem_fraglimit);
+                       float roundedplayerdamagescore = ((rint(playerdamagescore*10))/10);
+                       float playerscorevisual = (roundedplayerdamagescore * autocvar_g_tmayhem_visual_score_limit);
+                       float scoretoadd = (playerscorevisual - (PlayerScore_Get(scorer, SP_SCORE) * 100));
+                       GameRules_scoring_add_team(scorer, SCORE, floor(scoretoadd / 100));
+
+                       if(0){
+                               //debug printing
+                               if(!IS_BOT_CLIENT(scorer)){
+                                       print(sprintf("%f", scorer.total_damage_dealt),                 " scorer.total_damage_dealt \n");
+                                       print(sprintf("%f", playerdamagescore),                                 " playerdamagescore \n");
+                                       print(sprintf("%f", roundedplayerdamagescore),                  " rounded playerdamagescore \n");
+                                       print(sprintf("%f", playerscorevisual),                                 " visual playerscore \n");
+                                       print(sprintf("%f", scoretoadd),                                                " scoretoadd \n");
+                                       print(sprintf("%f", PlayerScore_Get(scorer, SP_SCORE)), " PlayerScore_Get(scorer, SP_SCORE) \n \n");
+                               }
+                       }
+               return;
                }
        }
 }
 
-MUTATOR_HOOKFUNCTION(tmayhem, GiveFragsForKill, CBC_ORDER_FIRST)
+MUTATOR_HOOKFUNCTION(tmayhem, PlayerDamage_SplitHealthArmor)
 {
-       entity frag_attacker = M_ARGV(0, entity);
-       entity frag_target = M_ARGV(1, entity);
+       if (autocvar_g_tmayhem_scoringmethod==2) return;
        
-       if(SAME_TEAM(frag_target, frag_attacker)){
-               switch(autocvar_g_tmayhem_scoringmethod)
-               {
-                       //frags only
-                       case 2:
-                       {
-                                                                                                                       //fix 999 score from 30 kills for example
-                               M_ARGV(2, float) = -1 * tmayhempointmultiplier * 1.0001;
-                               return true;
-                       }
+       entity frag_target = M_ARGV(2, entity);
 
-                       //damage only
-                       case 3:
-                       {
-                               M_ARGV(2, float) = 0;
-                               return true;
-                       }
+       if (StatusEffects_active(STATUSEFFECT_SpawnShield, frag_target) && autocvar_g_spawnshield_blockdamage >= 1)return;
+       
+       entity frag_attacker = M_ARGV(1, entity);
+       float frag_deathtype = M_ARGV(6, float);
+       float frag_damage = M_ARGV(7, float);
+       float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH));
+       float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR));
+       float excess = max(0, frag_damage - damage_take - damage_save);
+       float total = frag_damage - excess;
 
-                       //combined damage and frags
-                       default:
-                       case 1:
-                       {
-                               //when selfdamage2score is disabled don't enable cheap discounted suicides at the cost of the possibility of 
-                               //punishing for a full life when they only deal a single point worth of self damage to kill themselves
-                               if(autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score && frag_target==frag_attacker){
-                                       M_ARGV(2, float) = -1 * tmayhempointmultiplier * 1.0001;
-                               } else {
-                                       M_ARGV(2, float) = -autocvar_g_tmayhem_scoringmethod_1_frag_weight * tmayhempointmultiplier * 1.0001;
-                               }
-                               return true;
-                       }
-               }
-       } else {
-               switch(autocvar_g_tmayhem_scoringmethod)
-               {
-                       //frags only
-                       case 2:
-                       {
-                                                                                                                       //fix 999 score from 30 kills for example
-                               M_ARGV(2, float) = 1 * tmayhempointmultiplier * 1.0001;
-                               return true;
-                       }
+       if (total == 0) return;
 
-                       //damage only
-                       case 3:
-                       {
-                               M_ARGV(2, float) = 0;
-                               return true;
-                       }
+       if (StatusEffects_active(STATUSEFFECT_SpawnShield, frag_target) && autocvar_g_spawnshield_blockdamage < 1)
+               total *= 1 - bound(0, autocvar_g_spawnshield_blockdamage, 1);
 
-                       //combined damage and frags
-                       default:
-                       case 1:
-                       {
-                               M_ARGV(2, float) = autocvar_g_tmayhem_scoringmethod_1_frag_weight * tmayhempointmultiplier * 1.0001;
-                               return true;
-                       }
-               }
+       entity scorer = NULL; //entity which needs their score to be updated
+
+       if (IS_PLAYER(frag_attacker))
+       {
+               //non-friendly fire
+               if (!SAME_TEAM(frag_target, frag_attacker))
+                       frag_attacker.total_damage_dealt += total;
+
+               //friendly fire aka self damage
+               if (SAME_TEAM(frag_target, frag_attacker) || (frag_target == frag_attacker && !autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score))
+                       frag_attacker.total_damage_dealt -= total;
+
+               scorer = frag_attacker;
+       }
+       else
+       {
+               //handle (environmental hazard) suiciding, check first if player has a registered attacker who most likely pushed them there to avoid punishing pushed players as pushers are already rewarded
+               //deathtypes:
+               //kill = suicide, drown = drown in water/liquid, hurttrigger = out of the map void or hurt triggers inside maps like electric sparks
+               //camp = campcheck, lava = lava, slime = slime
+               //team change / rebalance suicides are currently not included
+               if (!autocvar_g_tmayhem_scoringmethod_1_disable_selfdamage2score && (
+                       frag_deathtype == DEATH_KILL.m_id ||
+                       frag_deathtype == DEATH_DROWN.m_id ||
+                       frag_deathtype == DEATH_HURTTRIGGER.m_id ||
+                       frag_deathtype == DEATH_CAMP.m_id ||
+                       frag_deathtype == DEATH_LAVA.m_id ||
+                       frag_deathtype == DEATH_SLIME.m_id ||
+                       frag_deathtype == DEATH_SWAMP.m_id))
+                               frag_target.total_damage_dealt -= total;
+
+               scorer = frag_target;
        }
+
+       TeamMayhemCalculatePlayerScore(scorer);
+}
+
+MUTATOR_HOOKFUNCTION(tmayhem, GiveFragsForKill, CBC_ORDER_FIRST)
+{
+       entity frag_attacker = M_ARGV(0, entity);
+       M_ARGV(2, float) = 0; //score to give for the frag directly
+       
+       if (IS_PLAYER(frag_attacker)) TeamMayhemCalculatePlayerScore(frag_attacker);
+       
+       return true;
 }