]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/dynamic_handicap/sv_dynamic_handicap.qc
Added handicap API.
[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         //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);
47 }
48
49 float DynamicHandicap_GetBaseValue(entity player)
50 {
51         int kills = PlayerScore_Get(player, SP_KILLS);
52         int deaths = PlayerScore_Get(player, SP_DEATHS);
53         if (kills == deaths)
54         {
55                 return 1;
56         }
57         if (deaths == 0)
58         {
59                 return kills;
60         }
61         if (kills == 0)
62         {
63                 return 1 / deaths;
64         }
65         return kills / deaths;
66 }
67
68 float DynamicHandicap_ScaleHandicap(float handicap)
69 {
70         if (handicap == 1)
71         {
72                 return 1;
73         }
74         if (autocvar_g_dynamic_handicap_scale == 1)
75         {
76                 return handicap;
77         }
78         if (handicap > 1)
79         {
80                 handicap -= 1;
81                 handicap *= autocvar_g_dynamic_handicap_scale;
82                 return handicap + 1;
83         }
84         if (handicap < 1)
85         {
86                 handicap = 1 / handicap;
87                 handicap -= 1;
88                 handicap *= autocvar_g_dynamic_handicap_scale;
89                 handicap += 1;
90                 return 1 / handicap;
91         }
92         return 1;
93 }
94
95 float DynamicHandicap_ClampHandicap(float handicap)
96 {
97         if ((autocvar_g_dynamic_handicap_min >= 0) && (handicap <
98                 autocvar_g_dynamic_handicap_min))
99         {
100                 handicap = autocvar_g_dynamic_handicap_min;
101         }
102         if ((autocvar_g_dynamic_handicap_max > 0) && (handicap >
103                 autocvar_g_dynamic_handicap_max))
104         {
105                 handicap = autocvar_g_dynamic_handicap_max;
106         }
107         return handicap;
108 }
109
110 //============================= Hooks ========================================
111
112 REGISTER_MUTATOR(dynamic_handicap, autocvar_g_dynamic_handicap);
113
114 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsString)
115 {
116         M_ARGV(0, string) = strcat(M_ARGV(0, string), ":handicap");
117 }
118
119 MUTATOR_HOOKFUNCTION(dynamic_handicap, BuildMutatorsPrettyString)
120 {
121         M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Dynamic handicap");
122 }
123
124 /// \brief Hook that is called when player connects to the server.
125 MUTATOR_HOOKFUNCTION(dynamic_handicap, ClientConnect)
126 {
127         entity player = M_ARGV(0, entity);
128         DynamicHandicap_UpdateHandicap(player);
129 }
130
131 /// \brief Hook that is called when player dies.
132 MUTATOR_HOOKFUNCTION(dynamic_handicap, PlayerDies)
133 {
134         entity attacker = M_ARGV(1, entity);
135         entity victim = M_ARGV(2, entity);
136         DynamicHandicap_UpdateHandicap(victim);
137         if (!IS_CLIENT(attacker))
138         {
139                 return;
140         }
141         DynamicHandicap_UpdateHandicap(attacker);
142 }