OnCargoPlaneSignaled
OnCargoPlaneSignaled is called when a thrown Supply Signal spawns its cargo plane, right after the plane entity is created and spawned but before the signal's timer finishes.
void OnCargoPlaneSignaled(BaseEntity entity, SupplySignal supplySignal)Parameters
| Parameter | Type | Description |
|---|---|---|
entity | BaseEntity | The cargo plane entity that was just created and spawned by the signal. It is a BaseEntity with net identity, so you can read its net.ID, transform.position, ShortPrefabName, and call Kill() or SendNetworkUpdate(). |
supplySignal | SupplySignal | The SupplySignal entity that was thrown and is now exploding. Use it to read transform.position, OwnerID, or the item skin if you need to identify who called the drop or customize the response. |
Return value
The return value is ignored; the game continues its normal path regardless of what you return. Return nothing (void hook methods simply end) and never rely on the hook to cancel the plane.
How it works
Oxide fires this hook inside SupplySignal.Explode, immediately after the game creates the cargo plane entity, sets its drop position, and calls Spawn() on it. This means the plane already exists in the world and has a valid network identity when your hook runs, but the Invoke(FinishUp, 210f) cleanup and the On flag update happen after the hook returns.
The entity parameter is the freshly spawned cargo plane. You can still cancel or redirect it here because nothing has been sent to clients yet in a way you cannot undo — calling Kill() removes it, and you can read net.ID to track it later. The supplySignal parameter is the thrown signal entity, useful for position, owner, or skin-based routing.
Declaring a more specific type narrows dispatch: if you write BaseEntity the hook always fires; if you declare CargoPlane Oxide skips calls where the spawned entity is somehow not a cargo plane (rare, but possible with prefab swaps). The signal can be typed as SupplySignal or ThrownEntity depending on what you need.
There is no return value handling — this is a notification hook.
Example plugin: Rewrite the cargo plane drop position to a random offset
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Cargo Plane Randomizer", "RustPluginGenerator", "1.0.0")]
[Description("Shifts cargo plane drop positions by a random offset when a supply signal fires.")]
public class CargoPlaneRandomizer : RustPlugin
{
private const string PermAdmin = "cargoPlanerandomizer.admin";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Enable random offset")]
public bool Enabled { get; set; } = true;
[JsonProperty("Maximum random offset (meters)")]
public float MaxOffset { get; set; } = 60f;
[JsonProperty("Broadcast plane announcement")]
public bool Announce { get; set; } = true;
}
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>
{
["Incoming"] = "Cargo plane inbound, dropping near {0}",
["ToggleOn"] = "Cargo plane offset enabled.",
["ToggleOff"] = "Cargo plane offset disabled."
}, 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 OnCargoPlaneSignaled(BaseEntity entity, SupplySignal supplySignal)
{
if (entity == null || entity.IsDestroyed) return;
if (config.Enabled)
{
float max = Mathf.Clamp(config.MaxOffset, 0f, 500f);
if (max > 0.5f)
{
Vector3 pos = entity.transform.position;
Vector3 offset = new Vector3(
UnityEngine.Random.Range(-max, max),
0f,
UnityEngine.Random.Range(-max, max));
entity.SendMessage("InitDropPosition", pos + offset, SendMessageOptions.DontRequireReceiver);
entity.SendNetworkUpdate();
}
}
if (config.Announce)
{
string direction = CompassDirection(entity.transform.position);
Server.Broadcast(Msg("Incoming", null, direction));
}
}
private string CompassDirection(Vector3 pos)
{
float angle = Mathf.Atan2(pos.x, pos.z) * Mathf.Rad2Deg;
string[] dirs = { "north", "north-east", "east", "south-east", "south", "south-west", "west", "north-west" };
int index = Mathf.RoundToInt(Mathf.Repeat(angle / 45f, 8));
return dirs[index];
}
[ConsoleCommand("cargoplane.toggle")]
private void CmdToggle(ConsoleSystem.Arg arg)
{
if (arg.Player() != null && !permission.UserHasPermission(arg.Player().UserIDString, PermAdmin))
{
arg.ReplyWith("You do not have permission.");
return;
}
config.Enabled = !config.Enabled;
SaveConfig();
arg.ReplyWith(Msg(config.Enabled ? "ToggleOn" : "ToggleOff"));
}
}
}The plugin listens for OnCargoPlaneSignaled and checks the config for an enabled flag and a maximum offset. If the plane entity is valid and the offset is above zero, it reads the current plane position, adds a random horizontal offset within the configured radius, and sends an InitDropPosition message with DontRequireReceiver — the same message the game itself uses — so the plane drifts to the new drop point instead of the original.
It also broadcasts an optional chat notice to all players using the language file. Config controls whether the message is sent and the maximum radius; Set to 0 to disable the shuffle. A [ConsoleCommand] lets admins toggle it at runtime.
Common use cases
Announce incoming cargo planes to the whole server
Use
supplySignal.transform.positionandentity.net.IDto broadcast a chat message with a compass direction so players know where to look. Combine with the plane's lifetime to remind them of the 210 second window.Track supply signals per player for stats
Read
supplySignal.OwnerID(or the item's owner via the signal entity) and increment a per-player counter in oxide/data. Useful for leaderboards or anti-abuse cooldowns on signal usage.Redistribute cargo drops away from monuments
Sample a random position, check a configured list of excluded zones, and send
InitDropPositionto the plane to move it before players catch the visual. Keeps loot away from heavily camped areas.
Pitfalls
Do not expect to cancel the drop
The hook is a notification — there is no return value that stops the game code. If you need to cancel, call
entity.Kill()inside the hook, but note the signal entity itself still explodes and despawns on its normal timer.The plane is already spawned
By the time your hook runs,
Spawn()has been called and the entity has a net ID. Any change you make (Kill, InitDropPosition message, SetFlag) is sent after the initial spawn, so useSendNetworkUpdate()if clients might have already received the first update.Narrowing to CargoPlane can drop calls
If you declare the first parameter as
CargoPlaneinstead ofBaseEntity, Oxide will not call your hook when the spawned entity is not a CargoPlane (for example if another plugin replaced the prefab). DeclareBaseEntityunless you need the typed members.
Build a plugin with OnCargoPlaneSignaled
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 OnCargoPlaneSignaled
Generate