]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Started unified resource system - step 2.
authorLyberta <lyberta@lyberta.net>
Mon, 28 Aug 2017 03:39:49 +0000 (06:39 +0300)
committerLyberta <lyberta@lyberta.net>
Mon, 28 Aug 2017 03:39:49 +0000 (06:39 +0300)
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/server/mutators/events.qh

index 6a6ce3fafdccd004a36a7c438b820b8423414040..f794d77a974d7b128df130ceeb306d79087e754d 100644 (file)
@@ -682,57 +682,134 @@ void Item_ScheduleInitialRespawn(entity e)
        Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
 }
 
-void GivePlayerResource(entity player, .float resource_type, float amount)
+int GetResourceType(.float resource_property)
+{
+       switch (resource_property)
+       {
+               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; }
+       }
+       error("GetResourceType: Invalid property.");
+       return 0;
+}
+
+.float GetResourceProperty(int resource_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; }
+       }
+       error("GetResourceProperty: Invalid resource type.");
+       return health;
+}
+
+float GetResourceLimit(int resource_type)
+{
+       float limit;
+       switch (resource_type)
+       {
+               case RESOURCE_HEALTH:
+               {
+                       limit = autocvar_g_balance_health_limit;
+                       break;
+               }
+               case RESOURCE_ARMOR:
+               {
+                       limit = autocvar_g_balance_armor_limit;
+                       break;
+               }
+               case RESOURCE_SHELLS:
+               {
+                       limit = g_pickup_shells_max;
+                       break;
+               }
+               case RESOURCE_BULLETS:
+               {
+                       limit = g_pickup_nails_max;
+                       break;
+               }
+               case RESOURCE_ROCKETS:
+               {
+                       limit = g_pickup_rockets_max;
+                       break;
+               }
+               case RESOURCE_CELLS:
+               {
+                       limit = g_pickup_cells_max;
+                       break;
+               }
+               case RESOURCE_PLASMA:
+               {
+                       limit = g_pickup_plasma_max;
+                       break;
+               }
+               case RESOURCE_FUEL:
+               {
+                       limit = g_pickup_fuel_max;
+                       break;
+               }
+               default:
+               {
+                       error("GetResourceLimit: Invalid resource type.");
+                       return 0;
+               }
+       }
+       MUTATOR_CALLHOOK(GetResourceLimit, resource_type, limit);
+       limit = M_ARGV(1, float);
+       if (limit > RESOURCE_AMOUNT_HARD_LIMIT)
+       {
+               limit = RESOURCE_AMOUNT_HARD_LIMIT
+       }
+       return limit;
+}
+
+void GivePlayerResource(entity player, int resource_type, float amount)
 {
        if (amount == 0)
        {
                return;
        }
+       bool forbid = MUTATOR_CALLHOOK(GivePlayerResource, player, resource_type,
+               amount);
+       if (forbid)
+       {
+               return;
+       }
+       resource_type = M_ARGV(1, int);
+       amount = M_ARGV(2, float);
+       .float resource_property = GetResourceProperty(resource_type);
+       float max_amount = GetResourceLimit(resource_type);
+       player.(resource_property) = bound(player.(resource_property),
+               player.(resource_property) + amount, max_amount);
        switch (resource_type)
        {
-               case health:
+               case RESOURCE_HEALTH:
                {
-                       // Ugly hack. We do not check if health goes beyond hard limit since
-                       // currently it is done in player_regen. We need to bring back this
-                       // check when other code is ported to this function.
-                       player.health = bound(player.health, player.health + amount,
-                               autocvar_g_balance_health_limit);
-                       // Correct code:
-                       //player.health = bound(player.health, player.health + amount,
-                       //      min(autocvar_g_balance_health_limit,
-                       //      RESOURCE_AMOUNT_HARD_LIMIT));
                        player.pauserothealth_finished = max(player.pauserothealth_finished,
                                time + autocvar_g_balance_pause_health_rot);
                        return;
                }
-               case armorvalue:
+               case RESOURCE_ARMOR:
                {
-                       // Ugly hack. We do not check if armor goes beyond hard limit since
-                       // currently it is done in player_regen. We need to bring back this
-                       // check when other code is ported to this function.
-                       player.armorvalue = bound(player.armorvalue, player.armorvalue +
-                               amount, autocvar_g_balance_armor_limit);
-                       // Correct code:
-                       //player.armorvalue = bound(player.armorvalue, player.armorvalue +
-                       //      amount, min(autocvar_g_balance_armor_limit,
-                       //      RESOURCE_AMOUNT_HARD_LIMIT));
                        player.pauserotarmor_finished = max(player.pauserotarmor_finished,
                                time + autocvar_g_balance_pause_armor_rot);
                        return;
                }
-               case ammo_shells:
-               case ammo_nails:
-               case ammo_rockets:
-               case ammo_cells:
-               case ammo_plasma:
+               case RESOURCE_FUEL:
                {
-                       GivePlayerAmmo(player, resource_type, amount);
-                       return;
-               }
-               case ammo_fuel:
-               {
-                       player.ammo_fuel = bound(player.ammo_fuel, player.ammo_fuel +
-                               amount, min(g_pickup_fuel_max, RESOURCE_AMOUNT_HARD_LIMIT));
                        player.pauserotfuel_finished = max(player.pauserotfuel_finished,
                                time + autocvar_g_balance_pause_fuel_rot);
                        return;
@@ -740,58 +817,25 @@ void GivePlayerResource(entity player, .float resource_type, float amount)
        }
 }
 
-void GivePlayerHealth(entity player, float amount)
+void GivePlayerResourceViaProperty(entity player, .float resource_property,
+       float amount)
 {
-       GivePlayerResource(player, health, amount);
+       GivePlayerResource(player, GetResourceType(resource_property), amount);
 }
 
-void GivePlayerArmor(entity player, float amount)
+void GivePlayerHealth(entity player, float amount)
 {
-       GivePlayerResource(player, armorvalue, amount);
+       GivePlayerResource(player, RESOURCE_HEALTH, amount);
 }
 
-void GivePlayerAmmo(entity player, .float ammotype, float amount)
+void GivePlayerArmor(entity player, float amount)
 {
-       if (amount == 0)
-       {
-               return;
-       }
-       float maxvalue = RESOURCE_AMOUNT_HARD_LIMIT;
-       switch (ammotype)
-       {
-               case ammo_shells:
-               {
-                       maxvalue = g_pickup_shells_max;
-                       break;
-               }
-               case ammo_cells:
-               {
-                       maxvalue = g_pickup_cells_max;
-                       break;
-               }
-               case ammo_rockets:
-               {
-                       maxvalue = g_pickup_rockets_max;
-                       break;
-               }
-               case ammo_plasma:
-               {
-                       maxvalue = g_pickup_plasma_max;
-                       break;
-               }
-               case ammo_nails:
-               {
-                       maxvalue = g_pickup_nails_max;
-                       break;
-               }
-       }
-       player.(ammotype) = min(player.(ammotype) + amount,
-               min(maxvalue, RESOURCE_AMOUNT_HARD_LIMIT));
+       GivePlayerResource(player, RESOURCE_ARMOR, amount);
 }
 
 void GivePlayerFuel(entity player, float amount)
 {
-       GivePlayerResource(player, ammo_fuel, amount);
+       GivePlayerResource(player, RESOURCE_FUEL, amount);
 }
 
 float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax)
@@ -808,7 +852,7 @@ float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax
                        {
                                amount = ammomax - player.(ammotype);
                        }
-                       GivePlayerResource(player, ammotype, amount);
+                       GivePlayerResourceViaProperty(player, ammotype, amount);
                        return true;
                }
        }
@@ -817,7 +861,8 @@ float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax
                float mi = min(item.(ammotype), ammomax);
                if (player.(ammotype) < mi)
                {
-                       GivePlayerResource(player, ammotype, mi - player.(ammotype));
+                       GivePlayerResourceViaProperty(player, ammotype, mi -
+                               player.(ammotype));
                }
                return true;
        }
index f557e10308cc0d961df222bcb9a021dc4fd33399..d150ee774d37c1ac60ff4c0abb591fda26a4a80c 100644 (file)
@@ -7,6 +7,19 @@
 /// \brief Unconditional maximum amount of resources the player can have.
 const int RESOURCE_AMOUNT_HARD_LIMIT = 999;
 
+/// \brief Describes the available resource types.
+enum
+{
+       RESOURCE_HEALTH, ///< Health.
+       RESOURCE_ARMOR, ///< Armor.
+       RESOURCE_SHELLS, ///< Shells (used by shotgun).
+       RESOURCE_BULLETS, ///< Bullets (used by machinegun and rifle)
+       RESOURCE_ROCKETS, ///< Rockets (used by mortar, hagar, devastator, etc).
+       RESOURCE_CELLS, ///< Cells (used by electro, crylink, vortex, etc)
+       RESOURCE_PLASMA, ///< Plasma (unused).
+       RESOURCE_FUEL ///< Fuel (used by jetpack).
+};
+
 const int AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
 
 // item networking
@@ -87,12 +100,30 @@ void Item_ScheduleRespawn(entity e);
 
 void Item_ScheduleInitialRespawn(entity e);
 
+/// \brief Converts resource entity property to resource type.
+/// \param[in] resource_property Resource entity property to convert.
+/// \return Resource type (a RESOURCE_* constant).
+int GetResourceType(.float resource_property);
+
+/// \brief Converts resource type (a RESOURCE_* constant) to entity property.
+/// \param[in] resource_type Type of the resource.
+/// \return Entity proprty for that resource.
+.float GetResourceProperty(int resource_type);
+
 /// \brief Gives player a resource such as health, armor or ammo.
 /// \param[in,out] player Player to give resource to.
-/// \param[in] resource_type Type of the resource.
+/// \param[in] resource_type Type of the resource (a RESOURCE_* constant).
+/// \param[in] amount Amount of resource to give.
+/// \return No return.
+void GivePlayerResource(entity player, int resource_type, float amount);
+
+/// \brief Gives player a resource such as health, armor or ammo.
+/// \param[in,out] player Player to give resource to.
+/// \param[in] resource_property Entity property of the resource.
 /// \param[in] amount Amount of resource to give.
 /// \return No return.
-void GivePlayerResource(entity player, .float resource_type, float amount);
+void GivePlayerResourceViaProperty(entity player, .float resource_property,
+       float amount);
 
 /// \brief Gives health to the player.
 /// \param[in,out] player Player to give health to.
@@ -106,13 +137,6 @@ void GivePlayerHealth(entity player, float amount);
 /// \return No return.
 void GivePlayerArmor(entity player, float amount);
 
-/// \brief Gives ammo of the specified type to the player.
-/// \param[in,out] player Player to give ammo to.
-/// \param[in] type Ammo type property.
-/// \param[in] amount Amount of ammo to give.
-/// \return No return.
-void GivePlayerAmmo(entity player, .float ammotype, float amount);
-
 /// \brief Gives fuel to the player.
 /// \param[in,out] player Player to give fuel to.
 /// \param[in] amount Amount of fuel to give.
index bc09d7a8cd9d92d3da6340807e8a09fd13b384cc..eddb1e5caaf7fb09991760723c7a8f55f38df5ba 100644 (file)
@@ -620,6 +620,26 @@ enum {
        MUT_ITEMTOUCH_PICKUP // return this flag to have the item "picked up" and taken even after mutator handled it
 };
 
+/** Called when the amount of player resources changes. Can be used to override
+resource limit. */
+#define EV_GetResourceLimit(i, o) \
+       /** resource type */ i(int, MUTATOR_ARGV_0_int) \
+       /** limit */         i(float, MUTATOR_ARGV_1_float) \
+       /**/                 o(float, MUTATOR_ARGV_1_float) \
+       /**/
+MUTATOR_HOOKABLE(GetResourceLimit, EV_GetResourceLimit);
+
+/** Called when player is being given some resource. See RESOURCE_* constants
+for resource types. Return true to forbid giving. */
+#define EV_GivePlayerResource(i, o) \
+       /** player */        i(entity, MUTATOR_ARGV_0_entity) \
+       /** resource type */ i(int, MUTATOR_ARGV_1_int) \
+       /**/                 o(int, MUTATOR_ARGV_1_int) \
+       /** amount */        i(float, MUTATOR_ARGV_2_float) \
+       /**/                 o(float, MUTATOR_ARGV_2_float) \
+       /**/
+MUTATOR_HOOKABLE(GivePlayerResource, EV_GivePlayerResource);
+
 /** called at when a player connect */
 #define EV_ClientConnect(i, o) \
     /** player */ i(entity, MUTATOR_ARGV_0_entity) \