OnHotAirBalloonToggle
OnHotAirBalloonToggle is called when a player sends the engine switch RPC on a hot air balloon, before Rust validates ownership and flips the engine state.
object OnHotAirBalloonToggle(HotAirBalloon hotAirBalloon, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
hotAirBalloon | HotAirBalloon | The HotAirBalloon entity whose engine switch RPC is being processed. Use it to read owner, position or mounted players before the toggle proceeds. |
player | BasePlayer | The BasePlayer who sent the engine toggle RPC (HotAirBalloon's creatorEntity check compares against this). May be null in edge cases, so null-check it. |
Return value
Returning null lets the game continue: ownership is checked and the engine state is switched. Returning any non-null value makes EngineSwitch return immediately, so the toggle is cancelled and the balloon's engine state stays as it was.
How it works
This hook fires inside HotAirBalloon.EngineSwitch(RPCMessage), which is the server-side handler for the client RPC sent when a player presses the balloon's engine/fuel toggle. The game runs the hook before it reads the requesting player, checks OnlyOwnerAccessible(), compares creatorEntity, and applies the state change. hotAirBalloon is the entity being toggled; player is the sender from the RPC message. Because the balloon parameter is already typed as HotAirBalloon, declaring it as anything less specific gains nothing, and declaring player as a narrower type than BasePlayer would make Oxide skip the call for players of another type. Return non-null to abort the toggle entirely. This is a control hook, not a notification: it runs before the switch happens, so gameplay state has not changed yet. For post-toggle logic use the companion hook OnHotAirBalloonToggled.
Example plugin: Restrict balloon engine toggling by permission
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("HotAirBalloonEngineLock", "RustPluginGenerator", "1.0.0")]
[Description("Restricts hot air balloon engine toggling to permitted players with a cooldown.")]
public class HotAirBalloonEngineLock : RustPlugin
{
private const string PermUse = "hotairballoonenginelock.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastToggle = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Toggle cooldown (seconds)")]
public float Cooldown { get; set; } = 2f;
[JsonProperty("Require permission")]
public bool RequirePermission { 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>
{
["NoPermission"] = "You are not allowed to operate this balloon's engine.",
["Cooldown"] = "Wait {0:0.0}s before toggling the engine again."
}, 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(PermUse, this);
}
private object OnHotAirBalloonToggle(HotAirBalloon hotAirBalloon, BasePlayer player)
{
if (hotAirBalloon == null || hotAirBalloon.IsDestroyed || player == null)
return null;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return true;
}
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (lastToggle.TryGetValue(player.userID.Get(), out last) && now - last < config.Cooldown)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, config.Cooldown - (now - last)));
return true;
}
lastToggle[player.userID.Get()] = now;
return null;
}
private void Unload()
{
lastToggle.Clear();
}
}
}The plugin gates engine toggling behind a permission and a minimum distance check. OnHotAirBalloonToggle null-checks the balloon and player, then verifies the player holds hotairballoonenginelock.use; unpermitted players get a localized chat message and the hook returns true, which stops EngineSwitch before ownership validation runs. A toggle cooldown stored per player ID throttles request spam from modified clients and warns the player instead of blocking permanently. The message keys live in LoadDefaultMessages, and the cooldown time is configurable through a nested config class that falls back to defaults when the file is invalid.
Common use cases
Permission-gated engine control
Deny engine toggling to players without a permission so only trusted players (or owners with a tier) can raise and land balloons.
Anti-spam throttle
Return non-null when the same player toggles within a short window to stop RPC spam from modified clients.
Restricted zones
Block toggling while the balloon sits inside a no-fly or event area by checking
hotAirBalloon.transform.positionbefore allowing it.
Pitfalls
It runs before the switch
The engine state has not changed when this hook fires, so reading it here gives the previous value. Use
OnHotAirBalloonToggledfor post-change logic.player can be null
The game itself null-checks
msg.playerafter the hook. Always guard against a nullplayerbefore callingUserHasPermissionorChatMessage.Hooks fire per RPC
Modified clients can spam the toggle RPC, so a cooldown or rate limit is worth adding; do not run heavy work in this hook.
Build a plugin with OnHotAirBalloonToggle
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 OnHotAirBalloonToggle
Generate