From 658b3cecc02ad7040d46f3c4602d1ee874ae5a19 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 27 Aug 2021 16:14:56 +1000 Subject: [PATCH] Add g_powerups_dropondeath setting (off by default, whitelisted) --- .../mutator/powerups/powerup/shield.qh | 2 +- .../mutators/mutator/powerups/sv_powerups.qc | 33 +++++++++++++++++++ .../mutators/mutator/powerups/sv_powerups.qh | 1 + qcsrc/server/items/spawning.qc | 13 ++++++++ qcsrc/server/items/spawning.qh | 6 ++++ qcsrc/server/world.qc | 1 + xonotic-server.cfg | 1 + 7 files changed, 56 insertions(+), 1 deletion(-) diff --git a/qcsrc/common/mutators/mutator/powerups/powerup/shield.qh b/qcsrc/common/mutators/mutator/powerups/powerup/shield.qh index 10900e86a..508a39487 100644 --- a/qcsrc/common/mutators/mutator/powerups/powerup/shield.qh +++ b/qcsrc/common/mutators/mutator/powerups/powerup/shield.qh @@ -53,7 +53,7 @@ SPAWNFUNC_ITEM(item_shield, ITEM_Shield) SPAWNFUNC_ITEM(item_invincible, ITEM_Shield) CLASS(Shield, Powerups) - ATTRIB(Shield, netname, string, "shield"); + ATTRIB(Shield, netname, string, "invincible"); // NOTE: referring to as invincible so that it matches the powerup item ATTRIB(Shield, m_name, string, _("Shield")); ATTRIB(Shield, m_icon, string, "shield"); ENDCLASS(Shield) diff --git a/qcsrc/common/mutators/mutator/powerups/sv_powerups.qc b/qcsrc/common/mutators/mutator/powerups/sv_powerups.qc index 2ac0bbccc..47ad0c509 100644 --- a/qcsrc/common/mutators/mutator/powerups/sv_powerups.qc +++ b/qcsrc/common/mutators/mutator/powerups/sv_powerups.qc @@ -77,6 +77,39 @@ MUTATOR_HOOKFUNCTION(powerups, MonsterValidTarget) return StatusEffects_active(STATUSEFFECT_Invisibility, targ); } +void powerups_DropItem(entity this, StatusEffects effect) +{ + entity item = Item_DefinitionFromInternalName(effect.netname); + float timeleft = StatusEffects_gettime(effect, this); + if((timeleft - time) <= 0 || !item) + return; + entity e = spawn(); + // TODO: items cannot hold their "item field" yet, so we need to list all the powerups here! + switch(item) + { + case ITEM_Strength: e.strength_finished = timeleft; break; + case ITEM_Shield: e.invincible_finished = timeleft; break; + case ITEM_Invisibility: e.invisibility_finished = timeleft; break; + case ITEM_Speed: e.speed_finished = timeleft; break; + } + Item_InitializeLoot(e, item.m_canonical_spawnfunc, this.origin + '0 0 32', randomvec() * 175 + '0 0 175', min(timeleft - time, 10)); + Item_SetExpiring(e, true); +} + +MUTATOR_HOOKFUNCTION(powerups, PlayerDies) +{ + if(!autocvar_g_powerups_dropondeath) + return; + + entity frag_target = M_ARGV(2, entity); + + FOREACH(StatusEffect, it.instanceOfPowerups, + { + if(StatusEffects_active(it, frag_target)) + powerups_DropItem(frag_target, it); + }); +} + MUTATOR_HOOKFUNCTION(powerups, PlayerPhysics_UpdateStats) { entity player = M_ARGV(0, entity); diff --git a/qcsrc/common/mutators/mutator/powerups/sv_powerups.qh b/qcsrc/common/mutators/mutator/powerups/sv_powerups.qh index b51438538..1d79396c8 100644 --- a/qcsrc/common/mutators/mutator/powerups/sv_powerups.qh +++ b/qcsrc/common/mutators/mutator/powerups/sv_powerups.qh @@ -5,6 +5,7 @@ #include "powerups.qh" int autocvar_g_powerups; +bool autocvar_g_powerups_dropondeath; bool autocvar_g_powerups_stack; REGISTER_MUTATOR(powerups, true); diff --git a/qcsrc/server/items/spawning.qc b/qcsrc/server/items/spawning.qc index fc8338f38..50ad6a1ce 100644 --- a/qcsrc/server/items/spawning.qc +++ b/qcsrc/server/items/spawning.qc @@ -29,6 +29,19 @@ entity Item_FindDefinition(string class_name) return NULL; } +entity Item_DefinitionFromInternalName(string item_name) +{ + FOREACH(Items, it.netname == item_name, + { + return it; + }); + FOREACH(Weapons, it.netname == item_name, + { + return it.m_pickup; + }); + return NULL; +} + bool Item_IsAllowed(string class_name) { entity definition = Item_FindDefinition(class_name); diff --git a/qcsrc/server/items/spawning.qh b/qcsrc/server/items/spawning.qh index b52449e71..f4bd32e7b 100644 --- a/qcsrc/server/items/spawning.qh +++ b/qcsrc/server/items/spawning.qh @@ -12,6 +12,12 @@ bool startitem_failed; /// found. entity Item_FindDefinition(string class_name); +/// \brief Returns the item definition corresponding to the given internal name. +/// \param[in] item_name Internal netname to search for. +/// \return Item definition corresponding to the given internal name or NULL is not +/// found. +entity Item_DefinitionFromInternalName(string item_name); + /// \brief Checks whether the items with the specified class name are allowed to /// spawn. /// \param[in] class_name Item class name to check. diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index 6c397d053..ee8bdbdde 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -461,6 +461,7 @@ void cvar_changes_init() BADCVAR("g_physics_clientselect"); BADCVAR("g_pinata"); BADCVAR("g_powerups"); + BADCVAR("g_powerups_dropondeath"); BADCVAR("g_player_brightness"); BADCVAR("g_rocket_flying"); BADCVAR("g_rocket_flying_disabledelays"); diff --git a/xonotic-server.cfg b/xonotic-server.cfg index 39323f0dc..b1718900a 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -198,6 +198,7 @@ set g_shootfromfixedorigin "" "if set to a string like 0 y z, the gun is moved t set g_weapon_stay 0 "1: ghost weapons can be picked up but give no ammo, thrown guns have ammo 2: ghost weapons can be picked up and refill ammo to one pickup size, thrown guns have no ammo (to prevent infinite ammo abuse)" set g_weapon_throwable 1 "if set to 1, weapons can be dropped" set g_powerups -1 "if set to 0 no powerups will spawn, if 1 they will spawn in all game modes, -1 is game mode default" +set g_powerups_dropondeath 0 "whether or not held powerups should be droppd when the player dies" set g_powerups_stack 0 "enables stacking of powerup timers when picking up a powerup you already have; otherwise timer is reset to the time granted by the item, if greater than the time you currently have" set g_powerups_strength 1 "allow strength powerups to spawn" set g_powerups_shield 1 "allow shield powerups to spawn" -- 2.39.2