1 #include "resources.qh"
4 /// \brief Source file that contains implementation of the resource system.
6 /// \copyright GNU GPLv2 or any later version.
8 #include "autocvars.qh"
9 #include "miscfunctions.qh"
11 float GetResourceLimit(entity e, int resource_type)
14 return RESOURCE_LIMIT_NONE; // no limits on non-players
17 switch (resource_type)
21 limit = autocvar_g_balance_health_limit;
26 limit = autocvar_g_balance_armor_limit;
31 limit = g_pickup_shells_max;
34 case RESOURCE_BULLETS:
36 limit = g_pickup_nails_max;
39 case RESOURCE_ROCKETS:
41 limit = g_pickup_rockets_max;
46 limit = g_pickup_cells_max;
51 limit = g_pickup_plasma_max;
56 limit = autocvar_g_balance_fuel_limit;
61 error("GetResourceLimit: Invalid resource type.");
65 MUTATOR_CALLHOOK(GetResourceLimit, e, resource_type, limit);
66 limit = M_ARGV(2, float);
67 if (limit > RESOURCE_AMOUNT_HARD_LIMIT)
69 limit = RESOURCE_AMOUNT_HARD_LIMIT;
74 float GetResourceAmount(entity e, int resource_type)
76 .float resource_field = GetResourceField(resource_type);
77 return e.(resource_field);
80 bool SetResourceAmountExplicit(entity e, int resource_type, float amount)
82 .float resource_field = GetResourceField(resource_type);
83 if (e.(resource_field) != amount)
85 e.(resource_field) = amount;
91 void SetResourceAmount(entity e, int resource_type, float amount)
93 bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, resource_type, amount);
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)
104 amount_wasted = amount - max_amount;
107 bool changed = SetResourceAmountExplicit(e, resource_type, amount);
110 MUTATOR_CALLHOOK(ResourceAmountChanged, e, resource_type, amount);
112 if (amount_wasted == 0)
116 MUTATOR_CALLHOOK(ResourceWasted, e, resource_type, amount_wasted);
119 void GiveResource(entity receiver, int resource_type, float amount)
125 bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, resource_type,
131 resource_type = M_ARGV(1, int);
132 amount = M_ARGV(2, float);
137 SetResourceAmount(receiver, resource_type,
138 GetResourceAmount(receiver, resource_type) + amount);
139 switch (resource_type)
141 case RESOURCE_HEALTH:
143 receiver.pauserothealth_finished =
144 max(receiver.pauserothealth_finished, time +
145 autocvar_g_balance_pause_health_rot);
150 receiver.pauserotarmor_finished =
151 max(receiver.pauserotarmor_finished, time +
152 autocvar_g_balance_pause_armor_rot);
157 receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
158 time + autocvar_g_balance_pause_fuel_rot);
164 void GiveResourceWithLimit(entity receiver, int resource_type, float amount,
171 bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver,
172 resource_type, amount, limit);
177 resource_type = M_ARGV(1, int);
178 amount = M_ARGV(2, float);
179 limit = M_ARGV(3, float);
184 float current_amount = GetResourceAmount(receiver, resource_type);
185 if (current_amount + amount > limit && limit != RESOURCE_LIMIT_NONE)
187 amount = limit - current_amount;
189 GiveResource(receiver, resource_type, amount);
192 void TakeResource(entity receiver, int resource_type, float amount)
198 bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, resource_type,
204 resource_type = M_ARGV(1, int);
205 amount = M_ARGV(2, float);
210 SetResourceAmount(receiver, resource_type,
211 GetResourceAmount(receiver, resource_type) - amount);
214 void TakeResourceWithLimit(entity receiver, int resource_type, float amount,
221 bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver,
222 resource_type, amount, limit);
227 resource_type = M_ARGV(1, int);
228 amount = M_ARGV(2, float);
229 limit = M_ARGV(3, float);
234 float current_amount = GetResourceAmount(receiver, resource_type);
235 if (current_amount - amount < -limit)
237 amount = -limit + current_amount;
239 TakeResource(receiver, resource_type, amount);
242 void GiveOrTakeResource(entity receiver, int resource_type, float amount)
246 TakeResource(receiver, resource_type, amount * -1);
250 GiveResource(receiver, resource_type, amount);
254 void GiveOrTakeResourceWithLimit(entity receiver, int resource_type, float amount,
259 TakeResourceWithLimit(receiver, resource_type, amount * -1, limit);
263 GiveResourceWithLimit(receiver, resource_type, amount, limit);
267 int GetResourceType(.float resource_field)
269 switch (resource_field)
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; }
280 error("GetResourceType: Invalid field.");
284 .float GetResourceField(int resource_type)
286 switch (resource_type)
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; }
297 error("GetResourceField: Invalid resource type.");