From 620e5c35f05bb1bc37848f1cf411dc2e8e4b8320 Mon Sep 17 00:00:00 2001 From: Lyberta Date: Mon, 4 Sep 2017 17:33:31 +0300 Subject: [PATCH] Added Dynamic handicap. --- mutators.cfg | 8 + qcsrc/common/mutators/mutator/_mod.inc | 1 + qcsrc/common/mutators/mutator/_mod.qh | 1 + .../mutator/dynamic_handicap/_mod.inc | 4 + .../mutators/mutator/dynamic_handicap/_mod.qh | 4 + .../dynamic_handicap/sv_dynamic_handicap.qc | 166 ++++++++++++++++++ .../dynamic_handicap/sv_dynamic_handicap.qh | 0 7 files changed, 184 insertions(+) create mode 100644 qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc create mode 100644 qcsrc/common/mutators/mutator/dynamic_handicap/_mod.qh create mode 100644 qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc create mode 100644 qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qh diff --git a/mutators.cfg b/mutators.cfg index 5eb8d1b9d..31d51f11a 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -464,3 +464,11 @@ set g_bugrigs_steer 1 "steering amount" // running guns // ============== set g_running_guns 0 "... or wonder, till it drives you mad, what would have followed if you had." + +// ================== +// dynamic handicap +// ================== +set g_dynamic_handicap 0 "Whether to enable dynamic handicap." +set g_dynamic_handicap_scale 1 "The scale of the handicap. Larget values mean more penalties for strong players and more buffs for weak players." +set g_dynamic_handicap_min 0 "The minimum value of the handicap." +set g_dynamic_handicap_max 0 "The maximum value of the handicap." diff --git a/qcsrc/common/mutators/mutator/_mod.inc b/qcsrc/common/mutators/mutator/_mod.inc index 0d6326fef..eeb93ba5e 100644 --- a/qcsrc/common/mutators/mutator/_mod.inc +++ b/qcsrc/common/mutators/mutator/_mod.inc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/common/mutators/mutator/_mod.qh b/qcsrc/common/mutators/mutator/_mod.qh index 917dc6557..956c0d975 100644 --- a/qcsrc/common/mutators/mutator/_mod.qh +++ b/qcsrc/common/mutators/mutator/_mod.qh @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc b/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc new file mode 100644 index 000000000..f4b0a30cd --- /dev/null +++ b/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc @@ -0,0 +1,4 @@ +// generated file; do not modify +#ifdef SVQC + #include +#endif diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.qh b/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.qh new file mode 100644 index 000000000..10aeb2243 --- /dev/null +++ b/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.qh @@ -0,0 +1,4 @@ +// generated file; do not modify +#ifdef SVQC + #include +#endif diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc b/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc new file mode 100644 index 000000000..43f10fd2c --- /dev/null +++ b/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc @@ -0,0 +1,166 @@ +/// \file +/// \brief Source file that contains implementation of the Dynamic handicap +/// mutator. +/// \author Lyberta +/// \copyright GNU GPLv2 or any later version. + +//======================= Global variables ==================================== + +int autocvar_g_dynamic_handicap; ///< Whether to enable dynamic handicap. +/// \brief The scale of the handicap. Larget values mean more penalties for +/// strong players and more buffs for weak players. +float autocvar_g_dynamic_handicap_scale; +float autocvar_g_dynamic_handicap_min; ///< The minimum value of the handicap. +float autocvar_g_dynamic_handicap_max; ///< The maximum value of the handicap. + +.float dynamic_handicap; ///< Holds the dynamic handicap value. + +//====================== Forward declarations ================================= + +/// \brief Returns the base value of the handicap. +/// \param[in] player Player to evaluate. +/// \return Base handicap value. +float DynamicHandicap_GetBaseValue(entity player); + +/// \brief Scales the base value of the handicap. +/// \param[in] handicap Value to scale. +/// \return Scaled value. +float DynamicHandicap_ScaleHandicap(float handicap); + +/// \brief Clamps the value of the handicap. +/// \param[in] handicap Value to clamp. +/// \return Clamped value. +float DynamicHandicap_ClampHandicap(float handicap); + +//========================= Free functions ==================================== + +/// \brief Updates the handicap of a given player. +/// \param[in,out] player Player to update. +/// \return No return. +void DynamicHandicap_UpdateHandicap(entity player) +{ + float handicap = DynamicHandicap_GetBaseValue(player); + //PrintToChat(player, strcat("Base handicap = ", ftos(handicap))); + handicap = DynamicHandicap_ScaleHandicap(handicap); + //PrintToChat(player, strcat("Scaled handicap = ", ftos(handicap))); + player.dynamic_handicap = DynamicHandicap_ClampHandicap(handicap); + //PrintToChat(player, strcat("Clamped handicap = ", + // ftos(player.dynamic_handicap))); +} + +float DynamicHandicap_GetBaseValue(entity player) +{ + int kills = PlayerScore_Get(player, SP_KILLS); + int deaths = PlayerScore_Get(player, SP_DEATHS); + if (kills == deaths) + { + return 1; + } + if (deaths == 0) + { + return kills; + } + if (kills == 0) + { + return 1 / deaths; + } + return kills / deaths; +} + +float DynamicHandicap_ScaleHandicap(float handicap) +{ + if (handicap == 1) + { + return 1; + } + if (autocvar_g_dynamic_handicap_scale == 1) + { + return handicap; + } + if (handicap > 1) + { + handicap -= 1; + handicap *= autocvar_g_dynamic_handicap_scale; + return handicap + 1; + } + if (handicap < 1) + { + handicap = 1 / handicap; + handicap -= 1; + handicap *= autocvar_g_dynamic_handicap_scale; + handicap += 1; + return 1 / handicap; + } + return 1; +} + +float DynamicHandicap_ClampHandicap(float handicap) +{ + if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap < + autocvar_g_dynamic_handicap_min)) + { + handicap = autocvar_g_dynamic_handicap_min; + } + if ((autocvar_g_dynamic_handicap_max > 0) && (handicap > + autocvar_g_dynamic_handicap_max)) + { + handicap = autocvar_g_dynamic_handicap_max; + } + return handicap; +} + +//============================= Hooks ======================================== + +REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap); + +MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString) +{ + M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap"); +} + +MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString) +{ + M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap"); +} + +/// \brief Hook that is called when player connects to the server. +MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientConnect) +{ + entity player = M_ARGV(0, entity); + DynamicHandicap_UpdateHandicap(player); +} + +/// \brief Hook which is called when the damage amount must be determined. +MUTATOR_HOOKFUNCTION(dynamic_handicap, Damage_Calculate) +{ + entity frag_attacker = M_ARGV(1, entity); + entity frag_target = M_ARGV(2, entity); + float deathtype = M_ARGV(3, float); + float damage = M_ARGV(4, float); + if (DEATH_ISSPECIAL(deathtype)) + { + return; + } + if (IS_CLIENT(frag_attacker)) + { + damage /= frag_attacker.dynamic_handicap; + } + if (IS_CLIENT(frag_target)) + { + damage *= frag_target.dynamic_handicap; + } + M_ARGV(4, float) = damage; +} + +/// \brief Hook that is called when player dies. +MUTATOR_HOOKFUNCTION(dynamic_handicap, PlayerDies) +{ + entity attacker = M_ARGV(1, entity); + entity victim = M_ARGV(2, entity); + DynamicHandicap_UpdateHandicap(victim); + if (!IS_CLIENT(attacker)) + { + return; + } + DynamicHandicap_UpdateHandicap(attacker); +} diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qh b/qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qh new file mode 100644 index 000000000..e69de29bb -- 2.39.2