1 #include "sv_dynamic_handicap.qh"
3 /// \brief Source file that contains implementation of the Dynamic handicap
6 /// \copyright GNU GPLv2 or any later version.
8 //======================= Global variables ====================================
10 int autocvar_g_dynamic_handicap; ///< Whether to enable dynamic handicap.
11 /// \brief The scale of the handicap. Larget values mean more penalties for
12 /// strong players and more buffs for weak players.
13 float autocvar_g_dynamic_handicap_scale;
14 /// \brief The exponent used to calculate handicap. 1 means linear scale. Values
15 /// more than 1 mean stronger non-linear handicap. Values less than 1 mean
16 /// weaker non-linear handicap.
17 float autocvar_g_dynamic_handicap_exponent;
18 float autocvar_g_dynamic_handicap_min; ///< The minimum value of the handicap.
19 float autocvar_g_dynamic_handicap_max; ///< The maximum value of the handicap.
21 //====================== Forward declarations =================================
23 /// \brief Clamps the value of the handicap.
24 /// \param[in] handicap Value to clamp.
25 /// \return Clamped value.
26 float DynamicHandicap_ClampHandicap(float handicap);
28 //========================= Free functions ====================================
30 /// \brief Updates the handicap of all players.
31 /// \return No return.
32 void DynamicHandicap_UpdateHandicap()
34 float total_score = 0;
35 float total_players = 0;
36 FOREACH_CLIENT(IS_PLAYER(it),
38 total_score += PlayerScore_Get(it, SP_SCORE);
41 float mean_score = total_score / total_players;
44 float score = PlayerScore_Get(it, SP_SCORE);
45 float handicap = fabs((score - mean_score) *
46 autocvar_g_dynamic_handicap_scale);
47 handicap = handicap ** autocvar_g_dynamic_handicap_exponent;
48 if (score < mean_score)
58 handicap = 1 / (fabs(handicap) + 1);
60 handicap = DynamicHandicap_ClampHandicap(handicap);
61 Handicap_SetForcedHandicap(it, handicap);
65 float DynamicHandicap_ClampHandicap(float handicap)
67 if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap <
68 autocvar_g_dynamic_handicap_min))
70 handicap = autocvar_g_dynamic_handicap_min;
72 if ((autocvar_g_dynamic_handicap_max > 0) && (handicap >
73 autocvar_g_dynamic_handicap_max))
75 handicap = autocvar_g_dynamic_handicap_max;
80 //============================= Hooks ========================================
82 REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap);
84 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString)
86 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap");
89 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString)
91 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap");
94 MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientDisconnect)
96 DynamicHandicap_UpdateHandicap();
99 MUTATOR_HOOKFUNCTION(dynamic_handicap, PutClientInServer)
101 DynamicHandicap_UpdateHandicap();
104 MUTATOR_HOOKFUNCTION(dynamic_handicap, MakePlayerObserver)
106 DynamicHandicap_UpdateHandicap();
109 MUTATOR_HOOKFUNCTION(dynamic_handicap, AddedPlayerScore)
111 if (M_ARGV(0, entity) != SP_SCORE)
115 DynamicHandicap_UpdateHandicap();