]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Lyberta/DynamicHandicap' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 16 Sep 2017 03:20:32 +0000 (03:20 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 16 Sep 2017 03:20:32 +0000 (03:20 +0000)
Dynamic handicap.

See merge request xonotic/xonotic-data.pk3dir!485

12 files changed:
mutators.cfg
qcsrc/common/mutators/mutator/_mod.inc
qcsrc/common/mutators/mutator/_mod.qh
qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc [new file with mode: 0644]
qcsrc/common/mutators/mutator/dynamic_handicap/_mod.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc [new file with mode: 0644]
qcsrc/server/_mod.inc
qcsrc/server/_mod.qh
qcsrc/server/client.qc
qcsrc/server/handicap.qc [new file with mode: 0644]
qcsrc/server/handicap.qh [new file with mode: 0644]
qcsrc/server/player.qc

index 5eb8d1b9d6dae7d806a64bc55c8771535fd42efa..be74e81872eb3c64a85325789450a6ef686bf159 100644 (file)
@@ -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. Larger 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."
index 0d6326fef0712b405f0ad88a856c27a61ef646ab..eeb93ba5e83f7cb9252274e397c994bf9e93a73e 100644 (file)
@@ -9,6 +9,7 @@
 #include <common/mutators/mutator/damagetext/_mod.inc>
 #include <common/mutators/mutator/dodging/_mod.inc>
 #include <common/mutators/mutator/doublejump/_mod.inc>
+#include <common/mutators/mutator/dynamic_handicap/_mod.inc>
 #include <common/mutators/mutator/globalforces/_mod.inc>
 #include <common/mutators/mutator/hook/_mod.inc>
 #include <common/mutators/mutator/instagib/_mod.inc>
index 917dc6557ceb02b2415649bc6d9546e6a400c9c6..956c0d97536fbfeaddc4d4b8b1728ce147d09bc5 100644 (file)
@@ -9,6 +9,7 @@
 #include <common/mutators/mutator/damagetext/_mod.qh>
 #include <common/mutators/mutator/dodging/_mod.qh>
 #include <common/mutators/mutator/doublejump/_mod.qh>
+#include <common/mutators/mutator/dynamic_handicap/_mod.qh>
 #include <common/mutators/mutator/globalforces/_mod.qh>
 #include <common/mutators/mutator/hook/_mod.qh>
 #include <common/mutators/mutator/instagib/_mod.qh>
diff --git a/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc b/qcsrc/common/mutators/mutator/dynamic_handicap/_mod.inc
new file mode 100644 (file)
index 0000000..f4b0a30
--- /dev/null
@@ -0,0 +1,4 @@
+// generated file; do not modify
+#ifdef SVQC
+    #include <common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc>
+#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 (file)
index 0000000..98fb481
--- /dev/null
@@ -0,0 +1 @@
+// generated file; do not modify
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 (file)
index 0000000..5549085
--- /dev/null
@@ -0,0 +1,139 @@
+/// \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.
+
+//====================== 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);
+       handicap = DynamicHandicap_ScaleHandicap(handicap);
+       handicap = DynamicHandicap_ClampHandicap(handicap);
+       Handicap_SetForcedHandicap(player, 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 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);
+}
index 99115fbdc4fcaa48d2b3b33f8aca6458d530d718..de7e01aa7a862d3f328d0c02a3fdd542e5238ad9 100644 (file)
@@ -10,6 +10,7 @@
 #include <server/g_models.qc>
 #include <server/g_subs.qc>
 #include <server/g_world.qc>
+#include <server/handicap.qc>
 #include <server/impulse.qc>
 #include <server/ipban.qc>
 #include <server/item_key.qc>
index 3a8898670354511f40a1e515d25aeae0d5b28068..67f6aae4db511fd7cb1b91cb1cdb7412c7f017ea 100644 (file)
@@ -10,6 +10,7 @@
 #include <server/g_models.qh>
 #include <server/g_subs.qh>
 #include <server/g_world.qh>
+#include <server/handicap.qh>
 #include <server/impulse.qh>
 #include <server/ipban.qh>
 #include <server/item_key.qh>
index 52a376b0a5990f56366caa3872406c5a18f92bd8..7acd7bb5eaeac4c6b4540b6e689752ffa4c7f088 100644 (file)
@@ -14,6 +14,7 @@
 #include "spawnpoints.qh"
 #include "resources.qh"
 #include "g_damage.qh"
+#include "handicap.qh"
 #include "g_hook.qh"
 #include "command/common.qh"
 #include "cheats.qh"
@@ -1283,6 +1284,8 @@ void ClientConnect(entity this)
                it.init_for_player(it, this);
        });
 
+       Handicap_Initialize(this);
+
        MUTATOR_CALLHOOK(ClientConnect, this);
 
        if (IS_REAL_CLIENT(this))
diff --git a/qcsrc/server/handicap.qc b/qcsrc/server/handicap.qc
new file mode 100644 (file)
index 0000000..d0dfc4d
--- /dev/null
@@ -0,0 +1,41 @@
+#include "handicap.qh"
+
+/// \file
+/// \brief Source file that contains implementation of the handicap system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+#include <common/state.qh>
+#include "client.qh"
+
+.float m_handicap; ///< Holds the handicap value.
+
+void Handicap_Initialize(entity player)
+{
+       CS(player).m_handicap = 1;
+}
+
+float Handicap_GetVoluntaryHandicap(entity player)
+{
+       return bound(1.0, CS(player).cvar_cl_handicap, 10.0);
+}
+
+float Handicap_GetForcedHandicap(entity player)
+{
+       return CS(player).m_handicap;
+}
+
+void Handicap_SetForcedHandicap(entity player, float value)
+{
+       if (value <= 0)
+       {
+               error("Handicap_SetForcedHandicap: Invalid handicap value.");
+       }
+       CS(player).m_handicap = value;
+}
+
+float Handicap_GetTotalHandicap(entity player)
+{
+       return Handicap_GetForcedHandicap(player) * Handicap_GetVoluntaryHandicap(
+               player);
+}
diff --git a/qcsrc/server/handicap.qh b/qcsrc/server/handicap.qh
new file mode 100644 (file)
index 0000000..fa45a0e
--- /dev/null
@@ -0,0 +1,40 @@
+#pragma once
+
+/// \file
+/// \brief Header file that describes the handicap system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+// Handicap is used to make the game harder for strong players and easier for
+// 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
+// handicap can be set by server mutators. The total handicap is the product of
+// voluntary and forced handicap.
+
+/// \brief Initializes handicap to its default value.
+/// \param[in,out] player Player to initialize.
+/// \return No return.
+void Handicap_Initialize(entity player);
+
+/// \brief Returns the voluntary handicap of the player.
+/// \param[in] player Player to check.
+/// \return Voluntary handicap of the player.
+float Handicap_GetVoluntaryHandicap(entity player);
+
+/// \brief Returns the forced handicap of the player.
+/// \param[in] player Player to check.
+/// \return Forced handicap of the player.
+float Handicap_GetForcedHandicap(entity player);
+
+/// \brief Sets the forced handicap of the player.
+/// \param[in] player Player to alter.
+/// \param[in] value Handicap value to set.
+/// \return No return.
+void Handicap_SetForcedHandicap(entity player, float value);
+
+/// \brief Returns the total handicap of the player.
+/// \param[in] player Player to check.
+/// \return Total handicap of the player.
+float Handicap_GetTotalHandicap(entity player);
index dd061526265c12501deb2add452d694b5b7752be..d9226f3437e351bec049ea26b5747b333f2530ad 100644 (file)
@@ -4,6 +4,7 @@
 #include "bot/api.qh"
 #include "cheats.qh"
 #include "g_damage.qh"
+#include "handicap.qh"
 #include "g_subs.qh"
 #include "miscfunctions.qh"
 #include "portals.qh"
@@ -317,9 +318,11 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
        if(!DEATH_ISSPECIAL(deathtype))
        {
-               damage *= bound(1.0, CS(this).cvar_cl_handicap, 10.0);
-               if(this != attacker && IS_PLAYER(attacker))
-                       damage /= bound(1.0, CS(attacker).cvar_cl_handicap, 10.0);
+               damage *= Handicap_GetTotalHandicap(this);
+               if (this != attacker && IS_PLAYER(attacker))
+               {
+                       damage /= Handicap_GetTotalHandicap(attacker);
+               }
        }
 
        if (time < this.spawnshieldtime && autocvar_g_spawnshield_blockdamage < 1)