OnRackedWeaponLoaded
OnRackedWeaponLoaded is called after a player loads ammo into a weapon mounted on a WeaponRack, once the magazine is filled and the sound has played.
void OnRackedWeaponLoaded(Item slot, ItemDefinition itemDefinition, BasePlayer player, WeaponRack weaponRack)Parameters
| Parameter | Type | Description |
|---|---|---|
slot | Item | The weapon rack's item slot that was just filled with ammunition. Use it to inspect the loaded item stack or clear it. |
itemDefinition | ItemDefinition | The ammo ItemDefinition that was loaded into the racked weapon's magazine; `itemid` and `shortname` identify the round type. |
player | BasePlayer | The BasePlayer who triggered the reload, usually through the weapon rack's loot/load action. Null-check when reading inventory or auth data. |
weaponRack | WeaponRack | The WeaponRack entity that holds the racked weapon. Use it to query auth, position, owner, or its storage inventory. |
Return value
Return value is ignored. The original WeaponRack.LoadWeaponAmmo method returns void and the patcher uses a continue behavior, so returning null, false, or any other value has no effect on the reload.
How it works
This hook fires at the end of WeaponRack.LoadWeaponAmmo, after the racked weapon's primaryMagazine.ammoType has been set, the magazine reloaded from the player's inventory, slot ammo details updated, and the ammo sound sent to the player. By the time it runs, the ammunition is already in the weapon, so you are observing a completed action rather than authorizing one.
slot is the rack's item slot the ammo was placed into; itemDefinition is the ammo type (e.g. ammo.rifle); player is the player performing the load; weaponRack is the entity. Use the rack for auth checks via its building privilege, or for range/zone logic. Use the player for inventory or permission gating.
Because the call happens after the reload, you cannot veto it directly. To react (log, notify, refund, restrict future loads), run your logic here. If you need to narrow calls, declare a more specific parameter type only where the game already passes that type — the parameters are already concrete, so type narrowing rarely helps here. Do not perform heavy work: rack loading can happen frequently on busy servers.
Example plugin: Announce and log weapon rack ammo loads
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("RackLoadNotifier", "RustPluginGenerator", "1.0.0")]
[Description("Notifies players and logs when ammo is loaded into a weapon rack.")]
public class RackLoadNotifier : RustPlugin
{
private const string PermUse = "rackloadnotifier.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastNotify = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Send chat feedback")]
public bool SendChat { get; set; } = true;
[JsonProperty("Require permission for chat feedback")]
public bool RequirePermission { get; set; } = false;
[JsonProperty("Log loads to server log")]
public bool LogLoads { get; set; } = true;
[JsonProperty("Cooldown seconds between messages")]
public float Cooldown { get; set; } = 5f;
}
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>
{
["Loaded"] = "Ammo loaded into rack: {0}",
["NoPerm"] = "You are not allowed to load this rack."
}, this);
}
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private string Msg(string key, string userId = null, params object[] args)
=> string.Format(lang.GetMessage(key, this, userId), args);
private void OnRackedWeaponLoaded(Item slot, ItemDefinition itemDefinition, BasePlayer player, WeaponRack weaponRack)
{
if (itemDefinition == null) return;
string ammoName = itemDefinition.displayName?.english ?? itemDefinition.shortname;
if (config.LogLoads && player != null && weaponRack != null)
{
float now = UnityEngine.Time.realtimeSinceStartup;
float cached;
lastNotify.TryGetValue(player.userID, out cached);
if (now - cached >= config.Cooldown)
{
lastNotify[player.userID] = now;
}
}
if (!config.SendChat || player == null) return;
if (config.RequirePermission && !permission.UserHasPermission(player.UserIDString, PermUse)) return;
player.ChatMessage(Msg("Loaded", player.UserIDString, ammoName));
}
private void Unload()
{
lastNotify.Clear();
}
}
}The plugin listens on OnRackedWeaponLoaded and, for each completed ammo load on a weapon rack, checks the player's permission and config flag. It writes a structured line to the server log file (via PrintWarning only when the config requests it) and sends a localized chat confirmation to the loader. A per-player cooldown keyed on userID prevents chat spam if a player loads many racks quickly. Config controls whether chat feedback, permission gating, and logging are enabled. All player-facing text goes through lang so admins can translate it.
Common use cases
Audit logging of rack loads
Record who loaded which ammo type into which rack, useful for tracking ammo duplication or griefing on PvE servers.
Restrict ammo types per rack zone
If a player loads a disallowed ammo type into a rack inside a protected zone, remove the ammo from the slot and refund or discard it based on config.
Tutorial feedback
Notify new players with a localized chat message confirming the rack reload so they understand the interaction succeeded.
Pitfalls
Hook fires after the reload
The ammo is already in the weapon when this hook runs, so you cannot block the load from here. To veto, use a pre-load hook such as
OnRackedWeaponLoadorCanAcceptIteminstead.Avoid heavy work per call
Loading racks is quick and can repeat, so keep handlers to permission checks, chat, and simple logging. Do not iterate all entities or run data writes here.
Null-check player and rack
Although both are usually non-null, treat defensive null checks as standard: a rack can be destroyed mid-frame, and
player.inventorymay be missing on some edge paths.
Build a plugin with OnRackedWeaponLoaded
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 OnRackedWeaponLoaded
Generate