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 void SetResourceAmount(entity e, int resource_type, float amount)
82 bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, resource_type, amount);
87 resource_type = M_ARGV(1, int);
88 amount = M_ARGV(2, float);
89 float max_amount = GetResourceLimit(e, resource_type); // TODO: should allow overriding these limits if cheats are enabled!
90 float amount_wasted = 0;
91 if (amount > max_amount && max_amount != RESOURCE_LIMIT_NONE)
93 amount_wasted = amount - max_amount;
96 .float resource_field = GetResourceField(resource_type);
97 if (e.(resource_field) != amount)
99 e.(resource_field) = amount;
100 MUTATOR_CALLHOOK(ResourceAmountChanged, e, resource_type, amount);
102 if (amount_wasted == 0)
106 MUTATOR_CALLHOOK(ResourceWasted, e, resource_type, amount_wasted);
109 void GiveResource(entity receiver, int resource_type, float amount)
115 bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, resource_type,
121 resource_type = M_ARGV(1, int);
122 amount = M_ARGV(2, float);
127 SetResourceAmount(receiver, resource_type,
128 GetResourceAmount(receiver, resource_type) + amount);
129 switch (resource_type)
131 case RESOURCE_HEALTH:
133 receiver.pauserothealth_finished =
134 max(receiver.pauserothealth_finished, time +
135 autocvar_g_balance_pause_health_rot);
140 receiver.pauserotarmor_finished =
141 max(receiver.pauserotarmor_finished, time +
142 autocvar_g_balance_pause_armor_rot);
147 receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
148 time + autocvar_g_balance_pause_fuel_rot);
154 void GiveResourceWithLimit(entity receiver, int resource_type, float amount,
161 bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver,
162 resource_type, amount, limit);
167 resource_type = M_ARGV(1, int);
168 amount = M_ARGV(2, float);
169 limit = M_ARGV(3, float);
174 float current_amount = GetResourceAmount(receiver, resource_type);
175 if (current_amount + amount > limit && limit != RESOURCE_LIMIT_NONE)
177 amount = limit - current_amount;
179 GiveResource(receiver, resource_type, amount);
182 void TakeResource(entity receiver, int resource_type, float amount)
188 bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, resource_type,
194 resource_type = M_ARGV(1, int);
195 amount = M_ARGV(2, float);
200 SetResourceAmount(receiver, resource_type,
201 GetResourceAmount(receiver, resource_type) - amount);
204 void TakeResourceWithLimit(entity receiver, int resource_type, float amount,
211 bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver,
212 resource_type, amount, limit);
217 resource_type = M_ARGV(1, int);
218 amount = M_ARGV(2, float);
219 limit = M_ARGV(3, float);
224 float current_amount = GetResourceAmount(receiver, resource_type);
225 if (current_amount - amount < -limit)
227 amount = -limit + current_amount;
229 TakeResource(receiver, resource_type, amount);
232 void GiveOrTakeResource(entity receiver, int resource_type, float amount)
236 TakeResource(receiver, resource_type, amount * -1);
240 GiveResource(receiver, resource_type, amount);
244 void GiveOrTakeResourceWithLimit(entity receiver, int resource_type, float amount,
249 TakeResourceWithLimit(receiver, resource_type, amount * -1, limit);
253 GiveResourceWithLimit(receiver, resource_type, amount, limit);
257 int GetResourceType(.float resource_field)
259 switch (resource_field)
261 case health: { return RESOURCE_HEALTH; }
262 case armorvalue: { return RESOURCE_ARMOR; }
263 case ammo_shells: { return RESOURCE_SHELLS; }
264 case ammo_nails: { return RESOURCE_BULLETS; }
265 case ammo_rockets: { return RESOURCE_ROCKETS; }
266 case ammo_cells: { return RESOURCE_CELLS; }
267 case ammo_plasma: { return RESOURCE_PLASMA; }
268 case ammo_fuel: { return RESOURCE_FUEL; }
270 error("GetResourceType: Invalid field.");
274 .float GetResourceField(int resource_type)
276 switch (resource_type)
278 case RESOURCE_HEALTH: { return health; }
279 case RESOURCE_ARMOR: { return armorvalue; }
280 case RESOURCE_SHELLS: { return ammo_shells; }
281 case RESOURCE_BULLETS: { return ammo_nails; }
282 case RESOURCE_ROCKETS: { return ammo_rockets; }
283 case RESOURCE_CELLS: { return ammo_cells; }
284 case RESOURCE_PLASMA: { return ammo_plasma; }
285 case RESOURCE_FUEL: { return ammo_fuel; }
287 error("GetResourceField: Invalid resource type.");