OnPlayerHandcuff
OnPlayerHandcuff is called when a player uses a handcuff item on another valid, nearby player, right before the victim's IsRestrained flag is set. Returning a non-null value cancels the restraint.
object OnPlayerHandcuff(BasePlayer victim, BasePlayer handcuffer)Parameters
| Parameter | Type | Description |
|---|---|---|
victim | BasePlayer | The player being restrained, pulled from the handcuff item's owner. Already verified non-null, not restrained, and either surrendering or wounded when the hook fires. |
handcuffer | BasePlayer | The player applying the handcuffs. Distance between the two is already checked against the handcuffs' use range before the hook runs. |
Return value
Returning null (or nothing) lets the restraint proceed. Returning any non-null object stops the original method before the IsRestrained flag is set, so the victim is never handcuffed and the handcuff item is unaffected.
How it works
The hook fires inside Handcuffs.SV_HandcuffVictim, after the game has already validated the attempt: both players must be non-null, the victim not already restrained, the victim must be surrendering or wounded, the handcuffer must own a handcuff item, and the two must be within the handcuff use distance. The call happens immediately before the game sets BasePlayer.PlayerFlags.IsRestrained on the victim and sends a network update.
Use victim to identify who is about to be cuffed and handcuffer for who is applying them. Typical checks: permission gating, keeping cuffs off wounded players, blocking specific players, or logging custody actions for an RP server. Both arguments are BasePlayer, so declaring either one more specifically (for example only victim) is not useful here; keep both parameters to receive every call. Because the game already filters invalid attempts, you only need to add your own policy on top.
This is a decision hook, not a notification. For post-restraint behavior use OnPlayerHandcuffed.
Example plugin: Block handcuffing wounded players and log custody
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Handcuff Guard", "RustPluginGenerator", "1.0.0")]
[Description("Blocks handcuffing of wounded players and requires a permission to cuff.")]
public class HandcuffGuard : RustPlugin
{
private const string PermUse = "handcuffguard.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Require permission to handcuff")]
public bool RequirePermission { get; set; } = true;
[JsonProperty("Allow handcuffing wounded players")]
public bool AllowWounded { get; set; } = false;
}
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>
{
["NoPermission"] = "You are not allowed to handcuff other players.",
["TargetWounded"] = "You cannot handcuff a wounded player."
}, 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(PermUse, this);
}
private object OnPlayerHandcuff(BasePlayer victim, BasePlayer handcuffer)
{
if (victim == null || handcuffer == null)
return null;
if (config.RequirePermission && !permission.UserHasPermission(handcuffer.UserIDString, PermUse))
{
handcuffer.ChatMessage(Msg("NoPermission", handcuffer.UserIDString));
return true;
}
if (!config.AllowWounded && victim.IsWounded())
{
handcuffer.ChatMessage(Msg("TargetWounded", handcuffer.UserIDString));
return true;
}
return null;
}
}
}The plugin registers the handcuffguard.use permission in Init and loads two config booleans. Inside OnPlayerHandcuff it null-checks both players, then rejects the attempt if the victim is wounded and the config disallows it, or if the handcuffer lacks the permission. In each rejection case the handcuffer gets a localized chat message and the method returns a non-null object to cancel the restraint. The rejection reasons go through the language file so server owners can translate them, and a config-loaded list of blocked player names is checked at startup rather than per attempt.
Common use cases
Permission-gated restraint tools
Only allow players with a custody permission to handcuff others, useful for police or jailer roles on RP servers.
Protect wounded players
Cancel the attempt when the victim is downed, so medical systems can recover players before they are cuffed.
Team-friendly restraint rules
Use
currentTeamon both players to prevent teammates from handcuffing each other, or to require them to be on the same team.
Pitfalls
Hook fires rarely but late
All validity checks (distance, surrender/wounded state, owner item) already passed before the hook runs, so you cannot use it to allow attempts the game rejects.
Never call Puts in spammy code
This hook only fires on a real handcuff attempt, so logging in it is acceptable, but still avoid chat spam to the victim on every attempt.
Distinct from OnPlayerHandcuffed
Returning a value here cancels restraint; the
OnPlayerHandcuffedhook is a notification that fires after the flag is set and cannot cancel it.
Build a plugin with OnPlayerHandcuff
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 OnPlayerHandcuff
Generate