]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Lyberta/FilterItemDefinition' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 4 Apr 2018 08:59:42 +0000 (08:59 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 4 Apr 2018 08:59:42 +0000 (08:59 +0000)
Added FilterItemDefinition hook.

See merge request xonotic/xonotic-data.pk3dir!546

qcsrc/common/items/item.qh
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/random_items/sv_random_items.qc
qcsrc/common/mutators/mutator/random_items/sv_random_items.qh
qcsrc/server/defs.qh
qcsrc/server/items.qc
qcsrc/server/items.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/weapons/spawning.qc

index b7fc933e8b5dbaf35dde8a37fca1762c51a4e08a..e59152076b754552eb266411710fdbab1e4efcbb 100644 (file)
@@ -7,6 +7,10 @@
 #include <common/stats.qh>
 #endif
 
+#ifdef SVQC
+#include <server/items.qh>
+#endif
+
 const int IT_UNLIMITED_WEAPON_AMMO             =  BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
 const int IT_UNLIMITED_SUPERWEAPONS            =  BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
 
@@ -48,7 +52,16 @@ const int IT_PICKUPMASK                      = IT_UNLIMITED_AMMO | IT_JETPACK | IT_FU
 .float  invincible_finished = _STAT(INVINCIBLE_FINISHED);
 
 #define SPAWNFUNC_ITEM(name, item) \
-    spawnfunc(name) { StartItem(this, item); }
+    spawnfunc(name) \
+       { \
+               if (!Item_IsDefinitionAllowed(item)) \
+               { \
+                       startitem_failed = true; \
+                       delete(this); \
+                       return; \
+               } \
+               StartItem(this, item); \
+       }
 
 #else
 
index d6796fc0590e0581be335989330a384934bee600..5603dd4901c0601cc8940320acbc1f87b6ab1f3e 100644 (file)
@@ -25,11 +25,11 @@ MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(melee_only, FilterItem)
+MUTATOR_HOOKFUNCTION(melee_only, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       switch (item.itemdef)
+       switch (definition)
        {
                case ITEM_HealthSmall:
                case ITEM_ArmorSmall:
index c174b530f0a48e94cb20d6661fd069ecb0e2ecc4..953321cc0ba5a708bb30d73e0e218b8e4ad67cf0 100644 (file)
@@ -244,15 +244,15 @@ MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
 }
 
-MUTATOR_HOOKFUNCTION(nix, FilterItem)
+MUTATOR_HOOKFUNCTION(nix, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       if(item.itemdef.instanceOfHealth || item.itemdef.instanceOfArmor)
+       if (definition.instanceOfHealth || definition.instanceOfArmor)
        {
                return !autocvar_g_nix_with_healtharmor;
        }
-       else if(item.itemdef.instanceOfPowerup)
+       else if (definition.instanceOfPowerup)
        {
                return !autocvar_g_nix_with_powerups;
        }
index 3d305746269e1a29cbfb718ceb536175d04693af..553dcf582ffccbd27d2ff23adc95e238d49bcb5d 100644 (file)
@@ -7,15 +7,6 @@
 
 //============================ Constants ======================================
 
-enum
-{
-       RANDOM_ITEM_TYPE_HEALTH = 1,
-       RANDOM_ITEM_TYPE_ARMOR,
-       RANDOM_ITEM_TYPE_RESOURCE,
-       RANDOM_ITEM_TYPE_WEAPON,
-       RANDOM_ITEM_TYPE_POWERUP
-};
-
 //======================= Global variables ====================================
 
 // Replace cvars
@@ -72,99 +63,137 @@ string RandomItems_GetRandomItemClassName(string prefix)
        {
                return RandomItems_GetRandomOverkillItemClassName(prefix);
        }
-       return RandomItems_GetRandomVanillaItemClassName(prefix);
+       return RandomItems_GetRandomVanillaItemClassName(prefix,
+               RANDOM_ITEM_TYPE_ALL);
 }
 
-string RandomItems_GetRandomVanillaItemClassName(string prefix)
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types)
 {
-       RandomSelection_Init();
-       string cvar_name = sprintf("g_%s_health_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_armor_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
+       if (types == 0)
        {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_resource_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_weapon_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
-       }
-       cvar_name = sprintf("g_%s_powerup_probability", prefix);
-       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
-       {
-               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
-       }
-       else
-       {
-               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+               return "";
        }
-       int item_type = RandomSelection_chosen_float;
-       switch (item_type)
+       while (types != 0)
        {
-               case RANDOM_ITEM_TYPE_HEALTH:
+               string cvar_name;
+               RandomSelection_Init();
+               if (types & RANDOM_ITEM_TYPE_HEALTH)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfHealth);
+                       cvar_name = sprintf("g_%s_health_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH,
+                                       cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_ARMOR:
+               if (types & RANDOM_ITEM_TYPE_ARMOR)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfArmor);
+                       cvar_name = sprintf("g_%s_armor_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR,
+                                       cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_RESOURCE:
+               if (types & RANDOM_ITEM_TYPE_RESOURCE)
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfAmmo);
+                       cvar_name = sprintf("g_%s_resource_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE,
+                                       cvar(cvar_name), 1);
+                       }
+               }
+               if (types & RANDOM_ITEM_TYPE_WEAPON)
+               {
+                       cvar_name = sprintf("g_%s_weapon_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
+                       }
+               }
+               if (types & RANDOM_ITEM_TYPE_POWERUP)
+               {
+                       cvar_name = sprintf("g_%s_powerup_probability", prefix);
+                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                       {
+                               LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+                       }
+                       else
+                       {
+                               RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+                       }
                }
-               case RANDOM_ITEM_TYPE_WEAPON:
+               int item_type = RandomSelection_chosen_float;
+               string class_name = "";
+               switch (item_type)
                {
-                       RandomSelection_Init();
-                       FOREACH(Weapons, it != WEP_Null &&
-                               !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
+                       case RANDOM_ITEM_TYPE_HEALTH:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfHealth);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_ARMOR:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfArmor);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_RESOURCE:
                        {
-                               cvar_name = sprintf("g_%s_%s_probability", prefix,
-                                       it.m_canonical_spawnfunc);
-                               if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfAmmo);
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_WEAPON:
+                       {
+                               RandomSelection_Init();
+                               FOREACH(Weapons, it != WEP_Null &&
+                                       !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
                                {
-                                       LOG_WARNF("Random items: cvar %s doesn't exist.",
-                                               cvar_name);
-                                       continue;
-                               }
-                               RandomSelection_AddString(it.m_canonical_spawnfunc,
-                                       cvar(cvar_name), 1);
-                       });
-                       return RandomSelection_chosen_string;
+                                       cvar_name = sprintf("g_%s_%s_probability", prefix,
+                                               it.m_canonical_spawnfunc);
+                                       if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+                                       {
+                                               LOG_WARNF("Random items: cvar %s doesn't exist.",
+                                                       cvar_name);
+                                               continue;
+                                       }
+                                       RandomSelection_AddString(it.m_canonical_spawnfunc,
+                                               cvar(cvar_name), 1);
+                               });
+                               class_name = RandomSelection_chosen_string;
+                               break;
+                       }
+                       case RANDOM_ITEM_TYPE_POWERUP:
+                       {
+                               class_name = RandomItems_GetRandomItemClassNameWithProperty(
+                                       prefix, instanceOfPowerup);
+                               break;
+                       }
                }
-               case RANDOM_ITEM_TYPE_POWERUP:
+               if (class_name != "")
                {
-                       return RandomItems_GetRandomItemClassNameWithProperty(prefix,
-                               instanceOfPowerup);
+                       return class_name;
                }
+               types &= ~item_type;
        }
        return "";
 }
@@ -172,7 +201,8 @@ string RandomItems_GetRandomVanillaItemClassName(string prefix)
 string RandomItems_GetRandomInstagibItemClassName(string prefix)
 {
        RandomSelection_Init();
-       FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB,
+       FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
@@ -190,7 +220,8 @@ string RandomItems_GetRandomOverkillItemClassName(string prefix)
 {
        RandomSelection_Init();
        FOREACH(Items, (it.spawnflags & ITEM_FLAG_OVERKILL) &&
-               !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED),
+               !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED) &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_overkill_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
@@ -242,7 +273,8 @@ string RandomItems_GetRandomItemClassNameWithProperty(string prefix,
        .bool item_property)
 {
        RandomSelection_Init();
-       FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL),
+       FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL) &&
+               Item_IsDefinitionAllowed(it),
        {
                string cvar_name = sprintf("g_%s_%s_probability", prefix,
                        it.m_canonical_spawnfunc);
index c9b4dbb9011ca91cd905d0c7221e3f089f4745b0..9ac738ca68ede11020c348c1a681d0b65a0eb7ca 100644 (file)
@@ -7,6 +7,16 @@
 
 bool autocvar_g_random_items; ///< Whether to enable random items.
 
+enum
+{
+       RANDOM_ITEM_TYPE_HEALTH = BIT(0),
+       RANDOM_ITEM_TYPE_ARMOR = BIT(1),
+       RANDOM_ITEM_TYPE_RESOURCE = BIT(2),
+       RANDOM_ITEM_TYPE_WEAPON = BIT(3),
+       RANDOM_ITEM_TYPE_POWERUP = BIT(4),
+       RANDOM_ITEM_TYPE_ALL = BITS(5)
+};
+
 /// \brief Returns a random classname of the item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
 /// \return Random classname of the item.
@@ -16,10 +26,11 @@ string RandomItems_GetRandomItemClassName(string prefix);
 
 /// \brief Returns a random classname of the vanilla item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \param[in] types Bitmask of the types. See RANDOM_ITEM_TYPE constants.
 /// \return Random classname of the vanilla item.
 /// \note This includes mutator items that don't change gameplay a lot such as
 /// jetpack and new toys.
-string RandomItems_GetRandomVanillaItemClassName(string prefix);
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types);
 
 /// \brief Returns a random classname of the instagib item.
 /// \param[in] prefix Prefix of the cvars that hold probabilities.
index 61770f01a71d4744038cb52e2baef86f6f903dc9..f85d6e2b6f22ae53ff521c4e52668c635f5dd5f4 100644 (file)
@@ -182,8 +182,6 @@ float default_weapon_alpha;
 
 string gamemode_name;
 
-float startitem_failed;
-
 string W_Apply_Weaponreplace(string in);
 
 void FixIntermissionClient(entity e);
index 7d248834f72566af97313317a42a3a50c226f637..04b0ba41d596e05d1c40addc88b06a3e8c2640c2 100644 (file)
@@ -6,6 +6,7 @@
 /// \copyright GNU GPLv2 or any later version.
 
 #include "g_subs.qh"
+#include "mutators/events.qh"
 #include <common/weapons/all.qh>
 
 .bool m_isloot; ///< Holds whether item is loot.
 /// this item is on the ground.
 .bool m_isexpiring;
 
+entity Item_FindDefinition(string class_name)
+{
+       FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+       {
+               return it;
+       });
+       FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+       {
+               return it.m_pickup;
+       });
+       return NULL;
+}
+
+bool Item_IsAllowed(string class_name)
+{
+       entity definition = Item_FindDefinition(class_name);
+       if (definition == NULL)
+       {
+               return false;
+       }
+       return Item_IsDefinitionAllowed(definition);
+}
+
+bool Item_IsDefinitionAllowed(entity definition)
+{
+       return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
+}
+
 entity Item_Create(string class_name, vector position, bool no_align)
 {
        entity item = spawn();
index 1abcf64e0879442a3b8ade446bc724ca8250e503..b52449e7158dffab62269d6b17d32a6a7cdcc439 100644 (file)
@@ -4,6 +4,28 @@
 /// \brief Header file that describes the functions related to game items.
 /// \copyright GNU GPLv2 or any later version.
 
+bool startitem_failed;
+
+/// \brief Returns the item definition corresponding to the given class name.
+/// \param[in] class_name Class name to search for.
+/// \return Item definition corresponding to the given class name or NULL is not
+/// found.
+entity Item_FindDefinition(string class_name);
+
+/// \brief Checks whether the items with the specified class name are allowed to
+/// spawn.
+/// \param[in] class_name Item class name to check.
+/// \return True items with the specified class name are allowed to spawn, false
+/// otherwise.
+bool Item_IsAllowed(string class_name);
+
+/// \brief Checks whether the items with the specified definition are allowed to
+/// spawn.
+/// \param[in] definition Item definition to check.
+/// \return True items with the specified definition are allowed to spawn, false
+/// otherwise.
+bool Item_IsDefinitionAllowed(entity definition);
+
 /// \brief Creates a new item.
 /// \param[in] class_name Class name of the item.
 /// \param[in] position Position of the item.
@@ -12,7 +34,7 @@
 /// \return Item on success, NULL otherwise.
 entity Item_Create(string class_name, vector position, bool no_align);
 
-/// \brief Initializes the item according to classname.
+/// \brief Initializes the item according to class name.
 /// \param[in,out] item Item to initialize.
 /// \param[in] class_name Class name to use.
 /// \return No return.
index 6cdf94feb41dd7427eed36b493a094768e634656..0d801ec22e2f811c3cc4ecf72cc50933987c83bf 100644 (file)
@@ -232,6 +232,14 @@ MUTATOR_HOOKABLE(SetStartItems, EV_NO_ARGS);
     /**/
 MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
 
+/** Check if items having the given definition are allowed to spawn.
+ *  Return true to disallow spawning.
+ */
+#define EV_FilterItemDefinition(i, o) \
+    /** item        */ i(entity, MUTATOR_ARGV_0_entity) \
+    /**/
+MUTATOR_HOOKABLE(FilterItemDefinition, EV_FilterItemDefinition);
+
 /**
  * checks if the current item may be spawned (.items and .weapons may be read and written to, as well as the ammo_ fields)
  * return error to request removal
index 94c4a998c2cc616b4d3f1f64487eb4b5fb98e42e..a57b2ae2d07ab150bfd494492935da44e421e221 100644 (file)
@@ -317,14 +317,14 @@ MUTATOR_HOOKFUNCTION(lms, ForbidPlayerScore_Clear)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(lms, FilterItem)
+MUTATOR_HOOKFUNCTION(lms, FilterItemDefinition)
 {
-       entity item = M_ARGV(0, entity);
+       entity definition = M_ARGV(0, entity);
 
-       if(autocvar_g_lms_extra_lives)
-       if(item.itemdef == ITEM_ExtraLife)
+       if (autocvar_g_lms_extra_lives && definition == ITEM_ExtraLife)
+       {
                return false;
-
+       }
        return true;
 }
 
index d47351cb37a727aab87f100d2ccb61ddd98a5824..17f2ddeeee2bb567271f1f689c8376494168a5a6 100644 (file)
@@ -88,6 +88,13 @@ void weapon_defaultspawnfunc(entity this, Weapon e)
                }
        }
 
+       if (!Item_IsDefinitionAllowed(wpn.m_pickup))
+       {
+               delete(this);
+               startitem_failed = true;
+               return;
+       }
+
        if (!this.respawntime)
        {
                if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)