]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/resources.qc
Don't count non-client attackers as valid for accuracy
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / resources.qc
1 #include "resources.qh"
2
3 /// \file
4 /// \brief Source file that contains implementation of the resource system.
5 /// \author Lyberta
6 /// \copyright GNU GPLv2 or any later version.
7
8 #include "autocvars.qh"
9 #include "miscfunctions.qh"
10
11 float GetResourceLimit(entity e, int resource_type)
12 {
13         if(!IS_PLAYER(e))
14                 return RESOURCE_LIMIT_NONE; // no limits on non-players
15
16         float limit;
17         switch (resource_type)
18         {
19                 case RESOURCE_HEALTH:
20                 {
21                         limit = autocvar_g_balance_health_limit;
22                         break;
23                 }
24                 case RESOURCE_ARMOR:
25                 {
26                         limit = autocvar_g_balance_armor_limit;
27                         break;
28                 }
29                 case RESOURCE_SHELLS:
30                 {
31                         limit = g_pickup_shells_max;
32                         break;
33                 }
34                 case RESOURCE_BULLETS:
35                 {
36                         limit = g_pickup_nails_max;
37                         break;
38                 }
39                 case RESOURCE_ROCKETS:
40                 {
41                         limit = g_pickup_rockets_max;
42                         break;
43                 }
44                 case RESOURCE_CELLS:
45                 {
46                         limit = g_pickup_cells_max;
47                         break;
48                 }
49                 case RESOURCE_PLASMA:
50                 {
51                         limit = g_pickup_plasma_max;
52                         break;
53                 }
54                 case RESOURCE_FUEL:
55                 {
56                         limit = autocvar_g_balance_fuel_limit;
57                         break;
58                 }
59                 default:
60                 {
61                         error("GetResourceLimit: Invalid resource type.");
62                         return 0;
63                 }
64         }
65         MUTATOR_CALLHOOK(GetResourceLimit, e, resource_type, limit);
66         limit = M_ARGV(2, float);
67         if (limit > RESOURCE_AMOUNT_HARD_LIMIT)
68         {
69                 limit = RESOURCE_AMOUNT_HARD_LIMIT;
70         }
71         return limit;
72 }
73
74 float GetResourceAmount(entity e, int resource_type)
75 {
76         .float resource_field = GetResourceField(resource_type);
77         return e.(resource_field);
78 }
79
80 bool SetResourceAmountExplicit(entity e, int resource_type, float amount)
81 {
82         .float resource_field = GetResourceField(resource_type);
83         if (e.(resource_field) != amount)
84         {
85                 e.(resource_field) = amount;
86                 return true;
87         }
88         return false;
89 }
90
91 void SetResourceAmount(entity e, int resource_type, float amount)
92 {
93         bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, resource_type, amount);
94         if (forbid)
95         {
96                 return;
97         }
98         resource_type = M_ARGV(1, int);
99         amount = M_ARGV(2, float);
100         float max_amount = GetResourceLimit(e, resource_type); // TODO: should allow overriding these limits if cheats are enabled!
101         float amount_wasted = 0;
102         if (amount > max_amount && max_amount != RESOURCE_LIMIT_NONE)
103         {
104                 amount_wasted = amount - max_amount;
105                 amount = max_amount;
106         }
107         bool changed = SetResourceAmountExplicit(e, resource_type, amount);
108         if (changed)
109         {
110                 MUTATOR_CALLHOOK(ResourceAmountChanged, e, resource_type, amount);
111         }
112         if (amount_wasted == 0)
113         {
114                 return;
115         }
116         MUTATOR_CALLHOOK(ResourceWasted, e, resource_type, amount_wasted);
117 }
118
119 void GiveResource(entity receiver, int resource_type, float amount)
120 {
121         if (amount <= 0)
122         {
123                 return;
124         }
125         bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, resource_type,
126                 amount);
127         if (forbid)
128         {
129                 return;
130         }
131         resource_type = M_ARGV(1, int);
132         amount = M_ARGV(2, float);
133         if (amount <= 0)
134         {
135                 return;
136         }
137         SetResourceAmount(receiver, resource_type,
138                 GetResourceAmount(receiver, resource_type) + amount);
139         switch (resource_type)
140         {
141                 case RESOURCE_HEALTH:
142                 {
143                         receiver.pauserothealth_finished =
144                                 max(receiver.pauserothealth_finished, time +
145                                 autocvar_g_balance_pause_health_rot);
146                         return;
147                 }
148                 case RESOURCE_ARMOR:
149                 {
150                         receiver.pauserotarmor_finished =
151                                 max(receiver.pauserotarmor_finished, time +
152                                 autocvar_g_balance_pause_armor_rot);
153                         return;
154                 }
155                 case RESOURCE_FUEL:
156                 {
157                         receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
158                                 time + autocvar_g_balance_pause_fuel_rot);
159                         return;
160                 }
161         }
162 }
163
164 void GiveResourceWithLimit(entity receiver, int resource_type, float amount,
165         float limit)
166 {
167         if (amount <= 0)
168         {
169                 return;
170         }
171         bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver,
172                 resource_type, amount, limit);
173         if (forbid)
174         {
175                 return;
176         }
177         resource_type = M_ARGV(1, int);
178         amount = M_ARGV(2, float);
179         limit = M_ARGV(3, float);
180         if (amount <= 0)
181         {
182                 return;
183         }
184         float current_amount = GetResourceAmount(receiver, resource_type);
185         if (current_amount + amount > limit && limit != RESOURCE_LIMIT_NONE)
186         {
187                 amount = limit - current_amount;
188         }
189         GiveResource(receiver, resource_type, amount);
190 }
191
192 void TakeResource(entity receiver, int resource_type, float amount)
193 {
194         if (amount <= 0)
195         {
196                 return;
197         }
198         bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, resource_type,
199                 amount);
200         if (forbid)
201         {
202                 return;
203         }
204         resource_type = M_ARGV(1, int);
205         amount = M_ARGV(2, float);
206         if (amount <= 0)
207         {
208                 return;
209         }
210         SetResourceAmount(receiver, resource_type,
211                 GetResourceAmount(receiver, resource_type) - amount);
212 }
213
214 void TakeResourceWithLimit(entity receiver, int resource_type, float amount,
215         float limit)
216 {
217         if (amount <= 0)
218         {
219                 return;
220         }
221         bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver,
222                 resource_type, amount, limit);
223         if (forbid)
224         {
225                 return;
226         }
227         resource_type = M_ARGV(1, int);
228         amount = M_ARGV(2, float);
229         limit = M_ARGV(3, float);
230         if (amount <= 0)
231         {
232                 return;
233         }
234         float current_amount = GetResourceAmount(receiver, resource_type);
235         if (current_amount - amount < -limit)
236         {
237                 amount = -limit + current_amount;
238         }
239         TakeResource(receiver, resource_type, amount);
240 }
241
242 void GiveOrTakeResource(entity receiver, int resource_type, float amount)
243 {
244         if(amount < 0)
245         {
246                 TakeResource(receiver, resource_type, amount * -1);
247         }
248         else
249         {
250                 GiveResource(receiver, resource_type, amount);
251         }
252 }
253
254 void GiveOrTakeResourceWithLimit(entity receiver, int resource_type, float amount,
255         float limit)
256 {
257         if(amount < 0)
258         {
259                 TakeResourceWithLimit(receiver, resource_type, amount * -1, limit);
260         }
261         else
262         {
263                 GiveResourceWithLimit(receiver, resource_type, amount, limit);
264         }
265 }
266
267 int GetResourceType(.float resource_field)
268 {
269         switch (resource_field)
270         {
271                 case health: { return RESOURCE_HEALTH; }
272                 case armorvalue: { return RESOURCE_ARMOR; }
273                 case ammo_shells: { return RESOURCE_SHELLS; }
274                 case ammo_nails: { return RESOURCE_BULLETS; }
275                 case ammo_rockets: { return RESOURCE_ROCKETS; }
276                 case ammo_cells: { return RESOURCE_CELLS; }
277                 case ammo_plasma: { return RESOURCE_PLASMA; }
278                 case ammo_fuel: { return RESOURCE_FUEL; }
279         }
280         error("GetResourceType: Invalid field.");
281         return 0;
282 }
283
284 .float GetResourceField(int resource_type)
285 {
286         switch (resource_type)
287         {
288                 case RESOURCE_HEALTH: { return health; }
289                 case RESOURCE_ARMOR: { return armorvalue; }
290                 case RESOURCE_SHELLS: { return ammo_shells; }
291                 case RESOURCE_BULLETS: { return ammo_nails; }
292                 case RESOURCE_ROCKETS: { return ammo_rockets; }
293                 case RESOURCE_CELLS: { return ammo_cells; }
294                 case RESOURCE_PLASMA: { return ammo_plasma; }
295                 case RESOURCE_FUEL: { return ammo_fuel; }
296         }
297         error("GetResourceField: Invalid resource type.");
298         return health;
299 }