Skip to content
RustPluginGenerator

OnPlayerLanded

OnPlayerLanded is called after BasePlayer.ApplyFallDamageFromVelocity finishes resolving a player's fall, including applying fall damage and the landing effect. It fires whenever the game processes a landing that reached the fall-damage code path.

Signature
void OnPlayerLanded(BasePlayer player, float num)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe BasePlayer whose fall was just resolved. Use it for position, health, inventory or permissions; always null-check before touching members.
numfloatThe raw fall velocity magnitude that Rust measured for this landing. Higher values mean a faster, harder impact; it is the same value the game compares against its fall damage threshold.

Return value

The hook's return value is ignored; the original method continues and returns normally. Returning a value or null changes nothing.

How it works

Oxide raises this hook from BasePlayer.ApplyFallDamageFromVelocity, at the end of the method. That method runs when the server resolves a player's downward velocity into impact: it calls Hurt(..., DamageType.Fall) for the calculated damage and plays the fall damage effect when the impact exceeded the game's internal threshold and the player is not invisible. The hook fires after both of those, so player.health already reflects the fall damage.

Use player for anything you want to do right after the landing: read the position, roll a chance, grant a reward, play an effect, or check health for a respawn/revive flow. num is the fall velocity magnitude the game used; you can threshold on it to separate small hops from long drops. Because the hook fires after damage is applied, you cannot prevent the fall damage from here; use OnEntityTakeDamage with Rust.DamageType.Fall for that.

Narrowing the parameter type is possible but rarely useful: since only a BasePlayer is passed, declaring BasePlayer is already the specific case. The hook fires frequently on any moving server, so keep the body cheap and avoid printing.

Example plugin: Reward players for surviving big falls

FallSurvivorReward.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Fall Survivor Reward", "RustPluginGenerator", "1.0.0")]
    [Description("Rewards players with scrap and regeneration for surviving hard landings.")]
    public class FallSurvivorReward : RustPlugin
    {
        private const string PermExempt = "fallsurvivorreward.exempt";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> lastReward = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Minimum fall velocity")]
            public float MinVelocity = 12f;

            [JsonProperty("Scrap reward")]
            public int ScrapReward = 15;

            [JsonProperty("Cooldown seconds")]
            public float Cooldown = 30f;

            [JsonProperty("Regeneration amount")]
            public float RegenAmount = 15f;

            [JsonProperty("Regeneration duration seconds")]
            public float RegenDuration = 6f;
        }

        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>
            {
                ["Reward"] = "Hard landing survived: +{0} scrap.",
                ["Regen"] = "You are regenerating after that fall."
            }, 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(PermExempt, this);
        }

        private void OnPlayerLanded(BasePlayer player, float num)
        {
            if (player == null || !player.IsConnected || player.IsDead() || player.IsWounded()) return;
            if (num < config.MinVelocity) return;
            if (permission.UserHasPermission(player.UserIDString, PermExempt)) return;

            float now = Time.realtimeSinceStartup;
            float last;
            if (lastReward.TryGetValue(player.userID, out last) && now - last < config.Cooldown) return;
            lastReward[player.userID] = now;

            if (config.ScrapReward > 0)
            {
                Item scrap = ItemManager.CreateByName("scrap", config.ScrapReward, 0);
                if (scrap != null && !player.inventory.GiveItem(scrap))
                {
                    scrap.Remove();
                }
                player.ChatMessage(Msg("Reward", player.UserIDString, config.ScrapReward));
            }

            if (config.RegenAmount > 0f)
            {
                player.ChatMessage(Msg("Regen", player.UserIDString));
                Regenerate(player, config.RegenAmount / Mathf.Max(1f, config.RegenDuration));
            }
        }

        private void Regenerate(BasePlayer player, float perSecond)
        {
            timer.Repeat(1f, Mathf.CeilToInt(config.RegenDuration), () =>
            {
                if (player == null || !player.IsConnected || player.IsDead()) return;
                player.Heal(perSecond);
            });
        }

        private void Unload()
        {
            lastReward.Clear();
        }
    }
}

The plugin configures a minimum fall velocity and a scrap reward. OnPlayerLanded checks the reported num against the threshold, ignores players who died or are wounded from the impact, and applies a short per-player cooldown so repeated landings do not stack. Survivors get scrap spawned into their inventory via ItemManager.CreateByName, with a chat message through the language file. A Timer runs the passive health regeneration over a few seconds, is tracked and destroyed in Unload. The config is loaded with the standard try/catch pattern so a corrupt file falls back to defaults.

Common use cases

  • Reward risky movement

    Track a hard landing and grant scrap, an item or a permission-based bonus for players who survive a long drop without dying.

  • Landing feedback

    Play a custom sound or effect and send a chat line when the impact velocity passes a configured threshold, for example on event maps with tall towers.

  • Anti-cheat signal

    Record suspicious landings such as high-velocity impacts with no subsequent damage, then compare against position data to flag movement exploits for staff review.

Pitfalls

  • Fires after damage, not before

    The hook runs at the end of ApplyFallDamageFromVelocity, so health is already reduced. Cancelling fall damage must be done in OnEntityTakeDamage with Rust.DamageType.Fall.

  • Not every step triggers it

    The game only reaches this code when a landing is resolved as a fall; small hops and many normal movements do not produce a call. Do not build logic that assumes one call per ground contact.

  • Player may be dead or wounded

    A lethal fall still runs through the method before the player is fully removed. Check IsConnected, IsDead and IsWounded before handing out rewards or messages.

Build a plugin with OnPlayerLanded

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Reward risky movement using the OnPlayerLanded hook, with a config file and a permission
Generate this plugin

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 OnPlayerLanded

Generate