OnPlayerCorpseSpawned
OnPlayerCorpseSpawned is called from BasePlayer.CreateCorpse right after the player's corpse entity is created and its items are populated, but before CreateCorpse returns the corpse.
void OnPlayerCorpseSpawned(BasePlayer player, PlayerCorpse playerCorpse)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer whose death produced the corpse. Still valid during this hook, so you can read UserIDString, displayName, team, and position from it. |
playerCorpse | PlayerCorpse | The freshly created PlayerCorpse entity that now holds the player's loot. Use it to clear the inventory, adjust loot, apply a skin, move the corpse, or store its net ID. |
Return value
The return value is ignored. The game still returns the created PlayerCorpse from CreateCorpse regardless of what your hook method returns, and the corpse is not destroyed, replaced, or modified by returning a value.
How it works
This hook fires inside BasePlayer.CreateCorpse, immediately after the corpse's containedItems list has received its final entries (including the fat bonus) and just before the method returns the corpse to the caller. That means it runs once per successful corpse creation, which in practice is when a player dies and leaves a lootable body — not when a corpse is later looted, decayed, or destroyed.
player is the dying player and is still usable for identity data (name, Steam ID, team, position). playerCorpse is the PlayerCorpse entity; from it you can reach inventory (ItemContainer), transform.position, net.ID.Value, OwnerID, and flags. Both arguments can be null-checked defensively; in normal gameplay they will be set.
Declaring the first parameter as BasePlayer is required. If you widen or narrow the second parameter, Oxide only calls your method when the runtime instance matches the declared type — a PlayerCorpse parameter is the safe choice because that is what the game creates.
Because the corpse already contains the copied loot at this point, clearing inventory.itemList, adding items, or tagging the corpse for later identification all work here. Returning anything has no effect on the corpse creation.
Example plugin: Disable player corpses with a permission bypass
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("NoPlayerCorpses", "RustPluginGenerator", "1.0.0")]
[Description("Empties fresh player corpses unless the owner has the bypass permission.")]
public class NoPlayerCorpses : RustPlugin
{
private const string PermBypass = "noplayercorpses.keep";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Empty player corpses")]
public bool EmptyCorpses { get; set; } = true;
[JsonProperty("Warn the dead player")]
public bool WarnPlayer { get; set; } = 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>
{
["CorpseEmptied"] = "Your body was cleared on death and cannot be looted."
}, 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 void OnPlayerCorpseSpawned(BasePlayer player, PlayerCorpse playerCorpse)
{
if (!config.EmptyCorpses) return;
if (player == null || playerCorpse == null) return;
if (player.IsNpc) return;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return;
var container = playerCorpse.containers != null && playerCorpse.containers.Length > 0
? playerCorpse.containers[0]
: null;
if (container == null) return;
for (int i = container.itemList.Count - 1; i >= 0; i--)
{
var item = container.itemList[i];
if (item == null) continue;
item.Remove();
}
container.MarkDirty();
if (config.WarnPlayer && player.IsConnected)
{
player.ChatMessage(Msg("CorpseEmptied", player.UserIDString));
}
}
}
}The plugin empties each new player corpse so nothing can be looted, leaving the body to decay normally. It registers a bypass permission (noplayercorpses.keep) and skips handling when the dead player has that permission. In OnPlayerCorpseSpawned it returns early if the config toggle is off, if the player or corpse is null, if the player is an NPC, or if the bypass permission is granted. It then takes the first container from playerCorpse.containers (bailing out if there is none), removes every item in its itemList, and calls MarkDirty() on that container so clients see the change. If the 'Warn the dead player' option is enabled and the player is still connected, the owner receives the CorpseEmptied message, which is stored in the language file so server owners can localize it. A config toggle lets admins turn the behaviour off without unloading.
Common use cases
Empty bodies on PvP servers
Clear every player corpse's inventory so kills never drop loot, keeping the economy controlled by vendors or custom loot tables.
Tag or mark corpses for later cleanup
Store
playerCorpse.net.ID.Valuein a data file with a timestamp so a scheduled task can despawn unlooted bodies after a configurable time.Relocate the corpse to a spawn room
Move
playerCorpse.transform.positionfor players dying inside a custom arena so their body appears at a designated corpse locker instead of where they died.
Pitfalls
Item mutations need a container refresh
Removing items directly from
playerCorpse.inventory.itemListdoes not automatically resync clients; callplayerCorpse.inventory.MarkDirty()after your changes.Runs for every death, not every body
CreateCorpseis only invoked when a lootable body is created. Players withEnableSavingoff, NPCs, or bodies that were disabled by another plugin may not hit this hook at all.Do not destroy the corpse here
Calling
playerCorpse.Kill()inside the hook interrupts nothing in the game path, but the method still returns the entity; other plugins listening forOnEntityKillmay run out of order. Prefer emptying the inventory or scheduling a delayedKill().
Build a plugin with OnPlayerCorpseSpawned
Describe what should happen and get a compiled plugin that uses this hook.
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 OnPlayerCorpseSpawned
Generate