OnTrapArm
OnTrapArm is called when a player arms a BearTrap, right before the trap is set armed. Returning a non-null value cancels the arming.
object OnTrapArm(BearTrap bearTrap, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
bearTrap | BearTrap | The BearTrap entity being armed. Use it to read the trap's position, owner, flags or short prefab name, or to arm other logic around it. |
player | BasePlayer | The BasePlayer whose client sent the arm RPC. It is the player who interacted with the trap to set it. May be null in edge cases, so always null-check it. |
Return value
Return null to allow the trap to be armed normally. Return any non-null value to stop the original Arm() call, leaving the trap unarmed. The returned value is not used as a result by the game method (it returns void), so a sentinel like true or false both simply cancel arming.
How it works
This hook fires from BearTrap.RPC_Arm, the server-side RPC that runs when a player interacts with an unarmed bear trap to set it. It only runs while the trap is not already armed; the original method first checks Armed() and only then calls the hook. Because the call happens before Arm(), your code runs while the trap still has its unarmed state.
The first argument is the trap entity itself, useful for position checks (bearTrap.transform.position), ownership (OwnerID) or distance checks. The second is the BasePlayer who triggered the RPC, appropriate for permission checks, cooldowns or logging who set a trap where.
The return value is what controls behavior. Because the hook accepts any return value type and the original method only checks for null, returning anything non-null blocks Arm() from running. Returning null lets arming continue normally. There is no way to inspect the incoming RPC message payload, only the trap and the player.
You can narrow dispatch by declaring BearTrap specifically (as shown) so you only receive calls for bear traps; other trap types that might use the same hook name in future would be skipped.
Example plugin: Limit bear trap arming to one per player
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Trap Arm Limit", "RustPluginGenerator", "1.0.0")]
[Description("Limits how many bear traps a single player may arm at once and can block arming in restricted areas.")]
public class TrapArmLimit : RustPlugin
{
private const string PermBypass = "traparmlimit.bypass";
private class PluginConfig
{
[JsonProperty("Max armed bear traps per player")]
public int MaxArmedTraps = 5;
[JsonProperty("Maximum arm distance in meters")]
public float MaxArmDistance = 4f;
[JsonProperty("Message radius (chat warning only)")]
public float MessageRadius = 2f;
}
private PluginConfig config;
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>
{
["LimitReached"] = "You already have {0} bear traps armed. Disarm one first.",
["TooFar"] = "You are too far from that bear trap to arm it."
}, 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 object OnTrapArm(BearTrap bearTrap, BasePlayer player)
{
if (bearTrap == null || player == null) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
if (Vector3.Distance(player.transform.position, bearTrap.transform.position) > config.MaxArmDistance)
{
player.ChatMessage(Msg("TooFar", player.UserIDString));
return true;
}
int owned = 0;
foreach (var entity in BaseNetworkable.serverEntities)
{
var trap = entity as BearTrap;
if (trap == null || trap.IsDestroyed) continue;
if (trap == bearTrap) continue;
if (trap.OwnerID != player.userID.Get()) continue;
if ((trap.HasFlag(BaseEntity.Flags.On) || trap.Armed())) owned++;
}
if (owned >= config.MaxArmedTraps)
{
player.ChatMessage(Msg("LimitReached", player.UserIDString, config.MaxArmedTraps));
return true;
}
return null;
}
}
}The plugin tracks how many bear traps each player has currently armed, using the trap owner id. When OnTrapArm fires it looks up the player's configured limit from the config, counts existing armed traps owned by that user, and if the count has reached the limit sends a chat message and returns true to block the new arm. It also checks an optional permission bypass and a max distance from the trap to catch odd interactions. A periodic timer clears stale entries for players who disconnect, and armed traps placed via other paths are still counted because the count is recomputed against BaseNetworkable.serverEntities each call rather than cached.
Common use cases
Per-player trap limits
Prevent a single player from arming dozens of bear traps around a base by counting their currently armed traps and cancelling the arm when a configured cap is reached.
Restricted zones
Return non-null when
bearTrap.transform.positionfalls inside a protected area such as a spawn zone, so players cannot set traps near safe areas.Audit logging
Record which player armed which trap and where, writing the data to a small runtime list to help admins investigate trap-related reports without blocking arming.
Pitfalls
Returning false still blocks arming
The injection compares the returned value to null, not to true. Returning
falsecancels arming just like returningtrue. Always returnnullwhen you want to let the trap arm.Trap is not armed yet
The hook runs before
Arm()executes, soHasFlag(BaseEntity.Flags.On)is not reliable as an armed indicator at this point. Count existing traps via the entity list or stored state instead of the current trap.Player can be null on some paths
RPCs normally arrive from a connected client, but null-check
playeranyway before touchingplayer.UserIDStringor sending chat messages to avoid a hook-thrown exception.
Build a plugin with OnTrapArm
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 OnTrapArm
Generate