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 res_type)
14 return RES_LIMIT_NONE; // no limits on non-players
21 limit = autocvar_g_balance_health_limit;
26 limit = autocvar_g_balance_armor_limit;
31 limit = g_pickup_shells_max;
36 limit = g_pickup_nails_max;
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, res_type, limit);
66 limit = M_ARGV(2, float);
67 if (limit > RES_AMOUNT_HARD_LIMIT)
69 limit = RES_AMOUNT_HARD_LIMIT;
74 float GetResourceAmount(entity e, int res_type)
76 return e.(GetResourceField(res_type));
79 void SetResourceAmount(entity e, int res_type, float amount)
81 bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, res_type, amount);
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)
92 amount_wasted = amount - max_amount;
95 .float res_field = GetResourceField(res_type);
96 if (e.(res_field) != amount)
98 e.(res_field) = amount;
99 MUTATOR_CALLHOOK(ResourceAmountChanged, e, res_type, amount);
101 if (amount_wasted == 0)
105 MUTATOR_CALLHOOK(ResourceWasted, e, res_type, amount_wasted);
108 void GiveResource(entity receiver, int res_type, float amount)
114 bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, res_type, amount);
119 res_type = M_ARGV(1, int);
120 amount = M_ARGV(2, float);
125 SetResourceAmount(receiver, res_type, GetResourceAmount(receiver, res_type) + amount);
130 receiver.pauserothealth_finished =
131 max(receiver.pauserothealth_finished, time +
132 autocvar_g_balance_pause_health_rot);
137 receiver.pauserotarmor_finished =
138 max(receiver.pauserotarmor_finished, time +
139 autocvar_g_balance_pause_armor_rot);
144 receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
145 time + autocvar_g_balance_pause_fuel_rot);
151 void GiveResourceWithLimit(entity receiver, int res_type, float amount, float limit)
157 bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver, res_type, amount, limit);
162 res_type = M_ARGV(1, int);
163 amount = M_ARGV(2, float);
164 limit = M_ARGV(3, float);
169 float current_amount = GetResourceAmount(receiver, res_type);
170 if (current_amount + amount > limit && limit != RES_LIMIT_NONE)
172 amount = limit - current_amount;
174 GiveResource(receiver, res_type, amount);
177 void TakeResource(entity receiver, int res_type, float amount)
183 bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, res_type, amount);
188 res_type = M_ARGV(1, int);
189 amount = M_ARGV(2, float);
194 SetResourceAmount(receiver, res_type, GetResourceAmount(receiver, res_type) - amount);
197 void TakeResourceWithLimit(entity receiver, int res_type, float amount, float limit)
203 bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver, res_type, amount, limit);
208 res_type = M_ARGV(1, int);
209 amount = M_ARGV(2, float);
210 limit = M_ARGV(3, float);
215 float current_amount = GetResourceAmount(receiver, res_type);
216 if (current_amount - amount < -limit)
218 amount = -limit + current_amount;
220 TakeResource(receiver, res_type, amount);
223 void GiveOrTakeResource(entity receiver, int res_type, float amount)
227 TakeResource(receiver, res_type, amount * -1);
231 GiveResource(receiver, res_type, amount);
235 void GiveOrTakeResourceWithLimit(entity receiver, int res_type, float amount, float limit)
239 TakeResourceWithLimit(receiver, res_type, amount * -1, limit);
243 GiveResourceWithLimit(receiver, res_type, amount, limit);
247 int GetResourceType(.float res_field)
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; }
260 error("GetResourceType: Invalid field.");
264 .float GetResourceField(int res_type)
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; }
277 error("GetResourceField: Invalid resource type.");