Skip to content
RustPluginGenerator

OnRackedWeaponTaken

OnRackedWeaponTaken is called after a player removes a weapon from a WeaponRack. It fires inside WeaponRack.GivePlayerWeapon, once the weapon has already left the rack, so it is a notification hook, not a veto.

Signature
void OnRackedWeaponTaken(Item weaponItem, BasePlayer player, WeaponRack weaponRack)

Parameters

Hook parameters
ParameterTypeDescription
weaponItemItemThe Item that was just removed from the weapon rack. Use weaponItem.info.shortname and weaponItem.amount to inspect what the player took.
playerBasePlayerThe BasePlayer who took the weapon off the rack. Null-check it before use; may be an NPC or otherwise invalid when the hook fires.
weaponRackWeaponRackThe WeaponRack entity the weapon was taken from. Use it to read position, OwnerID or building privilege for context.

Return value

The return value is ignored. The hook fires after the weapon has been moved to the player and the rack updated, so returning null, true or any other value changes nothing about the transfer.

How it works

The hook fires at the end of WeaponRack.GivePlayerWeapon, immediately after the rack's network update is sent (when one is required). At that point the weapon item has already been handed to player. This makes OnRackedWeaponTaken a post-action notification: it tells your plugin that a rack slot was emptied, but the item transfer is complete and cannot be cancelled by returning a value.

Use weaponItem to identify the weapon (shortname, skin, condition, attached modules in its container), player to attribute the action and check permissions or cooldowns, and weaponRack to record location, OwnerID or whether the rack is inside a build privilege zone. Because the injection is inside WeaponRack.GivePlayerWeapon, declaring a more specific type for the rack or player does not add value; the classes are already those types.

This hook is useful for logging, quest and score systems, or for re-applying a custom lock or tag check after the fact. Since it runs once per take and not on ticks, light work such as messages, data writes or permission checks is safe here, but avoid heavy entity scans.

Example plugin: Notify and log weapon rack takes

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

namespace Oxide.Plugins
{
    [Info("WeaponRackAudit", "RustPluginGenerator", "1.0.0")]
    [Description("Logs and optionally announces weapon takes from weapon racks")]
    public class WeaponRackAudit : RustPlugin
    {
        private const string PermNotify = "weaponrackaudit.notify";

        private PluginConfig config;
        private readonly List<string> auditEntries = new List<string>();

        private class PluginConfig
        {
            [JsonProperty("Log to console")]
            public bool LogToConsole { get; set; } = true;

            [JsonProperty("Max audit entries kept")]
            public int MaxEntries { get; set; } = 200;
        }

        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>
            {
                ["Taken"] = "{0} took {1} from a weapon rack at {2}",
                ["Announce"] = "{0} just removed {1} from a weapon rack"
            }, 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(PermNotify, this);
        }

        private void OnRackedWeaponTaken(Item weaponItem, BasePlayer player, WeaponRack weaponRack)
        {
            if (weaponItem?.info == null || player == null || weaponRack == null) return;

            string itemName = weaponItem.info.displayName.english;
            Vector3 pos = weaponRack.transform.position;
            string entry = $"{DateTime.UtcNow:u} | {player.displayName} ({player.UserIDString}) | {weaponItem.info.shortname} x{weaponItem.amount} | {pos.x:F0},{pos.y:F0},{pos.z:F0}";

            auditEntries.Add(entry);
            if (auditEntries.Count > Math.Max(10, config.MaxEntries))
                auditEntries.RemoveAt(0);

            if (config.LogToConsole)
                Puts(entry);

            foreach (BasePlayer online in BasePlayer.activePlayerList)
            {
                if (online == null || online == player) continue;
                if (!permission.UserHasPermission(online.UserIDString, PermNotify)) continue;
                online.ChatMessage(Msg("Announce", online.UserIDString, player.displayName, itemName));
            }
        }

        private void Unload()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, auditEntries);
        }
    }
}

The plugin registers a weaponrackaudit.notify permission and listens on OnRackedWeaponTaken. When a player who has the permission takes a weapon, the hook builds a readable line from the item's shortname, the player's display name and the rack's world position, saves it to a rotating audit list in oxide/data, and prints it to chat through the language messages. Every take is also written to the server console when LogToConsole is enabled in the config so admins can follow rack activity without watching the file. Unload flushes the buffered list to disk.

Common use cases

  • Track who empties clan racks

    Log every taken weapon with player ID, timestamp and rack owner so raid investigations can be reconstructed from server data.

  • Reward players for retrieving stored weapons

    Hand out a small Economics payout or a score point when a player pulls a specific high-tier weapon from a rack.

  • Admin chat alerts

    Notify online admins in chat when someone takes a weapon from a rack in a protected build zone.

Pitfalls

  • It is not a veto hook

    The weapon has already left the rack when the hook runs. To stop a take you need the pre-action hooks on the rack instead; returning a value here has no effect.

  • Player can be null

    Always guard against a null player before reading UserIDString or displayName, and skip logging messages that require a connected player.

  • Buffer writes instead of saving per take

    Writing the data file on every take adds disk churn during busy fights. Keep entries in memory and flush to oxide/data on Unload or on a timer.

Build a plugin with OnRackedWeaponTaken

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

Prompt: Track who empties clan racks using the OnRackedWeaponTaken 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 OnRackedWeaponTaken

Generate