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