OnLiftUse
OnLiftUse is called when a player presses use on a lift cabin or a procedural elevator, before the lift moves. Returning a non-null value cancels the movement.
object OnLiftUse(Lift lift, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
lift | Lift | The lift entity being used. For a standard Lift this is the cabin entity; for a ProceduralLift it is the multi-stop elevator entity. Cast to ProceduralLift when you need floor data. |
player | BasePlayer | The BasePlayer who sent the use RPC. Already passed CanInteract(), so the player is alive and allowed to interact with the world. |
Return value
Return null (or nothing) to let the lift proceed with its normal movement checks. Any non-null value stops the original code path, so the lift does not move; the returned object itself is discarded because the game method returns void.
How it works
The hook fires inside Lift.RPC_UseLift (standard one-cabin elevator) and ProceduralLift.RPC_UseLift (multi-floor elevator), after the game has confirmed the player can interact. In both places, if your hook returns null, the original check continues: for a Lift, PlayerIsAtCabin(player) must still pass before MoveUp() runs; for a ProceduralLift, the lift must not be busy before it advances to (floorIndex + 1) % stops.Length.
Use lift to inspect the entity (position, owner, short prefab name) or cast it to ProceduralLift to read floorIndex and stops. Use player for permission checks, cooldowns, team ownership rules, or teleport-style validation.
Because both sites call the same hook name with different first-argument types, Oxide's dispatch only invokes your method when the argument matches your declared parameter type. Declaring Lift never fires for procedural elevators, and declaring ProceduralLift never fires for plain lifts. If you need both, write two overloads or declare the parameter as BaseEntity to catch either. Note that player.CanInteract() is evaluated before the hook, so a dead or stunned player will not reach it.
Other signatures
Oxide also calls OnLiftUse from other places in the game with these parameter types. Declare the overload you need, or several:
object OnLiftUse(ProceduralLift proceduralLift, BasePlayer player)
Example plugin: Block lift use for unauthorized players
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Lift Access Guard", "RustPluginGenerator", "1.0.0")]
[Description("Restricts elevator use to an owner and their team, with admin override.")]
public class LiftAccessGuard : RustPlugin
{
private const string PermAdmin = "liftaccessguard.admin";
private PluginConfig config;
private StoredData data;
private class PluginConfig
{
[JsonProperty("Allow owner's team members")]
public bool AllowTeam { get; set; } = true;
}
private class StoredData
{
[JsonProperty("Lift owners (net id -> user id)")]
public Dictionary<string, string> Owners { get; set; } = new Dictionary<string, string>();
}
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>
{
["Denied"] = "This lift belongs to someone else.",
["NoLift"] = "Look at a lift and use the command again.",
["OwnerAdded"] = "Lift {0} is now owned by {1}.",
["OwnerRemoved"] = "Lift {0} no longer has an owner.",
["NoPermission"] = "You do not have permission to manage lifts."
}, 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);
data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name) ?? new StoredData();
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
private object OnLiftUse(BaseEntity lift, BasePlayer player)
{
if (lift == null || player == null) return null;
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, PermAdmin)) return null;
if (!data.Owners.TryGetValue(lift.net.ID.Value.ToString(), out string ownerId)) return null;
if (ownerId == player.UserIDString) return null;
if (config.AllowTeam && player.currentTeam != 0)
{
var owner = BasePlayer.FindAwakeOrSleeping(ownerId);
if (owner != null && owner.currentTeam == player.currentTeam) return null;
}
player.ChatMessage(Msg("Denied", player.UserIDString));
return true;
}
[ChatCommand("liftguard")]
private void CmdLiftGuard(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermAdmin))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return;
}
BaseEntity target = null;
RaycastHit hit;
if (Physics.Raycast(player.eyes.HeadRay(), out hit, 10f))
target = hit.GetEntity();
if (target == null || (!(target is Lift) && !(target is ProceduralLift)))
{
player.ChatMessage(Msg("NoLift", player.UserIDString));
return;
}
string id = target.net.ID.Value.ToString();
if (args.Length > 0 && args[0].ToLower() == "remove")
{
data.Owners.Remove(id);
player.ChatMessage(Msg("OwnerRemoved", player.UserIDString, id));
return;
}
data.Owners[id] = player.UserIDString;
player.ChatMessage(Msg("OwnerAdded", player.UserIDString, id, player.displayName));
}
}
}The plugin lets admins register a lift (by looking at it) to a specific owner and block everyone else from riding it. OnLiftUse is declared with BaseEntity so it catches both Lift and ProceduralLift entities. When a player presses use, the plugin checks the config's owner list for that entity's net.ID.Value; if an entry exists and the player is not the owner, an admin, or on the owner's team, the hook returns true to cancel the movement and sends a localized message. The lift.guard chat command opens a small menu of add, remove and list actions, and data is saved to oxide/data/LiftAccessGuard on unload.
Common use cases
Owner-restricted elevators
Lock a cabin to a player or team so only authorized users can trigger movement, while admins and the owner's team retain access.
Cooldown against lift spam
Track the last use time per player and return non-null when they press use again within the cooldown window, preventing rapid spam on procedural elevators.
Announce multi-floor arrivals
Cast the lift to ProceduralLift, read floorIndex and stops, and print the target floor to chat via a delayed timer after the hook returns null.
Pitfalls
Parameter type filters the hook
Declaring Lift leaves procedural elevators untouched and vice versa. Use BaseEntity or write both overloads if you need coverage across both lift types.
Returning false still blocks
The check is for a non-null return, so returning false does not mean 'allow'. Always return null explicitly when you want the lift to move.
PlayerIsAtCabin still applies
Returning null does not guarantee movement on a standard Lift; the game still requires the player to be at the cabin and, on a ProceduralLift, the lift must not be busy.
Build a plugin with OnLiftUse
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 OnLiftUse
Generate