#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.
.float invincible_finished = _STAT(INVINCIBLE_FINISHED);
#define SPAWNFUNC_ITEM(name, item) \
- spawnfunc(name) { StartItem(this, item); }
+ spawnfunc(name) \
+ { \
+ if (!Item_IsDefinitionAllowed(item)) \
+ { \
+ return; \
+ } \
+ StartItem(this, item); \
+ }
#else
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:
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;
}
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);
{
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);
.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);
/// 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();
/// \brief Header file that describes the functions related to game items.
/// \copyright GNU GPLv2 or any later version.
+/// \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.
/// \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.
/**/
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
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;
}
}
}
+ if (!Item_IsDefinitionAllowed(wpn.m_pickup))
+ {
+ delete(this);
+ startitem_failed = true;
+ return;
+ }
+
if (!this.respawntime)
{
if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)