CanDismountEntity
CanDismountEntity is called when a mounted player tries to leave a BaseMountable, before Rust actually detaches them from it. Returning a non-null value cancels the dismount and keeps the player seated.
object CanDismountEntity(BasePlayer player, BaseMountable mountable)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer who is being dismounted from the mountable. This is the player currently occupying the seat. |
mountable | BaseMountable | The BaseMountable entity the player is sitting on, such as a horse, boat, minicopter, car seat or chair. Use its type and position to decide whether to allow the dismount. |
Return value
Return null to let the dismount proceed normally. Return any non-null value (typically a short reason string or true) to abort the dismount, leaving the player mounted and skipping the rest of DismountPlayer.
How it works
The hook fires inside BaseMountable.DismountPlayer before any of the detach logic runs. Rust calls it whenever a player attempts to leave a mount: pressing the dismount input, using the seat's dismount command, taking damage/vehicle events that force a dismount call, and any server-side code that invokes DismountPlayer directly. Because the call sits at the top of the method, blocking it prevents the whole dismount path, not just part of it.
player is the occupant and mountable is the seat entity, so you can branch on prefab shortname, mountable type (horses, boats, minicopters, modular car seats), health state, or position. Declaring mountable as a more specific type such as BaseMountable subtypes is possible, but Oxide only calls your hook when the argument is an instance of that exact declared type, so a too-narrow type silently skips all other mounts. Keep BaseMountable and check the type yourself with pattern matching.
This is a decision hook, so do not send chat spam from it, since some systems call dismount repeatedly. Cache any reason strings and send them once per blocking action.
Example plugin: Keep players seated while their mount is in a safe zone
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("PvpMountLock", "RustPluginGenerator", "1.0.0")]
[Description("Blocks dismounting from mounts inside a configured zone")]
public class PvpMountLock : RustPlugin
{
private const string PermAdmin = "pvpmountlock.admin";
private class PluginConfig
{
[JsonProperty("Enabled")]
public bool Enabled = true;
[JsonProperty("Zone center (x,y,z)")]
public float[] Center = { 0f, 0f, 0f };
[JsonProperty("Zone radius (meters)")]
public float Radius = 100f;
[JsonProperty("Notify cooldown seconds")]
public float NotifyCooldown = 5f;
}
private PluginConfig config;
private readonly Dictionary<ulong, float> lastNotice = new Dictionary<ulong, float>();
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>
{
["Blocked"] = "You cannot dismount inside this zone.",
["NoPermission"] = "You do not have permission to use this command.",
["Toggled"] = "Mount lock is now {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(PermAdmin, this);
}
private void Unload()
{
lastNotice.Clear();
}
private Vector3 ZoneCenter()
{
var c = config.Center ?? new float[3];
float x = c.Length > 0 ? c[0] : 0f;
float y = c.Length > 1 ? c[1] : 0f;
float z = c.Length > 2 ? c[2] : 0f;
return new Vector3(x, y, z);
}
private object CanDismountEntity(BasePlayer player, BaseMountable mountable)
{
if (player == null || mountable == null) return null;
if (!config.Enabled) return null;
float distance = Vector3.Distance(mountable.transform.position, ZoneCenter());
if (distance > config.Radius) return null;
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (!lastNotice.TryGetValue(player.userID, out last) || now - last >= config.NotifyCooldown)
{
lastNotice[player.userID] = now;
player.ChatMessage(Msg("Blocked", player.UserIDString));
}
return "zone-locked";
}
[ChatCommand("mountlock")]
private void CmdMountLock(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (args != null && args.Length > 0 && args[0] == "status")
{
player.ChatMessage(Msg("Toggled", player.UserIDString, config.Enabled ? "enabled" : "disabled"));
}
}
[ConsoleCommand("mountlock.toggle")]
private void CcmdToggle(ConsoleSystem.Arg arg)
{
if (arg == null || arg.Player() != null && !permission.UserHasPermission(arg.Player().UserIDString, PermAdmin))
{
arg?.ReplyWith(Msg("NoPermission"));
return;
}
config.Enabled = !config.Enabled;
SaveConfig();
arg.ReplyWith(Msg("Toggled", null, config.Enabled ? "enabled" : "disabled"));
}
}
}The plugin blocks dismounting inside a configurable radius around a set of world coordinates, treating that area as a combat-safe zone where leaving a vehicle early would be a free escape. It reads a PvpMountLock config with the zone center, radius and an enable flag, and offers a mountlock.status chat command plus an admin toggle console command. CanDismountEntity returns a reason string when the player is inside the zone so the dismount is cancelled; otherwise it returns null. A per-player cooldown map throttles the chat notice so the hook can fire repeatedly without spamming the player, and all text is routed through the language file. Config validation falls back to defaults on parse failure.
Common use cases
Combat/drop zones
Prevent players from bailing out of helicopters or boats inside an active event area so they cannot skip a fight. Return a reason string when the mountable is within the zone radius.
Escape lock during capture
Keep a player seated on a mount after they are flagged by an arrest or capture minigame, releasing the lock only when the scripted phase ends.
Vehicle damage rules
Block dismounting a burning or low-health vehicle mid-flight to enforce a rule, or allow early exit only during a configurable grace window after an explosion hit.
Pitfalls
A boolean true or a string both block
Any non-null return cancels the dismount. Returning
truefrom a hook that is meant to allow the action is a common mistake that leaves players permanently stuck.Narrow parameter types skip mounts
If you declare
mountableas a subtype likeBaseBoat, Oxide only calls the hook for that type, so horse and car seats will not be evaluated by your logic at all.Forced dismounts also pass here
Server code that calls
DismountPlayerdirectly goes through this hook too, so blocking everything can trap players on a mount that is being destroyed or cleaned up. Whitelist those cases by health or entity state.
Build a plugin with CanDismountEntity
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 CanDismountEntity
Generate