How to make a Rust tool durability plugin (per-item condition multipliers)
Scales condition loss on tools and weapons through the OnLoseCondition hook, with per-shortname multipliers, a default multiplier and a permission that makes tools unbreakable.
Every swing of a pickaxe, every shot from a weapon and every chop of a hatchet shaves condition off the item, and on a busy server that means constant repair runs and frequent breakages. The clean way to change this is the OnLoseCondition hook, which fires whenever Rust is about to remove condition from an item and lets you scale the amount before it is applied.
This plugin reads a multiplier per item shortname, falls back to a global default, and optionally grants a permission group tools that never lose condition at all. Values under 1.0 make gear last longer, values over 1.0 wear it out faster, which is useful for balance passes on custom loot tables. Everything is configurable in oxide/config/ToolDurability.json and hot-reloadable with oxide.reload ToolDurability.
The plugin code
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("ToolDurability", "RustPluginGenerator", "1.0.0")]
[Description("Scales condition loss on tools and weapons with per-item multipliers and an unbreakable permission.")]
public class ToolDurability : RustPlugin
{
private const string PermUnbreakable = "tooldurability.unbreakable";
private const string PermCheck = "tooldurability.check";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Default multiplier")]
public float DefaultMultiplier { get; set; } = 0.5f;
[JsonProperty("Affect only tools and weapons")]
public bool AffectOnlyToolsAndWeapons { get; set; } = true;
[JsonProperty("Per item multipliers")]
public Dictionary<string, float> PerItemMultipliers { get; set; } = new Dictionary<string, float>
{
["rock"] = 0.5f,
["torch"] = 0.5f,
["hatchet"] = 0.5f,
["pickaxe"] = 0.5f,
["stone.pickaxe"] = 0.5f,
["stone.hatchet"] = 0.5f,
["salvaged.axe"] = 0.25f,
["salvaged.pickaxe"] = 0.25f,
["salvaged.sword"] = 0.25f,
["hammer"] = 0.0f
};
}
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();
}
if (config.PerItemMultipliers == null)
{
config.PerItemMultipliers = new Dictionary<string, float>();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoItem"] = "Hold a tool or weapon and try again.",
["Result"] = "Condition loss for {0}: x{1}",
["Clamped"] = "Condition loss for {0}: x{1} (no wear)"
}, 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(PermUnbreakable, this);
permission.RegisterPermission(PermCheck, this);
}
private void OnLoseCondition(Item item, ref float amount)
{
if (item == null || item.info == null || amount <= 0f)
{
return;
}
if (!IsAffected(item))
{
return;
}
var player = item.GetOwnerPlayer();
if (player != null && permission.UserHasPermission(player.UserIDString, PermUnbreakable))
{
amount = 0f;
return;
}
var multiplier = ResolveMultiplier(item);
if (multiplier == 1f)
{
return;
}
amount *= multiplier;
if (amount < 0f)
{
amount = 0f;
}
}
private bool IsAffected(Item item)
{
if (!config.AffectOnlyToolsAndWeapons)
{
return true;
}
var category = item.info.category;
return category == ItemCategory.Tool || category == ItemCategory.Weapon;
}
private float ResolveMultiplier(Item item)
{
if (config.PerItemMultipliers != null && item.info.shortname != null)
{
float value;
if (config.PerItemMultipliers.TryGetValue(item.info.shortname, out value))
{
return value;
}
}
return config.DefaultMultiplier;
}
[ChatCommand("durability")]
private void CmdDurability(BasePlayer player, string command, string[] args)
{
if (player == null)
{
return;
}
if (!permission.UserHasPermission(player.UserIDString, PermCheck))
{
player.ChatMessage(Msg("NoItem", player.UserIDString));
return;
}
var held = player.GetActiveItem();
if (held == null || held.info == null)
{
player.ChatMessage(Msg("NoItem", player.UserIDString));
return;
}
var multiplier = ResolveMultiplier(held);
var label = held.info.displayName != null ? held.info.displayName.english : held.info.shortname;
if (permission.UserHasPermission(player.UserIDString, PermUnbreakable))
{
player.ChatMessage(Msg("Clamped", player.UserIDString, label, "0"));
return;
}
player.ChatMessage(Msg("Result", player.UserIDString, label, multiplier));
}
}
}Hooks used: OnLoseCondition
Config file
Created automatically on first load at oxide/config/ToolDurability.json.
{
"Default multiplier": 0.5,
"Affect only tools and weapons": true,
"Per item multipliers": {
"rock": 0.5,
"torch": 0.5,
"hatchet": 0.5,
"pickaxe": 0.5,
"stone.pickaxe": 0.5,
"stone.hatchet": 0.5,
"salvaged.axe": 0.25,
"salvaged.pickaxe": 0.25,
"salvaged.sword": 0.25,
"hammer": 0
}
}Commands and permissions
| Command | What it does | Permission |
|---|---|---|
/durability | Prints the multiplier that applies to the tool or weapon you are holding. | tooldurability.check |
| Permission | Grants |
|---|---|
tooldurability.unbreakable | Items held by this player never lose condition. |
tooldurability.check | Allows use of the /durability chat command. |
How the code works
Hooking condition loss
void OnLoseCondition(Item item, ref float amount)fires every time Rust is about to subtract condition from an item.itemis theItemlosing condition andamountis the loss about to be applied. Becauseamountis arefparameter, changing it inside the hook changes what the game actually removes. Always null-checkitemanditem.info, and return early for items the plugin should not touch.Choosing the multiplier
ResolveMultiplierfirst checks thePer Item Multipliersdictionary foritem.info.shortname. Exact shortnames likesalvaged.swordandrockwork, and the config ships with sensible entries. If nothing matches it returnsDefault Multiplier. Values below1.0reduce wear, for example0.25makes a tool last four times as long between repairs.Unbreakable permission
Before scaling, the hook looks up the item owner with
item.GetOwnerPlayer(). If the owner holdstooldurability.unbreakable, the amount is set to zero and no condition is removed. Items without a player owner, such as loot in a box, fall through to the normal multiplier path, so world items are never accidentally made immune.Only tools and weapons
IsAffectedgates the hook toItemCategory.ToolandItemCategory.WeaponwhenAffect Only Tools And Weaponsistrue. That keeps armour, deployables and building materials out of the calculation. Set the option tofalseif you want multipliers applied to every item category in the dictionary, for example clothing wear on a survival server.Condition floor
Rust already breaks an item when condition reaches zero. The plugin never adds condition; it only reduces or increases the loss that is about to happen. A negative result is clamped to zero so a config mistake cannot heal an item. Break behaviour, salvage and repair mechanics stay exactly as vanilla players expect them.
Configuration and reload
LoadDefaultConfigseedsPluginConfig,LoadConfigre-readsoxide/config/ToolDurability.jsonand warns and resets if the file is corrupt. ThePer Item Multipliersdictionary is rebuilt on load, so an admin can edit the JSON and runoxide.reload ToolDurabilitywithout restarting the server.
Install it on your server
Save ToolDurability.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/ToolDurability.json(Carbon:carbon/configs/ToolDurability.json). After editing, reload it:oxide.reload ToolDurability c.reload ToolDurability # CarbonGrant the permission
Give it to every player, or swapdefaultfor a group such asvip:oxide.grant group default tooldurability.unbreakable c.grant group default tooldurability.unbreakable # Carbon
Variations
Each one opens the generator with a ready prompt you can tweak.
Infinite tools for a named group only
Replaces the permission check with an Oxide group check so members of the `vip` group keep their tools forever.
Generate this versionChance to consume no condition
Adds a per-swing random chance for the tool to lose no condition at all.
Generate this versionDaily wear budget
Caps total condition loss per player per day and blocks further loss until midnight UTC.
Generate this version
FAQ
Does this plugin break repair or salvage?
No. It only changes the amount of condition removed during normal use. Repair benches, salvage and recycling still work with the current condition value on the item.
Why is my tool still losing condition?
Check that the shortname in Per Item Multipliers matches the item exactly, for example salvaged.axe not salvaged axe. Use /durability while holding the tool to see which multiplier applies. A multiplier of 1.0 is the same as vanilla.
How do I install this on Oxide or Carbon?
Drop ToolDurability.cs into your oxide/plugins folder and let the server load it. Carbon loads the same file from its Oxide plugin directory. Grant permissions with oxide.grant user <steamid> tooldurability.unbreakable.
Can I set a multiplier above 1.0?
Yes. Values above 1.0 increase condition loss, so a 2.0 multiplier breaks tools twice as fast. This is useful for slowing down progression on high-population servers without editing loot tables.
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 gathering plugins
- Auto smelt on gatherConverts gathered metal ore into metal fragments, sulfur ore into sulfur and optionally wood into charcoal for players with a permission, usingโฆOnDispenserGatherOnDispenserBonus
- Farming yield multiplierMultiplies the amount of crops a player receives when harvesting planter crops or wild plants, with a separate multiplier per item shortname.OnServerInitializedOnGrowableGathered
- Fishing catch bonusMultiplies the amount of each caught fish and rolls a configurable chance for bonus items after every successful catch, using the OnFishCaught hook.OnFishCaught
Last updated Oct 26, 2026.
Customize tool durability multiplier
Customize