OnPlayerDeath
OnPlayerDeath is called inside BasePlayer.Die just before the player fully dies, after the wound check. Return a non-null value to skip the vanilla death sequence (sleeping bag registration and base death handling).
object OnPlayerDeath(BasePlayer player, HitInfo info)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer who is dying. Check it for null and use IsNpc() to separate bots and scientists from real players when your logic should only cover humans. |
info | HitInfo | The HitInfo describing the killing blow: InitiatorPlayer (the attacker if a player landed it), Initiator, Weapon, HitPositionWorld and damageTypes. It can be null when the player dies from environment or suicide, so null-check it before reading anything. |
Return value
Return null to let the vanilla death continue: sleeping bag death handling runs and the base death logic executes. Return any non-null value to abort that block, so the player is not registered as dead through the normal path and stays as they were.
How it works
The hook fires from BasePlayer.Die at the point where the game has decided the player is not going to be wounded instead. It runs after the active belt item has been dropped and after WoundInsteadOfDying returns false, but before SleepingBag.OnPlayerDeath and the base Die call. That ordering matters: the player still exists, is still connected, and their backpack, sleeping bags and world state have not been touched yet.
player is the victim. info is the hit that caused the death and is the only way to identify the killer from this hook; it may be null for non-combat deaths. Read info.InitiatorPlayer for the player responsible, or info.Initiator for turrets, traps and animals. Declaring the second parameter as the exact HitInfo type is required; you cannot narrow it further.
Returning a non-null object suppresses the rest of the death path, which makes this useful for postponing or replacing a death, but the player is not revived automatically. Call Heal and reset wounds yourself if you block it.
Example plugin: New-player spawn protection from player kills
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Death Protection", "RustPluginGenerator", "1.0.0")]
[Description("Protects freshly connected players from being killed by other players.")]
public class DeathProtection : RustPlugin
{
private const string PermBypass = "deathprotection.bypass";
private PluginConfig config;
private readonly Dictionary<ulong, float> joinTimes = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Protection seconds after connect")]
public float ProtectionSeconds { get; set; } = 300f;
[JsonProperty("Announce blocked kills to attacker")]
public bool NotifyAttacker { 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>
{
["Protected"] = "You killed {0}, but they are under spawn protection.",
["Blocked"] = "Your spawn protection saved you from {0}."
}, 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 OnPlayerConnected(BasePlayer player)
{
if (player == null) return;
joinTimes[player.userID] = Time.realtimeSinceStartup;
}
private void OnPlayerDisconnected(BasePlayer player, string reason)
{
if (player == null) return;
joinTimes.Remove(player.userID);
}
private bool IsProtected(BasePlayer player)
{
if (player == null) return false;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return false;
float joined;
if (!joinTimes.TryGetValue(player.userID, out joined)) return false;
return Time.realtimeSinceStartup - joined < config.ProtectionSeconds;
}
private object OnPlayerDeath(BasePlayer player, HitInfo info)
{
if (player == null || player.IsNpc || !player.IsConnected) return null;
if (!IsProtected(player)) return null;
if (info == null) return null;
BasePlayer attacker = info.InitiatorPlayer;
if (attacker == null || attacker == player || attacker.IsNpc) return null;
if (attacker.currentTeam != 0 && attacker.currentTeam == player.currentTeam) return null;
player.Heal(player.MaxHealth());
if (config.NotifyAttacker)
attacker.ChatMessage(Msg("Protected", attacker.UserIDString, player.displayName));
player.ChatMessage(Msg("Blocked", player.UserIDString, attacker.displayName));
return true;
}
}
}The plugin tracks how long each player has been connected and shields anyone under the configured threshold from dying to another player. In OnPlayerDeath it confirms the victim is a real connected player, reads info.InitiatorPlayer, and skips NPCs, attackers on the same team and non-player kills. If the victim is still protected it heals them to full, notifies the attacker and returns true so the vanilla death path is skipped. The join timestamp is stored in memory and cleared on disconnect, so no data files are involved. All chat text goes through the language file, and the protection flag is exposed as a permission for staff.
Common use cases
Spawn protection
Cancel deaths of freshly connected players who are killed by other players, then heal them and warn the attacker. Keep a timer or join timestamp to know who is still protected.
Kill feed and kill rewards
Read info.InitiatorPlayer to identify the killer, then award Economics currency or broadcast a kill message. Returning null keeps the death normal.
Arena and event handling
Detect deaths inside a custom event zone, strip the victim's event kit and return them to a lobby. Pair with OnPlayerRespawn to restore normal gear afterwards.
Pitfalls
info can be null
Fall damage, starvation, radiation and suicide do not always carry a HitInfo. Always null-check info and info.InitiatorPlayer before using them, or the hook will throw for those deaths.
Blocking death does not revive the player
Returning a value skips the vanilla death block only. If you want the player to survive, call Heal with the max health and make sure they are not already flagged wounded; otherwise state can desync.
This is not OnEntityDeath
OnEntityDeath fires for every entity including players, but OnPlayerDeath fires earlier, inside BasePlayer.Die. Use this hook when you need the pre-death state, and OnEntityDeath when you need the corpse or loot that exists after the kill.
Plugin recipes that use OnPlayerDeath
- How to make a Rust /back to death plugin (Oxide/Carbon)Records each player's death position in OnPlayerDeath and lets them teleport back with /back while a configurable time window is still open, subject to a per-player cooldown and a permission.
- How to make a Rust backpack plugin (Oxide/Carbon personal storage)Adds a /backpack command that opens a per-player StorageContainer sized by permission, with contents persisted to oxide/data and optionally dropped on death. Contents are saved in OnPlayerLootEnd and restored on open.
- How to make a Rust death cause stats plugin (Oxide/Carbon)This plugin records every player death, classifies the cause from the HitInfo passed to OnPlayerDeath, and stores running totals per player so /deaths can print a breakdown of PvP kills, NPCs, animals, falls, drowning, cold and other causes.
- How to make a Rust death messages plugin (Oxide/Carbon)Broadcasts a formatted death message to the whole server for every player death, using OnPlayerDeath to read the victim, the attacker, the weapon and the distance and to pick a PvP, NPC, animal or environmental template from config.
- How to make a Rust death penalty plugin (scrap transfer on PvP death)Moves a configurable percentage of a dead player's carried scrap to their killer using OnPlayerDeath, with min/max clamps and separate handling for team kills and NPC kills.
- How to make a Rust longest shot plugin (Oxide/Carbon)Tracks each player's longest projectile kill distance and the server-wide record, saved to oxide/data, with a /longest chat command and an announcement when the server record is beaten. It uses OnPlayerDeath.
- How to make a Rust PvP kill log plugin (rolling history + /kills lookup)Records every PvP kill (killer, victim, weapon, distance, headshot flag, position, timestamp) into a capped data file and lets admins read any player's last 10 kills with /kills <name>. Built on the OnPlayerDeath hook.
- How to make a Rust team death alerts plugin (killer and grid)Sends a chat alert to every online teammate when a player dies, including the killer name and the map grid of the death. Uses OnPlayerDeath and RelationshipManager team lookup.
Build a plugin with OnPlayerDeath
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 OnPlayerDeath
Generate