OnItemUpgrade
OnItemUpgrade is called when a successful item upgrade rolls the upgraded item, after the consumed amount is removed from the original and before the new item is placed into the player's inventory.
void OnItemUpgrade(Item item, Item upgradedItem, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
item | Item | The original item being upgraded. It has already had the upgrade cost consumed at this point, so read item.amount for the remaining count, not the pre-upgrade amount. |
upgradedItem | Item | The new item created by ItemManager.Create as the upgrade result, before it is written to the player's inventory or dropped. Null-check it; it can be null if the prefab failed to create. |
player | BasePlayer | The BasePlayer who triggered the upgrade. Use it for permissions, messaging, position and inventory access. |
Return value
The return value is ignored. Returning anything, including a non-null object or false, does not stop the upgrade and does not change the created item; the game always proceeds to set ownership and move the new item into the player's main inventory or drop it.
How it works
This hook fires inside ItemModUpgrade.ServerCommand, only on the success branch of the random roll. The sequence is: the required amount is consumed from the source item, the upgraded item is created with ItemManager.Create, the hook fires, and then the new item gets ownership set and is moved into player.inventory.containerMain (or dropped if the main container is full).
item is the source stack, already reduced by the upgrade cost. upgradedItem is the freshly created result and has not yet been claimed by the player. player is the initiator.
The return value is ignored, so you cannot use it to cancel or alter the upgrade. Anything you change on upgradedItem (amount, skin, condition, name) before the game continues will be carried into the player's inventory, because the same object is moved. Removing the item's amount or killing it is not a supported cancellation path; the game will still attempt to move it.
Declare the parameters exactly as Item, Item, BasePlayer. Declaring BasePlayer is already the narrowest useful type here; the hook only fires from a player-driven upgrade.
Example plugin: Announce and track high-value item upgrades
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("UpgradeBroadcast", "RustPluginGenerator", "1.0.0")]
[Description("Announces successful item upgrades and applies a bonus amount to chosen results")]
public class UpgradeBroadcast : RustPlugin
{
private const string PermBonus = "upgradebroadcast.bonus";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Broadcast upgrades")]
public bool BroadcastUpgrades { get; set; } = true;
[JsonProperty("Only broadcast these shortnames (empty = all)")]
public List<string> WatchShortnames { get; set; } = new List<string>();
[JsonProperty("Bonus amount percent for permitted players")]
public int BonusPercent { get; set; } = 50;
}
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>
{
["Upgrade"] = "{0} upgraded into {1} x{2}",
["YourUpgrade"] = "You upgraded into {0} x{1}",
["Bonus"] = "Bonus applied: +{0} extra {1}"
}, 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(PermBonus, this);
}
private void OnItemUpgrade(Item item, Item upgradedItem, BasePlayer player)
{
if (upgradedItem == null || upgradedItem.info == null || player == null || !player.IsConnected)
return;
if (config.WatchShortnames != null && config.WatchShortnames.Count > 0 && !config.WatchShortnames.Contains(upgradedItem.info.shortname))
return;
string name = player.displayName ?? "A survivor";
string display = upgradedItem.info.displayName != null ? upgradedItem.info.displayName.english : upgradedItem.info.shortname;
if (config.BonusPercent > 0 && permission.UserHasPermission(player.UserIDString, PermBonus))
{
int extra = Mathf.FloorToInt(upgradedItem.amount * (config.BonusPercent / 100f));
if (extra > 0)
{
upgradedItem.amount += extra;
player.ChatMessage(Msg("Bonus", player.UserIDString, extra, display));
}
}
if (config.BroadcastUpgrades)
Server.Broadcast(Msg("Upgrade", null, name, display, upgradedItem.amount));
else
player.ChatMessage(Msg("YourUpgrade", player.UserIDString, display, upgradedItem.amount));
}
}
}The plugin listens on OnItemUpgrade, checks the configured list of upgraded shortnames, and if the result matches, broadcasts a chat line to the whole server and optionally sends the player a direct confirmation. It also applies a configurable amount bonus to the created item before the game moves it, demonstrating that mutating upgradedItem here is safe because the same object lands in the inventory. Permissions are not needed for a broadcast, but the plugin guards against a disconnected or null player before calling ChatMessage. All player-facing text comes from the language file.
Common use cases
Server-wide upgrade announcements
Broadcast in chat when a player successfully upgrades into a rare result such as a high-tier component, so the whole server sees the achievement.
Upgrade reward bonuses
Increase upgradedItem.amount by a configured percentage for players with a permission, or roll a chance to add a bonus item with GiveItem.
Upgrade statistics
Increment a per-player counter in oxide/data each time the hook fires, then expose it through a chat command for leaderboards.
Pitfalls
Cannot cancel the upgrade
The return value is ignored and the game moves the created item regardless. Do not try to remove the item inside the hook to block the upgrade; that produces an inconsistent state.
The source item amount is already reduced
item.amount reflects the stack after the upgrade cost was consumed. Do not use it to compute how many the player had before the upgrade.
Null upgraded item
ItemManager.Create can return null for an unknown prefab. Always null-check upgradedItem before reading info or modifying it.
Build a plugin with OnItemUpgrade
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 OnItemUpgrade
Generate