]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc
Merge branch 'Lyberta/DynamicHandicap' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / dynamic_handicap / sv_dynamic_handicap.qc
1 /// \file
2 /// \brief Source file that contains implementation of the Dynamic handicap
3 /// mutator.
4 /// \author Lyberta
5 /// \copyright GNU GPLv2 or any later version.
6
7 //======================= Global variables ====================================
8
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.
15
16 //====================== Forward declarations =================================
17
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);
22
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);
27
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);
32
33 //========================= Free functions ====================================
34
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)
39 {
40         float handicap = DynamicHandicap_GetBaseValue(player);
41         handicap = DynamicHandicap_ScaleHandicap(handicap);
42         handicap = DynamicHandicap_ClampHandicap(handicap);
43         Handicap_SetForcedHandicap(player, handicap);
44 }
45
46 float DynamicHandicap_GetBaseValue(entity player)
47 {
48         int kills = PlayerScore_Get(player, SP_KILLS);
49         int deaths = PlayerScore_Get(player, SP_DEATHS);
50         if (kills == deaths)
51         {
52                 return 1;
53         }
54         if (deaths == 0)
55         {
56                 return kills;
57         }
58         if (kills == 0)
59         {
60                 return 1 / deaths;
61         }
62         return kills / deaths;
63 }
64
65 float DynamicHandicap_ScaleHandicap(float handicap)
66 {
67         if (handicap == 1)
68         {
69                 return 1;
70         }
71         if (autocvar_g_dynamic_handicap_scale == 1)
72         {
73                 return handicap;
74         }
75         if (handicap > 1)
76         {
77                 handicap -= 1;
78                 handicap *= autocvar_g_dynamic_handicap_scale;
79                 return handicap + 1;
80         }
81         if (handicap < 1)
82         {
83                 handicap = 1 / handicap;
84                 handicap -= 1;
85                 handicap *= autocvar_g_dynamic_handicap_scale;
86                 handicap += 1;
87                 return 1 / handicap;
88         }
89         return 1;
90 }
91
92 float DynamicHandicap_ClampHandicap(float handicap)
93 {
94         if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap <
95                 autocvar_g_dynamic_handicap_min))
96         {
97                 handicap = autocvar_g_dynamic_handicap_min;
98         }
99         if ((autocvar_g_dynamic_handicap_max > 0) && (handicap >
100                 autocvar_g_dynamic_handicap_max))
101         {
102                 handicap = autocvar_g_dynamic_handicap_max;
103         }
104         return handicap;
105 }
106
107 //============================= Hooks ========================================
108
109 REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap);
110
111 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString)
112 {
113         M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap");
114 }
115
116 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString)
117 {
118         M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap");
119 }
120
121 /// \brief Hook that is called when player connects to the server.
122 MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientConnect)
123 {
124         entity player = M_ARGV(0, entity);
125         DynamicHandicap_UpdateHandicap(player);
126 }
127
128 /// \brief Hook that is called when player dies.
129 MUTATOR_HOOKFUNCTION(dynamic_handicap, PlayerDies)
130 {
131         entity attacker = M_ARGV(1, entity);
132         entity victim = M_ARGV(2, entity);
133         DynamicHandicap_UpdateHandicap(victim);
134         if (!IS_CLIENT(attacker))
135         {
136                 return;
137         }
138         DynamicHandicap_UpdateHandicap(attacker);
139 }