2 /// \brief Source file that contains implementation of the Dynamic handicap
5 /// \copyright GNU GPLv2 or any later version.
7 //======================= Global variables ====================================
9 int autocvar_g_dynamic_handicap; ///< Whether to enable dynamic handicap.
10 /// \brief The scale of the handicap. Larget values mean more penalties for
11 /// strong players and more buffs for weak players.
12 float autocvar_g_dynamic_handicap_scale;
13 float autocvar_g_dynamic_handicap_min; ///< The minimum value of the handicap.
14 float autocvar_g_dynamic_handicap_max; ///< The maximum value of the handicap.
16 //====================== Forward declarations =================================
18 /// \brief Returns the base value of the handicap.
19 /// \param[in] player Player to evaluate.
20 /// \return Base handicap value.
21 float DynamicHandicap_GetBaseValue(entity player);
23 /// \brief Scales the base value of the handicap.
24 /// \param[in] handicap Value to scale.
25 /// \return Scaled value.
26 float DynamicHandicap_ScaleHandicap(float handicap);
28 /// \brief Clamps the value of the handicap.
29 /// \param[in] handicap Value to clamp.
30 /// \return Clamped value.
31 float DynamicHandicap_ClampHandicap(float handicap);
33 //========================= Free functions ====================================
35 /// \brief Updates the handicap of a given player.
36 /// \param[in,out] player Player to update.
37 /// \return No return.
38 void DynamicHandicap_UpdateHandicap(entity player)
40 float handicap = DynamicHandicap_GetBaseValue(player);
41 //PrintToChat(player, strcat("Base handicap = ", ftos(handicap)));
42 handicap = DynamicHandicap_ScaleHandicap(handicap);
43 //PrintToChat(player, strcat("Scaled handicap = ", ftos(handicap)));
44 handicap = DynamicHandicap_ClampHandicap(handicap);
45 //PrintToChat(player, strcat("Clamped handicap = ", ftos(handicap)));
46 Handicap_SetForcedHandicap(player, handicap);
49 float DynamicHandicap_GetBaseValue(entity player)
51 int kills = PlayerScore_Get(player, SP_KILLS);
52 int deaths = PlayerScore_Get(player, SP_DEATHS);
65 return kills / deaths;
68 float DynamicHandicap_ScaleHandicap(float handicap)
74 if (autocvar_g_dynamic_handicap_scale == 1)
81 handicap *= autocvar_g_dynamic_handicap_scale;
86 handicap = 1 / handicap;
88 handicap *= autocvar_g_dynamic_handicap_scale;
95 float DynamicHandicap_ClampHandicap(float handicap)
97 if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap <
98 autocvar_g_dynamic_handicap_min))
100 handicap = autocvar_g_dynamic_handicap_min;
102 if ((autocvar_g_dynamic_handicap_max > 0) && (handicap >
103 autocvar_g_dynamic_handicap_max))
105 handicap = autocvar_g_dynamic_handicap_max;
110 //============================= Hooks ========================================
112 REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap);
114 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString)
116 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap");
119 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString)
121 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap");
124 /// \brief Hook that is called when player connects to the server.
125 MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientConnect)
127 entity player = M_ARGV(0, entity);
128 DynamicHandicap_UpdateHandicap(player);
131 /// \brief Hook that is called when player dies.
132 MUTATOR_HOOKFUNCTION(dynamic_handicap, PlayerDies)
134 entity attacker = M_ARGV(1, entity);
135 entity victim = M_ARGV(2, entity);
136 DynamicHandicap_UpdateHandicap(victim);
137 if (!IS_CLIENT(attacker))
141 DynamicHandicap_UpdateHandicap(attacker);