OnBallistaGunReload
OnBallistaGunReload is called when a mounted player tries to start reloading a BallistaGun, after the mount and reload preconditions pass and before the reload flag is set.
object OnBallistaGunReload(BallistaGun ballistaGun, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
ballistaGun | BallistaGun | The BallistaGun entity that is about to start reloading. Use it for position checks, ownership (OwnerID), and to send effects or network updates. |
player | BasePlayer | The BasePlayer who sent the reload RPC and is mounted on the ballista. This is the player you can block, charge, or annotate. |
Return value
Return null to allow the reload to start normally. Returning any non-null value stops the original method, so the ballista does not set its reloading flag or reloadingPlayer for that attempt; the returned object itself is discarded.
How it works
The hook fires inside BallistaGun.SERVER_ReloadStart, which is reached from the reload RPC sent by a player. Before the hook runs, the game already verified that the player is mounted on this exact ballista and that UnableToStartReloadServer returned false, so you are not fighting basic validity checks. The method returns void, so returning null lets the reload proceed: the ballista records reloadingPlayer and sets the reserved reload flag, sending a network update.
Returning any non-null object aborts that original code path, so the ballista never enters the reloading state for this attempt. Inside the hook you can read ballistaGun.transform.position for range restrictions, ballistaGun.OwnerID to enforce ownership or a building privilege check, and player for permission and cooldown checks. Returning null does not confirm the reload later, and blocking is silent unless you send a reply yourself.
Both parameters can be null in edge cases, so guard before dereferencing. The hook is per-attempt: a blocked player can retry immediately, so pair blocking with a message or a cooldown if you want it to stick.
Example plugin: Restrict ballista reloads to permitted players
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("BallistaReloadGuard", "RustPluginGenerator", "1.0.0")]
[Description("Restricts who can reload a BallistaGun using a permission and optional cooldown.")]
public class BallistaReloadGuard : RustPlugin
{
private const string PermUse = "ballistareloadguard.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastAttempt = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Require permission to reload")]
public bool RequirePermission { get; set; } = true;
[JsonProperty("Cooldown between reload attempts (seconds, 0 = off)")]
public float CooldownSeconds { get; set; } = 0f;
}
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 do not have permission to reload this ballista.",
["Cooldown"] = "Wait {0} more seconds before reloading the ballista.",
["Granted"] = "You granted ballista reload access to {0}.",
["Revoked"] = "You revoked ballista reload access from {0}."
}, 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);
}
[ChatCommand("ballistareload")]
private void CmdBallistaReload(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsAdmin) return;
if (args == null || args.Length < 2)
{
SendReply(player, "/ballistareload <allow|deny> <playerNameOrId>");
return;
}
BasePlayer target = BasePlayer.FindAwakeOrSleeping(args[1]);
if (target == null)
{
SendReply(player, "Player not found.");
return;
}
bool allow = args[0].ToLower() == "allow";
if (allow) permission.GrantUserPermission(target.UserIDString, PermUse, this);
else permission.RevokeUserPermission(target.UserIDString, PermUse);
SendReply(player, Msg(allow ? "Granted" : "Revoked", player.UserIDString, target.displayName));
}
private object OnBallistaGunReload(BallistaGun ballistaGun, BasePlayer player)
{
if (ballistaGun == null || player == null) return null;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return true;
}
if (config.CooldownSeconds > 0f)
{
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (lastAttempt.TryGetValue(player.userID.Get(), out last))
{
float remaining = config.CooldownSeconds - (now - last);
if (remaining > 0f)
{
player.ChatMessage(Msg("Cooldown", player.UserIDString, Math.Ceiling(remaining)));
return true;
}
}
lastAttempt[player.userID.Get()] = now;
}
return null;
}
private void Unload()
{
lastAttempt.Clear();
}
}
}The plugin registers a ballistareloadguard.use permission and an admin-only chat command /ballistareload <allow|deny> <playerNameOrId> to grant or revoke it per player. OnBallistaGunReload checks whether the calling player holds the permission; if not, it sends a localized chat message and returns a non-null value so the reload never starts. The permission check runs against the player's user ID string, so it also honors permissions the player has through Oxide groups. Optional settings in the config file control whether the permission is required (RequirePermission, default true) and a cooldown in seconds between reload attempts (CooldownSeconds, default 0 = off), tracked per player in memory. Unload clears that in-memory cooldown state. Admins can therefore deploy ballistas that only trusted players can reload, for example on arena maps where reload speed is part of the balance.
Common use cases
Permission-gated siege weapons
Only players with a specific permission (or group) may reload ballistas, letting server owners limit who operates heavy siege weapons on event maps.
Cooldown between reload attempts
Return a non-null value when the player is still within a cooldown window and send them a chat notice, slowing down rapid-fire reload cycles on modified siege devices.
Ownership and raid zone checks
Compare
ballistaGun.OwnerIDor the ballista position against a region/zone plugin so enemy players cannot reload a captured ballista during an active raid.
Pitfalls
Blocking is silent unless you reply
Returning a non-null value simply stops the reload. Send the player a chat or console message inside the hook so they understand why nothing happened.
Both parameters can be null
Although the game checks the mounting player before calling the hook, defensive null checks on
ballistaGunandplayeravoid exceptions if other plugins patched the flow.Blocking invites retries
A blocked reload can be attempted again immediately. Track attempts per player if you need a cooldown rather than a one-shot deny.
Build a plugin with OnBallistaGunReload
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 OnBallistaGunReload
Generate