]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/resources.qc
GetResourceAmount --> GetResource, SetResourceAmount --> SetResource
[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 res_type)
12 {
13         if(!IS_PLAYER(e))
14                 return RES_LIMIT_NONE; // no limits on non-players
15
16         float limit;
17         switch (res_type)
18         {
19                 case RES_HEALTH:
20                 {
21                         limit = autocvar_g_balance_health_limit;
22                         break;
23                 }
24                 case RES_ARMOR:
25                 {
26                         limit = autocvar_g_balance_armor_limit;
27                         break;
28                 }
29                 case RES_SHELLS:
30                 {
31                         limit = g_pickup_shells_max;
32                         break;
33                 }
34                 case RES_BULLETS:
35                 {
36                         limit = g_pickup_nails_max;
37                         break;
38                 }
39                 case RES_ROCKETS:
40                 {
41                         limit = g_pickup_rockets_max;
42                         break;
43                 }
44                 case RES_CELLS:
45                 {
46                         limit = g_pickup_cells_max;
47                         break;
48                 }
49                 case RES_PLASMA:
50                 {
51                         limit = g_pickup_plasma_max;
52                         break;
53                 }
54                 case RES_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, res_type, limit);
66         limit = M_ARGV(2, float);
67         if (limit > RES_AMOUNT_HARD_LIMIT)
68         {
69                 limit = RES_AMOUNT_HARD_LIMIT;
70         }
71         return limit;
72 }
73
74 float GetResource(entity e, int res_type)
75 {
76         return e.(GetResourceField(res_type));
77 }
78
79 void SetResource(entity e, int res_type, float amount)
80 {
81         bool forbid = MUTATOR_CALLHOOK(SetResource, e, res_type, amount);
82         if (forbid)
83         {
84                 return;
85         }
86         res_type = M_ARGV(1, int);
87         amount = M_ARGV(2, float);
88         float max_amount = GetResourceLimit(e, res_type); // TODO: should allow overriding these limits if cheats are enabled!
89         float amount_wasted = 0;
90         if (amount > max_amount && max_amount != RES_LIMIT_NONE)
91         {
92                 amount_wasted = amount - max_amount;
93                 amount = max_amount;
94         }
95         .float res_field = GetResourceField(res_type);
96         if (e.(res_field) != amount)
97         {
98                 e.(res_field) = amount;
99                 MUTATOR_CALLHOOK(ResourceAmountChanged, e, res_type, amount);
100         }
101         if (amount_wasted == 0)
102         {
103                 return;
104         }
105         MUTATOR_CALLHOOK(ResourceWasted, e, res_type, amount_wasted);
106 }
107
108 void GiveResource(entity receiver, int res_type, float amount)
109 {
110         if (amount <= 0)
111         {
112                 return;
113         }
114         bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, res_type, amount);
115         if (forbid)
116         {
117                 return;
118         }
119         res_type = M_ARGV(1, int);
120         amount = M_ARGV(2, float);
121         if (amount <= 0)
122         {
123                 return;
124         }
125         SetResource(receiver, res_type, GetResource(receiver, res_type) + amount);
126         switch (res_type)
127         {
128                 case RES_HEALTH:
129                 {
130                         receiver.pauserothealth_finished =
131                                 max(receiver.pauserothealth_finished, time +
132                                 autocvar_g_balance_pause_health_rot);
133                         return;
134                 }
135                 case RES_ARMOR:
136                 {
137                         receiver.pauserotarmor_finished =
138                                 max(receiver.pauserotarmor_finished, time +
139                                 autocvar_g_balance_pause_armor_rot);
140                         return;
141                 }
142                 case RES_FUEL:
143                 {
144                         receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
145                                 time + autocvar_g_balance_pause_fuel_rot);
146                         return;
147                 }
148         }
149 }
150
151 void GiveResourceWithLimit(entity receiver, int res_type, float amount, float limit)
152 {
153         if (amount <= 0)
154         {
155                 return;
156         }
157         bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver, res_type, amount, limit);
158         if (forbid)
159         {
160                 return;
161         }
162         res_type = M_ARGV(1, int);
163         amount = M_ARGV(2, float);
164         limit = M_ARGV(3, float);
165         if (amount <= 0)
166         {
167                 return;
168         }
169         float current_amount = GetResource(receiver, res_type);
170         if (current_amount + amount > limit && limit != RES_LIMIT_NONE)
171         {
172                 amount = limit - current_amount;
173         }
174         GiveResource(receiver, res_type, amount);
175 }
176
177 void TakeResource(entity receiver, int res_type, float amount)
178 {
179         if (amount <= 0)
180         {
181                 return;
182         }
183         bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, res_type, amount);
184         if (forbid)
185         {
186                 return;
187         }
188         res_type = M_ARGV(1, int);
189         amount = M_ARGV(2, float);
190         if (amount <= 0)
191         {
192                 return;
193         }
194         SetResource(receiver, res_type, GetResource(receiver, res_type) - amount);
195 }
196
197 void TakeResourceWithLimit(entity receiver, int res_type, float amount, float limit)
198 {
199         if (amount <= 0)
200         {
201                 return;
202         }
203         bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver, res_type, amount, limit);
204         if (forbid)
205         {
206                 return;
207         }
208         res_type = M_ARGV(1, int);
209         amount = M_ARGV(2, float);
210         limit = M_ARGV(3, float);
211         if (amount <= 0)
212         {
213                 return;
214         }
215         float current_amount = GetResource(receiver, res_type);
216         if (current_amount - amount < -limit)
217         {
218                 amount = -limit + current_amount;
219         }
220         TakeResource(receiver, res_type, amount);
221 }
222
223 void GiveOrTakeResource(entity receiver, int res_type, float amount)
224 {
225         if(amount < 0)
226         {
227                 TakeResource(receiver, res_type, amount * -1);
228         }
229         else
230         {
231                 GiveResource(receiver, res_type, amount);
232         }
233 }
234
235 void GiveOrTakeResourceWithLimit(entity receiver, int res_type, float amount, float limit)
236 {
237         if(amount < 0)
238         {
239                 TakeResourceWithLimit(receiver, res_type, amount * -1, limit);
240         }
241         else
242         {
243                 GiveResourceWithLimit(receiver, res_type, amount, limit);
244         }
245 }
246
247 int GetResourceType(.float res_field)
248 {
249         switch (res_field)
250         {
251                 case health: { return RES_HEALTH; }
252                 case armorvalue: { return RES_ARMOR; }
253                 case ammo_shells: { return RES_SHELLS; }
254                 case ammo_nails: { return RES_BULLETS; }
255                 case ammo_rockets: { return RES_ROCKETS; }
256                 case ammo_cells: { return RES_CELLS; }
257                 case ammo_plasma: { return RES_PLASMA; }
258                 case ammo_fuel: { return RES_FUEL; }
259         }
260         error("GetResourceType: Invalid field.");
261         return 0;
262 }
263
264 .float GetResourceField(int res_type)
265 {
266         switch (res_type)
267         {
268                 case RES_HEALTH: { return health; }
269                 case RES_ARMOR: { return armorvalue; }
270                 case RES_SHELLS: { return ammo_shells; }
271                 case RES_BULLETS: { return ammo_nails; }
272                 case RES_ROCKETS: { return ammo_rockets; }
273                 case RES_CELLS: { return ammo_cells; }
274                 case RES_PLASMA: { return ammo_plasma; }
275                 case RES_FUEL: { return ammo_fuel; }
276         }
277         error("GetResourceField: Invalid resource type.");
278         return health;
279 }