How to make a Rust loot multiplier plugin (Oxide/Carbon)
This plugin multiplies the stack sizes of items generated inside loot containers such as crates and barrels, using a global multiplier, per-item overrides and a blacklist. It hooks OnLootSpawn(LootContainer) to scale the freshly generated inventory before the container opens.
Running a busy server usually means you want loot to feel more rewarding without rewriting the entire loot table. Instead of editing every prefab in the server filesystem, you can intercept the moment Rust fills a loot container and scale up the stacks it just produced.
The tricky part is doing this without touching weapons, tools and attachments that break if you multiply them. This plugin uses the OnLootSpawn(LootContainer lootContainer) hook, which fires after the container's inventory has been generated and before a player can open it. It applies a global multiplier, checks a shortname blacklist, then falls through to per-item overrides so you can keep wood at x5 while boosting scrap to x3. Stack sizes are always clamped to the item definition's stackable limit, and amounts are rounded down so you never create fractional items. A single permission-gated chat command lets admins check the current settings or reload the config file.
The plugin code
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Loot Multiplier", "RustPluginGenerator", "1.0.0")]
[Description("Multiplies stackable items spawned inside loot containers with overrides and a blacklist.")]
public class LootMultiplier : RustPlugin
{
private const string PermAdmin = "lootmultiplier.admin";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Global Multiplier")]
public double GlobalMultiplier = 2.0;
[JsonProperty("Ignored Shortnames")]
public List<string> IgnoredShortnames = new List<string>
{
"rifle.ak",
"rifle.lr300",
"rifle.bolt",
"rifle.semiauto",
"smg.2",
"smg.thompson",
"smg.mp5",
"pistol.semiauto",
"pistol.m92",
"pistol.python",
"pistol.revolver",
"shotgun.pump",
"shotgun.double",
"shotgun.waterpipe",
"lmg.m249",
"rocket.launcher",
"explosive.timed",
"explosive.satchel",
"grenade.f1",
"tool.camera",
"hammer",
"building.planner",
"box.repair.bench",
"toolgun"
};
[JsonProperty("Item Overrides")]
public Dictionary<string, double> ItemOverrides = new Dictionary<string, double>
{
["scrap"] = 3.0,
["wood"] = 5.0,
["metal.fragments"] = 4.0
};
}
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 use this command.",
["Status"] = "Loot multiplier: global {0}x, overrides: {1}, blacklisted: {2}.",
["Reloaded"] = "Loot multiplier configuration reloaded."
}, 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(PermAdmin, this);
}
private object OnLootSpawn(LootContainer lootContainer)
{
if (lootContainer == null || lootContainer.inventory == null) return null;
if (config == null) return null;
var items = lootContainer.inventory.itemList;
if (items == null || items.Count == 0) return null;
foreach (var item in items)
{
if (item == null || item.info == null) continue;
var shortname = item.info.shortname;
if (string.IsNullOrEmpty(shortname)) continue;
if (config.IgnoredShortnames != null && config.IgnoredShortnames.Contains(shortname)) continue;
double multiplier = config.GlobalMultiplier;
if (config.ItemOverrides != null && config.ItemOverrides.TryGetValue(shortname, out double ov))
multiplier = ov;
if (multiplier <= 1.0) continue;
int original = item.amount;
int maxStack = Math.Max(1, item.info.stackable);
int scaled = (int)Math.Floor(original * multiplier);
if (scaled <= original) continue;
if (scaled > maxStack) scaled = maxStack;
if (scaled == original) continue;
item.amount = scaled;
item.MarkDirty();
}
return null;
}
[ChatCommand("lootmult")]
private void CmdLootMult(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
{
SendReply(player, Msg("NoPermission", player.UserIDString));
return;
}
string sub = args != null && args.Length > 0 ? args[0].ToLowerInvariant() : "status";
if (sub == "reload")
{
LoadConfig();
SendReply(player, Msg("Reloaded", player.UserIDString));
return;
}
int overrideCount = config?.ItemOverrides?.Count ?? 0;
int ignoreCount = config?.IgnoredShortnames?.Count ?? 0;
double global = config?.GlobalMultiplier ?? 1.0;
SendReply(player, Msg("Status", player.UserIDString, global, overrideCount, ignoreCount));
}
}
}Hooks used: OnLootSpawn
Config file
Created automatically on first load at oxide/config/LootMultiplier.json.
{
"Global Multiplier": 2,
"Ignored Shortnames": [
"rifle.ak",
"rifle.lr300",
"rifle.bolt",
"rifle.semiauto",
"smg.2",
"smg.thompson",
"smg.mp5",
"pistol.semiauto",
"pistol.m92",
"pistol.python",
"pistol.revolver",
"shotgun.pump",
"shotgun.double",
"shotgun.waterpipe",
"lmg.m249",
"rocket.launcher",
"explosive.timed",
"explosive.satchel",
"grenade.f1",
"tool.camera",
"hammer",
"building.planner",
"box.repair.bench",
"toolgun"
],
"Item Overrides": {
"scrap": 3,
"wood": 5,
"metal.fragments": 4
}
}Commands and permissions
| Command | What it does | Permission |
|---|---|---|
/lootmult status | Prints the active global multiplier, override count and blacklist count to the caller. | lootmultiplier.admin |
/lootmult reload | Reloads the config file from disk and reapplies the settings. | lootmultiplier.admin |
| Permission | Grants |
|---|---|
lootmultiplier.admin | Grants access to the /lootmult chat command. |
How the code works
Hook into loot spawning
The plugin registers
private object OnLootSpawn(LootContainer lootContainer). This hook fires after the container has generated its contents. We returnnullso Rust continues with its normal behavior and the container opens as usual; only the items are mutated. Every call first null-checkslootContainerand itsinventory, then bails out whenitemListis empty. The method also bails whenconfigis null. Because this fires for every barrel, crate, food box and lootable corpse, the loop stays cheap: no logging, no allocations beyond what the multiply loop needs.Apply global multiplier and blacklist
The handler loops over
lootContainer.inventory.itemListand reads each item's shortname fromitem.info.shortname. Blacklisted shortnames (weapons, tools and attachments by default) are skipped withContainsbefore any multiplication. Non-blacklisted items get the globalGlobal Multiplierfrom the config, then a per-item override fromItem Overrideswhen one exists. Because we work on the stack Rust already generated, this composes cleanly with custom loot tables.Respect the stack limit
item.info.stackableis the maximum amount the item definition allows in one slot. After multiplying, the amount is rounded down withMath.Floorand clamped to that limit so Rust never leaves the stack in an invalid state. If the scaled amount is not larger than the original, the item is left untouched andMarkDirtyis never called. Items that gained quantity are marked dirty so connected clients see the correct stack when they open the container.Configure overrides and blacklist
The
PluginConfigclass exposesGlobal Multiplier(a double, default 2.0),Ignored Shortnames(a list of strings, prefilled with common weapons and tools) andItem Overrides(a dictionary mapping shortname to a multiplier). TheLoadConfigoverride reads the file, falls back to defaults with a warning if the file is invalid, and callsSaveConfigso the file is always complete. Settings are read into memory once, not parsed on every spawn.Chat command and permission
[ChatCommand("lootmult")]handles astatussubcommand that reports the current settings and areloadsubcommand that callsLoadConfig. With no argument the command defaults tostatus. Both are gated on thelootmultiplier.adminpermission registered inInit(). Each call checkspermission.UserHasPermission(player.UserIDString, PermAdmin)first, so regular players cannot inspect or reload the plugin. Player-facing text uses theNoPermission,StatusandReloadedlang keys.Nothing to clean up on unload
The plugin holds no active state that needs tearing down, so it does not override
Unload. Everything it needs lives in thePluginConfiginstance, which is written bySaveConfigduringLoadConfig. If you later add a repeating action or a persistent data file, add anUnloadoverride and clear those resources there. For the multiplier alone, Oxide unloading the plugin is enough.
Install it on your server
Save LootMultiplier.cs
Keep the file name exactly as the class name. Oxide matches them.Upload it to the plugins folder
Oxide:oxide/plugins/. Carbon:carbon/plugins/. The server compiles and loads it within a few seconds, no restart needed.Edit the config if you want
On first load the default config is written tooxide/config/LootMultiplier.json(Carbon:carbon/configs/LootMultiplier.json). After editing, reload it:oxide.reload LootMultiplier c.reload LootMultiplier # CarbonGrant the permission
Give it to every player, or swapdefaultfor a group such asvip:oxide.grant group default lootmultiplier.admin c.grant group default lootmultiplier.admin # Carbon
Variations
Each one opens the generator with a ready prompt you can tweak.
Per-container multiplier
Scale the multiplier based on the container's short prefab name so elite crates get a higher boost than food boxes.
Generate this versionOnly boost stackables
Skip items whose stackable limit is 1 so weapons, tools and attachments are never touched.
Generate this versionLoot multiplier by zone
Apply a different multiplier inside monuments versus the open world using position checks.
Generate this version
FAQ
Will this inflate loot that's already in a container?
No. OnLootSpawn fires before a container is opened for the first time, so it only affects freshly generated contents. Items players place into containers and items dropped on the ground are not affected, which keeps the multiplier predictable.
How do I keep weapons at x1?
The default Ignored Shortnames list already contains weapons, tools and attachments. Any shortname you add there is skipped before the multiplier is applied. You can find shortnames from the Rust item list or by giving yourself the item with inventory.give.
Can I set a different multiplier for one item?
Yes. Add an entry to Item Overrides in the config using the item's shortname as key and the multiplier as value, for example "scrap": 3.0. Per-item overrides take precedence over the global multiplier, but the blacklist still wins.
Does this work on Carbon as well as Oxide?
Yes. Carbon loads Oxide plugins unchanged, and this plugin only uses hooks and APIs present in both. Drop the .cs file into oxide/plugins/ or Carbon's plugin directory, let it compile, then edit oxide/config/LootMultiplier.json.
What happens if I set the multiplier very high?
Every stack is clamped to item.info.stackable, so a stack of rifle ammo will not exceed its definition limit. The item amount is also rounded down, so a x2.5 multiplier on an amount of 3 yields 7 (7.5 floored), not 8.
Customize it for your server
Change the reward, add a cooldown, restrict it to VIPs. Start from this prompt and edit anything.
Edit the prompt on the next screen. 2 free plugins a month, no card.
More loot plugins
- Barrel scrap bonusAwards bonus scrap when a player destroys a loot barrel, with a configurable chance and a VIP multiplier permission.OnEntityDeath
- First opener crate lockThis plugin gives the first player who opens a loot container a temporary claim on it, enforced through the CanLootEntity hook, so anyone outsideโฆCanLootEntityOnEntityKill
- Custom loot tablesReplaces the contents of configured LootContainer crates, matched by short prefab name, with weighted items that have per-item chances and min/maxโฆOnLootSpawn
Last updated Oct 26, 2026.
Customize loot multiplier
Customize