Skip to content
RustPluginGenerator

How to make a Rust NPC health multiplier plugin (per-prefab scaling)

Scales the health of scientists and animals when they spawn by reading a per-prefab multiplier from the config, using the OnEntitySpawned hook to detect NPC entities and heal them to the scaled target.

Default Rust NPC health rarely matches a modded server. Admins running PvE, hardcore or custom scientist events want scientists that take more bullets, or animals that die faster so hunting is not a grind. The problem is that Rust spawns scientists and animals from many different prefabs, and health is baked into each one at spawn time.

This plugin listens for OnEntitySpawned, checks whether the spawned entity is a ScientistNPC, BaseAnimalNPC or ScarecrowNPC, and looks up a multiplier for its ShortPrefabName. If no exact entry exists it falls back to Default Multiplier. The plugin then computes MaxHealth() * multiplier on the BaseCombatEntity and calls Heal so the NPC starts at the adjusted value instead of its vanilla amount.

Because matching is done on prefab name, you can scale one scientist prefab differently from another, or leave bears and boars at different values. Config edits save to disk, so no server restart is needed.

The plugin code

NpcHealthMultiplier.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Npc Health Multiplier", "RustPluginGenerator", "1.0.0")]
    [Description("Scales scientist and animal health on spawn using per-prefab multipliers.")]
    public class NpcHealthMultiplier : RustPlugin
    {
        private const string PermAdmin = "npchealthmultiplier.admin";
        private const int SeenCap = 5000;

        private PluginConfig config;
        private readonly HashSet<ulong> seen = new HashSet<ulong>();

        private class PluginConfig
        {
            [JsonProperty("Default multiplier")]
            public float DefaultMultiplier { get; set; } = 1.0f;

            [JsonProperty("Prefab multipliers")]
            public Dictionary<string, float> PrefabMultipliers { get; set; } = new Dictionary<string, float>
            {
                ["scientistnpc_heavy"] = 1.5f,
                ["scientistnpc_roam"] = 1.25f,
                ["bear"] = 0.75f,
                ["boar"] = 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>
            {
                ["NoPerm"] = "You do not have permission to use this command.",
                ["Set"] = "Set multiplier for {0} to {1}.",
                ["Default"] = "Default multiplier set to {0}.",
                ["List Header"] = "NPC health multipliers (default {0}):",
                ["List Row"] = "{0} = {1}",
                ["Usage Set"] = "Usage: /npchealth.set <prefab> <multiplier>",
                ["Usage Default"] = "Usage: /npchealth.default <multiplier>",
                ["Bad Number"] = "{0} is not a valid number.",
                ["Out Of Range"] = "Multiplier must be between 0.1 and 50."
            }, this);
        }

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

        private void Unload()
        {
            seen.Clear();
        }

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

        private void OnEntitySpawned(BaseNetworkable networkable)
        {
            if (networkable == null || networkable.IsDestroyed) return;

            var combat = networkable as BaseCombatEntity;
            if (combat == null) return;

            if (!(networkable is ScientistNPC) && !(networkable is BaseAnimalNPC) && !(networkable is ScarecrowNPC))
                return;

            var id = networkable.net?.ID.Value ?? 0;
            if (id == 0 || seen.Contains(id)) return;
            if (seen.Count >= SeenCap) seen.Clear();
            seen.Add(id);

            var prefab = networkable.ShortPrefabName;
            float multiplier = config.DefaultMultiplier;
            if (!string.IsNullOrEmpty(prefab) && config.PrefabMultipliers.TryGetValue(prefab, out var specific))
                multiplier = specific;

            if (Mathf.Approximately(multiplier, 1f)) return;
            if (multiplier <= 0f) multiplier = 0.1f;

            var target = Mathf.Max(1f, combat.MaxHealth() * multiplier);
            if (combat.health >= target) return;

            combat.Heal(target - combat.health);
        }

        [ChatCommand("npchealth.set")]
        private void CmdSet(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                SendReply(player, Msg("NoPerm", player.UserIDString));
                return;
            }
            if (args == null || args.Length < 2)
            {
                SendReply(player, Msg("Usage Set", player.UserIDString));
                return;
            }

            if (!float.TryParse(args[1], out var multiplier))
            {
                SendReply(player, Msg("Bad Number", player.UserIDString, args[1]));
                return;
            }
            if (multiplier < 0.1f || multiplier > 50f)
            {
                SendReply(player, Msg("Out Of Range", player.UserIDString));
                return;
            }

            var prefab = args[0].ToLowerInvariant();
            config.PrefabMultipliers[prefab] = multiplier;
            SaveConfig();
            SendReply(player, Msg("Set", player.UserIDString, prefab, multiplier));
        }

        [ChatCommand("npchealth.default")]
        private void CmdDefault(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                SendReply(player, Msg("NoPerm", player.UserIDString));
                return;
            }
            if (args == null || args.Length < 1)
            {
                SendReply(player, Msg("Usage Default", player.UserIDString));
                return;
            }
            if (!float.TryParse(args[0], out var multiplier))
            {
                SendReply(player, Msg("Bad Number", player.UserIDString, args[0]));
                return;
            }
            if (multiplier < 0.1f || multiplier > 50f)
            {
                SendReply(player, Msg("Out Of Range", player.UserIDString));
                return;
            }

            config.DefaultMultiplier = multiplier;
            SaveConfig();
            SendReply(player, Msg("Default", player.UserIDString, multiplier));
        }

        [ChatCommand("npchealth.list")]
        private void CmdList(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                SendReply(player, Msg("NoPerm", player.UserIDString));
                return;
            }

            SendReply(player, Msg("List Header", player.UserIDString, config.DefaultMultiplier));
            foreach (var pair in config.PrefabMultipliers.OrderBy(p => p.Key))
                SendReply(player, Msg("List Row", player.UserIDString, pair.Key, pair.Value));
        }
    }
}

Hooks used: OnEntitySpawned

Config file

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

NpcHealthMultiplier.json
{
  "Default multiplier": 1,
  "Prefab multipliers": {
    "scientistnpc_heavy": 1.5,
    "scientistnpc_roam": 1.25,
    "bear": 0.75,
    "boar": 1
  }
}

Commands and permissions

Chat and console commands
CommandWhat it doesPermission
/npchealth.set <prefab> <multiplier>Adds or updates a per-prefab multiplier and writes the config.npchealthmultiplier.admin
/npchealth.default <multiplier>Sets the fallback multiplier used for NPCs without a specific entry.npchealthmultiplier.admin
/npchealth.listPrints the current multiplier table to chat.npchealthmultiplier.admin
Permissions
PermissionGrants
npchealthmultiplier.adminGrants access to the /npchealth.* chat commands.

How the code works

  1. Detect NPC spawns

    The plugin registers private void OnEntitySpawned(BaseNetworkable networkable). Every spawned networkable passes through it, so the first checks reject what cannot be scaled: null, IsDestroyed, and casts to BaseCombatEntity with as. Casting to BaseCombatEntity gives you MaxHealth(), health and Heal(float) without touching player or building classes.

  2. Filter to scientists and animals

    Only combat NPCs are scaled. The plugin checks networkable is ScientistNPC, networkable is BaseAnimalNPC and networkable is ScarecrowNPC. Players, cars, doors and building blocks are ignored even if they are BaseCombatEntity. This keeps the plugin from touching prefabs that share the spawn hook but should never change health, such as deployables that happen to be combat entities.

  3. Resolve the multiplier

    The prefab's ShortPrefabName is looked up in the Prefab Multipliers dictionary from PluginConfig. An exact match wins. If none exists, config.DefaultMultiplier is used. The method returns early when the multiplier is approximately 1.0, so vanilla NPCs are untouched and no network update is sent.

  4. Apply the scaled health

    BaseCombatEntity has no public health setter, so the plugin computes Mathf.Max(1f, combat.MaxHealth() * multiplier) and calls combat.Heal(target - combat.health) only when the NPC is below the target. A multiplier of 0.5 on a bear with a 400 base drops its spawned health to 200. Values below zero are clamped to 0.1f so a bad config cannot zero out an NPC.

  5. Avoid compounding on the same entity

    The plugin keeps a HashSet<ulong> called seen of networkable.net.ID.Value values it already processed, so a second spawn notification for the same entity is ignored. When the set reaches SeenCap (5000 entries) it is cleared, which bounds memory on long-running maps. Unload clears the set as well.

  6. Manage the config in game

    /npchealth.set <prefab> <multiplier> writes to Prefab Multipliers and saves with SaveConfig(). /npchealth.default changes Default Multiplier, and /npchealth.list prints the current table ordered by prefab key. All three are chat commands guarded by npchealthmultiplier.admin, registered in Init(). Changes apply to newly spawned NPCs; existing ones keep their current health until they die or are replaced.

Install it on your server

  1. Save NpcHealthMultiplier.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/NpcHealthMultiplier.json (Carbon: carbon/configs/NpcHealthMultiplier.json). After editing, reload it:oxide.reload NpcHealthMultiplier c.reload NpcHealthMultiplier # Carbon
  4. Grant the permission

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

Variations

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

  • Different multiplier by day phase

    Scale scientist health up at night so PvE servers get harder after dark.

    Generate this version
  • Health scaling by distance from spawn

    Nerf NPCs near spawn and buff them at the far side of the map.

    Generate this version
  • Kill reward tied to health

    Award scrap proportional to the health multiplier when a scaled NPC dies.

    Generate this version

FAQ

Does this change NPC health that already spawned before the plugin loaded?

No. Scaling happens in OnEntitySpawned, so only NPCs that spawn after the plugin loads (or after the config is saved) get the new health. Restart the server or trigger a wave for existing NPCs to pick up the new values.

Which prefab names can I use?

Use the ShortPrefabName value, not the asset path. Common examples are scientistnpc_heavy, scientistnpc_roam and bear. Spawn one NPC and check its short prefab name before you add a row, since exact matching means a typo silently falls back to the default multiplier.

How do I install this on Oxide or Carbon?

Save the file as NpcHealthMultiplier.cs inside oxide/plugins, then reload the plugin from the server console or the admin console. Carbon loads Oxide C# plugins from the same folder. The plugin creates oxide/config/NpcHealthMultiplier.json with defaults on first load.

Will a multiplier of 1.0 change anything?

No. The plugin skips the heal entirely when the resolved multiplier is approximately 1.0, so vanilla NPCs are untouched. This is why the default multiplier ships at 1.0 and you opt individual prefabs in.

Does the scaled health show to players during the fight?

Yes. Heal raises health to the scaled target and the change is sent over the network, so clients see the higher health bar while fighting the NPC. Loot tables are unaffected unless another plugin modifies them.

Customize it for your server

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

Prompt: Create an Oxide Rust plugin called NpcHealthMultiplier that scales scientist and animal max health on spawn using per-prefab multipliers from config plus a default fallback, with admin chat commands to set, list and change values.
Customize for my server

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

Last updated Oct 26, 2026.

Customize npc health multiplier

Customize