OnTrapDisarm
OnTrapDisarm is called when a player tries to disarm an armed landmine via the Landmine.RPC_Disarm path. Returning a non-null value cancels the disarm attempt.
object OnTrapDisarm(Landmine landmine, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
landmine | Landmine | The Landmine entity being disarmed. Use it to read owner, position, flags or building privilege context. |
player | BasePlayer | The BasePlayer who sent the disarm RPC. This is the player attempting to disarm the trap, not necessarily its owner. |
Return value
Return null to let the disarm proceed normally. Return any non-null value (for example true) and the game method returns immediately, so the mine stays armed and untriggered; the return value itself is discarded because Landmine.RPC_Disarm returns void.
How it works
OnTrapDisarm fires inside Landmine.RPC_Disarm, which runs when a client sends the disarm request for a deployed, armed landmine. The call is placed after the ownership check and the Armed() check but before Triggered(), so it only runs for armed traps that the caller is allowed to touch. The landmine parameter is the trap entity; player is the BasePlayer sending the RPC. Because the parameters are already Landmine and BasePlayer, there is no meaningful narrowing to do; declaring a broader type would not change dispatch here. Note that the hook fires before the 15% random chance that the mine triggers on the disarmer, so a cancel also skips that risk. The hook does not fire for players who own the trap (they pass the triggerPlayerID check and return early), for unarmed mines, or for NPC interactions. Use it for permission gates, cooldowns, or notifications.
Example plugin: Restrict mine disarming to authorized players with a cooldown
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Trap Disarm Guard", "RustPluginGenerator", "1.0.0")]
[Description("Restricts landmine disarming behind a permission and per-player cooldown.")]
public class TrapDisarmGuard : RustPlugin
{
private const string PermDisarm = "trapdisarmguard.disarm";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastDisarm = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Require permission to disarm")]
public bool RequirePermission { get; set; } = true;
[JsonProperty("Cooldown seconds between disarms")]
public float CooldownSeconds { get; set; } = 5f;
}
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>
{
["Disarmed"] = "You disarmed the landmine at {0}.",
["NoPermission"] = "You are not authorized to disarm landmines.",
["Cooldown"] = "Wait {0:0.0}s before disarming another landmine."
}, 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(PermDisarm, this);
}
private object OnTrapDisarm(Landmine landmine, BasePlayer player)
{
if (landmine == null || player == null) return null;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermDisarm))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return true;
}
float now = Time.realtimeSinceStartup;
float last;
if (config.CooldownSeconds > 0f && lastDisarm.TryGetValue(player.userID, out last))
{
float remaining = config.CooldownSeconds - (now - last);
if (remaining > 0f)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, remaining));
return true;
}
}
lastDisarm[player.userID] = now;
Vector3 pos = landmine.transform.position;
player.ChatMessage(Msg("Disarmed", player.UserIDString, $"{pos.x:0},{pos.z:0}"));
return true;
}
private void Unload()
{
lastDisarm.Clear();
}
}
}The plugin lets server owners require a permission (trapdisarmguard.disarm) before anyone can defuse a landmine. It also enforces a per-player cooldown so a single defender cannot sweep every trap instantly. In OnTrapDisarm, the trap commander for bullet-style checks is skipped: we check the permission, then compute the remaining cooldown from a Dictionary<ulong, float> keyed by the player's user ID using Time.realtimeSinceStartup. On success we record the timestamp, send a language message with the mine position, and return true to hand control back to the game. Denied attempts return true as well but send a rejection message. The cooldown length and permission text come from the config, and the dictionary is cleared on unload.
Common use cases
Permission-gated defusal
Require a combat-engineer permission so only trusted players can disarm team mines or captured traps, and cancel the attempt for everyone else.
Cooldown and rate limits
Track last-disarm timestamps per player and block attempts that come too fast, preventing macro or scripted trap farming.
Audit and notify
Broadcast or log to a staff channel when a specific player disarms a mine in a raid area, using the landmine position and owner ID for context.
Pitfalls
Owners bypass the hook
RPC_Disarmreturns early when the caller's user ID equals the mine'striggerPlayerID, so a player disarming their own trap never reachesOnTrapDisarm. Do not expect to block self-disarm here.Cancelling skips the trigger roll
The 15% chance that the mine detonates on the disarmer is calculated after the hook, so returning non-null also removes the risk of triggering. If that risk should still apply, handle the damage yourself before returning.
Unarmed mines do not fire the hook
Landmines that were never armed or were already armed and disarmed at least once will not reach the call. Check
Armed()elsewhere if you need to gate those cases.
Build a plugin with OnTrapDisarm
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 OnTrapDisarm
Generate