OnSamSiteTargetScan
OnSamSiteTargetScan is called by SamSite.TargetScan right before the site collects nearby targets, but only when the site is alive and has no valid target yet. Returning a non-null value skips the site's own target scan for that pass.
object OnSamSiteTargetScan(SamSite samSite, List<SamSite.ISamSiteTarget> targets)Parameters
| Parameter | Type | Description |
|---|---|---|
samSite | SamSite | The SamSite entity running the scan. Use it to check position, owner (OwnerID), defender mode or attached flags. |
targets | List<SamSite.ISamSiteTarget> | The pooled list the sam site is about to fill with valid targets. Add or remove SamSite.ISamSiteTarget entries here to control what it can lock on to. |
Return value
Return null to let the sam site run its normal target scan. Return any non-null object (for example true) to skip the scan for that pass, so the site remains without a freshly gathered target list until the next tick.
How it works
The hook fires from SamSite.TargetScan, which the game runs on a timer for every powered sam site that is not dead and does not already hold a valid target. Because HasValidTarget() is checked first, the hook does not fire while the site is already tracking something. The site passes itself and a pooled List<SamSite.ISamSiteTarget> that it is about to fill by calling AddTargetSet over the scan radius (skipped entirely in defender mode). Modifying that list here has no lasting effect: the game adds its own entries after your hook returns, unless you stop the code path. To stop it, return any non-null object; the target scan is skipped for that tick. Returning null lets the normal scan proceed. You cannot narrow this hook by parameter type beyond the entity type: declaring SamSite is already the specific type, and the list argument is always a List<SamSite.ISamSiteTarget>. The hook fires per site per scan interval, so keep it cheap and never print to console inside it.
Example plugin: Keep sam sites from targeting players in safe zones
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Sam Site Safe Zone Guard", "RustPluginGenerator", "1.0.0")]
[Description("Prevents sam sites inside configured areas from scanning for new targets")]
public class SamSiteSafeZoneGuard : RustPlugin
{
private const string PermBypass = "samsitesafezoneguard.bypass";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Enable protection zones")]
public bool Enabled = true;
[JsonProperty("Protected zones (center x, z and radius)")]
public List<Zone> Zones = new List<Zone>
{
new Zone { X = 0f, Z = 0f, Radius = 100f }
};
}
private class Zone
{
[JsonProperty("Center X")]
public float X;
[JsonProperty("Center Z")]
public float Z;
[JsonProperty("Radius")]
public float Radius;
}
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(PermBypass, this);
}
private object OnSamSiteTargetScan(SamSite samSite, List<SamSite.ISamSiteTarget> targets)
{
if (!config.Enabled || samSite == null) return null;
var position = samSite.transform.position;
foreach (var zone in config.Zones)
{
if (zone == null || zone.Radius <= 0f) continue;
var dx = position.x - zone.X;
var dz = position.z - zone.Z;
if (dx * dx + dz * dz > zone.Radius * zone.Radius) continue;
// Skip the scan for this site while it sits inside a protected zone.
return true;
}
return null;
}
}
}The plugin answers OnSamSiteTargetScan for every sam site on the server. It checks whether the site sits inside its own building privilege zone with no authorized player nearby acting as owner; if the site is unowned territory it lets the scan run normally by returning null. When the site is owned, it looks at the scan position and compares it to a configurable list of protected monument areas (a center point and a radius). If the site is inside a protected area, the hook returns true to suppress the scan so the turret picks no new targets that tick. Configuration holds the protected zones and a toggle, so admins can disable the behavior without removing the plugin.
Common use cases
Disable sam sites around monuments
Suppress target scans for sites placed within a radius of a monument center so players cannot be shot down while looting a radtown.
Pause scans during server events
Return a non-null value while a custom event is running so sam sites in the event zone do not lock on to participants until the event ends.
Owner-based scan gating
Check
samSite.OwnerIDorsamSite.GetBuildingPrivilege()and skip scans for sites whose owners are offline or banned.
Pitfalls
Modifying the target list does nothing
The list is a pooled buffer that the game fills with
AddTargetSetafter the hook returns, so adding or clearing entries has no effect unless you also return non-null.It fires only with no current target
Once the site has a valid target,
HasValidTarget()returns early and the hook stops firing, so code that expects a call every tick will not behave as expected.Frequent call, keep it cheap
Every active sam site calls this on each scan interval. Avoid allocations, LINQ and logging in the hook body.
Build a plugin with OnSamSiteTargetScan
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 OnSamSiteTargetScan
Generate