Skip to content
RustPluginGenerator

How to make a Rust kill rewards plugin (scrap per kill, Oxide)

Awards a configurable item (scrap by default) to the killer on every player kill, with a separate headshot bonus and optional permission gate. It hooks OnEntityDeath, reads info.InitiatorPlayer, and skips NPC victims, suicides and team kills.

Most PvP servers want to pay players for kills, but vanilla Rust gives you nothing on a kill beyond loot. This plugin hooks OnEntityDeath, confirms the victim is a real, connected player, and confirms the killer is a different, connected, non-NPC player. It then hands out the configured item directly to the killer's inventory, adds a separate bonus when info.isHeadshot is true, and refuses when the two players share a team. A permission gate lets you restrict rewards to a rank, and every message goes through the language file so the wording is editable. All amounts, item shortnames and messages live in the config, so changing the reward from scrap to something else is a one-key edit plus a reload.

The plugin code

KillRewards.cs
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("KillRewards", "RustPluginGenerator", "1.0.0")]
    [Description("Awards a configurable item to the killer on every player kill, with an optional headshot bonus.")]
    public class KillRewards : RustPlugin
    {
        private const string PermUse = "killrewards.use";

        private PluginConfig config;
        private bool warnedInvalidItem;

        private class PluginConfig
        {
            [JsonProperty("Reward Shortname")]
            public string RewardShortname { get; set; } = "scrap";

            [JsonProperty("Reward Amount")]
            public int RewardAmount { get; set; } = 25;

            [JsonProperty("Headshot Bonus Amount")]
            public int HeadshotBonusAmount { get; set; } = 25;

            [JsonProperty("Require Permission")]
            public bool RequirePermission { get; set; } = false;

            [JsonProperty("Message Killer")]
            public bool MessageKiller { get; set; } = true;

            [JsonProperty("Announce To Server")]
            public bool AnnounceToServer { get; set; } = false;
        }

        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>
            {
                ["Reward"] = "You received {0} x {1} for killing {2}.",
                ["RewardHeadshot"] = "You received {0} x {1} for a headshot kill on {2}.",
                ["Announce"] = "{0} was killed by {1}.",
                ["InvalidItem"] = "KillRewards: the reward shortname '{0}' is not a valid item."
            }, this);
        }

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info == null) return;

            var victim = entity as BasePlayer;
            if (victim == null || victim.IsNpc || !victim.IsConnected) return;

            var killer = info.InitiatorPlayer;
            if (killer == null || killer.IsNpc || !killer.IsConnected) return;
            if (killer.userID == victim.userID) return;

            // Team check: same non-zero team id means a team kill.
            if (killer.currentTeam != 0 && killer.currentTeam == victim.currentTeam) return;

            if (config.RequirePermission && !permission.UserHasPermission(killer.UserIDString, PermUse)) return;

            GiveReward(killer, victim, info.isHeadshot);
        }

        private void GiveReward(BasePlayer killer, BasePlayer victim, bool headshot)
        {
            int amount = config.RewardAmount;
            if (headshot) amount += config.HeadshotBonusAmount;
            if (amount <= 0) return;

            var item = ItemManager.CreateByName(config.RewardShortname, amount, 0);
            if (item == null)
            {
                if (!warnedInvalidItem)
                {
                    warnedInvalidItem = true;
                    PrintWarning($"Invalid reward shortname '{config.RewardShortname}', no rewards will be given until it is fixed.");
                }
                return;
            }

            killer.GiveItem(item);

            if (config.MessageKiller)
            {
                string key = headshot ? "RewardHeadshot" : "Reward";
                SendReply(killer, Msg(key, killer.UserIDString, amount, item.info.displayName.english, victim.displayName));
            }

            if (config.AnnounceToServer)
            {
                Server.Broadcast(Msg("Announce", null, victim.displayName, killer.displayName));
            }
        }

        private string Msg(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);
    }
}

Hooks used: OnEntityDeath

Config file

Created automatically on first load at oxide/config/KillRewards.json.

KillRewards.json
{
  "Reward Shortname": "scrap",
  "Reward Amount": 25,
  "Headshot Bonus Amount": 25,
  "Require Permission": false,
  "Message Killer": true,
  "Announce To Server": false
}

Commands and permissions

No chat commands. The plugin works on its own.

Permissions
PermissionGrants
killrewards.useGrants the player kill rewards. When Require Permission is enabled, players without it get nothing.

How the code works

  1. Filtering who gets a reward

    OnEntityDeath fires for every entity death, so the first job is narrowing it down. The plugin casts the victim to BasePlayer and rejects anything that is null, an NPC (IsNpc), or disconnected. It then reads info.InitiatorPlayer. If that is null (suicide, fall damage, decay, bleeding without a killer), nothing happens. It also stops when victim and killer are the same player, which covers suicide commands and self-damage.

  2. Blocking team kills

    When both players have a non-zero currentTeam and the values match, the kill is a team kill and is skipped. This simple check covers vanilla teams without needing RelationshipManager. If you run a separate clans plugin, that system is a different data store and is not consulted here; the FAQ covers how to extend the check if your server needs it.

  3. Paying the killer

    GiveReward builds the item with ItemManager.CreateByName(config.RewardShortname, amount, 0). A null return means the shortname in the config is wrong, and the plugin warns once per kill rather than crashing. player.GiveItem(item) puts the item in the first free slot or drops it at the player's feet when the inventory is full, so the reward is never silently lost. The permission check against killrewards.use runs before this point.

  4. Headshot bonus

    info.isHeadshot is read in OnEntityDeath and passed into GiveReward, which adds config.HeadshotBonusAmount on top of the base amount. Set the bonus to 0 in the config to disable it without touching code. Since the two amounts are summed before the item is created, the killer receives a single stack instead of two separate item creations.

  5. Config and messages

    PluginConfig holds the item shortname, base amount, headshot bonus, whether the permission is required, whether the killer gets a chat confirmation, and whether the kill is announced to the whole server. LoadConfig falls back to LoadDefaultConfig with a warning when the file cannot be parsed, then rewrites it. All player text is registered in LoadDefaultMessages and fetched through the Msg helper.

Install it on your server

  1. Save KillRewards.cs

    Keep the file name exactly as the class name. Oxide matches them.
  2. 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.
  3. Edit the config if you want

    On first load the default config is written to oxide/config/KillRewards.json (Carbon: carbon/configs/KillRewards.json). After editing, reload it:oxide.reload KillRewards c.reload KillRewards # Carbon
  4. Grant the permission

    Give it to every player, or swap default for a group such as vip:oxide.grant group default killrewards.use c.grant group default killrewards.use # Carbon

Variations

Each one opens the generator with a ready prompt you can tweak.

FAQ

Does this pay for killing NPCs, animals or other players on the same team?

No. NPC victims are rejected via IsNpc on the victim, suicides are rejected because InitiatorPlayer is the victim or null, and team kills are rejected when both players have the same non-zero currentTeam. Only real players killed by a different, connected player produce a reward.

How do I change the reward item or amount?

Edit oxide/config/KillRewards.json: set Reward Shortname to any valid item shortname such as scrap, economics-free alternatives like rifle.ak (minding stack sizes), then set Reward Amount and Headshot Bonus Amount. Reload the plugin with oxide.reload KillRewards to apply.

Why did my killer not receive scrap?

Check three things: Require Permission is false or the killer has killrewards.use, the shortname in the config exists (a typo logs a warning on kill), and the killer is not on the same team as the victim. If the inventory is full the item is dropped at their feet rather than lost.

How do I install it on Oxide or Carbon?

Drop the compiled KillRewards.cs into oxide/plugins, wait for the server to compile it, then edit oxide/config/KillRewards.json. Carbon loads the same file from its plugins folder. Grant the permission with oxide.grant user <steamid> killrewards.use if you enable the gate.

Customize it for your server

Change the reward, add a cooldown, restrict it to VIPs. Start from this prompt and edit anything.

Prompt: Make an Oxide Rust kill rewards plugin that gives scrap to the killer on player kills, skips NPCs, suicides and team kills, has a headshot bonus, a killrewards.use permission, and configurable amounts and messages.
Customize for my server

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026.

Customize kill rewards

Customize