Skip to content
RustPluginGenerator

OnDecayHeal

OnDecayHeal is called when a decay entity is about to heal itself because it has been left untouched; returning a non-null value skips that heal for this tick.

Signature
object OnDecayHeal(DecayEntity decayEntity)

Parameters

Hook parameters
ParameterTypeDescription
decayEntityDecayEntityThe DecayEntity (building block, door, deployable, etc.) that the game is about to heal during its upkeep tick. Cast it to BuildingBlock or another specific type when you need those members.

Return value

Returning null lets the game run its normal heal for this tick. Returning any non-null value (a bool, a string, anything) prevents the heal call for this tick; the entity simply stays at its current health and the next upkeep tick is evaluated normally.

How it works

The hook fires inside DecayEntity.OnDecay, the upkeep tick each decaying entity runs on a timer (roughly once per second per entity). The game only reaches the call when all of these are true: the entity's healthFraction is below 1, its heal scale is above 0, and SecondsSinceAttacked is greater than 600. When those conditions hold, Oxide calls OnDecayHeal with the entity before applying Heal(MaxHealth() * decayDeltaTime / GetEntityDecayDuration() * GetEntityHealScale()).

This is the recovery side of decay: an entity that stopped taking damage for ten minutes slowly regains health until it hits its maximum. Use the parameter to inspect Health(), MaxHealth(), OwnerID, net.ID.Value, or to cast to BuildingBlock for grade and ownership checks. The hook already filters to entities that qualify for healing, so you only need extra conditions when you want to change the outcome.

There is no earlier hook that fires for this branch, so this is the only place to observe or stop natural repair. Returning nothing (null) lets the shipped heal formula run unchanged.

Example plugin: Disable natural repair, or lock it to privileged owners

DecayHealControl.cs
using System;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("DecayHealControl", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks or restricts natural decay repair on structures.")]
    public class DecayHealControl : RustPlugin
    {
        private const string PermAdmin = "decayhealcontrol.admin";

        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Block all healing")]
            public bool BlockAllHealing { get; set; } = false;

            [JsonProperty("Require owner authorization")]
            public bool RequireOwnerAuthorization { 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);

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

        private object OnDecayHeal(DecayEntity decayEntity)
        {
            if (decayEntity == null) return null;
            if (config.BlockAllHealing) return true;
            if (!config.RequireOwnerAuthorization) return null;

            var block = decayEntity as BuildingBlock;
            if (block == null) return null;

            var privilege = block.GetBuildingPrivilege();
            if (privilege == null) return true;

            if (block.OwnerID == 0) return null;

            var owner = BasePlayer.FindByID(block.OwnerID);
            if (owner == null) return true;

            return privilege.IsAuthed(owner) ? (object)null : true;
        }

        [ChatCommand("decayheal")]
        private void CmdDecayHeal(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermAdmin))
            {
                player.ChatMessage("You do not have permission to use this command.");
                return;
            }

            config.BlockAllHealing = !config.BlockAllHealing;
            SaveConfig();
            player.ChatMessage($"Decay healing is now {(config.BlockAllHealing ? "blocked" : "allowed")}.");
        }
    }
}

The plugin reads a config with two switches: BlockAllHealing stops every decay heal, while RequireOwnerAuthorization only allows healing on building blocks whose cupboard authorizes the owner. The hook returns true to cancel the heal and null otherwise, matching the hook's contract exactly. A small chat command, guarded by the decayhealcontrol.admin permission, toggles the global switch and reports the current state, so admins can change behavior without editing the config file on disk. Casting to BuildingBlock inside the check is safe because decayEntity arrives non-null from the game call.

Common use cases

  • Keep abandoned bases damaged

    Return a non-null value for structures that have no authorized owner online, so raided or decayed bases do not slowly repair themselves while the server is quiet.

  • Tie repair to cupboard access

    Only allow the heal when the owning player is authorized on the building privilege, which turns upkeep into a continuous cost for active groups.

  • Log repair for entity tracking

    Track when specific entities start healing to spot structures that never get attacked and then adjust decay settings or raid balance.

Pitfalls

  • Fires for many entities

    Every decaying entity runs its upkeep tick, so avoid allocations, string formatting, and chat output in this hook. Cache lookups and check a cheap flag first.

  • The six-hundred-second gate

    The hook only runs when the entity has not been attacked for 600 seconds. If you rely on it for monitoring, remember absence of calls can simply mean the structure is still fresh.

  • Any non-null return cancels

    Returning false still cancels the heal, because the game checks for null. Always return null when you want default behavior, not a boolean false.

Build a plugin with OnDecayHeal

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Keep abandoned bases damaged using the OnDecayHeal hook, with a config file and a permission
Generate this plugin

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

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnDecayHeal

Generate