CanHelicopterTarget
CanHelicopterTarget is called from PatrolHelicopterAI.PlayerVisible when the patrol helicopter checks whether it can see a specific player. Returning a bool overrides the game's line-of-sight result for that check.
object CanHelicopterTarget(PatrolHelicopterAI patrolHelicopterAI, BasePlayer ply)Parameters
| Parameter | Type | Description |
|---|---|---|
patrolHelicopterAI | PatrolHelicopterAI | The PatrolHelicopterAI instance that is evaluating whether it can see and target a player. Use it to read the helicopter's position, health or identity if you need per-helicopter rules. |
ply | BasePlayer | The BasePlayer being tested for visibility. This is the player the helicopter is considering as a target, not necessarily the attacker. |
Return value
Return a bool to override the visibility result: true makes the AI treat the player as visible and eligible to target, false makes it treat the player as not visible. Return null, or anything that is not a bool, to let the game's normal line-of-sight check run unchanged.
How it works
The hook fires inside PatrolHelicopterAI.PlayerVisible(BasePlayer ply), which the helicopter AI calls while scanning for and confirming targets. Every visibility test for a player goes through this method, so the hook can run frequently while a helicopter is active and players are near it. Use ply to inspect the candidate target (team, position, mounted state, permissions) and patrolHelicopterAI to key rules to a specific helicopter.
Because the original method returns bool, Oxide accepts a returned bool as the visibility result: true tells the AI the player is visible (so it may target and shoot), false tells it the player is not visible. Any other return value or null lets the normal line-of-sight check run. Declaring ply as a more specific type such as BasePlayer is already the given signature; there is no narrower player subtype to exploit here, but you can still filter inside the method (for example skip NPCs, sleeping players or players inside safe zones).
Practical uses are safe zones, event arenas, VIP immunity, and temporary truces. Keep the method cheap: it may be called repeatedly per helicopter and per nearby player, so avoid allocations, raycasts or lookups that could run every tick.
Example plugin: Keep players safe inside safe zones from the patrol helicopter
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("HelicopterSafeZone", "RustPluginGenerator", "1.0.0")]
[Description("Prevents the patrol helicopter from targeting players inside configured safe zones")]
public class HelicopterSafeZone : RustPlugin
{
private const string PermSafe = "helicoptersafezone.safe";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Use permission")]
public bool UsePermission = true;
[JsonProperty("Safe zone centres")]
public List<Zone> Zones = new List<Zone>
{
new Zone { X = 0f, Y = 0f, Z = 0f, Radius = 50f }
};
}
private class Zone
{
[JsonProperty("X")]
public float X;
[JsonProperty("Y")]
public float Y;
[JsonProperty("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);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["ZoneReloaded"] = "Helicopter safe zones reloaded. Zones: {0}"
}, 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(PermSafe, this);
}
[ChatCommand("hszreload")]
private void CmdReload(BasePlayer player, string command, string[] args)
{
if (player != null && !player.IsAdmin) return;
LoadConfig();
string text = Msg("ZoneReloaded", player?.UserIDString, config.Zones.Count);
if (player != null) SendReply(player, text);
else Puts(text);
}
private object CanHelicopterTarget(PatrolHelicopterAI patrolHelicopterAI, BasePlayer ply)
{
if (patrolHelicopterAI == null || ply == null || !ply.IsConnected) return null;
if (ply.IsDead() || ply.IsSleeping()) return null;
if (config.UsePermission && !permission.UserHasPermission(ply.UserIDString, PermSafe)) return null;
Vector3 position = ply.transform.position;
for (int i = 0; i < config.Zones.Count; i++)
{
Zone zone = config.Zones[i];
Vector3 centre = new Vector3(zone.X, zone.Y, zone.Z);
if (Vector3.Distance(position, centre) <= zone.Radius) return false;
}
return null;
}
}
}The plugin hooks CanHelicopterTarget and, before any game line-of-sight check runs, decides whether the candidate is protected. It checks that the player is valid and connected, then confirms the player has the configured permission and is standing inside a defined safe-zone sphere. Protected players return false, so the helicopter treats them as invisible and will not target them. Everyone else returns null, which keeps the default visibility logic. Safe-zone centres, radius and the permission toggle live in the config, and a chat command lets admins reload settings at runtime without restarting the server.
Common use cases
Safe-zone protection
Make players standing in designated safe areas invisible to the patrol helicopter so it never targets them while they trade or bank loot.
Event arenas
During a custom event, deny helicopter targeting for everyone outside the arena bounds so the helicopter only engages participants.
VIP immunity
Grant a permission that makes a player temporarily untargetable by the helicopter, for example as a donor perk or as part of a revive timer.
Pitfalls
Runs often
The hook is invoked each time the helicopter evaluates a player, which can be many times per second while players are nearby. Keep the logic allocation-free and avoid heavy lookups or printing to console.
Returning a bool always overrides
If you return
trueorfalseunconditionally you replace the game's real line-of-sight check, which can make the helicopter target through walls or ignore players it should see. Returnnullwhen your rule does not apply.Final targets are chosen elsewhere
Returning
falseonly makes the player invisible to this check. The helicopter can still be pushed toward targets by other AI paths and hooks such asOnHelicopterTarget, so test the full engagement loop on a live server.
Build a plugin with CanHelicopterTarget
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 CanHelicopterTarget
Generate