Skip to content
RustPluginGenerator

OnPlayerActiveShieldDrop

OnPlayerActiveShieldDrop is called when PlayerBelt.DropActive is about to drop a player's active shield item, before the item is detached from the player.

Signature
object OnPlayerActiveShieldDrop(BasePlayer player, Shield foundShield)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer whose active held entity is the shield being dropped. This is the player that TryGetActiveShield resolved, not necessarily the one who triggered the drop if the method is called indirectly.
foundShieldShieldThe Shield component of the active belt/wear item being dropped. Use foundShield.GetItem() to access the underlying Item and inspect or remove it.

Return value

Returning null (or nothing, since C# void-like hook bodies can just fall through) lets the game continue and the shield item is dropped as DroppedItem. Returning any non-null value stops the method immediately, so the shield stays attached to the player and is not dropped.

How it works

This hook fires inside PlayerBelt.DropActive(Vector3 position, Vector3 velocity), which the game calls when the active belt item is a shield and the drop path runs (default drop input, death handling, or another system invoking DropActive). It runs after the shield has been resolved with TryGetActiveShield but before foundShield.GetItem().Drop(...) is executed.

  • player is the owning player, useful for permission checks, team lookups, or chat feedback.
  • foundShield exposes the Shield component; call foundShield.GetItem() to read skin, condition, or amount, and GetOwnerPlayer() to confirm the owner.

Declaring player as a more specific type (e.g. BasePlayer is already specific) has no effect here; the hook always receives a BasePlayer. If you plan to read the item, null-check foundShield and its item anyway.

Because returning a non-null value cancels the original drop, this is the correct place to block shield drops for admins, event arenas, or teams protecting a valuable shield. Do not call PrintWarning or Puts inside this hook because it can fire often on busy PvP servers.

Example plugin: Block shield drops for players in a protected group

ShieldDropGuard.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Shield Drop Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks shield drops for players without a bypass permission and reports the block in chat.")]
    public class ShieldDropGuard : RustPlugin
    {
        private const string PermBypass = "shielddropguard.bypass";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Block shield drops")]
            public bool BlockDrops = true;

            [JsonProperty("Notify player when blocked")]
            public bool NotifyPlayer = true;
        }

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["DropBlocked"] = "Dropping your shield is disabled on this server."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
            => string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            permission.RegisterPermission(PermBypass, this);
        }

        private object OnPlayerActiveShieldDrop(BasePlayer player, Shield foundShield)
        {
            if (!config.BlockDrops || player == null || foundShield == null)
                return null;

            if (permission.UserHasPermission(player.UserIDString, PermBypass))
                return null;

            var item = foundShield.GetItem();
            if (item == null || item.info == null)
                return null;

            if (config.NotifyPlayer && player.IsConnected)
                player.ChatMessage(Msg("DropBlocked", player.UserIDString));

            return true;
        }
    }
}

The plugin adds a shielddropguard.bypass permission. In Init it registers the permission. When OnPlayerActiveShieldDrop fires, the player's id is checked against the permission; if the player does not have it, the hook sends a localized chat message and returns a non-null value, which cancels the drop and keeps the shield equipped. If the player has the bypass permission, the hook returns null so the default drop runs. The item shortname is read from foundShield.GetItem() only inside a null check, just to confirm it is a shield, and admin feedback is kept to a single chat line so the hook stays cheap under load. Unload clears state.

Common use cases

  • Event arena rules

    Cancel shield drops for players inside an arena zone so accidental drops do not litter the play area or let opponents pick up a free shield.

  • Anti-theft for teams

    Block shield drops when the shield belongs to a different player than the dropper (for example a borrowed shield), returning a value only when GetOwnerPlayer() mismatches player.

  • Ranked PvP restrictions

    Prevent shield drops in a ranked queue to keep loadouts deterministic, while granting a bypass permission to moderators for testing.

Pitfalls

  • Any non-null return cancels the drop

    The original method is void, but the patched check treats any non-null return as a stop. Return true or false to cancel; return null to allow the drop. Returning a value you expect to be ignored still blocks it.

  • Not just drop input

    PlayerBelt.DropActive can be invoked by death cleanup or other systems, so blocking here may also block automatic drops. Only cancel when you really want the item to stay in the belt for every call path.

  • Keep the hook cheap

    The hook can fire per player per death. Avoid chat spam, LINQ over the whole server, or expensive permission checks; cache anything you need at load time.

Build a plugin with OnPlayerActiveShieldDrop

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Event arena rules using the OnPlayerActiveShieldDrop hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnPlayerActiveShieldDrop

Generate