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 <server/mutators/_mod.qh>
10 #include <server/world.qh>
12 float GetResourceLimit(entity e, int res_type)
15 return RES_LIMIT_NONE; // no limits on non-players
22 limit = autocvar_g_balance_health_limit;
27 limit = autocvar_g_balance_armor_limit;
32 limit = g_pickup_shells_max;
37 limit = g_pickup_nails_max;
42 limit = g_pickup_rockets_max;
47 limit = g_pickup_cells_max;
52 limit = g_pickup_plasma_max;
57 limit = autocvar_g_balance_fuel_limit;
62 error("GetResourceLimit: Invalid resource type.");
66 MUTATOR_CALLHOOK(GetResourceLimit, e, res_type, limit);
67 limit = M_ARGV(2, float);
68 if (limit > RES_AMOUNT_HARD_LIMIT)
70 limit = RES_AMOUNT_HARD_LIMIT;
75 float GetResource(entity e, int res_type)
77 return e.(GetResourceField(res_type));
80 bool SetResourceExplicit(entity e, int res_type, float amount)
82 .float res_field = GetResourceField(res_type);
83 if (e.(res_field) != amount)
85 e.(res_field) = amount;
91 void SetResource(entity e, int res_type, float amount)
93 bool forbid = MUTATOR_CALLHOOK(SetResource, e, res_type, amount);
98 res_type = M_ARGV(1, int);
99 amount = M_ARGV(2, float);
100 float max_amount = GetResourceLimit(e, res_type); // TODO: should allow overriding these limits if cheats are enabled!
101 float amount_wasted = 0;
102 if (amount > max_amount && max_amount != RES_LIMIT_NONE)
104 amount_wasted = amount - max_amount;
107 bool changed = SetResourceExplicit(e, res_type, amount);
110 MUTATOR_CALLHOOK(ResourceAmountChanged, e, res_type, amount);
112 if (amount_wasted == 0)
116 MUTATOR_CALLHOOK(ResourceWasted, e, res_type, amount_wasted);
119 void GiveResource(entity receiver, int res_type, float amount)
125 bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, res_type, amount);
130 res_type = M_ARGV(1, int);
131 amount = M_ARGV(2, float);
136 SetResource(receiver, res_type, GetResource(receiver, res_type) + amount);
141 receiver.pauserothealth_finished =
142 max(receiver.pauserothealth_finished, time +
143 autocvar_g_balance_pause_health_rot);
148 receiver.pauserotarmor_finished =
149 max(receiver.pauserotarmor_finished, time +
150 autocvar_g_balance_pause_armor_rot);
155 receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
156 time + autocvar_g_balance_pause_fuel_rot);
162 void GiveResourceWithLimit(entity receiver, int res_type, float amount, float limit)
168 bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver, res_type, amount, limit);
173 res_type = M_ARGV(1, int);
174 amount = M_ARGV(2, float);
175 limit = M_ARGV(3, float);
180 float current_amount = GetResource(receiver, res_type);
181 if (current_amount + amount > limit && limit != RES_LIMIT_NONE)
183 amount = limit - current_amount;
185 GiveResource(receiver, res_type, amount);
188 void TakeResource(entity receiver, int res_type, float amount)
194 bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, res_type, amount);
199 res_type = M_ARGV(1, int);
200 amount = M_ARGV(2, float);
205 SetResource(receiver, res_type, GetResource(receiver, res_type) - amount);
208 void TakeResourceWithLimit(entity receiver, int res_type, float amount, float limit)
214 bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver, res_type, amount, limit);
219 res_type = M_ARGV(1, int);
220 amount = M_ARGV(2, float);
221 limit = M_ARGV(3, float);
226 float current_amount = GetResource(receiver, res_type);
227 if (current_amount - amount < -limit)
229 amount = -limit + current_amount;
231 TakeResource(receiver, res_type, amount);
234 int GetResourceType(.float res_field)
238 case health: { return RES_HEALTH; }
239 case armorvalue: { return RES_ARMOR; }
240 case ammo_shells: { return RES_SHELLS; }
241 case ammo_nails: { return RES_BULLETS; }
242 case ammo_rockets: { return RES_ROCKETS; }
243 case ammo_cells: { return RES_CELLS; }
244 case ammo_plasma: { return RES_PLASMA; }
245 case ammo_fuel: { return RES_FUEL; }
247 error("GetResourceType: Invalid field.");
251 .float GetResourceField(int res_type)
255 case RES_HEALTH: { return health; }
256 case RES_ARMOR: { return armorvalue; }
257 case RES_SHELLS: { return ammo_shells; }
258 case RES_BULLETS: { return ammo_nails; }
259 case RES_ROCKETS: { return ammo_rockets; }
260 case RES_CELLS: { return ammo_cells; }
261 case RES_PLASMA: { return ammo_plasma; }
262 case RES_FUEL: { return ammo_fuel; }
264 error("GetResourceField: Invalid resource type.");