From 640f5fadfa6be37ebc1a2699e37bd12bb1607e71 Mon Sep 17 00:00:00 2001 From: drjaska Date: Tue, 18 Jan 2022 20:30:51 +0200 Subject: [PATCH] finish refactoring score system debug prints are in the code still but disabled, enable to test easily and more accurately --- .../gamemodes/gamemode/mayhem/sv_mayhem.qc | 28 +- .../gamemodes/gamemode/tmayhem/sv_tmayhem.qc | 294 ++++++++++-------- 2 files changed, 171 insertions(+), 151 deletions(-) diff --git a/qcsrc/common/gamemodes/gamemode/mayhem/sv_mayhem.qc b/qcsrc/common/gamemodes/gamemode/mayhem/sv_mayhem.qc index aeca56e40..7a8ae68e3 100644 --- a/qcsrc/common/gamemodes/gamemode/mayhem/sv_mayhem.qc +++ b/qcsrc/common/gamemodes/gamemode/mayhem/sv_mayhem.qc @@ -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; } diff --git a/qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc b/qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc index 41b3ae633..4c9e7f85d 100644 --- a/qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc +++ b/qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc @@ -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; } -- 2.39.2