]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/resources.qc
Merge branch 'master' into Mario/stats_eloranking
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / resources.qc
index 6526e2f11d262f80dd888a66d6bfbad60a904d60..e36eb57508680f7d4b9fd8e980aaa3c9d59b9864 100644 (file)
@@ -1,54 +1,57 @@
+#include "resources.qh"
+
 /// \file
 /// \brief Source file that contains implementation of the resource system.
 /// \author Lyberta
-/// \copyright GNU GPLv3 or any later version.
-
-#include "resources.qh"
+/// \copyright GNU GPLv2 or any later version.
 
 #include "autocvars.qh"
 #include "miscfunctions.qh"
 
-float GetResourceLimit(entity e, int resource_type)
+float GetResourceLimit(entity e, int res_type)
 {
+       if(!IS_PLAYER(e))
+               return RES_LIMIT_NONE; // no limits on non-players
+
        float limit;
-       switch (resource_type)
+       switch (res_type)
        {
-               case RESOURCE_HEALTH:
+               case RES_HEALTH:
                {
                        limit = autocvar_g_balance_health_limit;
                        break;
                }
-               case RESOURCE_ARMOR:
+               case RES_ARMOR:
                {
                        limit = autocvar_g_balance_armor_limit;
                        break;
                }
-               case RESOURCE_SHELLS:
+               case RES_SHELLS:
                {
                        limit = g_pickup_shells_max;
                        break;
                }
-               case RESOURCE_BULLETS:
+               case RES_BULLETS:
                {
                        limit = g_pickup_nails_max;
                        break;
                }
-               case RESOURCE_ROCKETS:
+               case RES_ROCKETS:
                {
                        limit = g_pickup_rockets_max;
                        break;
                }
-               case RESOURCE_CELLS:
+               case RES_CELLS:
                {
                        limit = g_pickup_cells_max;
                        break;
                }
-               case RESOURCE_PLASMA:
+               case RES_PLASMA:
                {
                        limit = g_pickup_plasma_max;
                        break;
                }
-               case RESOURCE_FUEL:
+               case RES_FUEL:
                {
                        limit = autocvar_g_balance_fuel_limit;
                        break;
@@ -59,80 +62,94 @@ float GetResourceLimit(entity e, int resource_type)
                        return 0;
                }
        }
-       MUTATOR_CALLHOOK(GetResourceLimit, e, resource_type, limit);
+       MUTATOR_CALLHOOK(GetResourceLimit, e, res_type, limit);
        limit = M_ARGV(2, float);
-       if (limit > RESOURCE_AMOUNT_HARD_LIMIT)
+       if (limit > RES_AMOUNT_HARD_LIMIT)
        {
-               limit = RESOURCE_AMOUNT_HARD_LIMIT;
+               limit = RES_AMOUNT_HARD_LIMIT;
        }
        return limit;
 }
 
-float GetResourceAmount(entity e, int resource_type)
+float GetResource(entity e, int res_type)
 {
-       .float resource_field = GetResourceField(resource_type);
-       return e.(resource_field);
+       return e.(GetResourceField(res_type));
+}
+
+bool SetResourceExplicit(entity e, int res_type, float amount)
+{
+       .float res_field = GetResourceField(res_type);
+       if (e.(res_field) != amount)
+       {
+               e.(res_field) = amount;
+               return true;
+       }
+       return false;
 }
 
-void SetResourceAmount(entity e, int resource_type, float amount)
+void SetResource(entity e, int res_type, float amount)
 {
-       bool forbid = MUTATOR_CALLHOOK(SetResourceAmount, e, resource_type, amount);
+       bool forbid = MUTATOR_CALLHOOK(SetResource, e, res_type, amount);
        if (forbid)
        {
                return;
        }
-       resource_type = M_ARGV(1, int);
+       res_type = M_ARGV(1, int);
        amount = M_ARGV(2, float);
-       .float resource_field = GetResourceField(resource_type);
-       if (e.(resource_field) == amount)
+       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)
        {
-               return;
+               amount_wasted = amount - max_amount;
+               amount = max_amount;
        }
-       float max_amount = GetResourceLimit(e, resource_type);
-       if (amount > max_amount)
+       bool changed = SetResourceExplicit(e, res_type, amount);
+       if (changed)
        {
-               amount = max_amount;
+               MUTATOR_CALLHOOK(ResourceAmountChanged, e, res_type, amount);
        }
-       e.(resource_field) = amount;
+       if (amount_wasted == 0)
+       {
+               return;
+       }
+       MUTATOR_CALLHOOK(ResourceWasted, e, res_type, amount_wasted);
 }
 
-void GiveResource(entity receiver, int resource_type, float amount)
+void GiveResource(entity receiver, int res_type, float amount)
 {
-       if (amount == 0)
+       if (amount <= 0)
        {
                return;
        }
-       bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, resource_type,
-               amount);
+       bool forbid = MUTATOR_CALLHOOK(GiveResource, receiver, res_type, amount);
        if (forbid)
        {
                return;
        }
-       resource_type = M_ARGV(1, int);
+       res_type = M_ARGV(1, int);
        amount = M_ARGV(2, float);
        if (amount <= 0)
        {
                return;
        }
-       SetResourceAmount(receiver, resource_type,
-               GetResourceAmount(receiver, resource_type) + amount);
-       switch (resource_type)
+       SetResource(receiver, res_type, GetResource(receiver, res_type) + amount);
+       switch (res_type)
        {
-               case RESOURCE_HEALTH:
+               case RES_HEALTH:
                {
                        receiver.pauserothealth_finished =
                                max(receiver.pauserothealth_finished, time +
                                autocvar_g_balance_pause_health_rot);
                        return;
                }
-               case RESOURCE_ARMOR:
+               case RES_ARMOR:
                {
                        receiver.pauserotarmor_finished =
                                max(receiver.pauserotarmor_finished, time +
                                autocvar_g_balance_pause_armor_rot);
                        return;
                }
-               case RESOURCE_FUEL:
+               case RES_FUEL:
                {
                        receiver.pauserotfuel_finished = max(receiver.pauserotfuel_finished,
                                time + autocvar_g_balance_pause_fuel_rot);
@@ -141,35 +158,107 @@ void GiveResource(entity receiver, int resource_type, float amount)
        }
 }
 
-int GetResourceType(.float resource_field)
+void GiveResourceWithLimit(entity receiver, int 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, int);
+       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, int res_type, float amount)
 {
-       switch (resource_field)
+       if (amount <= 0)
+       {
+               return;
+       }
+       bool forbid = MUTATOR_CALLHOOK(TakeResource, receiver, res_type, amount);
+       if (forbid)
+       {
+               return;
+       }
+       res_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       if (amount <= 0)
        {
-               case health: { return RESOURCE_HEALTH; }
-               case armorvalue: { return RESOURCE_ARMOR; }
-               case ammo_shells: { return RESOURCE_SHELLS; }
-               case ammo_nails: { return RESOURCE_BULLETS; }
-               case ammo_rockets: { return RESOURCE_ROCKETS; }
-               case ammo_cells: { return RESOURCE_CELLS; }
-               case ammo_plasma: { return RESOURCE_PLASMA; }
-               case ammo_fuel: { return RESOURCE_FUEL; }
+               return;
+       }
+       SetResource(receiver, res_type, GetResource(receiver, res_type) - amount);
+}
+
+void TakeResourceWithLimit(entity receiver, int 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, int);
+       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);
+}
+
+int GetResourceType(.float res_field)
+{
+       switch (res_field)
+       {
+               case health: { return RES_HEALTH; }
+               case armorvalue: { return RES_ARMOR; }
+               case ammo_shells: { return RES_SHELLS; }
+               case ammo_nails: { return RES_BULLETS; }
+               case ammo_rockets: { return RES_ROCKETS; }
+               case ammo_cells: { return RES_CELLS; }
+               case ammo_plasma: { return RES_PLASMA; }
+               case ammo_fuel: { return RES_FUEL; }
        }
        error("GetResourceType: Invalid field.");
        return 0;
 }
 
-.float GetResourceField(int resource_type)
+.float GetResourceField(int res_type)
 {
-       switch (resource_type)
-       {
-               case RESOURCE_HEALTH: { return health; }
-               case RESOURCE_ARMOR: { return armorvalue; }
-               case RESOURCE_SHELLS: { return ammo_shells; }
-               case RESOURCE_BULLETS: { return ammo_nails; }
-               case RESOURCE_ROCKETS: { return ammo_rockets; }
-               case RESOURCE_CELLS: { return ammo_cells; }
-               case RESOURCE_PLASMA: { return ammo_plasma; }
-               case RESOURCE_FUEL: { return ammo_fuel; }
+       switch (res_type)
+       {
+               case RES_HEALTH: { return health; }
+               case RES_ARMOR: { return armorvalue; }
+               case RES_SHELLS: { return ammo_shells; }
+               case RES_BULLETS: { return ammo_nails; }
+               case RES_ROCKETS: { return ammo_rockets; }
+               case RES_CELLS: { return ammo_cells; }
+               case RES_PLASMA: { return ammo_plasma; }
+               case RES_FUEL: { return ammo_fuel; }
        }
        error("GetResourceField: Invalid resource type.");
        return health;