Skip to content
RustPluginGenerator

OnEntityPickedUp

OnEntityPickedUp is called after a BaseCombatEntity's own OnPickedUp method runs, which happens when a player picks up a lootable combat entity such as a corpse. It receives the entity, the item created for the player and the player who picked it up.

Signature
void OnEntityPickedUp(BaseCombatEntity entity, Item createdItem, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
entityBaseCombatEntityThe BaseCombatEntity that was picked up, such as a corpse, animal, NPC or player.
createdItemItemThe Item instance that the pickup created for the player. It may be null on unusual paths, so null-check it before reading properties.
playerBasePlayerThe BasePlayer who performed the pickup. This can be null when the pickup was not triggered by a connected player.

Return value

The hook is injected with a plain continue behavior: the original OnPickedUp method returns void, so whatever your method returns is discarded. Returning a value does not block, cancel or change the pickup.

How it works

This hook fires inside BaseCombatEntity.OnPickedUp, the virtual method the game calls when a combat entity is converted into a carryable item and handed to a player. The common trigger is picking up a corpse or similar lootable combat body. The method only publishes the event; it does not change what the game does with the item after dispatch.

entity is the combat entity being picked up and is useful when you need its prefab, position, owner ID or the container it carried. createdItem is the new Item the pickup produced, so you can inspect its shortname, amount or skin before or after it reaches the inventory. player is the picker, handy for permission checks or per-player messaging.

Because the hook is patched into a virtual method on BaseCombatEntity, every subclass inherits it. Declaring a more specific parameter type (for example LootableCorpse or BasePlayer) narrows dispatch: Oxide skips your method when the argument is not an instance of the declared type. Only fire your code for the subtypes you care about.

Keep the method cheap. This can run frequently on populated servers when players clear corpses.

Example plugin: Log corpse pickups to an in-memory tally and notify the picker

CorpsePickupNotifier.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Corpse Pickup Notifier", "RustPluginGenerator", "1.0.0")]
    [Description("Notifies players when they pick up a corpse and tracks per-player pickup counts.")]
    public class CorpsePickupNotifier : RustPlugin
    {
        private const string PermCommand = "corpsepickupnotifier.use";

        private PluginConfig config;
        private readonly Dictionary<ulong, int> pickupCounts = new Dictionary<ulong, int>();

        private class PluginConfig
        {
            [JsonProperty("Notify player on pickup")]
            public bool NotifyOnPickup = 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>
            {
                ["PickedUp"] = "You picked up {0} ({1} item(s)). Total corpse pickups: {2}.",
                ["NoData"] = "You have not picked up any corpses yet.",
                ["CommandUsage"] = "Usage: /corpsepickups"
            }, 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(PermCommand, this);
        }

        private void OnEntityPickedUp(LootableCorpse corpse, Item createdItem, BasePlayer player)
        {
            if (corpse == null || player == null) return;
            if (!player.userID.IsSteamId()) return;

            int count;
            pickupCounts.TryGetValue(player.userID, out count);
            count++;
            pickupCounts[player.userID] = count;

            if (!config.NotifyOnPickup) return;

            string corpseName = corpse.ShortPrefabName ?? "corpse";
            string itemName = createdItem != null && createdItem.info != null ? createdItem.info.displayName.english : "loot";
            int amount = createdItem != null ? createdItem.amount : 0;

            player.ChatMessage(Msg("PickedUp", player.UserIDString, corpseName, amount, count));
        }

        [ChatCommand("corpsepickups")]
        private void CmdCorpsePickups(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermCommand))
            {
                player.ChatMessage("You do not have permission to use this command.");
                return;
            }

            int count;
            if (!pickupCounts.TryGetValue(player.userID, out count) || count <= 0)
            {
                player.ChatMessage(Msg("NoData", player.UserIDString));
                return;
            }

            player.ChatMessage(Msg("PickedUp", player.UserIDString, "your last corpse", 0, count));
        }

        private void Unload()
        {
            pickupCounts.Clear();
        }
    }
}

The plugin listens for OnEntityPickedUp and narrows the entity parameter to LootableCorpse, so it only reacts to corpses and ignores other combat entities. It null-checks the player and item, reads the corpse's short prefab name and the created item's shortname, then sends a localized chat message to the picker with the details. A per-player counter stored in a Dictionary<ulong, int> tracks how many corpses each player has picked up during the session; the /corpsepickups chat command prints the caller's current total. Nothing is written to disk, so the counter resets on reload. Messages live in the language file and are read through the Msg helper, so admins can translate them without touching code.

Common use cases

  • Reward corpse cleanups

    Grant a small in-game reward or currency whenever a player picks up a corpse, using the player parameter to identify who to pay and the entity parameter to filter by prefab.

  • Track player activity

    Increment a per-player stat each time a combat entity is picked up so you can display PvE cleanup counts on a leaderboard or in a chat command.

  • Audit item grants

    Log the createdItem shortname and amount together with the picker's ID to an oxide/data file for admin review of unusual corpse contents.

Pitfalls

  • Fires for more than corpses

    The hook is patched into the base virtual method, so any BaseCombatEntity subclass can reach it. Narrow the parameter type or check the prefab if you only want corpses.

  • Argument can be null

    The created item or the player may be null on some code paths. Always null-check both before reading members or calling chat methods.

  • Return value is ignored

    Returning a value does not block or alter the pickup. Use permission checks or item removal after the fact if you need to intervene.

Build a plugin with OnEntityPickedUp

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

Prompt: Reward corpse cleanups using the OnEntityPickedUp 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 OnEntityPickedUp

Generate