Иконка ресурса

FREE BetterScarecrows : 1.5.9 1.5.9

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using ProtoBuf;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Better Scarecrows", "Spiikesan", "1.5.9")]
    [Description("Fix and improve scarecrows")]
    public class BetterScarecrows : RustPlugin {
        const string b64ScarecrowDesign = "CAEIAwgPCBwIHQgeCB8SUggAEAEaFAgBEAEYACAAKAAwAKoGBQ0AACBBGhkIAxAFGAAgBCgAMAGiBgoNAAAAABUAAAAAGhkIABAGGAAgACgAMAKiBgoNAAAAQRUAAHBBIAASPQgBEAMaDAgFEAIYACAAKAAwABoMCBQQABgAIAAoADABGhkIAxAFGAAgBCgAMAKiBgoNAAAAABUAAAAAIAASRQgCEA8aDAgUEAAYACAAKAAwABoMCAUQARgBIAAoADABGiEIExAEGAAgACgAMASiBgoNAAAAABUAAAAA6gYFDc3MzD0gABJ6CAMQHBoZCAIQABgAIAAoADABogYKDQAAAAAVAAAAABoZCAQQABgAIAAoADACogYKDQAAAAAVAAAAABohCAEQARgAIAAoADADogYKDQAAAAAVAAAAAKoGBQ0AACBBGhkIAxAFGAAgBCgAMASiBgoNAAAAABUAAAAAIAASPAgEEB0aGQgCEAAYACAAKAAwAaIGCg0AAAAAFQAAAAAaGQgEEAEYACAAKAAwAqIGCg0AAAAAFQAAAAAgABI8CAUQHhoZCAIQARgAIAAoADABogYKDQAAAAAVAAAAABoZCAQQABgAIAAoADACogYKDQAAAAAVAAAAACAAEjwIBhAfGhkIAhAAGAAgACgAMAGiBgoNAAAAABUAAAAAGhkIBBADGAAgACgAMAKiBgoNAAAAABUAAAAAIAAYACIQQmV0dGVyIHNjYXJlY3JvdygBMAA=";
        const float SOUND_DELAY = 3f;
        static AIState _lastAIStateEnumValue = AIState.Blinded;
        static AIState _maxAIStateEnumValue = Enum.GetValues(typeof(AIState)).Cast<AIState>().Max();
        static BetterScarecrows _instance;
        enum AICustomState {
            UnusedState,  //For compatibility with my AIManager plugin (used to create or update the content of the b64ScarecrowDesign) - Do not remove
            RoamState, ThrowGrenadeState, FleeInhuman, Awaken,  // Maybe more states in the future ?
        }
        ;
        ProtoBuf.AIDesign _customDesign;
#region Configuration
        private ScarecrowConfiguration _config;
        private ConVars _previousConVars;
        public class ConVars {
            [JsonProperty("OverrideConVars")]
            public bool OverrideConVars = false;
            [JsonProperty("ScarecrowPopulation")]
            public float ScarecrowPopulation = 5.0f;
            [JsonProperty("scarecrowsThrowBeancans")]
            public bool ScarecrowsThrowBeancans = true;
            [JsonProperty("scarecrowThrowBeancanGlobalDelay")]
            public float ScarecrowThrowBeancanGlobalDelay = 8.0f;
        }
        public class Sounds {
            [JsonProperty("Death")]
            public string Death = "assets/prefabs/npc/murderer/sound/death.prefab";
        }
        public class ScarecrowConfiguration {
            [JsonProperty("Health")]
            public float Health = 250.0f;
            [JsonProperty("AttackRangeMultiplier")]
            public float AttackRangeMultiplier = 0.75f;
            [JsonProperty("TargetLostRange")]
            public float TargetLostRange = 20f;
            [JsonProperty("SenseRange")]
            public float SenseRange = 15f;
            [JsonProperty("WalkSpeedFraction")]
            public float WalkSpeed = 0.3f;
            [JsonProperty("RunSpeedFraction")]
            public float RunSpeed = 1f;
            [JsonProperty("IgnoreSafeZonePlayers")]
            public bool IgnoreSafeZonePlayers = true;
            [JsonProperty("CanBradleyAPCTargetScarecrow")]
            public bool CanBradleyAPCTargetScarecrow = true;
            [JsonProperty("CanNPCTurretsTargetScarecrow")]
            public bool CanNPCTurretsTargetScarecrow = true;
            [JsonProperty("CanNPCScientistsTargetScarecrow")]
            public bool CanNPCScientistsTargetScarecrow = true;
            [JsonProperty("CanScarecrowTargetNPCScientists")]
            public bool CanScarecrowTargetNPCScientists = true;
            [JsonProperty("CanNPCBanditGuardTargetScarecrow")]
            public bool CanNPCBanditGuardTargetScarecrow = true;
            [JsonProperty("CanScarecrowTargetNPCBanditGuard")]
            public bool CanScarecrowTargetNPCBanditGuard = true;
            [JsonProperty("DisableLoot")]
            public bool DisableLoot = false;
            [JsonProperty("UseCustomAI")]
            public bool UseCustomAI = true;
            public Sounds Sounds = new Sounds();
            [JsonProperty("ConVars")]
            public ConVars ConVars = new ConVars();
            public string ToJson() => JsonConvert.SerializeObject(this);
            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }
        ;
        protected override void LoadDefaultConfig() => _config = new ScarecrowConfiguration();
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _config = Config.ReadObject<ScarecrowConfiguration>();
                if (_config == null) {
                    throw new JsonException();
                }
                if (!_config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys)) {
                    PrintWarning("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch {
                PrintWarning($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() {
            PrintWarning($"Configuration changes saved to {Name}.json");
            Config.WriteObject(_config, true);
        }
#endregion
#region Oxide hooks
        void Init() {
            _instance = this;
            _customDesign = ProtoBuf.AIDesign.Deserialize(Convert.FromBase64String(b64ScarecrowDesign));
            if (_lastAIStateEnumValue != _maxAIStateEnumValue) {
                PrintWarning($"{_maxAIStateEnumValue - _lastAIStateEnumValue} new state(s) have been added by Facepunch.An update of the AI is required !");
                computeNewDesign(_maxAIStateEnumValue - _lastAIStateEnumValue);
            }
            if (_customDesign == null) {
                PrintError("The custom design could not be loaded !");
                Unload();
            }
        }
        private void computeNewDesign(int offset) {
            //Updating availableStates.for (int i = 0; i < _customDesign.availableStates.Count; i++)
            {
                if (_customDesign.availableStates[i] > (int)_lastAIStateEnumValue) {
                    _customDesign.availableStates[i] += offset;
                }
            }
            //Updating state container
            for (int i = 0; i < _customDesign.stateContainers.Count; i++) {
                if (_customDesign.stateContainers[i].state > (int)_lastAIStateEnumValue) {
                    _customDesign.stateContainers[i].state += offset;
                }
            }
            PrintWarning("AI is updated with the new values.An update of the plugin is probably already pending from the plugin developer, but the plugin will continue to work.");
        }
        void OnServerInitialized() {
            updateAllScarecrows(false);
            if (_config.ConVars.OverrideConVars) {
                _previousConVars = new ConVars() {
                    OverrideConVars = true, ScarecrowPopulation = ConVar.Halloween.scarecrowpopulation, ScarecrowsThrowBeancans = ConVar.Halloween.scarecrows_throw_beancans, ScarecrowThrowBeancanGlobalDelay = ConVar.Halloween.scarecrow_throw_beancan_global_delay
                }
                ;
                ConVar.Halloween.scarecrowpopulation = _config.ConVars.ScarecrowPopulation;
                ConVar.Halloween.scarecrows_throw_beancans = _config.ConVars.ScarecrowsThrowBeancans;
                ConVar.Halloween.scarecrow_throw_beancan_global_delay = _config.ConVars.ScarecrowThrowBeancanGlobalDelay;
            }
        }
        void Unload() {
            updateAllScarecrows(true);
            if (_config.ConVars.OverrideConVars && _previousConVars != null) {
                ConVar.Halloween.scarecrowpopulation = _previousConVars.ScarecrowPopulation;
                ConVar.Halloween.scarecrows_throw_beancans = _previousConVars.ScarecrowsThrowBeancans;
                ConVar.Halloween.scarecrow_throw_beancan_global_delay = _previousConVars.ScarecrowThrowBeancanGlobalDelay;
            }
            _instance = null;
        }
        private void OnEntitySpawned(ScarecrowNPC entity) {
            // The brain is hooked on the next frame.if (entity != null
            && !entity.IsDestroyed) {
                NextTick(() => {
                    if (entity.Brain != null) {
                        UpdateScarecrowConfiguration(entity, false);
                    }
                }
                );
            }
        }
        private void OnEntityDeath(ScarecrowNPC entity) {
            Effect.server.Run(_config.Sounds.Death, entity, 0, Vector3.zero, entity.eyes.transform.forward.normalized);
        }
        private object CanBradleyApcTarget(BradleyAPC bradley, ScarecrowNPC scarecrow) {
            if (!_config.CanBradleyAPCTargetScarecrow) return false;
            return null;
        }
        private object CanBeTargeted(ScarecrowNPC scarecrow, NPCAutoTurret turret) {
            if (!_config.CanNPCTurretsTargetScarecrow) return false;
            return null;
        }
        private object OnNpcTarget(BaseEntity npc, BaseEntity entity) {
            // ScarecrowNPC is targeted.if (entity is ScarecrowNPC)
            {
                if (npc is ScientistNPC && !_config.CanNPCScientistsTargetScarecrow || npc is BanditGuard && !_config.CanNPCBanditGuardTargetScarecrow) {
                    return true;
                }
            }
            // ScarecrowNPC is targeting.if (npc is ScarecrowNPC)
            {
                if (entity is ScientistNPC && !_config.CanScarecrowTargetNPCScientists || entity is BanditGuard && !_config.CanScarecrowTargetNPCBanditGuard) {
                    return true;
                }
            }
            return null;
        }
        private object OnCorpsePopulate(ScarecrowNPC scarecrow, NPCPlayerCorpse corpse) {
            return _config.DisableLoot ? corpse : null;
        }
#endregion
#region Helpers
        static AIState GetAIState(AICustomState state) => (AIState)((int)_maxAIStateEnumValue + 1 + (int)state);
        static AICustomState GetAICustomState(AIState state) => (AICustomState)((int)state - (int)(_maxAIStateEnumValue + 1));
        static bool IsCustomState(AIState state) => state > _maxAIStateEnumValue;
        static void TraceLog(string format, [CallerLineNumber] int lineNumber = 0, [CallerMemberName] string caller = null) => _instance.Puts("(" + caller + ":" + lineNumber + ") " + format);
        public void updateAllScarecrows(bool revert) {
            foreach (var entity in BaseNetworkable.serverEntities) {
                ScarecrowNPC scarecrow = entity as ScarecrowNPC;
                if (scarecrow != null && !scarecrow.IsDestroyed) {
                    if (scarecrow.Brain != null) {
                        UpdateScarecrowConfiguration(scarecrow, revert);
                    }
                    else {
                        // If the scarecrow just spawned, his brain will only be there the next tick.NextTick(() =>
                        {
                            if (scarecrow.Brain != null) {
                                UpdateScarecrowConfiguration(scarecrow, revert);
                            }
                        }
                        );
                    }
                }
            }
        }
        private void UpdateScarecrowConfiguration(ScarecrowNPC entity, bool revert) {
            entity.InitializeHealth(_config.Health, _config.Health);
            entity.Brain.AttackRangeMultiplier = _config.AttackRangeMultiplier;
            entity.Brain.TargetLostRange = _config.TargetLostRange;
            entity.Brain.SenseRange = _config.SenseRange;
            entity.Brain.Senses.ignoreSafeZonePlayers = _config.IgnoreSafeZonePlayers;
            entity.Brain.Navigator.SlowSpeedFraction = _config.WalkSpeed;
            entity.Brain.Navigator.FastSpeedFraction = _config.RunSpeed;
            if (_config.UseCustomAI) {
                if (entity.Brain.states == null) entity.Brain.AddStates();
                if (!revert) {
                    if (!entity.Brain.states.ContainsKey(GetAIState(AICustomState.RoamState))) entity.Brain.AddState(new RoamState());
                    if (!entity.Brain.states.ContainsKey(GetAIState(AICustomState.ThrowGrenadeState))) entity.Brain.AddState(new ThrowGrenadeState());
                    if (!entity.Brain.states.ContainsKey(GetAIState(AICustomState.FleeInhuman))) entity.Brain.AddState(new FleeInhuman());
                    if (!entity.Brain.states.ContainsKey(GetAIState(AICustomState.Awaken))) entity.Brain.AddState(new Awaken());
                    entity.Brain.states[AIState.Attack] = new AttackState();
                    entity.Brain.states[AIState.Attack].brain = entity.Brain;
                    entity.Brain.states[AIState.Attack].Reset();
                    entity.Brain.InstanceSpecificDesign = _customDesign;
                }
                else {
                    entity.Brain.states[AIState.Attack] = new ScarecrowBrain.AttackState();
                    entity.Brain.states[AIState.Attack].brain = entity.Brain;
                    entity.Brain.states[AIState.Attack].Reset();
                    entity.Brain.InstanceSpecificDesign = null;
                }
            }
            entity.Brain.LoadAIDesignAtIndex(entity.Brain.LoadedDesignIndex());
        }
#endregion
#region AI States
        public class AttackState : BaseAIBrain.BasicAIState {
            private IAIAttack attack;
            Chainsaw chainsaw;
            public AttackState() : base(AIState.Attack) {
                AgrresiveState = true;
            }
            private static Vector3 GetAimDirection(Vector3 from, Vector3 target) {
                return Vector3Ex.Direction2D(target, from);
            }
            private void StartAttacking(BaseEntity entity) {
                attack.StartAttacking(entity);
                if (chainsaw != null) {
                    chainsaw.ServerNPCStart();
                    chainsaw.SetFlag(BaseEntity.Flags.Busy, true, false, true);
                    chainsaw.SetFlag(BaseEntity.Flags.Reserved8, true, false, true);
                }
            }
            public override void StateEnter(BaseAIBrain brain, BaseEntity entity) {
                base.StateEnter(brain, entity);
                ScarecrowNPC scarecrow = entity as ScarecrowNPC;
                attack = entity as IAIAttack;
                chainsaw = scarecrow.GetHeldEntity() as Chainsaw;
                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (baseEntity != null) {
                    Vector3 aimDirection = GetAimDirection(brain.Navigator.transform.position, baseEntity.transform.position);
                    brain.Navigator.SetFacingDirectionOverride(aimDirection);
                    if (attack.CanAttack(baseEntity)) {
                        StartAttacking(baseEntity);
                    }
                    brain.Navigator.SetDestination(baseEntity.transform.position, BaseNavigator.NavigationSpeed.Fast, 0f, 0f);
                }
            }
            public override void StateLeave(BaseAIBrain brain, BaseEntity entity) {
                base.StateLeave(brain, entity);
                brain.Navigator.ClearFacingDirectionOverride();
                brain.Navigator.Stop();
                StopAttacking();
            }
            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity) {
                base.StateThink(delta, brain, entity);
                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (attack == null) {
                    return StateStatus.Error;
                }
                if (baseEntity == null) {
                    brain.Navigator.ClearFacingDirectionOverride();
                    StopAttacking();
                    return StateStatus.Finished;
                }
                if (brain.Senses.ignoreSafeZonePlayers) {
                    BasePlayer basePlayer = baseEntity as BasePlayer;
                    if (basePlayer != null && basePlayer.InSafeZone()) {
                        return StateStatus.Error;
                    }
                }
                if (!brain.Navigator.SetDestination(baseEntity.transform.position, BaseNavigator.NavigationSpeed.Fast, 0.25f, 0f)) {
                    return StateStatus.Error;
                }
                Vector3 aimDirection = GetAimDirection(brain.Navigator.transform.position, baseEntity.transform.position);
                brain.Navigator.SetFacingDirectionOverride(aimDirection);
                if (!attack.CanAttack(baseEntity)) {
                    StopAttacking();
                }
                else {
                    StartAttacking(baseEntity);
                }
                return StateStatus.Running;
            }
            private void StopAttacking() {
                attack.StopAttacking();
                if (chainsaw != null) {
                    chainsaw.SetFlag(BaseEntity.Flags.Busy, false, false, true);
                    chainsaw.SetFlag(BaseEntity.Flags.Reserved8, false, false, true);
                }
            }
        }
#endregion
#region AI Custom states
        private class RoamState : BaseAIBrain.BasicAIState {
            private StateStatus status = StateStatus.Error;
            public RoamState() : base(GetAIState(AICustomState.RoamState)) {
            }
            public override void StateEnter(BaseAIBrain brain, BaseEntity entity) {
                Vector3 bestRoamPosition;
                base.StateEnter(brain, entity);
                status = StateStatus.Error;
                if (brain.PathFinder != null) {
                    if (!brain.InGroup() || brain.IsGroupLeader) {
                        bestRoamPosition = brain.PathFinder.GetBestRoamPosition(brain.Navigator, brain.Navigator.transform.position, brain.Events.Memory.Position.Get(4), 20f, 100f);
                    }
                    else {
                        bestRoamPosition = BasePathFinder.GetPointOnCircle(brain.Events.Memory.Position.Get(5), Core.Random.Range(2f, 7f), Core.Random.Range(0f, 359f));
                    }
                    if (brain.Navigator.SetDestination(bestRoamPosition, BaseNavigator.NavigationSpeed.Slow, 0f, 0f)) {
                        if (brain.InGroup() && brain.IsGroupLeader) {
                            brain.SetGroupRoamRootPosition(bestRoamPosition);
                        }
                        status = StateStatus.Running;
                    }
                }
            }
            public override void StateLeave(BaseAIBrain brain, BaseEntity entity) {
                base.StateLeave(brain, entity);
                brain.Navigator.Stop();
            }
            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity) {
                base.StateThink(delta, brain, entity);
                if (status == StateStatus.Error) {
                    return status;
                }
                if (brain.Navigator.Moving) {
                    return StateStatus.Running;
                }
                return StateStatus.Finished;
            }
        }
        private class ThrowGrenadeState : BaseAIBrain.BasicAIState {
            bool _isThrown;
            NPCPlayer _entity = null;
            BasePlayer _target = null;
            Item _grenade = null;
            const float _MAX_DISTANCE = 5f;
            const float _THROW_TIME = 1.5f;
            public ThrowGrenadeState() : base(GetAIState(AICustomState.ThrowGrenadeState)) {
                AgrresiveState = true;
            }
            public override bool CanEnter() {
                bool canEnter = false;
                if (ConVar.Halloween.scarecrows_throw_beancans && TimeSinceState() >= ConVar.Halloween.scarecrow_throw_beancan_global_delay) {
                    _target = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot) as BasePlayer;
                    canEnter = base.CanEnter() && _target != null && (!brain.Senses.ignoreSafeZonePlayers || !_target.InSafeZone());
                }
                return canEnter;
            }
            public override void StateEnter(BaseAIBrain brain, BaseEntity entity) {
                base.StateEnter(brain, entity);
                _entity = entity as NPCPlayer;
                _grenade = _entity.inventory.containerBelt.GetSlot(1);
                if (_grenade != null) _entity.UpdateActiveItem(_grenade.uid);
                _isThrown = false;
            }
            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity) {
                base.StateThink(delta, brain, entity);
                _target = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot) as BasePlayer;
                StateStatus status = StateStatus.Error;
                if (_target != null && _grenade != null) {
                    float distance = Vector3.Distance(_entity.transform.position, _target.transform.position);
                    if (distance < _MAX_DISTANCE) {
                        status = StateStatus.Running;
                        _entity.SetAimDirection((_target.ServerPosition - _entity.ServerPosition).normalized);
                        if (!_isThrown && TimeInState >= _THROW_TIME) {
                            _entity.SignalBroadcast(BaseEntity.Signal.Throw);
                            (_grenade.GetHeldEntity() as ThrownWeapon)?.ServerThrow(_target.transform.position);
                            _isThrown = true;
                        }
                        else if (TimeInState >= _THROW_TIME + 1f) {
                            status = StateStatus.Finished;
                        }
                    }
                }
                return status;
            }
            public override void StateLeave(BaseAIBrain brain, BaseEntity entity) {
                base.StateLeave(brain, entity);
                if (_entity.inventory.containerBelt.GetSlot(0) != null) _entity.UpdateActiveItem(_entity.inventory.containerBelt.GetSlot(0).uid);
            }
        }
        public class FleeInhuman : BaseAIBrain.BasicAIState {
            private float nextInterval;
            private float stopFleeDistance;
            public FleeInhuman() : base(GetAIState(AICustomState.FleeInhuman)) {
            }
            private bool FleeFrom(BaseEntity fleeFromEntity, BaseEntity thisEntity) {
                Vector3 vector3;
                if (thisEntity == null || fleeFromEntity == null) {
                    return false;
                }
                nextInterval = UnityEngine.Random.Range(3f, 6f);
                if (!brain.PathFinder.GetBestFleePosition(brain.Navigator, brain.Senses, fleeFromEntity, brain.Events.Memory.Position.Get(4), 50f, 100f, out vector3)) {
                    return false;
                }
                bool flag = brain.Navigator.SetDestination(vector3, BaseNavigator.NavigationSpeed.Fast, 0f, 0f);
                if (!flag) {
                    Stop();
                }
                return flag;
            }
            public override void StateEnter(BaseAIBrain brain, BaseEntity entity) {
                base.StateEnter(brain, entity);
                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (baseEntity != null && !(baseEntity is BasePlayer)) {
                    stopFleeDistance = UnityEngine.Random.Range(5f, 10f);
                    FleeFrom(baseEntity, entity);
                }
            }
            public override bool CanLeave() {
                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                return base.CanLeave() && (baseEntity == null || baseEntity is BasePlayer || Vector3Ex.Distance2D(brain.Navigator.transform.position, baseEntity.transform.position) >= stopFleeDistance);
            }
            public override void StateLeave(BaseAIBrain brain, BaseEntity entity) {
                base.StateLeave(brain, entity);
                Stop();
            }
            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity) {
                base.StateThink(delta, brain, entity);
                BaseEntity baseEntity = brain.Events.Memory.Entity.Get(brain.Events.CurrentInputMemorySlot);
                if (baseEntity == null) {
                    return StateStatus.Finished;
                }
                else if (baseEntity is BasePlayer && !(baseEntity is NPCPlayer)) {
                    return StateStatus.Error;
                }
                if (Vector3Ex.Distance2D(brain.Navigator.transform.position, baseEntity.transform.position) >= stopFleeDistance) {
                    return StateStatus.Finished;
                }
                if (!brain.Navigator.UpdateIntervalElapsed(nextInterval) && brain.Navigator.Moving || FleeFrom(baseEntity, entity)) {
                    return StateStatus.Running;
                }
                return StateStatus.Error;
            }
            private void Stop() {
                brain.Navigator.Stop();
            }
        }
        public class Awaken : BaseAIBrain.BasicAIState {
            BasePlayer[] players = new BasePlayer[1];
            public Awaken() : base(GetAIState(AICustomState.Awaken)) {
            }
            public override StateStatus StateThink(float delta, BaseAIBrain brain, BaseEntity entity) {
                StateStatus status = StateStatus.Finished;
                if (Rust.Ai.AiManager.ai_dormant && BaseEntity.Query.Server.GetPlayersInSphere(entity.transform.position, Rust.Ai.AiManager.ai_to_player_distance_wakeup_range, players, (p) => p.userID.IsSteamId()) == 0) {
                    status = StateStatus.Error;
                }
                players[0] = null;
                return status;
            }
        }
#endregion
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху