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

FREE ScientistHorse : 1.0.4 1.0.4

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using System.Collections;
using System.Linq;

namespace Oxide.Plugins
{
    [Info("ScientistHorse", "[modhub.to] WOLF SPIRIT", "1.0.4")]
    internal class ScientistHorse : RustPlugin
    {
        #region Static

        private Configuration _config;
        private List<RiderInWorld> Riders = new List<RiderInWorld>();
        private Timer _timer;
        private List<Vector3> positions = new List<Vector3>();
        private const int scanHeight = 100;
        private static int getBlockMask => LayerMask.GetMask("Construction", "Prevent Building", "Water");
        private static bool MaskIsBlocked(int mask) => getBlockMask == (getBlockMask | (1 << mask));

        #region Classes

        private class RiderInWorld
        {
            public RidableHorse horse;
            public BasePlayer npc;
        }
        
        private class Rider
        {
            [JsonProperty(PropertyName = "Prefab of NPC")]
            public string NPCPrefab;

            [JsonProperty(PropertyName = "List of armor for NPC", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<string> armor;

            [JsonProperty(PropertyName = "Prefab of Horse")]
            public string horsePrefab;

            [JsonProperty(PropertyName = "Horse armor")]
            public string horseArmor;

            [JsonProperty(PropertyName = "Scan radius for Rider(Find player)")]
            public int scanRadius;
        }
        
        private class Configuration
        {
            [JsonProperty(PropertyName = "Bonus damage to NPCs on horseback")]
            public float bonusDamage = 6;

            [JsonProperty(PropertyName = "Maximum Riders population")]
            public int maxPopulation = 10;

            [JsonProperty(PropertyName = "Kill horse after NPC death")]
            public bool DeathTogether = true;

            [JsonProperty(PropertyName = "Rider types", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<Rider> Riders = new List<Rider>
            {
                new Rider
                {
                    NPCPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_lr300.prefab",
                    horsePrefab = "assets/rust.ai/nextai/testridablehorse.prefab",
                    horseArmor = "horse.armor.roadsign",
                    scanRadius = 100,
                    armor = new List<string>{"hazmatsuit"}
                }
            };
        }

        #endregion

        #endregion

        #region Config

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Your configuration file contains an error.Using default configuration values.");
                LoadDefaultConfig();
            }
        }

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

        protected override void LoadDefaultConfig() => _config = new Configuration();

        #endregion

        #region OxideHooks
        
        private void OnServerInitialized()
        {
            GeneratePositions();
            _timer = timer.Every(60, () =>
            {
                while (Riders.Count < _config.maxPopulation) SpawnRider(_config.Riders.GetRandom(), positions.GetRandom());
            });
        }

        private void OnEntityTakeDamage(BasePlayer player, HitInfo info)
        {
            if (player == null || info == null || player.userID.IsSteamId() || !player.isMounted) return;
            info.damageTypes.ScaleAll(_config.bonusDamage);
        }

        private void OnEntityDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || player.userID.IsSteamId()) return;
            foreach (var check in Riders.ToArray())
            {
                if (check.npc.userID != player.userID) continue; 
                if (_config.DeathTogether) check.horse?.Kill();
                else check.horse?.GetComponent<RiderAI>().Kill();
                Riders.Remove(check);
            }
        }

        private void Unload()
        {
            _timer?.Destroy();
            foreach (var check in Riders)
            {
                if (check.npc != null) check.npc.Kill();
                if (check.horse != null) check.horse.Kill();
            }
        }

        #endregion

        #region Functions

        [ChatCommand("spawnrider")]
        private void cmdChatspawnrider(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin) return;
            SpawnRider(_config.Riders.GetRandom(), player.transform.position);
        }
        private void GeneratePositions()
        {
            positions.Clear();
            var generationSuccess = 0;
            var islandSize = ConVar.Server.worldsize / 2;
            for (var i = 0; i < 500; i++)
            {
                if (generationSuccess >= 500) break;
                var x = Core.Random.Range(-islandSize, islandSize);
                var z = Core.Random.Range(-islandSize, islandSize);
                var original = new Vector3(x, scanHeight, z);
                var position = GetClosestValidPosition(original);
                if (position == new Vector3()) continue;
                positions.Add(position);
                generationSuccess++;
            }
        }

        private Vector3 GetClosestValidPosition(Vector3 original)
        {
            var target = original - new Vector3(0, 200, 0);
            RaycastHit hitInfo;
            if (Physics.Linecast(original, target, out hitInfo) == false) return new Vector3();
            var position = hitInfo.point;
            var collider = hitInfo.collider;
            var colliderLayer = collider?.gameObject.layer ?? 4;
            if (collider == null) return new Vector3();
            if (MaskIsBlocked(colliderLayer) || colliderLayer != 23) return new Vector3();
            return IsValidPosition(position) == false ? new Vector3() : position;
        }

        private Vector3 GetValidSpawnPoint()
        {
            for (var i = 0; i < 25; i++)
            {
                var number = Core.Random.Range(0, positions.Count);
                var position = positions.ElementAt(number);
                if (IsValidPosition(position)) return position;
                positions.Remove(position);
            }

            return new Vector3();
        }

        private static bool IsValidPosition(Vector3 position)
        {
            var entities = new List<BuildingBlock>();
            Vis.Entities(position, 25, entities);
            return entities.Count == 0;
        }

        private void SpawnRider(Rider rider, Vector3 position)
        {
            var npc = (ScientistNPC)GameManager.server.CreateEntity(rider.NPCPrefab, position);
            npc.Spawn();
            npc.GetComponent<BaseNavigator>().CanUseNavMesh = false;
            npc.inventory.containerWear.Clear();
            foreach (var check in rider.armor) ItemManager.CreateByName(check).MoveToContainer(npc.inventory.containerWear);
            var horse = (RidableHorse)GameManager.server.CreateEntity(rider.horsePrefab, position);
            horse.Spawn();
            ItemManager.CreateByName(rider.horseArmor).MoveToContainer(horse.inventory);
            horse.EquipmentUpdate();
            (horse.children.FirstOrDefault(x => x.PrefabName.Contains("saddle")) as BaseMountable).MountPlayer(npc);
            var comp = horse.gameObject.AddComponent<RiderAI>();
            comp._rider = rider;
            comp.npc = npc;
            comp.load = true;
            Riders.Add(new RiderInWorld{npc = npc, horse = horse});
        }
        
        private class RiderAI : FacepunchBehaviour
        {
            private BasePlayer _target;
            private Coroutine _coroutine;
            private BaseRidableAnimal _horse;
            public Rider _rider;
            public bool load = false;
            public BasePlayer npc;
            
            private void Start()
            {
                _horse = GetComponent<BaseRidableAnimal>();
                StartCoroutine(FindPath());
            }

            private IEnumerator FindPath()
            {
                while (load) yield return new WaitForSeconds(Think());
            }

            private float Think()
            {
                if (_horse == null || _horse.IsDead() || npc == null || npc.IsDead())
                {
                    load = false;
                    Destroy(this);
                    return 0;
                }
                if (_target == null)
                {
                    FindTarget();
                    if (_target != null) return 0.5f;
                    StopMove();
                    StopRotate();
                    return 5;
                }
                if (_target == null || _target.IsSleeping() || !_target.IsConnected || _target.IsDead() || _target.IsSwimming() || _target.InSafeZone())
                {
                    _target = null;
                    return 5;
                }
                _horse.lastInputTime = Time.time;
                _horse.staminaSeconds = _horse.maxStaminaSeconds;
                RotateToTarget();
                MoveToTarget();
                return 0.5f;
            }

            private void MoveToTarget()
            {
                var distance = GetDistance();
                if (distance > _rider.scanRadius)
                {
                    _target = null;
                    return;
                }
                
                if (distance > distance * 0.85)
                {
                    StartRun();
                    return;
                }
                StartWalk();
            }

            private void RotateToTarget()
            {
                var angle = GetAngle();
                if (angle > 0)
                {
                    if (angle < 35)
                    {
                        StopRotate();
                        return;
                    }
                    RotateRight();
                    return;
                }

                if (angle > -35)
                {
                    StopRotate();
                    return;
                }
                
                RotateLeft();
            }

            private float GetDistance() => Vector3.Distance(_target.transform.position, transform.position);
            private float GetAngle() => Vector3.SignedAngle(_target.transform.position - transform.position, transform.forward, Vector3.up);
            private void StartRun() => _horse.ModifyRunState(2);
            private void StartWalk() => _horse.ModifyRunState(1);
            private void StopMove() => _horse.ModifyRunState(0);
            private void RotateLeft() => _horse.desiredRotation = 1;
            private void RotateRight() =>_horse.desiredRotation = -1;
            private void StopRotate() =>_horse.desiredRotation = 0;
            
            private void FindTarget()
            {
                var players = Facepunch.Pool.GetList<BasePlayer>();
                Vis.Entities(_horse.transform.position, _rider.scanRadius, players);
                foreach (var check in players.ToArray()) if (check.IsSleeping() || !check.userID.IsSteamId() || !check.IsConnected || check.IsDead() || check.IsSwimming() || check.InSafeZone()) players.Remove(check);
                if (players.Count > 0) _target = players[0];
                Facepunch.Pool.FreeList(ref players);
            }

            public void Kill() => Destroy(this);
            private void OnDestroy()
            {
                load = false;
                StopCoroutine(FindPath());
            }
        }
        
        #endregion
    }
}

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