OnDecayDamage
OnDecayDamage is called when a DecayEntity is about to apply a decay damage tick inside DecayEntity.OnDecay.Instance methods that return null let the tick continue normally.
object OnDecayDamage(DecayEntity decayEntity)Parameters
| Parameter | Type | Description |
|---|---|---|
decayEntity | DecayEntity | The DecayEntity that is about to take a decay tick (BuildingBlock, base deployables such as doors and boxes, and other entities built on decay timers). Null-check it before reading owner, grade or transform data. |
Return value
Return null (or nothing useful) to let the decay damage apply as normal. Return any non-null value to skip the health loss for that tick; the method's original return type is void, so the value itself is not used beyond being non-null.
How it works
The hook fires inside DecayEntity.OnDecay, after the game has worked out the entity's decay point, its protection value and the remaining decay amount for this tick. It fires for any entity that inherits from DecayEntity - building blocks, doors, boxes, and other deployables that carry a decay timer - and only when the entity is actually ticking decay, not on every frame or every hit. The single argument is the entity itself, so you can inspect its owner, grade, health, parent structure or position and decide whether the tick should happen. Return a non-null value to skip the health loss for that tick; returning null keeps normal decay. Declaring the parameter as DecayEntity matches everything, but you can narrow it to BuildingBlock or another subtype to only be called for those entities - values of other types make Oxide skip your method for that call. The hook fires on the server only and can run frequently on large bases, so keep the body cheap and avoid logging.
Example plugin: Pause decay on buildings inside a raid-protection flag
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Raid Protection Decay Pause", "RustPluginGenerator", "1.0.0")]
[Description("Pauses decay damage on bases whose owner has a bypass permission while protection is active")]
public class RaidProtectionDecayPause : RustPlugin
{
private const string PermBypass = "raidprotectiondecaypause.bypass";
private const string PermToggle = "raidprotectiondecaypause.toggle";
private PluginConfig config;
private bool protectionActive = true;
private class PluginConfig
{
[JsonProperty("Protection active on load")]
public bool ActiveOnLoad { get; set; } = true;
[JsonProperty("Announce protection state changes")]
public bool Announce { get; set; } = true;
[JsonProperty("Protection tag")]
public string Tag { get; set; } = "[DecayGuard]";
}
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>
{
["Active"] = "{0} Decay protection is now ACTIVE. Protected bases will not decay.",
["Inactive"] = "{0} Decay protection is now INACTIVE. Normal decay resumed.",
["NoPerm"] = "You do not have permission to toggle decay protection."
}, 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(PermBypass, this);
permission.RegisterPermission(PermToggle, this);
protectionActive = config.ActiveOnLoad;
}
[ConsoleCommand("decayprotection.toggle")]
private void CmdToggle(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player != null && !permission.UserHasPermission(player.UserIDString, PermToggle))
{
arg.ReplyWith(Msg("NoPerm", player.UserIDString));
return;
}
protectionActive = !protectionActive;
var key = protectionActive ? "Active" : "Inactive";
var message = Msg(key, null, config.Tag);
if (config.Announce)
{
Server.Broadcast(message);
}
else if (arg != null)
{
arg.ReplyWith(message);
}
}
private object OnDecayDamage(DecayEntity decayEntity)
{
if (!protectionActive || decayEntity == null) return null;
var privilege = decayEntity.GetBuildingPrivilege();
if (privilege == null) return null;
var ownerId = privilege.OwnerID;
if (ownerId == 0UL) return null;
if (!permission.UserHasPermission(ownerId.ToString(), PermBypass)) return null;
// Non-null return cancels this decay tick
return true;
}
private void Unload()
{
protectionActive = false;
}
}
}The plugin adds an admin console command that toggles a bypass flag and a raidprotection.decaybypass permission. OnDecayDamage looks at the decay entity, finds its owning privilege cupboard via GetBuildingPrivilege(), and checks whether the owner holds the bypass permission. If they do, the hook returns true, which is non-null and therefore cancels that decay tick, so protected bases keep full health until the permission is removed. All work is a single permission lookup per tick and config values are loaded from oxide/config, keeping the hot hook body inexpensive on busy servers.
Common use cases
Pause decay during admin events
Return non-null while a scheduled event or wipe-anniversary period is active so bases do not lose health, then clear the flag to resume normal decay.
Scale decay by building grade
Skip decay for high-grade structures on a server where only twig and wood should erode, letting admins keep top-tier bases intact between wipes.
Protect recently placed structures
Track placement timestamps and cancel decay ticks for a grace period so players logging in after a break do not lose new sections to missed upkeep.
Pitfalls
Not every entity you expect inherits DecayEntity
Only classes derived from DecayEntity reach this hook. If you need to affect non-decaying entities, use
OnEntityTakeDamagewithDamageType.Decayinstead.Returning false still cancels the tick
The check is
== null, so any non-null value - includingfalseor0- prevents the decay damage. Return null explicitly when you want normal decay.High call volume on large servers
Every decay-ticking entity calls this hook, which can mean thousands of calls per second on populated maps. Keep the body to cheap checks and avoid string building, LINQ or logging inside it.
Build a plugin with OnDecayDamage
Describe what should happen and get a compiled plugin that uses this hook.
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 OnDecayDamage
Generate