OnTreeMarkerHit
OnTreeMarkerHit is called when a player hits the marker on a TreeEntity, the small strike point that lets them harvest the tree faster. It fires from TreeEntity.DidHitMarker.
object OnTreeMarkerHit(TreeEntity treeEntity, HitInfo info)Parameters
| Parameter | Type | Description |
|---|---|---|
treeEntity | TreeEntity | The tree that was struck. Use it for its position, net.ID or to check its prefab before allowing the marker hit. |
info | HitInfo | The HitInfo of the blow, including InitiatorPlayer, Weapon, damageTypes and HitPositionWorld. Null-check it before reading nested members. |
Return value
Return null (or any non-boolean value) to let the game decide the marker hit normally. Return a bool and it becomes the method's result: true tells the caller the marker hit succeeded, false treats it as though the strike did not register on the marker.
How it works
This hook runs inside TreeEntity.DidHitMarker, which the game calls when a hit lands on a tree's marker point rather than the trunk itself. A single swing only invokes it when the attack actually resolves against that marker, so it does not fire for ordinary trunk hits, for harvests with tools that ignore markers, or for environmental damage such as decay.
treeEntity gives you the tree (position, prefab, network id), while info carries the InitiatorPlayer, the Weapon attack entity and the damage list. Use info.InitiatorPlayer to identify the harvester; it can be null for NPC or server-driven hits. Because a non-null boolean return replaces the method's own result, you can let the marker hit be treated as normal or vetoed.
Declaring the first parameter as TreeEntity is the only meaningful narrowing here; the game only calls this from tree code, so BaseEntity would not match any other caller in practice. The hook fires on every marker strike, so keep the body cheap and avoid logging.
Example plugin: Reward precise tree marker hits with bonus wood
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Tree Marker Bonus", "RustPluginGenerator", "1.0.0")]
[Description("Gives bonus wood when players hit a tree's marker point.")]
public class TreeMarkerBonus : RustPlugin
{
private const string PermUse = "treemarkerbonus.use";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastBonus = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Bonus wood amount")]
public int BonusAmount = 15;
[JsonProperty("Cooldown seconds per player")]
public float CooldownSeconds = 3f;
}
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>
{
["Bonus"] = "Marker hit! +{0} wood"
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
{
return string.Format(lang.GetMessage(key, this, userId), args);
}
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private object OnTreeMarkerHit(TreeEntity treeEntity, HitInfo info)
{
if (treeEntity == null || info == null) return null;
if (config.BonusAmount <= 0) return null;
BasePlayer player = info.InitiatorPlayer;
if (player == null || player.IsNpc || !player.IsConnected) return null;
if (!permission.UserHasPermission(player.UserIDString, PermUse)) return null;
ulong id = player.userID.Get();
float now = Time.realtimeSinceStartup;
float last;
if (lastBonus.TryGetValue(id, out last) && now - last < config.CooldownSeconds) return null;
lastBonus[id] = now;
Item wood = ItemManager.CreateByName("wood", config.BonusAmount);
if (wood == null) return null;
player.GiveItem(wood);
player.ChatMessage(Msg("Bonus", player.UserIDString, config.BonusAmount));
return null;
}
}
}The plugin listens for marker hits and grants extra wood to the harvester when the config enables it. OnTreeMarkerHit pulls the player out of info.InitiatorPlayer, checks the permission, and creates wood with ItemManager.CreateByName, handing it to the player so it drops if their inventory is full. A short lang message tells them about the bonus. A per-player cooldown timestamp prevents the bonus from stacking on rapid successive marker hits, and the config lets admins tune the amount and cooldown. All values are registered in LoadDefaultConfig and the permission is set up in Init, keeping the hook body lightweight.
Common use cases
Bonus harvest rewards
Grant extra resources or a small payout for skilled marker hits, encouraging players to aim for the strike point.
Anti-bot marker detection
Track how often a single player lands marker hits in a short window to flag scripted harvesting for admin review.
Veto specific trees
Return false when the tree prefab is on a blacklist so protected trees ignore marker hits and only take normal trunk damage.
Pitfalls
Returning true does not grant resources
A true return only tells the caller the marker hit succeeded; it does not change yield itself. Give items explicitly if you want a reward.
info.InitiatorPlayer can be null
Explosions or NPC-driven hits may not carry a player. Always null-check before reading permission or inventory members.
Hot path
The hook fires on every marker strike, so avoid Puts, PrintWarning or broad entity scans inside it.
Build a plugin with OnTreeMarkerHit
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 OnTreeMarkerHit
Generate