OnPlayerPveDamage
OnPlayerPveDamage is called from BuildingBlock.Hurt when ConVar.Server.pve is enabled and a player attacks a building block, before the server applies the PvE rule of hurting the attacker instead. Returning a non-null value stops that refund damage.
object OnPlayerPveDamage(BaseEntity Initiator, HitInfo info, BuildingBlock buildingBlock)Parameters
| Parameter | Type | Description |
|---|---|---|
Initiator | BaseEntity | The entity that caused the hit. At this injection site it is always a BasePlayer who attacked the building block; still null-check it and cast with `as` before use. |
info | HitInfo | The HitInfo for the incoming hit, containing damageTypes, Weapon, HitPositionWorld and IsProjectile(). Use it to inspect or scale the damage before the PvE rules apply. |
buildingBlock | BuildingBlock | The BuildingBlock that is being hurt. Use grade, buildingID and GetBuildingPrivilege() to decide whether to block the hit. |
Return value
Returning null lets the original code run, which hurts the attacking player for the hit's total damage and leaves the structure untouched. Any non-null return value stops the original path, so the attacker takes no PvE refund damage; the structure still does not lose health on this call.
How it works
The hook fires inside BuildingBlock.Hurt, but only when the server has PvE mode on (ConVar.Server.pve) and the hit's initiator is a player. In that situation vanilla would damage the attacking player with DamageType.Generic for the total of the hit instead of damaging the structure. OnPlayerPveDamage runs before that refund, so it lets you decide whether the structure should be protected, whether the attacker should be hurt, or both.
info carries the full hit data: use info.damageTypes.Total() for the damage amount, info.Weapon/info.IsProjectile() to see if it is a melee or ranged hit, and info.HitPositionWorld for the contact point. buildingBlock gives you grade, buildingID and GetBuildingPrivilege() so you can restrict behavior to authed players, specific bases or specific materials.
Because this fires only on player-versus-structure hits in PvE mode, it is cheap enough to run per hit, but keep the body light. It does not fire in normal PvP servers, and it does not cover damage from NPCs, explosions without a player initiator, or decay.
Example plugin: Protect teammate-owned structures from PvE refunds
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Pve Structure Guard", "RustPluginGenerator", "1.0.0")]
[Description("Lets players hit their own structures in PvE mode without taking refund damage.")]
public class PveStructureGuard : RustPlugin
{
private const string PermUse = "pvestructureguard.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Only skip refund for authed players")]
public bool OnlyAuthed { get; set; } = true;
[JsonProperty("Minimum grade to skip (0 = Twigs, 4 = TopTier)")]
public int MinimumGrade { get; set; } = 0;
}
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>
{
["Settings"] = "Refund skip: onlyAuthed={0}, minGrade={1}",
["NoPerm"] = "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(PermUse, this);
}
[ChatCommand("pveguard")]
private void CmdPveGuard(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermUse))
{
SendReply(player, Msg("NoPerm", player.UserIDString));
return;
}
SendReply(player, Msg("Settings", player.UserIDString, config.OnlyAuthed, config.MinimumGrade));
}
private object OnPlayerPveDamage(BaseEntity Initiator, HitInfo info, BuildingBlock buildingBlock)
{
if (Initiator == null || buildingBlock == null) return null;
var player = Initiator as BasePlayer;
if (player == null || player.IsNpc) return null;
if ((int)buildingBlock.grade < config.MinimumGrade) return null;
if (!config.OnlyAuthed) return true;
var privilege = buildingBlock.GetBuildingPrivilege();
if (privilege == null) return null;
return privilege.IsAuthed(player) ? (object)true : null;
}
}
}The plugin keeps a small config with a toggle and a minimum grade. On each PvE hit it confirms the initiator is a player and the building block is upgraded to at least the configured grade. It then checks the building privilege: if the attacker is authenticated on that base, the hook returns true, which skips the vanilla refund damage so players can freely hit their own walls. Otherwise it returns null and lets the server handle the hit normally. A chat command lets admins print the current settings without reloading the plugin.
Common use cases
Allow owners to hit their own walls
Return non-null when the attacker is authed on the building privilege so base owners can test or repair-hit their structures in PvE mode without hurting themselves.
Whitelist squishy early bases
Skip the refund for Twigs and Wood blocks so new players do not die while punching their own foundation down to rebuild.
Raise a counter for staff review
Track how many PvE hits hit each building ID and report the totals to admins, so you can spot players repeatedly smacking bases in PvE.
Pitfalls
Only active in PvE mode
The hook never fires unless
ConVar.Server.pveis true. Plugins that rely on it will silently do nothing on PvP servers or when the flag is toggled off.Returning non-null blocks the refund, not the hit
A non-null return stops the original code path, which is the attacker taking damage. It does not add extra damage to the structure; if you need that, call
buildingBlock.Hurtlogic yourself carefully, outside the hook.Initiator is typed BaseEntity
The parameter is a BaseEntity, not BasePlayer. Cast with
as BasePlayerand null-check; do not assume it is always a player just because the injection site checks that.
Build a plugin with OnPlayerPveDamage
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 OnPlayerPveDamage
Generate