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