Skip to content
RustPluginGenerator

OnAirdrop

OnAirdrop is called when a CargoPlane finishes choosing where to release its airdrop crate, right after the plane's drop position is set and before the crate spawns. It fires once per airdrop, not per frame.

Signature
void OnAirdrop(CargoPlane cargoPlane, UnityEngine.Vector3 newDropPosition)

Parameters

Hook parameters
ParameterTypeDescription
cargoPlaneCargoPlaneThe CargoPlane entity representing the airdrop that is about to be released. It exists and is spawned; use it to read the plane's position, network ID or owner, but the drop point is controlled by the second argument.
newDropPositionUnityEngine.Vector3The world position the plane is currently set to drop its crate at, already chosen near the plane's flight path. Read it to inspect or record where the airdrop will land; the hook cannot change it because the field is assigned before the hook fires.

Return value

The hook is called as a void call and its return value is ignored, so returning null or any other value never stops the plane or changes where it drops its crate. Use the hook only to observe or to start side effects such as announcements.

How it works

The hook fires from CargoPlane.UpdateDropPosition, the method the plane calls when it decides where to release its crate. By the time Oxide invokes OnAirdrop, the plane has already been placed at its start position, rotated toward the drop point, and its internal drop position has been assigned to the value passed as newDropPosition. The plane then continues flying and later spawns the supply drop crate at that spot.

Use cargoPlane to identify the specific plane (for example its net.ID.Value or OwnerID) and to read its current position and heading. Use newDropPosition to know the exact landing coordinates, which is what most plugins care about: announcing the drop in chat, writing it to a data file, or spawning a marker.

The hook fires once per plane when it is created and positioned, so it is not a per-tick hook and logging inside it is acceptable. Because the drop position is assigned before the hook runs, you cannot redirect the crate by returning a value or by mutating the parameter. To move the drop you would have to act on the spawned SupplyDrop entity later using the coordinates captured here.

Declaring CargoPlane as the parameter type is accurate; there is no parent type that would broaden or narrow the calls in a useful way.

Example plugin: Announce airdrop landing coordinates to all players

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

namespace Oxide.Plugins
{
    [Info("Airdrop Announcer", "RustPluginGenerator", "1.0.0")]
    [Description("Announces the landing coordinates of each airdrop in chat")]
    public class AirdropAnnouncer : RustPlugin
    {
        private const string PermAnnounce = "airdropannouncer.announce";

        private PluginConfig config;
        private readonly Dictionary<ulong, int> recentDrops = new Dictionary<ulong, int>();

        private class PluginConfig
        {
            [JsonProperty("Announce to all players")]
            public bool AnnounceToAll { get; set; } = true;

            [JsonProperty("Minimum seconds between announcements")]
            public int MinimumSeconds { get; set; } = 60;
        }

        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>
            {
                ["Announce"] = "Airdrop incoming! Landing at {0} (grid {1}).",
                ["AnnounceBroadcast"] = "[Airdrop] Crate landing at {0} (grid {1})."
            }, 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(PermAnnounce, this);
        }

        private void OnAirdrop(CargoPlane cargoPlane, Vector3 newDropPosition)
        {
            if (cargoPlane == null) return;

            ulong planeId = cargoPlane.net != null ? cargoPlane.net.ID.Value : 0UL;
            int now = Facepunch.Math.Epoch.Current;

            if (recentDrops.TryGetValue(planeId, out int last) && now - last < config.MinimumSeconds)
                return;

            recentDrops[planeId] = now;

            string coords = string.Format("{0:F0}, {1:F0}", newDropPosition.x, newDropPosition.z);
            string grid = PositionToGrid(newDropPosition);

            if (config.AnnounceToAll)
            {
                Server.Broadcast(Msg("AnnounceBroadcast", null, coords, grid));
                return;
            }

            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player == null || !player.IsConnected) continue;
                if (permission.UserHasPermission(player.UserIDString, PermAnnounce))
                    player.ChatMessage(Msg("Announce", player.UserIDString, coords, grid));
            }
        }

        private string PositionToGrid(Vector3 position)
        {
            const float cellSize = 146.5f;
            int x = Mathf.FloorToInt((position.x + 2000f) / cellSize);
            int z = Mathf.FloorToInt((position.z + 2000f) / cellSize);
            if (x < 0 || z < 0 || x > 27 || z > 27) return "?";
            return ((char)('A' + x)).ToString() + z;
        }
    }
}

The plugin listens for OnAirdrop and reads the crate's landing point from newDropPosition. It builds a chat message from a localized template with the coordinates and the map grid reference, then sends it to every connected player via Server.Broadcast. A config option controls whether the message is enabled and a minimum interval prevents spam when several planes are triggered close together. The plane's network ID is passed through UserId in the language lookup so future per-player customization is possible, and the message text lives in the language file rather than being hard-coded.

Common use cases

  • Announce drop coordinates in chat

    Broadcast the landing coordinates so players know where the crate will fall and can contest it, instead of having to watch the plane.

  • Log airdrop history for admins

    Append the position and plane ID to a data file so admins can review when and where airdrops were triggered on the server.

  • Trigger a custom event marker

    Use the coordinates to spawn a map marker or fire a chat ping for a scheduled airdrop event, keeping the drop location in sync with where the crate actually lands.

Pitfalls

  • You cannot move the drop here

    The plane's drop position is assigned before the hook runs, so neither the return value nor changing newDropPosition affects the crate. To relocate a drop, handle the spawned SupplyDrop separately.

  • Not the same as SupplyDropLanded

    This hook fires when the plane chooses its drop point, which is well before the crate spawns or lands. Use OnSupplyDropDropped or OnSupplyDropLanded if you need to react to the crate itself.

  • Several planes at once

    Multiple CargoPlanes can be active and trigger the hook close together, so debounce chat broadcasts if you do not want repeated messages in a short window.

Build a plugin with OnAirdrop

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

Prompt: Announce drop coordinates in chat using the OnAirdrop 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 OnAirdrop

Generate