]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/resources.qc
Merge branch 'sev/luma-menu-xpm' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / resources.qc
index a6e0e07245895fa9df80b8386dce80f395762985..74a0c55788a71a2f19de6accaeaacba47f1c9c3b 100644 (file)
@@ -1,9 +1,18 @@
 #include "resources.qh"
 
-//#include <server/autocvars.qh>
+/// \file
+/// \brief Source file that contains implementation of the resource system.
+/// \author Lyberta
+/// \copyright GNU GPLv2 or any later version.
+
+#include "autocvars.qh"
+#include "miscfunctions.qh"
 
 float GetResourceLimit(entity e, int resource_type)
 {
+       if(!IS_PLAYER(e))
+               return RESOURCE_LIMIT_NONE; // no limits on non-players
+
        float limit;
        switch (resource_type)
        {
@@ -62,9 +71,54 @@ float GetResourceLimit(entity e, int resource_type)
        return limit;
 }
 
+float GetResourceAmount(entity e, int resource_type)
+{
+       .float resource_field = GetResourceField(resource_type);
+       return e.(resource_field);
+}
+
+bool SetResourceAmountExplicit(entity e, int resource_type, float amount)
+{
+       .float resource_field = GetResourceField(resource_type);
+       if (e.(resource_field) != amount)
+       {
+               e.(resource_field) = amount;
+               return true;
+       }
+       return false;
+}
+
+void SetResourceAmount(entity e, int resource_type, float amount)
+{
+       bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, resource_type, amount);
+       if (forbid)
+       {
+               return;
+       }
+       resource_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       float max_amount = GetResourceLimit(e, resource_type); // TODO: should allow overriding these limits if cheats are enabled!
+       float amount_wasted = 0;
+       if (amount > max_amount && max_amount != RESOURCE_LIMIT_NONE)
+       {
+               amount_wasted = amount - max_amount;
+               amount = max_amount;
+       }
+       bool changed = SetResourceAmountExplicit(e, resource_type, amount);
+       if (changed)
+       {
+               MUTATOR_CALLHOOK(ResourceAmountChanged, e, resource_type, amount);
+       }
+       if (amount_wasted == 0)
+       {
+               return;
+       }
+       MUTATOR_CALLHOOK(ResourceWasted, e, resource_type, amount_wasted);
+}
+
 void GiveResource(entity receiver, int resource_type, float amount)
 {
-       if (amount == 0)
+       if (amount <= 0)
        {
                return;
        }
@@ -76,10 +130,12 @@ void GiveResource(entity receiver, int resource_type, float amount)
        }
        resource_type = M_ARGV(1, int);
        amount = M_ARGV(2, float);
-       .float resource_property = GetResourceProperty(resource_type);
-       float max_amount = GetResourceLimit(receiver, resource_type);
-       receiver.(resource_property) = bound(receiver.(resource_property),
-               receiver.(resource_property) + amount, max_amount);
+       if (amount <= 0)
+       {
+               return;
+       }
+       SetResourceAmount(receiver, resource_type,
+               GetResourceAmount(receiver, resource_type) + amount);
        switch (resource_type)
        {
                case RESOURCE_HEALTH:
@@ -105,9 +161,112 @@ void GiveResource(entity receiver, int resource_type, float amount)
        }
 }
 
-int GetResourceType(.float resource_property)
+void GiveResourceWithLimit(entity receiver, int resource_type, float amount,
+       float limit)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver,
+               resource_type, amount, limit);
+       if (forbid)
+       {
+               return;
+       }
+       resource_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       limit = M_ARGV(3, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       float current_amount = GetResourceAmount(receiver, resource_type);
+       if (current_amount + amount > limit && limit != RESOURCE_LIMIT_NONE)
+       {
+               amount = limit - current_amount;
+       }
+       GiveResource(receiver, resource_type, amount);
+}
+
+void TakeResource(entity receiver, int resource_type, float amount)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, resource_type,
+               amount);
+       if (forbid)
+       {
+               return;
+       }
+       resource_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       SetResourceAmount(receiver, resource_type,
+               GetResourceAmount(receiver, resource_type) - amount);
+}
+
+void TakeResourceWithLimit(entity receiver, int resource_type, float amount,
+       float limit)
+{
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(TakeResourceWithLimit, receiver,
+               resource_type, amount, limit);
+       if (forbid)
+       {
+               return;
+       }
+       resource_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       limit = M_ARGV(3, float);
+       if (amount <= 0)
+       {
+               return;
+       }
+       float current_amount = GetResourceAmount(receiver, resource_type);
+       if (current_amount - amount < -limit)
+       {
+               amount = -limit + current_amount;
+       }
+       TakeResource(receiver, resource_type, amount);
+}
+
+void GiveOrTakeResource(entity receiver, int resource_type, float amount)
+{
+       if(amount < 0)
+       {
+               TakeResource(receiver, resource_type, amount * -1);
+       }
+       else
+       {
+               GiveResource(receiver, resource_type, amount);
+       }
+}
+
+void GiveOrTakeResourceWithLimit(entity receiver, int resource_type, float amount,
+       float limit)
+{
+       if(amount < 0)
+       {
+               TakeResourceWithLimit(receiver, resource_type, amount * -1, limit);
+       }
+       else
+       {
+               GiveResourceWithLimit(receiver, resource_type, amount, limit);
+       }
+}
+
+int GetResourceType(.float resource_field)
 {
-       switch (resource_property)
+       switch (resource_field)
        {
                case health: { return RESOURCE_HEALTH; }
                case armorvalue: { return RESOURCE_ARMOR; }
@@ -118,11 +277,11 @@ int GetResourceType(.float resource_property)
                case ammo_plasma: { return RESOURCE_PLASMA; }
                case ammo_fuel: { return RESOURCE_FUEL; }
        }
-       error("GetResourceType: Invalid property.");
+       error("GetResourceType: Invalid field.");
        return 0;
 }
 
-.float GetResourceProperty(int resource_type)
+.float GetResourceField(int resource_type)
 {
        switch (resource_type)
        {
@@ -135,6 +294,6 @@ int GetResourceType(.float resource_property)
                case RESOURCE_PLASMA: { return ammo_plasma; }
                case RESOURCE_FUEL: { return ammo_fuel; }
        }
-       error("GetResourceProperty: Invalid resource type.");
+       error("GetResourceField: Invalid resource type.");
        return health;
 }