How to make a Rust PvP damage multiplier plugin (global, per-weapon, headshot)
Scales damage players deal to other players using a global multiplier, per-weapon shortname overrides and an extra headshot factor. It runs in OnEntityTakeDamage(BasePlayer, HitInfo) and rewrites hitInfo.damageTypes before the hit is applied.
On a normal Rust server every player-vs-player fight uses vanilla damage numbers, which makes it hard to push longer fights, make specific guns weaker, or reward headshots without touching real weapon stats. This plugin solves that by scaling the damage in the damage event itself: OnEntityTakeDamage(BasePlayer player, HitInfo hitInfo) fires before the hit is applied, so the plugin can check both the victim and the attacker, confirm they are different players, and adjust hitInfo.damageTypes with ScaleAll.
Three layers of control are exposed in the config: a global PvP multiplier, a per-weapon override keyed by the weapon shortname from hitInfo.Weapon.ShortPrefabName (rifles, melee, explosives all work), and a separate headshot multiplier applied on top when hitInfo.isHeadshot is true. NPCs, structures, animals and environmental damage are left untouched. A /pvpcd command shows the current numbers so admins can verify a config change without reading the file.
The plugin code
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("PvP Damage Multiplier", "RustPluginGenerator", "1.0.0")]
[Description("Scales player versus player damage with a global multiplier, per-weapon overrides and a headshot multiplier.")]
public class PvPDamageMultiplier : RustPlugin
{
private const string PermUse = "pvpdamagemultiplier.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Global multiplier")]
public float GlobalMultiplier = 1.0f;
[JsonProperty("Headshot multiplier")]
public float HeadshotMultiplier = 1.0f;
[JsonProperty("Minimum damage scale")]
public float MinDamageScale = 0.1f;
[JsonProperty("Maximum damage scale")]
public float MaxDamageScale = 5.0f;
[JsonProperty("Weapon multipliers (shortname)")]
public Dictionary<string, float> WeaponMultipliers = new Dictionary<string, float>
{
["rifle.ak"] = 1.0f,
["smg.2"] = 1.0f,
["shotgun.pump"] = 1.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();
}
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(config);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Status"] = "PvP damage: global {0}x, headshot {1}x, {2} weapon overrides.",
["NoPermission"] = "You do not have permission to use this command."
}, this);
}
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private void Unload()
{
SaveConfig();
}
private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
private object OnEntityTakeDamage(BasePlayer player, HitInfo hitInfo)
{
if (player == null || hitInfo == null || hitInfo.damageTypes == null) return null;
if (player.IsNpc) return null;
BasePlayer attacker = hitInfo.InitiatorPlayer;
if (attacker == null || attacker.IsNpc || attacker == player) return null;
float scale = config.GlobalMultiplier;
AttackEntity weapon = hitInfo.Weapon;
if (weapon != null && !string.IsNullOrEmpty(weapon.ShortPrefabName))
{
float overrideScale;
if (config.WeaponMultipliers != null && config.WeaponMultipliers.TryGetValue(weapon.ShortPrefabName, out overrideScale))
{
scale = overrideScale;
}
}
if (hitInfo.isHeadshot) scale *= config.HeadshotMultiplier;
scale = Mathf.Clamp(scale, config.MinDamageScale, config.MaxDamageScale);
hitInfo.damageTypes.ScaleAll(scale);
return null;
}
[ChatCommand("pvpcd")]
private void CmdStatus(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return;
}
int overrides = config.WeaponMultipliers != null ? config.WeaponMultipliers.Count : 0;
player.ChatMessage(Msg("Status", player.UserIDString, config.GlobalMultiplier, config.HeadshotMultiplier, overrides));
}
}
}Hooks used: OnEntityTakeDamage
Config file
Created automatically on first load at oxide/config/PvPDamageMultiplier.json.
{
"Global multiplier": 1,
"Headshot multiplier": 1,
"Minimum damage scale": 0.1,
"Maximum damage scale": 5,
"Weapon multipliers (shortname)": {
"rifle.ak": 1,
"smg.2": 1,
"shotgun.pump": 1
}
}Commands and permissions
| Command | What it does | Permission |
|---|---|---|
/pvpcd | Prints the active global multiplier, headshot multiplier and the number of configured weapon overrides. | pvpdamagemultiplier.use |
| Permission | Grants |
|---|---|
pvpdamagemultiplier.use | Allows the player to run /pvpcd to inspect the active damage settings. |
How the code works
Restrict the hook to player-versus-player hits
OnEntityTakeDamage(BasePlayer player, HitInfo hitInfo)only fires when the victim is aBasePlayer, but that still includes NPC scientists and damage with no attacker. Null-checkhitInfoandhitInfo.InitiatorPlayerfirst, then comparehitInfo.InitiatorPlayer == playerto bail out on self damage such as fall or bleed caused by the player's own actions. Finally skip whenplayer.IsNpcorhitInfo.InitiatorPlayer.IsNpcis true so PvE fights stay vanilla.Resolve the weapon shortname for overrides
hitInfo.Weaponis anAttackEntity; itsShortPrefabNameis the shortname used as the config key (for examplerifle.ak). Melee hits, thrown explosives and the hotbar weapon all pass through this field, so long as the method name is checked for null before readingShortPrefabName. WhenWeaponis null (some ambient damage) the plugin falls back to the global multiplier only, which keeps the code safe.Apply global, weapon and headshot multipliers in order
config.GlobalMultiplieris read first, then the dictionaryconfig.WeaponMultipliersis queried by shortname and, if present, used instead of the global value. IfhitInfo.isHeadshotis true the result is multiplied byconfig.HeadshotMultiplier. The final value is clamped between the two config limitsMinDamageScaleandMaxDamageScaleso a mistyped5.0cannot produce a one-shot weapon.hitInfo.damageTypes.ScaleAll(scale)then rewrites every damage type in the hit.Keep the global override readable in the config
The nested
PluginConfigclass holdsGlobalMultiplier,HeadshotMultiplierandDictionary<string, float> WeaponMultiplierswith[JsonProperty]names.LoadConfigreads the file, re-creates defaults on any exception and callsSaveConfig. Onlyrifle.ak,smg.2andshotgun.pumpship with sample overrides so admins can see the shape of the dictionary and add their own entries.Expose the values for quick checks
[ChatCommand("pvpcd")]runs a permission-checked method that formatsMsg("Status", ...)with the three configured values. Messages live inLoadDefaultMessagesso the text can be translated. There is no hot-reload command: change the config, runoxide.reload PvPDamageMultiplier, and the new numbers are active immediately.Clean up on unload
The plugin has no timers or CUI, so
Unloadjust callsSaveConfigin case defaults were regenerated while running. Destroy any timer reference you add later in this same method; Oxide will callUnloadautomatically onoxide.unload PvPDamageMultiplierand on server shutdown.
Install it on your server
Save PvPDamageMultiplier.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/PvPDamageMultiplier.json(Carbon:carbon/configs/PvPDamageMultiplier.json). After editing, reload it:oxide.reload PvPDamageMultiplier c.reload PvPDamageMultiplier # CarbonGrant the permission
Give it to every player, or swapdefaultfor a group such asvip:oxide.grant group default pvpdamagemultiplier.use c.grant group default pvpdamagemultiplier.use # Carbon
Variations
Each one opens the generator with a ready prompt you can tweak.
Per-weapon multipliers by weapon category
Scale all guns together via the item category instead of listing every shortname.
Generate this versionApply multipliers only inside building-protected areas
Use a simpler fight rule: only scale damage near a tool cupboard.
Generate this versionAdd per-player damage permissions
Let donators take less PvP damage via a permission group.
Generate this version
FAQ
Does this affect damage to NPCs, animals or building blocks?
No. The hook used here is the BasePlayer overload, so it only sees damage where the victim is a player. NPC scientists are still BasePlayer instances, so the method checks IsNpc on both sides and leaves those hits at vanilla values.
Why is my per-weapon override not applied?
The key must match AttackEntity.ShortPrefabName, which is usually the item shortname but not always (for example some melee prefabs differ from the item shortname). Test the weapon in-game and check that the config key matches the prefab name shown when the weapon hits.
Do the multipliers stack with headshot damage?
Yes. The order is: pick the weapon override or global value, then multiply by HeadshotMultiplier if hitInfo.isHeadshot is true, then clamp to MinDamageScale and MaxDamageScale. A 1.2 weapon override with a 1.5 headshot multiplier results in 1.8x total.
How do I install it on Oxide or Carbon?
Drop PvPDamageMultiplier.cs into oxide/plugins, wait for compilation, then edit oxide/config/PvPDamageMultiplier.json and run oxide.reload PvPDamageMultiplier. Carbon loads the same file from its plugins folder without changes.
Does it work with decay, raid explosions or environmental damage?
Explosions only route through this hook when the attacker is a player and the victim is a player, so C4 on a wall and decay damage stay untouched. Explosive damage thrown by a player at another player is scaled like any other hit.
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 pvp plugins
- Combat blockTracks combat with the OnEntityTakeDamage hook and blocks a configurable list of chat commands while a player is in combat, using OnPlayerCommand toโฆOnEntityTakeDamageOnPlayerCommand
- DuelsAdds a player-vs-player duel system where /duel <player> sends a challenge, /duel accept starts it, and damage outside the duel pair is blocked.OnEntityTakeDamageOnEntityDeathOnPlayerDisconnected
- Friendly fire protectionBlocks damage between members of the same Rust team using OnEntityTakeDamage, with a permission whitelist and a /ff toggle for team leaders thatโฆOnEntityTakeDamageOnPlayerDisconnected
Last updated Oct 26, 2026.
Customize pvp damage multiplier
Customize