From d2b7c0ac153e6d7559b786096c720982a4ebf27b Mon Sep 17 00:00:00 2001 From: "Dr. Jaska" Date: Thu, 13 Jun 2024 22:50:50 +0000 Subject: [PATCH] Separated handicap into give and take variables --- .../dynamic_handicap/sv_dynamic_handicap.qc | 3 +- qcsrc/common/replicate.qh | 10 ++- qcsrc/server/client.qh | 3 +- qcsrc/server/handicap.qc | 75 +++++++++++++++---- qcsrc/server/handicap.qh | 17 +++-- qcsrc/server/player.qc | 4 +- xonotic-client.cfg | 6 +- 7 files changed, 93 insertions(+), 25 deletions(-) diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc b/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc index 237d14a6e..4796830d4 100644 --- a/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc +++ b/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc @@ -58,7 +58,8 @@ void DynamicHandicap_UpdateHandicap() handicap = 1 / (fabs(handicap) + 1); } handicap = DynamicHandicap_ClampHandicap(handicap); - Handicap_SetForcedHandicap(it, handicap); + Handicap_SetForcedHandicap(it, handicap, false); + Handicap_SetForcedHandicap(it, handicap, true); }); } diff --git a/qcsrc/common/replicate.qh b/qcsrc/common/replicate.qh index 6115223b4..6c66771f8 100644 --- a/qcsrc/common/replicate.qh +++ b/qcsrc/common/replicate.qh @@ -1,18 +1,24 @@ #pragma once +// TODO: Remove cvar_cl_handicap vector after 0.9 release + #ifdef GAMEQC REPLICATE_INIT(bool, cvar_cl_autoswitch); REPLICATE_INIT(int, cvar_cl_autoscreenshot); REPLICATE_INIT(bool, cvar_cl_clippedspectating); REPLICATE_INIT(bool, cvar_cl_cts_noautoswitch); -REPLICATE_INIT(float, cvar_cl_handicap); +REPLICATE_INIT(vector, cvar_cl_handicap); +REPLICATE_INIT(float, cvar_cl_handicap_damage_given); +REPLICATE_INIT(float, cvar_cl_handicap_damage_taken); REPLICATE_INIT(bool, cvar_cl_noantilag); REPLICATE_INIT(string, cvar_g_xonoticversion); REPLICATE(cvar_cl_autoswitch, bool, "cl_autoswitch"); REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot"); REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating"); REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch"); -REPLICATE(cvar_cl_handicap, float, "cl_handicap"); +REPLICATE(cvar_cl_handicap, vector, "cl_handicap"); +REPLICATE(cvar_cl_handicap_damage_given, float, "cl_handicap_damage_given"); +REPLICATE(cvar_cl_handicap_damage_taken, float, "cl_handicap_damage_taken"); REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag"); REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion"); #endif diff --git a/qcsrc/server/client.qh b/qcsrc/server/client.qh index 9611df4e8..5e9f17ff6 100644 --- a/qcsrc/server/client.qh +++ b/qcsrc/server/client.qh @@ -204,7 +204,8 @@ CLASS(Client, Object) ATTRIB(Client, cvar_cl_pokenade_type, string, this.cvar_cl_pokenade_type); ATTRIB(Client, cvar_cl_spawn_near_teammate, bool, this.cvar_cl_spawn_near_teammate); ATTRIB(Client, cvar_cl_gunalign, int, this.cvar_cl_gunalign); - ATTRIB(Client, cvar_cl_handicap, float, this.cvar_cl_handicap); + ATTRIB(Client, cvar_cl_handicap_damage_given, float, this.cvar_cl_handicap_damage_given); + ATTRIB(Client, cvar_cl_handicap_damage_taken, float, this.cvar_cl_handicap_damage_taken); ATTRIB(Client, cvar_cl_clippedspectating, bool, this.cvar_cl_clippedspectating); ATTRIB(Client, cvar_cl_autoscreenshot, int, this.cvar_cl_autoscreenshot); ATTRIB(Client, cvar_cl_jetpack_jump, bool, this.cvar_cl_jetpack_jump); diff --git a/qcsrc/server/handicap.qc b/qcsrc/server/handicap.qc index ce0d6cd0a..5c03cd11b 100644 --- a/qcsrc/server/handicap.qc +++ b/qcsrc/server/handicap.qc @@ -8,34 +8,83 @@ #include #include -.float m_handicap; ///< Holds the handicap value. +.float m_handicap_give; ///< Holds the forced handicap value. +.float m_handicap_take; ///< Holds the forced handicap value. void Handicap_Initialize(entity player) { - CS(player).m_handicap = 1; + // forced handicap defaults + CS(player).m_handicap_give = 1; + CS(player).m_handicap_take = 1; } -float Handicap_GetVoluntaryHandicap(entity player) +float Handicap_GetVoluntaryHandicap(entity player, bool receiving) { - return bound(1.0, CS_CVAR(player).cvar_cl_handicap, 10.0); +#if 0 + if (receiving) + return bound(1.0, CS_CVAR(player).cvar_cl_handicap_damage_taken, 10.0); + else + return bound(1.0, CS_CVAR(player).cvar_cl_handicap_damage_given, 10.0); +#else + // TODO: remove the else vector branch after 0.9 release + // Forwards compatibility for old clients on new servers. `cl_handicap 2` + // ( '2 0 0' ) is treated the same as `cl_handicap_damage_{given,taken} 2`. + // The x is give and y is take. + // '2 0 0' gives and takes x2 + // '2 2 0' gives and takes x2 + // '2 1 0' only gives x2 + // '1 2 0' only takes x2 + // z is wasted + + int handicap_value; + + // First read if the new cvars have a valid value, + // if they don't then read old cvar, checking if the old cvar has + // separate give and take values or we should use the first value for both + if (receiving) + { + if (CS_CVAR(player).cvar_cl_handicap_damage_taken > 1) + handicap_value = CS_CVAR(player).cvar_cl_handicap_damage_taken; + else if (CS_CVAR(player).cvar_cl_handicap.y > 0) + handicap_value = CS_CVAR(player).cvar_cl_handicap.y; + else + handicap_value = CS_CVAR(player).cvar_cl_handicap.x; + } + else + { + if (CS_CVAR(player).cvar_cl_handicap_damage_given > 1) + handicap_value = CS_CVAR(player).cvar_cl_handicap_damage_given; + else + handicap_value = CS_CVAR(player).cvar_cl_handicap.x; + } + + return bound(1.0, handicap_value, 10.0); +#endif + } -float Handicap_GetForcedHandicap(entity player) +float Handicap_GetForcedHandicap(entity player, bool receiving) { - return (CS(player)) ? CS(player).m_handicap : 1; + if (receiving) + return (CS(player)) ? CS(player).m_handicap_take : 1; + else + return (CS(player)) ? CS(player).m_handicap_give : 1; + } -void Handicap_SetForcedHandicap(entity player, float value) +void Handicap_SetForcedHandicap(entity player, float value, bool receiving) { if (value <= 0) - { error("Handicap_SetForcedHandicap: Invalid handicap value."); - } - CS(player).m_handicap = value; + + if (receiving) + CS(player).m_handicap_take = value; + else + CS(player).m_handicap_give = value; } -float Handicap_GetTotalHandicap(entity player) +float Handicap_GetTotalHandicap(entity player, bool receiving) { - return Handicap_GetForcedHandicap(player) * Handicap_GetVoluntaryHandicap( - player); + return Handicap_GetForcedHandicap(player, receiving) * + Handicap_GetVoluntaryHandicap(player, receiving); } diff --git a/qcsrc/server/handicap.qh b/qcsrc/server/handicap.qh index fa45a0ed0..48129ed5c 100644 --- a/qcsrc/server/handicap.qh +++ b/qcsrc/server/handicap.qh @@ -9,9 +9,12 @@ // weak players. Values greater than 1 make the game harder and values less than // 1 make the game easier. Right now handicap only affects damage. There are 2 // types of handicap: voluntary and forced. Voluntary handicap can be set via -// cl_handicap cvar. For obvious reasons, it can't be less than 1. Forced +// cl_handicap cvars. For obvious reasons, it can't be less than 1. Forced // handicap can be set by server mutators. The total handicap is the product of // voluntary and forced handicap. +// Both handicaps are separated into _take and _give so that mutators and +// players are able to nerf their damage output or increase intake +// without changing the other. /// \brief Initializes handicap to its default value. /// \param[in,out] player Player to initialize. @@ -20,21 +23,25 @@ void Handicap_Initialize(entity player); /// \brief Returns the voluntary handicap of the player. /// \param[in] player Player to check. +/// \param[in] receiving Whether handicap is for receiving or dealing. /// \return Voluntary handicap of the player. -float Handicap_GetVoluntaryHandicap(entity player); +float Handicap_GetVoluntaryHandicap(entity player, bool receiving); /// \brief Returns the forced handicap of the player. /// \param[in] player Player to check. +/// \param[in] receiving Whether handicap is for receiving or dealing. /// \return Forced handicap of the player. -float Handicap_GetForcedHandicap(entity player); +float Handicap_GetForcedHandicap(entity player, bool receiving); /// \brief Sets the forced handicap of the player. /// \param[in] player Player to alter. /// \param[in] value Handicap value to set. +/// \param[in] receiving Whether handicap is for receiving or dealing. /// \return No return. -void Handicap_SetForcedHandicap(entity player, float value); +void Handicap_SetForcedHandicap(entity player, float value, bool receiving); /// \brief Returns the total handicap of the player. /// \param[in] player Player to check. +/// \param[in] receiving Whether handicap is for receiving or dealing. /// \return Total handicap of the player. -float Handicap_GetTotalHandicap(entity player); +float Handicap_GetTotalHandicap(entity player, bool receiving); diff --git a/qcsrc/server/player.qc b/qcsrc/server/player.qc index 3ca1bbc1b..a9ae47eb1 100644 --- a/qcsrc/server/player.qc +++ b/qcsrc/server/player.qc @@ -238,10 +238,10 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, { if(!DEATH_ISSPECIAL(deathtype)) { - damage *= Handicap_GetTotalHandicap(this); + damage *= Handicap_GetTotalHandicap(this, true); if (this != attacker && IS_PLAYER(attacker)) { - damage /= Handicap_GetTotalHandicap(attacker); + damage /= Handicap_GetTotalHandicap(attacker, false); } } diff --git a/xonotic-client.cfg b/xonotic-client.cfg index 666a06538..cfd3e0747 100644 --- a/xonotic-client.cfg +++ b/xonotic-client.cfg @@ -689,7 +689,11 @@ alias _gl_flashblend_update_01 "gl_flashblend 0" alias _gl_flashblend_update_11 "gl_flashblend 0" alias gl_flashblend_update "_gl_flashblend_update_$r_shadow_realtime_dlight$r_showsurfaces" -set cl_handicap 1 "multiplies damage received and divides damage dealt" +// TODO: remove cl_handicap cvar after 0.9 release +set cl_handicap 1 "multiplies damage received and divides damage dealt" +alias cl_handicap "cl_handicap_damage_given ${* ?} ; cl_handicap_damage_taken ${* ?} ; set cl_handicap ${* ?}" +set cl_handicap_damage_given 1 "damage given is divided by this factor if > 1" +set cl_handicap_damage_taken 1 "damage taken is multiplied by this factor if > 1" seta cl_clippedspectating 1 "movement collision for spectators so that you can't pass through walls and such" -- 2.39.2