]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/resources/sv_resources.qc
Migrating resources (ammo, health etc) to a registry for ease of maintenance and...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / resources / sv_resources.qc
diff --git a/qcsrc/common/resources/sv_resources.qc b/qcsrc/common/resources/sv_resources.qc
new file mode 100644 (file)
index 0000000..9984e91
--- /dev/null
@@ -0,0 +1,234 @@
+#include "sv_resources.qh"
+
+/// \file
+/// \brief Source file that contains implementation of the resource system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+#include <common/resources/resources.qh>
+#include <server/mutators/_mod.qh>
+#include <server/world.qh>
+
+float GetResourceLimit(entity e, Resource res_type)
+{
+       if(!IS_PLAYER(e))
+               return RES_LIMIT_NONE; // no limits on non-players
+
+       float limit;
+       // TODO: registry handles
+       switch (res_type)
+       {
+               case RES_HEALTH:
+               {
+                       limit = autocvar_g_balance_health_limit;
+                       break;
+               }
+               case RES_ARMOR:
+               {
+                       limit = autocvar_g_balance_armor_limit;
+                       break;
+               }
+               case RES_SHELLS:
+               {
+                       limit = g_pickup_shells_max;
+                       break;
+               }
+               case RES_BULLETS:
+               {
+                       limit = g_pickup_nails_max;
+                       break;
+               }
+               case RES_ROCKETS:
+               {
+                       limit = g_pickup_rockets_max;
+                       break;
+               }
+               case RES_CELLS:
+               {
+                       limit = g_pickup_cells_max;
+                       break;
+               }
+               case RES_PLASMA:
+               {
+                       limit = g_pickup_plasma_max;
+                       break;
+               }
+               case RES_FUEL:
+               {
+                       limit = autocvar_g_balance_fuel_limit;
+                       break;
+               }
+               default:
+               {
+                       error("GetResourceLimit: Invalid resource type.");
+                       return 0;
+               }
+       }
+       MUTATOR_CALLHOOK(GetResourceLimit, e, res_type, limit);
+       limit = M_ARGV(2, float);
+       if (limit > RES_AMOUNT_HARD_LIMIT)
+       {
+               limit = RES_AMOUNT_HARD_LIMIT;
+       }
+       return limit;
+}
+
+float GetResource(entity e, Resource res_type)
+{
+       return e.(GetResourceField(res_type));
+}
+
+bool SetResourceExplicit(entity e, Resource res_type, float amount)
+{
+       .float res_field = GetResourceField(res_type);
+       if (e.(res_field) != amount)
+       {
+               e.(res_field) = amount;
+               return true;
+       }
+       return false;
+}
+
+void SetResource(entity e, Resource res_type, float amount)
+{
+       bool forbid = MUTATOR_CALLHOOK(SetResource, e, res_type, amount);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, entity);
+       amount = M_ARGV(2, float);
+       float max_amount = GetResourceLimit(e, res_type); // TODO: should allow overriding these limits if cheats are enabled!
+       float amount_wasted = 0;
+       if (amount > max_amount && max_amount != RES_LIMIT_NONE)
+       {
+               amount_wasted = amount - max_amount;
+               amount = max_amount;
+       }
+       bool changed = SetResourceExplicit(e, res_type, amount);
+       if (changed)
+       {
+               MUTATOR_CALLHOOK(ResourceAmountChanged, e, res_type, amount);
+       }
+       if (amount_wasted == 0)
+       {
+               return;
+       }
+       MUTATOR_CALLHOOK(ResourceWasted, e, res_type, amount_wasted);
+}
+
+void GiveResource(entity receiver, Resource res_type, float amount)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, res_type, amount);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, entity);
+       amount = M_ARGV(2, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       SetResource(receiver, res_type, GetResource(receiver, res_type) + amount);
+       // TODO: registry handles
+       switch (res_type)
+       {
+               case RES_HEALTH:
+               {
+                       receiver.pauserothealth_finished =
+                               max(receiver.pauserothealth_finished, time +
+                               autocvar_g_balance_pause_health_rot);
+                       return;
+               }
+               case RES_ARMOR:
+               {
+                       receiver.pauserotarmor_finished =
+                               max(receiver.pauserotarmor_finished, time +
+                               autocvar_g_balance_pause_armor_rot);
+                       return;
+               }
+               case RES_FUEL:
+               {
+                       receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
+                               time + autocvar_g_balance_pause_fuel_rot);
+                       return;
+               }
+       }
+}
+
+void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver, res_type, amount, limit);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, entity);
+       amount = M_ARGV(2, float);
+       limit = M_ARGV(3, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       float current_amount = GetResource(receiver, res_type);
+       if (current_amount + amount > limit && limit != RES_LIMIT_NONE)
+       {
+               amount = limit - current_amount;
+       }
+       GiveResource(receiver, res_type, amount);
+}
+
+void TakeResource(entity receiver, Resource res_type, float amount)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, res_type, amount);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, entity);
+       amount = M_ARGV(2, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       SetResource(receiver, res_type, GetResource(receiver, res_type) - amount);
+}
+
+void TakeResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver, res_type, amount, limit);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, entity);
+       amount = M_ARGV(2, float);
+       limit = M_ARGV(3, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       float current_amount = GetResource(receiver, res_type);
+       if (current_amount - amount < -limit)
+       {
+               amount = -limit + current_amount;
+       }
+       TakeResource(receiver, res_type, amount);
+}