Skip to content
RustPluginGenerator

How to make a Rust explosive damage multiplier plugin (per-weapon raiding)

Scales explosion damage against building blocks, deployables and other structures using per-weapon multipliers keyed by the attacker's weapon prefab short name. It uses OnEntityTakeDamage to intercept explosion hits and rewrites the damage amount.

Vanilla Rust gives every explosive a fixed amount of damage against structures, so balancing a raid meta usually means recompiling the whole game or running several overlapping plugins. This plugin puts one multiplier table in a config file and applies it the moment an explosion lands, so C4, rockets, satchels and explosive ammo can each be tuned independently without touching vanilla values.

It listens to OnEntityTakeDamage, ignores anything that is not explosion damage, and looks up the attacker's weapon prefab short name (for example explosive.satchel or rocket_basic) in a config dictionary. When a match is found it multiplies the hit's total damage and caps the result if a maximum is configured. Damage against players and non-structure entities is left alone, and a global toggle lets you disable the whole system instantly during an event.

The plugin code

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

namespace Oxide.Plugins
{
    [Info("Explosive Damage Multiplier", "RustPluginGenerator", "1.0.0")]
    [Description("Scales explosion damage against structures and deployables with per-weapon multipliers.")]
    public class ExplosiveDamageMultiplier : RustPlugin
    {
        private const string PermAdmin = "explosivedamagemultiplier.admin";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Enabled")]
            public bool Enabled = true;

            [JsonProperty("Max Multiplier")]
            public float MaxMultiplier = 4f;

            [JsonProperty("Weapon Multipliers")]
            public Dictionary<string, float> WeaponMultipliers = new Dictionary<string, float>
            {
                ["explosive.satchel"] = 1.25f,
                ["explosive.timed"] = 1.0f,
                ["rocket_basic"] = 1.5f,
                ["rocket_hv"] = 1.25f,
                ["ammo.rocket.basic"] = 1.25f
            };
        }

        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>
            {
                ["Reloaded"] = "Explosive damage multipliers reloaded: {0} weapon entries, enabled: {1}",
                ["NoPermission"] = "You do not have permission to use this command."
            }, 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 void Unload()
        {
            config = null;
        }

        [ChatCommand("edm.reload")]
        private void CmdReload(BasePlayer player, string command, string[] args)
        {
            if (player != null && !permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                SendReply(player, Msg("NoPermission", player.UserIDString));
                return;
            }

            LoadConfig();
            string msg = Msg("Reloaded", player?.UserIDString, config.WeaponMultipliers.Count, config.Enabled);
            if (player != null) SendReply(player, msg);
            else PrintWarning(msg);
        }

        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo)
        {
            if (config == null || !config.Enabled || entity == null || hitInfo == null) return null;
            if (hitInfo.damageTypes == null) return null;
            if (entity is BasePlayer) return null;

            if (hitInfo.damageTypes.GetMajorityDamageType() != Rust.DamageType.Explosion) return null;
            if (!IsRaidable(entity)) return null;

            string prefab = GetWeaponShortName(hitInfo);
            if (string.IsNullOrEmpty(prefab)) return null;

            float multiplier;
            if (!config.WeaponMultipliers.TryGetValue(prefab.ToLower(), out multiplier)) return null;
            if (multiplier <= 0f) return null;

            float original = hitInfo.damageTypes.Total();
            if (original <= 0f) return null;

            float capped = Mathf.Min(multiplier, config.MaxMultiplier);
            hitInfo.damageTypes.ScaleAll(capped);
            return null;
        }

        private static bool IsRaidable(BaseCombatEntity entity)
        {
            if (entity is BuildingBlock) return true;
            if (entity is Door) return true;
            if (entity is StorageContainer) return true;
            if (entity is BaseOven) return true;
            if (entity is CodeLock) return true;
            if (entity is BuildingPrivlidge) return true;
            if (entity is AutoTurret) return true;
            if (entity is SamSite) return true;
            return false;
        }

        private static string GetWeaponShortName(HitInfo hitInfo)
        {
            try
            {
                if (hitInfo.WeaponPrefab != null && !string.IsNullOrEmpty(hitInfo.WeaponPrefab.ShortPrefabName))
                    return hitInfo.WeaponPrefab.ShortPrefabName;

                if (hitInfo.Weapon != null)
                {
                    BaseEntity weaponEntity = hitInfo.Weapon as BaseEntity;
                    if (weaponEntity != null && !string.IsNullOrEmpty(weaponEntity.ShortPrefabName))
                        return weaponEntity.ShortPrefabName;
                }
            }
            catch
            {
                // ignore resolve failures
            }
            return null;
        }
    }
}

Hooks used: OnEntityTakeDamage

Config file

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

ExplosiveDamageMultiplier.json
{
  "Enabled": true,
  "Max Multiplier": 4,
  "Weapon Multipliers": {
    "explosive.satchel": 1.25,
    "explosive.timed": 1,
    "rocket_basic": 1.5,
    "rocket_hv": 1.25,
    "ammo.rocket.basic": 1.25
  }
}

Commands and permissions

Chat and console commands
CommandWhat it doesPermission
/edm.reloadReloads the config from disk and reports the number of active weapon multipliers.explosivedamagemultiplier.admin
Permissions
PermissionGrants
explosivedamagemultiplier.adminGrants access to /edm.reload so staff can re-apply config changes without restarting the plugin.

How the code works

  1. Read the multiplier config

    The nested PluginConfig class holds a boolean Enabled switch, a MaxMultiplier cap, and a dictionary named WeaponMultipliers keyed by weapon prefab short name. Defaults cover the common raid tools: explosive.satchel, explosive.timed, rocket_basic, rocket_hv and ammo.rocket.basic. Because values are stored in oxide/config/ExplosiveDamageMultiplier.json, admins can add new keys as Facepunch ships new explosives without recompiling anything.

  2. Filter for explosion damage in OnEntityTakeDamage

    The hook receives a BaseCombatEntity and a HitInfo. The first checks are cheap: bail if the config is disabled, if hitInfo or hitInfo.damageTypes is null, or if the majority damage type in hitInfo.damageTypes.GetMajorityDamageType() is not Rust.DamageType.Explosion. This keeps bullet, melee and decay hits untouched even though the hook fires for every damage event on the server.

  3. Restrict to structures and deployables

    IsRaidable returns true for BuildingBlock, Door, StorageContainer, BaseOven, CodeLock, BuildingPrivlidge, AutoTurret and SamSite. Players, animals and NPCs return false, so a rocket that clips a raider through a wall still deals vanilla damage. If you want player damage scaled too, extend the method with a BasePlayer branch and adjust the multiplier lookup.

  4. Resolve the weapon prefab short name

    Thrown explosives do not always carry a HitInfo.Weapon attack entity, so the plugin prefers hitInfo.WeaponPrefab.ShortPrefabName, falling back to the short name of the HitInfo.Weapon cast to BaseEntity. The result is lowercased and compared against the dictionary, which the defaults seed in lowercase too. Matching on the short name means the multiplier follows the actual prefab that exploded, not the inventory item the raider used.

  5. Scale and cap the damage

    When a key matches, hitInfo.damageTypes.ScaleAll(multiplier) multiplies every damage entry on the hit. The applied factor is clamped to MaxMultiplier before scaling, so a config typo like 10 cannot one-shot a wall. Returning null from the hook lets Rust apply the modified damage normally. Nothing is written to chat, so the hook can fire thousands of times per raid without spamming the console.

  6. Reload without restarting

    The /edm.reload chat command is registered with [ChatCommand("edm.reload")] and gated by the explosivedamagemultiplier.admin permission. It calls the plugin's own LoadConfig and reports the number of dictionary entries back through the language file. Server owners can hand-edit oxide/config/ExplosiveDamageMultiplier.json, save, and run the command to apply changes during a wipe without touching player connections.

Install it on your server

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

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

Variations

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

  • Scale damage by structure grade

    Apply a different multiplier per building grade so wood and stone are softer than metal and HQM.

    Generate this version
  • Diminishing returns per raid

    Track a running total of explosive damage per building ID and reduce later hits to slow down raid zerging.

    Generate this version
  • Toggle multipliers by day or time

    Use a different multiplier table during scheduled raid hours.

    Generate this version

FAQ

Will this affect damage to players?

No. IsRaidable only accepts placed structures and deployables, so rockets and C4 that splash a player still deal the vanilla amount. If you want raiders to take scaled damage, add an explicit BasePlayer branch in IsRaidable โ€” most servers leave it out so raiding stays fair.

Why is my satchel multiplier not applied?

Thrown explosives expose their prefab through hitInfo.WeaponPrefab, which is often explosive.satchel. Confirm the key in oxide/config/ExplosiveDamageMultiplier.json matches the short name exactly and is lowercase. Use items.find in the server console to inspect a prefab's short name if you are unsure.

Does the multiplier stack with decay or fire damage?

No. The hook returns early unless the majority damage type on the hit is Rust.DamageType.Explosion. Decay ticks and fire damage run through separate damage types and never touch the scaling code, so you cannot accidentally amplify passive losses.

How do I install it on Oxide or Carbon?

Drop the compiled .cs file into oxide/plugins on Oxide or carbon/plugins on Carbon. Both frameworks load the same plugin file. Run oxide.reload ExplosiveDamageMultiplier (or c.reload) once to generate oxide/config/ExplosiveDamageMultiplier.json, then edit the multipliers and reload the plugin with /edm.reload.

Does the scale survive plugin reloads mid-raid?

Yes. The multiplier is applied to the live HitInfo.damageTypes before Rust resolves the hit, so it is not a persistent effect. Reloading the plugin between explosions simply changes which multiplier the next hit reads, and no existing building state is re-evaluated.

Customize it for your server

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

Prompt: Write an Oxide Rust plugin that scales explosion damage against structures and deployables using a per-weapon multiplier dictionary keyed by prefab short name in oxide/config, with a max multiplier cap, an enabled switch and an admin reload command.
Customize for my server

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

Last updated Oct 26, 2026.

Customize explosive damage multiplier

Customize