From 56a863a9799e7a51a0ac628125a5e42b1babbcca Mon Sep 17 00:00:00 2001 From: Lyberta Date: Mon, 19 Mar 2018 13:59:10 +0300 Subject: [PATCH] Added FilterItemDefinition hook. --- qcsrc/common/items/item.qh | 13 ++++++++- .../mutator/melee_only/sv_melee_only.qc | 6 ++-- qcsrc/common/mutators/mutator/nix/sv_nix.qc | 8 +++--- .../mutator/random_items/sv_random_items.qc | 9 ++++-- qcsrc/server/items.qc | 28 +++++++++++++++++++ qcsrc/server/items.qh | 22 ++++++++++++++- qcsrc/server/mutators/events.qh | 8 ++++++ qcsrc/server/mutators/mutator/gamemode_lms.qc | 10 +++---- qcsrc/server/weapons/spawning.qc | 7 +++++ 9 files changed, 94 insertions(+), 17 deletions(-) diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh index b7fc933e8..effbf0c7e 100644 --- a/qcsrc/common/items/item.qh +++ b/qcsrc/common/items/item.qh @@ -7,6 +7,10 @@ #include #endif +#ifdef SVQC +#include +#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,14 @@ 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)) \ + { \ + return; \ + } \ + StartItem(this, item); \ + } #else diff --git a/qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc b/qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc index d6796fc05..5603dd490 100644 --- a/qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc +++ b/qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc @@ -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: diff --git a/qcsrc/common/mutators/mutator/nix/sv_nix.qc b/qcsrc/common/mutators/mutator/nix/sv_nix.qc index c174b530f..953321cc0 100644 --- a/qcsrc/common/mutators/mutator/nix/sv_nix.qc +++ b/qcsrc/common/mutators/mutator/nix/sv_nix.qc @@ -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; } diff --git a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc index 3d3057462..3d5d5c0f8 100644 --- a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc +++ b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc @@ -172,7 +172,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 +191,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 +244,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); diff --git a/qcsrc/server/items.qc b/qcsrc/server/items.qc index 7d248834f..ebb16543d 100644 --- a/qcsrc/server/items.qc +++ b/qcsrc/server/items.qc @@ -13,6 +13,34 @@ /// 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(); diff --git a/qcsrc/server/items.qh b/qcsrc/server/items.qh index 1abcf64e0..d8703370c 100644 --- a/qcsrc/server/items.qh +++ b/qcsrc/server/items.qh @@ -4,6 +4,26 @@ /// \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. @@ -12,7 +32,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. diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index 6853c04a1..ab713e044 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -229,6 +229,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 diff --git a/qcsrc/server/mutators/mutator/gamemode_lms.qc b/qcsrc/server/mutators/mutator/gamemode_lms.qc index 94c4a998c..a57b2ae2d 100644 --- a/qcsrc/server/mutators/mutator/gamemode_lms.qc +++ b/qcsrc/server/mutators/mutator/gamemode_lms.qc @@ -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; } diff --git a/qcsrc/server/weapons/spawning.qc b/qcsrc/server/weapons/spawning.qc index d47351cb3..17f2ddeee 100644 --- a/qcsrc/server/weapons/spawning.qc +++ b/qcsrc/server/weapons/spawning.qc @@ -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) -- 2.39.2