Guards Following Home Recently Killed Players

It seems as if the guards will maintain aggro of any player they have recently killed, and as such, will end up "following" that player to any nearby base that they respawn at. Is there a way to break aggro when a player dies?

Worked out a fix by removing their chase logic (which I think is inherently faulty and doesn't make sense anyway considering they're supposed to be guarding wreckage), and also added a bit to the code which makes the guards choose a random position around the wreckage, instead of them all congregating inside of the wreckage.

using System.Collections.Generic;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using UnityEngine.AI;

namespace Oxide.Plugins
{
    [Info("Bradley Guards", "Bazz3l", "1.4.5")]
    [Description("Call for armed reinforcements when bradley is destroyed at launch site.")]
    public class BradleyGuards : RustPlugin
    {
        #region Fields
        
        private const string GUARD_PREFAB = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_heavy.prefab";
        private const string CH47_PREFAB = "assets/prefabs/npc/ch47/ch47scientists.entity.prefab";
        private const string PROTECTION_NAME = "BradleyGuardsProtection";
        private const string LANDING_NAME = "BradleyGuardsLandingZone";

        private readonly List<ScientistNPC> _guards = new List<ScientistNPC>();
        private static ProtectionProperties _ch47ProtectionProperties;
        private CH47HelicopterAIController _chinook;
        private CH47LandingZone _landingZone;
        private Quaternion _landingRotation;
        private Vector3 _monumentPosition;
        private Vector3 _landingPosition;
        private Vector3 _chinookPosition;
        private Vector3 _bradleyPosition;
        private Vector3 _bradleyPositionActual;
        private bool _cleaningUp;
        
        private PluginConfig _config;

        #endregion

        #region Config

        protected override void LoadDefaultConfig() => _config = PluginConfig.DefaultConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                _config = Config.ReadObject<PluginConfig>();
                if (_config == null) throw new JsonException();
            }
            catch
            {
                PrintWarning("Default config loaded.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config, true);

        private class PluginConfig
        {
            [JsonProperty(PropertyName = "ChatIcon (chat icon SteamID64)")]
            public ulong ChatIcon;

            [JsonProperty(PropertyName = "APCHealth (set starting health)")]
            public float APCHealth;

            [JsonProperty(PropertyName = "APCCrates (amount of crates to spawn)")]
            public int APCCrates;

            [JsonProperty(PropertyName = "NPCAmount (amount of guards to spawn max 11)")]
            public int NPCAmount;

            [JsonProperty(PropertyName = "InstantCrates (unlock crates when guards are eliminated)")]
            public bool InstantCrates;

            [JsonProperty(PropertyName = "DisableChinookDamage (should chinook be able to take damage)")]
            public bool DisableChinookDamage;

            [JsonProperty(PropertyName = "GuardSettings (create different types of guards must contain atleast 1)")]
            public List<GuardSetting> GuardSettings;
            
            [JsonProperty(PropertyName = "Chinook (spawn position)")]
            public Vector3 ChinookSpawnPosition = new Vector3(-193f, 150.0f, 13.2f);
            
            [JsonProperty(PropertyName = "Landing (spawn position)")]
            public Vector3 LandingSpawnPosition = new Vector3(162.3f, 3.0f, 7.4f);
            
            [JsonProperty(PropertyName = "Landing (spawn rotation)")]
            public Vector3 LandingSpawnRotation = new Vector3(0.0f, -109.8f, 0.0f);

            [JsonProperty("EffectiveWeaponRange (range weapons will be effective)")]
            public Dictionary<string, float> EffectiveWeaponRange = new Dictionary<string, float>
            {
                { "snowballgun", 60f },
                { "rifle.ak", 150f },
                { "rifle.bolt", 150f },
                { "bow.hunting", 30f },
                { "bow.compound", 30f },
                { "crossbow", 30f },
                { "shotgun.double", 10f },
                { "pistol.eoka", 10f },
                { "multiplegrenadelauncher", 50f },
                { "rifle.l96", 150f },
                { "rifle.lr300", 150f },
                { "lmg.m249", 150f },
                { "rifle.m39", 150f },
                { "pistol.m92", 15f },
                { "smg.mp5", 80f },
                { "pistol.nailgun", 10f },
                { "shotgun.waterpipe", 10f },
                { "pistol.python", 60f },
                { "pistol.revolver", 50f },
                { "rocket.launcher", 60f },
                { "shotgun.pump", 10f },
                { "pistol.semiauto", 30f },
                { "rifle.semiauto", 100f },
                { "smg.2", 80f },
                { "shotgun.spas12", 30f },
                { "speargun", 10f },
                { "smg.thompson", 30f }
            };

            public static PluginConfig DefaultConfig()
            {
                return new PluginConfig
                {
                    ChatIcon = 0,
                    APCHealth = 1000f,
                    APCCrates = 4,
                    NPCAmount = 8,
                    InstantCrates = true,
                    ChinookSpawnPosition = new Vector3(-193f, 150.0f, 13.2f),
                    LandingSpawnPosition = new Vector3(162.3f, 3.0f, 7.4f),
                    LandingSpawnRotation = new Vector3(0.0f, -109.8f, 0.0f),
                    GuardSettings = new List<GuardSetting> {
                        new GuardSetting
                        {
                            Name = "Heavy Gunner",
                            Health = 300f,
                            MaxRoamRadius = 80f,
                            MaxAggressionRange = 200f,
                        },
                        new GuardSetting
                        {
                            Name = "Light Gunner",
                            Health = 200f,
                            MaxRoamRadius = 80f,
                            MaxAggressionRange = 150f,
                        }
                    }
                };
            }

            public string ToJson() =>
                JsonConvert.SerializeObject(this);

            public Dictionary<string, object> ToDictionary() =>
                JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }
        
        private class GuardSetting
        {
            [JsonProperty(PropertyName = "Name (custom display name)")]
            public string Name = "Bradley Guard";

            [JsonProperty(PropertyName = "Health (set starting health)")]
            public float Health = 100f;

            [JsonProperty(PropertyName = "DamageScale (higher the value more damage)")]
            public float DamageScale = 0.5f;
            
            [JsonProperty(PropertyName = "AimConeScale (lower the value more accurate)")]
            public float AimConeScale = 0.2f;

            [JsonProperty(PropertyName = "MaxRoamRadius (max radius guards will roam)")]
            public float MaxRoamRadius = 30f;

            [JsonProperty(PropertyName = "MaxAggressionRange (distance guards will become aggressive)")]
            public float MaxAggressionRange = 200f;

            [JsonProperty(PropertyName = "KitName (custom kit name)")]
            public string KitName = "";

            [JsonProperty(PropertyName = "KitEnabled (enable custom kit)")]
            public bool KitEnabled = false;
        }

        #endregion

        #region Lang

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string> 
            {
                    {"EventStart", "<i><color=#53a66f>The Scientists are angered by the demise of Bradley, and have sent reinforcements to quell the attackers.</color></i>"},
                {"EventEnded", "<i><color=#53a66f>The Bradley reinforcements have been eliminated.</color></i>"},
            }, this);
        }
        
        private string Lang(string key, string id = null, params object[] args) 
            => string.Format(lang.GetMessage(key, this, id), args);

        private void BroadcastMessage(string key) 
            => Server.Broadcast(Lang(key), _config.ChatIcon);

        #endregion

        #region Oxide

        private void OnServerInitialized()
        {
            HooksUnsubscribe();

            if (!FindLandingPoint()) 
                return;
            
            HooksSubscribe();
            CreateProtection();
        }

        private void Unload()
        {
            PerformCleanUp();
            DestroyProtection();
        }

        private void OnEntitySpawned(BradleyAPC bradley) => OnAPCSpawned(bradley);

        private void OnEntityDeath(BradleyAPC bradley, HitInfo info) => OnAPCDeath(bradley);

        private void OnEntityDeath(ScientistNPC npc, HitInfo info) => OnNPCDeath(npc);

        private void OnEntityKill(ScientistNPC npc) => OnNPCDeath(npc);
        
        private void OnEntityDismounted(BaseMountable mountable, ScientistNPC npc)
        {
            if (npc.HasBrain && _guards.Contains(npc))
            {
                npc.Brain.Navigator.PlaceOnNavMesh();
                npc.Brain.Navigator.SetDestination(RandomCircle(_bradleyPosition, 5f));                
            }
        }

        private void OnFireBallDamage(FireBall fireball, ScientistNPC npc, HitInfo info)
        {
            if (info?.Initiator is FireBall && _guards.Contains(npc))
            {
                info.DoHitEffects = false;
                info.damageTypes.ScaleAll(0f);                
            }
        }

        #endregion

        #region Subscribe Hook

        private void HooksSubscribe()
        {
            Subscribe(nameof(OnEntitySpawned));
            Subscribe(nameof(OnEntityDeath));
            Subscribe(nameof(OnEntityKill));
            Subscribe(nameof(OnEntityDismounted));
        }
        
        private void HooksUnsubscribe()
        {
            Unsubscribe(nameof(OnEntitySpawned));
            Unsubscribe(nameof(OnEntityDeath));
            Unsubscribe(nameof(OnEntityKill));
            Unsubscribe(nameof(OnEntityDismounted));
        }

        #endregion

        #region Event

        private void SpawnEvent()
        {
            _cleaningUp = false;
            
            _chinook = GameManager.server.CreateEntity(CH47_PREFAB, _chinookPosition, Quaternion.identity) as CH47HelicopterAIController;
            _chinook.Spawn();
            _chinook.CancelInvoke(_chinook.SpawnScientists);
            _chinook.SetLandingTarget(_landingPosition);
            _chinook.SetMinHoverHeight(0f);
            _chinook.gameObject.AddComponent<CH47LandedController>();

            if (_config.DisableChinookDamage)
                ApplyProtection(_chinook);

            SpawnGuards();
            
            BroadcastMessage("EventStart");
        }

        #region Oxide Hooks

        private void OnAPCSpawned(BradleyAPC bradley)
        {
            var position = bradley.transform.position;
            if (!IsInBounds(position)) return;

            bradley.maxCratesToSpawn = _config.APCCrates;
            bradley._maxHealth = bradley._health = _config.APCHealth;
            bradley.health = bradley._maxHealth;

            ClearGuards();
        }

        private void OnAPCDeath(BradleyAPC bradley)
        {
            if (bradley == null || bradley.IsDestroyed) 
                return;
            //var position = bradley.transform.position + offset;
            var position = RandomCircle(bradley.transform.position,32f); // Krythic edit for random event target.

            if (!IsInBounds(position)) 
                return;

            _bradleyPosition = position;
            _bradleyPositionActual = bradley.transform.position;

            SpawnEvent();
        }
        
        private Vector3 RandomCircle(Vector3 center, float radius)
        {
            var ang = UnityEngine.Random.value * 360;
            
            var pos = center;
            pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
            pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
            pos.y = center.y;
            
            return pos;
        }

        private void OnNPCDeath(ScientistNPC npc)
        {
            if (_cleaningUp || !_guards.Remove(npc) || _guards.Count > 0) 
                return;

            if (_config.InstantCrates)
            {
                RemoveFlames();
                UnlockCrates();
            }

            BroadcastMessage("EventEnded");
        }
        
        #endregion

        #region Crates

        private void RemoveFlames()
        {
            var entities = Pool.GetList<FireBall>();

            Vis.Entities(_bradleyPositionActual, 25f, entities);

            foreach (var fireball in entities)
            {
                if (fireball.IsValid() && !fireball.IsDestroyed)
                    fireball.Extinguish();
            }

            Pool.FreeList(ref entities);
        }

        private void UnlockCrates()
        {
            var entities = Pool.GetList<LockedByEntCrate>();

            Vis.Entities(_bradleyPositionActual, 25f, entities);

            foreach (var crate in entities)
            {
                if (!crate.IsValid() || crate.IsDestroyed) 
                    continue;
                
                crate.SetLocked(false);
                
                if (crate.lockingEnt == null) 
                    continue;
                
                var entity = crate.lockingEnt.GetComponent<BaseEntity>();

                if (entity.IsValid() && !entity.IsDestroyed)
                    entity.Kill();
            }

            Pool.FreeList(ref entities);
        }    

        #endregion

        #region Guards
        
        private void SpawnGuards()
        {
            for (var i = 0; i < _config.NPCAmount - 1; i++)
                SpawnGuardAndMount(_config.GuardSettings.GetRandom(), _chinook.transform.position + _chinook.transform.forward * 10f, _bradleyPosition);

            for (var j = 0; j < 1; j++)
                SpawnGuardAndMount(_config.GuardSettings.GetRandom(), _chinook.transform.position - _chinook.transform.forward * 15f, _bradleyPosition);
        }
        
        private void SpawnGuardAndMount(GuardSetting settings, Vector3 position, Vector3 eventPos)
        {
            var npc = GameManager.server.CreateEntity(GUARD_PREFAB, position, Quaternion.identity) as ScientistNPC;
            if (npc == null) return;
            npc.Spawn();
            
            npc.displayName = settings.Name;
            npc.startHealth = settings.Health;
            npc.damageScale = settings.DamageScale;
            npc.aimConeScale = settings.AimConeScale;
            npc.InitializeHealth(settings.Health, settings.Health);

            _chinook.AttemptMount(npc);
            
            _guards.Add(npc);

            GiveGuardLoadout(npc, settings);

            NextFrame(() =>
            {
                if (npc == null || npc.IsDestroyed) return;

                npc.Brain.Navigator.Agent.agentTypeID = -1372625422;
                npc.Brain.Navigator.DefaultArea = "Walkable";
                npc.Brain.Navigator.Destination = eventPos;
                npc.Brain.Navigator.Init(npc, npc.Brain.Navigator.Agent);
                npc.Brain.ForceSetAge(0);
                
                npc.Brain.states.Remove(AIState.TakeCover);
                npc.Brain.states.Remove(AIState.Roam);
                npc.Brain.states.Remove(AIState.Chase);
                npc.Brain.states.Remove(AIState.Idle);
                npc.Brain.states.Remove(AIState.Flee);
                
                npc.Brain.AddState(new TakeCoverState { brain = npc.Brain, Position = npc.Brain.Navigator.Destination });
                npc.Brain.AddState(new RoamState(npc) { brain = npc.Brain, Position = npc.Brain.Navigator.Destination });
                npc.Brain.AddState(new IdleState(npc) { brain = npc.Brain });
                //npc.Brain.AddState(new ChaseState(npc) { brain = npc.Brain });
                
                npc.Brain.Navigator.BestCoverPointMaxDistance = settings.MaxRoamRadius / 2;
                npc.Brain.Navigator.BestRoamPointMaxDistance = settings.MaxRoamRadius;
                npc.Brain.Navigator.MaxRoamDistanceFromHome = settings.MaxRoamRadius;
                
                npc.Brain.Senses.Init(npc, 5f, settings.MaxAggressionRange, settings.MaxAggressionRange + 5f, -1f, true, true, true, settings.MaxAggressionRange, false, false, true, EntityType.Player, false);
            });
        }

        private void GiveGuardLoadout(ScientistNPC npc, GuardSetting settings)
        {
            if (settings.KitEnabled)
            {
                npc.inventory.Strip();
                
                Interface.Oxide.CallHook("GiveKit", npc, settings.KitName);
            }

            for (var i = 0; i < npc.inventory.containerBelt.itemList.Count; i++)
            {
                var item = npc.inventory.containerBelt.itemList[i];
                if (item == null) 
                    continue;

                var projectile = item.GetHeldEntity() as BaseProjectile;
                if (projectile == null) 
                    continue;
                
                projectile.effectiveRange = _config.EffectiveWeaponRange.ContainsKey(item.info.shortname) ? _config.EffectiveWeaponRange[item.info.shortname] : settings.MaxAggressionRange;
                projectile.CanUseAtMediumRange = true;
                projectile.CanUseAtLongRange = true;
            }

            npc.EquipWeapon();
        }
        
        public class RoamState : ScientistBrain.BasicAIState
        { 
            private readonly float _maxRoamRadius = 10f;
            private readonly ScientistNPC _npc;
            private StateStatus status = StateStatus.Error;
            public Vector3 Position;

            public RoamState(ScientistNPC npc) : base(AIState.Roam) { _npc = npc; }

            public override float GetWeight() => 0.0f;
            
            public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateEnter(brain, entity);
                status = StateStatus.Error;
                
                if (brain.Navigator.SetDestination(Position, BaseNavigator.NavigationSpeed.Slow))
                    status = StateStatus.Running;
                
                _npc.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, true);
            }

            public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateLeave(brain, entity);
                Stop();
                _npc.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, false);
            }

            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
            {
                base.StateThink(delta, brain, entity);
                
                if (Vector3.Distance(entity.transform.position, Position) >= _maxRoamRadius) 
                    brain.Navigator.SetDestination(Position, BaseNavigator.NavigationSpeed.Fast);
                else if (!brain.Navigator.Moving) 
                    brain.Navigator.SetDestination(GetRoamPosition(entity), BaseNavigator.NavigationSpeed.Slowest);
                
                return StateStatus.Running;
            }

            private void Stop() => brain.Navigator.Stop();
            
            private Vector3 GetRoamPosition(BaseEntity entity)
            {
                Vector3 positionAround = brain.PathFinder.GetRandomPositionAround(Position, 0f, _maxRoamRadius - 2f < 0f ? 0f : _maxRoamRadius - 2f);
                
                NavMeshHit meshHit;
                
                if (NavMesh.SamplePosition(positionAround, out meshHit, 2f, _npc.NavAgent.areaMask))
                {
                    NavMeshPath path = new NavMeshPath();
                    
                    if (NavMesh.CalculatePath(entity.transform.position, meshHit.position, _npc.NavAgent.areaMask, path)) 
                        positionAround = path.status == NavMeshPathStatus.PathComplete ? meshHit.position : path.corners.Last();
                    else 
                        positionAround = Position;
                }
                else 
                    positionAround = Position;
                
                return positionAround;
            }
        }

        public class IdleState : ScientistBrain.BasicAIState
        {
            private readonly ScientistNPC _npc;

            public IdleState(ScientistNPC npc) : base(AIState.Idle) { _npc = npc; }

            public override float GetWeight() => 50f;

            public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateEnter(brain, entity);
                _npc.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, true);
            }

            public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateLeave(brain, entity);
                _npc.SetPlayerFlag(BasePlayer.PlayerFlags.Relaxed, false);
            }
        }

        public class ChaseState : ScientistBrain.BasicAIState
        {
            private StateStatus status = StateStatus.Error;
            private float nextPositionUpdateTime;

            public ChaseState(ScientistNPC npc) : base(AIState.Chase)
            {
                AgrresiveState = true;
            }

            public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateEnter(brain, entity);
                status = StateStatus.Error;
                if (brain.PathFinder == null) 
                    return;

                status = StateStatus.Running;
                nextPositionUpdateTime = 0.0f;
            }

            public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateLeave(brain, entity);
                Stop();
            }

            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
            {
                if (status == StateStatus.Error)
                    return status;

                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (baseEntity == null) 
                    return StateStatus.Error;
                
                float distance = Vector3.Distance(entity.transform.position, baseEntity.transform.position);

                if (brain.Senses.Memory.IsLOS(baseEntity) || (double)distance <= brain.Navigator.MaxRoamDistanceFromHome)
                    brain.Navigator.SetFacingDirectionEntity(baseEntity);
                else
                    brain.Navigator.ClearFacingDirectionOverride();

                brain.Navigator.SetCurrentSpeed(distance <= brain.Navigator.MaxRoamDistanceFromHome ? 
                    BaseNavigator.NavigationSpeed.Normal : 
                    BaseNavigator.NavigationSpeed.Fast);
                
                if (Time.time > nextPositionUpdateTime)
                {
                    nextPositionUpdateTime = Time.time + UnityEngine.Random.Range(0.5f, 1f);
                    brain.Navigator.SetDestination(baseEntity.transform.position, BaseNavigator.NavigationSpeed.Normal);
                }

                return brain.Navigator.Moving ? 
                    StateStatus.Running : 
                    StateStatus.Finished;
            }

            private void Stop()
            {
                brain.Navigator.Stop();
                brain.Navigator.ClearFacingDirectionOverride();
            }
        }

        public class TakeCoverState : ScientistBrain.BasicAIState
        {
            private StateStatus status = StateStatus.Error;
            private BaseEntity coverFromEntity;
            public Vector3 Position;

            public TakeCoverState() : base(AIState.TakeCover) {  }

            public override void StateEnter(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateEnter(brain, entity);
                status = StateStatus.Running;
                if (StartMovingToCover())
                    return;
                
                status = StateStatus.Error;
            }

            public override void StateLeave(BaseAIBrain brain, BaseEntity entity)
            {
                base.StateLeave(brain, entity);
                brain.Navigator.ClearFacingDirectionOverride();
                ClearCoverPointUsage(entity);
            }

            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity)
            {
                FaceCoverFromEntity();

                if (status == StateStatus.Error)
                    return status;
                
                return brain.Navigator.Moving ? 
                    StateStatus.Running : 
                    StateStatus.Finished;
            }
            
            private void ClearCoverPointUsage(BaseEntity entity)
            {
                AIPoint aiPoint = brain.Events.Memory.AIPoint.Get(4);
                if (aiPoint == null)
                    return;
                
                aiPoint.ClearIfUsedBy(entity);
            }

            private bool StartMovingToCover() => brain.Navigator.SetDestination(Position, BaseNavigator.NavigationSpeed.Normal);

            private void FaceCoverFromEntity()
            {
                coverFromEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (coverFromEntity != null)
                    brain.Navigator.SetFacingDirectionEntity(coverFromEntity);
            }
        }

        #endregion

        #region Cleanup

        private void PerformCleanUp()
        {
            ClearGuards();
            ClearZones();
        }

        private void ClearZones()
        {
            if (_landingZone != null) 
                UnityEngine.Object.Destroy(_landingZone.gameObject);

            _landingZone = null;
        }

        private void ClearGuards()
        {
            _cleaningUp = true;
            
            for (var i = 0; i < _guards.Count; i++)
            {
                var npc = _guards[i];
                if (npc.IsValid() && !npc.IsDestroyed)
                    npc.Invoke(() => npc?.KillMessage(), 0.25f);
            }
            
            _guards.Clear();
        }

        #endregion

        #region Landing

        private void CreateLandingZone()
        {
            _landingZone = new GameObject(LANDING_NAME)
            {
                transform =
                {
                    position = _landingPosition,
                    rotation = _landingRotation
                }
            }.AddComponent<CH47LandingZone>();
        }

        private bool FindLandingPoint()
        {
            foreach (var monument in TerrainMeta.Path.Monuments)
            {
                if (!monument.gameObject.name.Contains("launch_site_1")) 
                    continue;

                CreateLandingPoint(monument);
                CreateLandingZone();

                return true;
            }

            return false;
        }

        private void CreateLandingPoint(MonumentInfo monument)
        {
            _monumentPosition = monument.transform.position;
            _chinookPosition = monument.transform.TransformPoint(_config.ChinookSpawnPosition);
            _landingPosition = monument.transform.TransformPoint(_config.LandingSpawnPosition);
            _landingRotation = Quaternion.Euler(monument.transform.rotation.eulerAngles + _config.LandingSpawnRotation);
        }
        
        #endregion

        #region Controller

        private class CH47LandedController : MonoBehaviour
        {
            private CH47HelicopterAIController _chinook;

            private void Awake()
            {
                _chinook = GetComponent<CH47HelicopterAIController>();

                InvokeRepeating(nameof(CheckDropped), 5f, 5f);
            }

            private void OnDestroy()
            {
                CancelInvoke();

                if (_chinook.IsValid() && !_chinook.IsDestroyed)
                    _chinook.Invoke(_chinook.DelayedKill, 10f);
            }

            private void CheckDropped()
            {
                if (_chinook.NumMounted() > 0) 
                    return;

                Destroy(this);
            }
        }

        #endregion

        #endregion
        
        #region Protection
        
        private void CreateProtection()
        {
            _ch47ProtectionProperties = ScriptableObject.CreateInstance<ProtectionProperties>();
            _ch47ProtectionProperties.name = PROTECTION_NAME;
            _ch47ProtectionProperties.Add(1);
        }

        private void DestroyProtection()
        {
            ScriptableObject.Destroy(_ch47ProtectionProperties);
            
            _ch47ProtectionProperties = null;
        }

        private void ApplyProtection(BaseEntity entity)
        {
            var combatEntity = entity as BaseCombatEntity;
            if (combatEntity != null)
                combatEntity.baseProtection = _ch47ProtectionProperties;
        }

        #endregion

        #region Helpers
        
        private bool IsInBounds(Vector3 position) => Vector3.Distance(_monumentPosition, position) <= 300f;

        
        
        #endregion
    }
}​

will take a look thanks for the report

Been trying to send you a msg but wasnt allowing me there Bazz31, Afternoon, after i did the update you did for us, i notice now the ch47 does show up for any brads at other monuments to drop off the guards. Works good for brad at launch site. I use the monument Bradley from Lone design, its also located on codefling.

hello, thanks for your work, I would like to make a couple of suggestions, some of them have already been mentioned:
1) the ability to change the NPC in the config, but this is not the most important
2) remove the damage and accuracy setting from the NPC, or take the standard values ​​from the game with a value of -1
3) so that the bots evenly diverge around the wreckage along the radius specified in the config, and not stand at one point
4) so that the bots do not chase the player at all, so that they have a debris protection mode
thanks a lot!