Skip to content
RustPluginGenerator

OnSiegeWeaponPull

OnSiegeWeaponPull is called when a player sends the server RPC to start pulling a siege weapon (catapult or ballista), before the game subtracts calories and applies the pull state.

Signature
object OnSiegeWeaponPull(BaseSiegeWeapon siegeWeapon, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
siegeWeaponBaseSiegeWeaponThe BaseSiegeWeapon (catapult or ballista) the player is trying to start pulling. Use it to read position, health or ownership before allowing the action.
playerBasePlayerThe BasePlayer who sent the pull request. Use it for permission checks, team checks or to send feedback when the pull is blocked.

Return value

Returning null (or nothing in a void-style handler that returns null) lets the pull proceed normally. Returning any non-null object stops the original method before calories are subtracted and before the pull state is applied, so the player gets no pull and no calorie cost.

How it works

The hook fires inside BaseSiegeWeapon.SERVER_StartPulling, which runs when a client sends the pull RPC for a siege weapon it is allowed to pull. This happens before the game checks whether the weapon is owner-restricted, before it deducts 3 calories from the player and before it wakes the rigidbody and starts the pull. The hook receives the weapon entity and the requesting player.

Because it runs server-side before any state change, it is the right place to gate the action: restrict pulling to a permission group, block pulling while the weapon is being towed or is unowned by the player's team, or rate-limit spam. The player argument is the connection's player object, so permission.UserHasPermission(player.UserIDString, ...) and team lookups via player.currentTeam work directly. The siegeWeapon argument gives you OwnerID, creatorEntity, net.ID, transform.position and the standard BaseEntity members.

Note that the owner check (OnlyOwnerAccessible) is evaluated after this hook, so returning non-null also blocks the pull for the owner. The hook does not fire for non-pull interactions such as firing or reloading, which have their own hooks.

Example plugin: Restrict siege weapon pulling to a permission group

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

namespace Oxide.Plugins
{
    [Info("Siege Pull Permission", "RustPluginGenerator", "1.0.0")]
    [Description("Restricts pulling of siege weapons to players with permission.")]
    public class SiegePullPermission : RustPlugin
    {
        private const string PermUse = "siegepullpermission.use";

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

        private class PluginConfig
        {
            [JsonProperty("Cooldown between pulls (seconds)")]
            public float CooldownSeconds = 1.5f;

            [JsonProperty("Require permission")]
            public bool RequirePermission = 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 do not have permission to pull this siege weapon.",
                ["TooFast"] = "Wait a moment before pulling 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 OnSiegeWeaponPull(BaseSiegeWeapon siegeWeapon, BasePlayer player)
        {
            if (siegeWeapon == null || player == null) return null;

            if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse))
            {
                player.ChatMessage(Msg("NoPermission", player.UserIDString));
                return true;
            }

            ulong id = player.userID.Get();
            float now = UnityEngine.Time.realtimeSinceStartup;
            float nextAllowed;
            if (cooldowns.TryGetValue(id, out nextAllowed) && now < nextAllowed)
            {
                player.ChatMessage(Msg("TooFast", player.UserIDString));
                return true;
            }
            cooldowns[id] = now + config.CooldownSeconds;
            return null;
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player != null) cooldowns.Remove(player.userID.Get());
        }

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

The plugin registers the permission siegepullpermission.use in Init. When a player tries to start pulling a siege weapon, OnSiegeWeaponPull returns a non-null object unless the player has that permission, which makes SERVER_StartPulling bail out before it charges calories or moves the weapon. A per-player cooldown keyed by UserIDString blocks rapid repeat pulls and sends a localized chat message through the language file. Cooldowns are timestamped with UnityEngine.Time.realtimeSinceStartup and cleared for disconnected players in OnPlayerDisconnected, and the dictionary is emptied in Unload.

Common use cases

  • Restrict pulling to a permission group

    Only players with siegepull.use may move catapults or ballistas, keeping the weapons in the hands of event staff or VIP donors.

  • Block pulling by non-team members

    Check siegeWeapon.OwnerID against the caller's team members so raiders cannot yank an enemy catapult around.

  • Stop calorie drain while the owner is absent

    Return non-null when the pulling player is not the creator and the weapon is owned, avoiding the 3 calorie cost without altering the weapon itself.

Pitfalls

  • Returning a value also blocks the owner

    The owner check runs after the hook, so any non-null return blocks everyone, including the player who built the weapon. Make the permission check return null for authorized players.

  • Do not print output on every pull

    OnSiegeWeaponPull can fire often during a fight. Only send chat messages when you actually block the pull, and keep the rest of the handler cheap.

  • creatorEntity can be null

    A siege weapon spawned by server code may have no creator. If you compare against creatorEntity, null-check it first or you will throw inside the hook.

Build a plugin with OnSiegeWeaponPull

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

Prompt: Restrict pulling to a permission group using the OnSiegeWeaponPull 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 OnSiegeWeaponPull

Generate