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

FREE NpcHorses : 2.2.0 2.2.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Linq;
using Oxide.Core.Plugins;
using UnityEngine.AI;
using System.Collections;
using Facepunch;
using Newtonsoft.Json.Linq;
using Oxide.Core.Libraries.Covalence;
using Rust;
using Random = System.Random;
namespace Oxide.Plugins {
    [Info("NpcHorses", "Razor", "2.2.0")]
    [Description("Make Npc ride horses")]
    public class NpcHorses : RustPlugin {
        [PluginReference]
        Plugin Kits;
        public bool debug = false;
        private static NpcHorses ins;
        private static Coroutine SpawnRoutine2 {
            get;
            set;
        }
        public Dictionary<ulong, ulong> HorseAndRider = new Dictionary<ulong, ulong>();
        public Dictionary<ulong, bool> _allNpc = new Dictionary<ulong, bool>();
        //  private List<Vector3> SpawnLocations = new List<Vector3>();
        public List<ulong> UsedPile = new List<ulong>();
        public bool rebooting = false;
        public int failed;
        public int totalHorses;
        public bool booted;
        public Dictionary<string, int> TropToInt = new Dictionary<string, int>() {
            {
                "field", 1
            }
            , {
                "cliff", 2
            }
            , {
                "summit", 4
            }
            , {
                "beachside", 8
            }
            , {
                "beach", 16
            }
            , {
                "forest", 32
            }
            , {
                "forestside", 64
            }
            , {
                "ocean", 128
            }
            , {
                "oceanside", 256
            }
            , {
                "decor", 512
            }
            , {
                "monument", 1024
            }
            , {
                "road", 2048
            }
            , {
                "roadside", 4096
            }
            , {
                "swamp", 8192
            }
            , {
                "river", 16384
            }
            , {
                "riverside", 32768
            }
            , {
                "lake", 65536
            }
            , {
                "lakeside", 131072
            }
            , {
                "offshore", 262144
            }
            , {
                "powerline", 524288
            }
            , {
                "plain", 1048576
            }
            , {
                "building", 2097152
            }
            , {
                "cliffside", 4194304
            }
            , {
                "mountain", 8388608
            }
            , {
                "clutter", 16777216
            }
            , {
                "alt", 33554432
            }
            , {
                "tier0", 67108864
            }
            , {
                "tier1", 134217728
            }
            , {
                "tier2", 268435456
            }
            , {
                "mainland", 536870912
            }
            , {
                "hilltop", 1073741824
            }
        }
        ;
        public Dictionary<string, List<Vector3>> TropSpawns = new Dictionary<string, List<Vector3>>();
        public Dictionary<string, List<ulong>> totalTypes = new Dictionary<string, List<ulong>>();
        public static Dictionary<Vector3, bool> deathLocation = new Dictionary<Vector3, bool>();
#region Config
        private ConfigData configData;
        class ConfigData {
            [JsonProperty(PropertyName = "Spawn Settings")]
            public SpawnSettings spawnSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Horse Inventory Configs")]
            public Settings settings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Horse And Npc Spawn Settings")]
            public NpcHorseSpawn npcHorseSpawn {
                get;
                set;
            }
            public class Settings {
                public Dictionary<string, List<int>> HorseItems {
                    get;
                    set;
                }
            }
            public class SpawnSettings {
                public float NavScanRange {
                    get;
                    set;
                }
                public bool CanKillSleepers {
                    get;
                    set;
                }
            }
            public class NpcHorseSpawn {
                public Dictionary<string, horseSpawns> HorseAndNpc {
                    get;
                    set;
                }
            }
            public Oxide.Core.VersionNumber Version {
                get;
                set;
            }
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            configData = Config.ReadObject<ConfigData>();
            if (configData.Version < Version) UpdateConfigValues();
            Config.WriteObject(configData, true);
        }
        protected override void LoadDefaultConfig() => configData = GetBaseConfig();
        private ConfigData GetBaseConfig() {
            return new ConfigData {
                settings = new ConfigData.Settings {
                    HorseItems = new Dictionary<string, List<int>> {
                        {
                            "item", new List<int> {
                                60528587, 1400460850
                            }
                        }
                        , {
                            "item2", new List<int> {
                                60528587, 1400460850
                            }
                        }
                    }
                }
                , spawnSettings = new ConfigData.SpawnSettings {
                    NavScanRange = 50f, CanKillSleepers = false
                }
                , npcHorseSpawn = new ConfigData.NpcHorseSpawn {
                    HorseAndNpc = new Dictionary<string, horseSpawns>()
                }
                , Version = Version
            }
            ;
        }
        protected override void SaveConfig() => Config.WriteObject(configData, true);
        private void UpdateConfigValues() {
            PrintWarning("Config update detected! Updating config values...");
            ConfigData baseConfig = GetBaseConfig();
            if (configData.Version < new VersionNumber(2, 0, 0)) configData = baseConfig;
            configData.Version = Version;
            PrintWarning("Config update completed!");
        }
        public class horseSpawns {
            public int TotalToSpawn;
            public float HorseHealth;
            public float NpcHealth;
            public float VisionRange;
            public bool KillHorseOnRiderDeath;
            public bool ClearHorseInventoryOnDeath;
            public List<string> KitsList;
            public List<string> NpcNames;
            public List<string> HorseItemsConfigs;
            public float speed;
            public bool CanWander;
            public float RomeRange;
            public bool UseDormant;
            public bool RadioChatter;
            public string WayPoint;
            public float WayPointRespawn;
            public List<string> TopologiesAllowed;
            public horseSpawns(int TotalToSpawn, float HorseHealth, float NpcHealth, float VisionRange, bool KillHorseOnRiderDeath, bool ClearHorseInventoryOnDeath, List<string> KitsList, List<string> NpcNames, List<string> HorseItemsConfigs, float speed, bool CanWander, float RomeRange, bool UseDormant, string WayPoint, float WayPointRespawn, List<string> TopologiesAllowed) {
                this.TotalToSpawn = TotalToSpawn;
                this.HorseHealth = HorseHealth;
                this.NpcHealth = NpcHealth;
                this.VisionRange = VisionRange;
                this.KillHorseOnRiderDeath = KillHorseOnRiderDeath;
                this.ClearHorseInventoryOnDeath = ClearHorseInventoryOnDeath;
                this.KitsList = KitsList;
                this.NpcNames = NpcNames;
                this.HorseItemsConfigs = HorseItemsConfigs;
                this.speed = speed;
                this.CanWander = CanWander;
                this.RomeRange = RomeRange;
                this.UseDormant = UseDormant;
                this.RadioChatter = true;
                this.WayPoint = WayPoint;
                this.WayPointRespawn = WayPointRespawn;
                this.TopologiesAllowed = TopologiesAllowed;
            }
        }
#endregion Config
        private void OnServerInitialized() {
            ins = this;
            if (configData.npcHorseSpawn.HorseAndNpc.Count <= 0) {
                configData.npcHorseSpawn.HorseAndNpc.Add("easy", new horseSpawns(10, 50, 20f, 30f, true, true, new List<string>(), new List<string>() {
                    "Cowboy Bill"
                }
                , new List<string>() {
                    "item", "item2"
                }
                , 5.0f, true, 20f, true, "", 0, new List<string>() {
                    "Field", "Summit", "Forest", "Forestside", "Monument", "Road", "Roadside", "Swamp", "Lakeside", "Plain", "Clutter", "Mainland"
                }
                ));
                configData.npcHorseSpawn.HorseAndNpc.Add("hard", new horseSpawns(10, 60, 30f, 30f, true, true, new List<string>(), new List<string>() {
                    "Cowboy Bob"
                }
                , new List<string>() {
                    "item", "item2"
                }
                , 5.0f, true, 20f, true, "", 0, new List<string>() {
                    "Field", "Summit", "Forest", "Forestside", "Monument", "Road", "Roadside", "Swamp", "Lakeside", "Plain", "Clutter", "Mainland"
                }
                ));
                SaveConfig();
            }
            foreach (var key in configData.npcHorseSpawn.HorseAndNpc) {
                TropSpawns.Add(key.Key, GenerateVecotrList(key.Value.TotalToSpawn * 10, key.Key));
            }
            BeginSpawning();
            timer.Every(60f, () => {
                if (totalTypes.Count > 0) {
                    foreach (var key in totalTypes.ToList()) {
                        if (key.Value.Count < configData.npcHorseSpawn.HorseAndNpc[key.Key].TotalToSpawn) {
                            if (SpawnRoutine2 == null) SpawnRoutine2 = ServerMgr.Instance.StartCoroutine(ins.startSpawn(key.Value.Count, key.Key));
                            break;
                        }
                    }
                }
            }
            );
        }
        private void Unload() {
            StopSpawning();
            rebooting = true;
            var Controller = UnityEngine.Object.FindObjectsOfType<horseBoxBehavior>();
            foreach (var gameObj in Controller) {
                UnityEngine.Object.Destroy(gameObj);
            }
            foreach (var HandR in HorseAndRider) {
                var rider = FindEntity(HandR.Value);
                if (rider != null) rider?.Kill();
                var horse = FindEntity(HandR.Key);
                if (horse != null) horse?.Kill();
            }
        }
        public BaseNetworkable FindEntity(ulong netID) {
            return BaseNetworkable.serverEntities.Find(new NetworkableId(netID));
        }
        private List<Vector3> GenerateVecotrList(int TotalSpawn, string configs) {
            List<Vector3> newTrop = new List<Vector3>();
            var success = 0;
            var size = ConVar.Server.worldsize / 2;
            for (var i = 0; i < TotalSpawn * 3; i++) {
                if (success > TotalSpawn) {
                    break;
                }
                var x = Core.Random.Range(-size, size);
                var z = Core.Random.Range(-size, size);
                Vector3 original = GetGround(new Vector3(x, 0, z));
                if (original == Vector3.zero) continue;
                var position = FindPointOnNavmesh(original);
                if (position != null && position is Vector3 && (Vector3)position != Vector3.zero) {
                    if (TerrainMeta.HeightMap.GetHeight((Vector3)position) > TerrainMeta.WaterMap.GetHeight((Vector3)position)) {
                        if (IsValidTopology((Vector3)position, configs)) {
                            newTrop.Add((Vector3)position);
                            success++;
                        }
                    }
                }
            }
            return newTrop;
        }
        //Thanks to PowerSpawn Plugin
        public bool IsValidTopology(Vector3 position, string configs) {
            if (configData.npcHorseSpawn.HorseAndNpc[configs].TopologiesAllowed != null && configData.npcHorseSpawn.HorseAndNpc[configs].TopologiesAllowed.Count > 0) {
                foreach (var topology in configData.npcHorseSpawn.HorseAndNpc[configs].TopologiesAllowed) if (TropToInt.ContainsKey(topology.ToLower()) && TerrainMeta.TopologyMap.GetTopology(position, (int)TropToInt[topology.ToLower()])) {
                    return true;
                }
                return false;
            }
            return true;
        }
        private Vector3 GetGround(Vector3 position) {
            if (position == Vector3.zero) return Vector3.zero;
            position.y = TerrainMeta.HeightMap.GetHeight(position);
            if (TerrainMeta.HeightMap.GetHeight(position) < TerrainMeta.WaterMap.GetHeight(position)) return Vector3.zero;
            if (position == Vector3.zero) return Vector3.zero;
            return position;
        }
        internal static Coroutine BeginSpawning() => SpawnRoutine2 = ServerMgr.Instance.StartCoroutine(ins.startSpawn(0));
        internal static void StopSpawning() {
            if (SpawnRoutine2 != null) ServerMgr.Instance.StopCoroutine(SpawnRoutine2);
            SpawnRoutine2 = null;
        }
        private IEnumerator startSpawn(int total, string theConfig = "") {
            if (theConfig != "") {
                while (total < configData.npcHorseSpawn.HorseAndNpc[theConfig].TotalToSpawn) {
                    Vector3 spawnPoint = TropSpawns[theConfig].GetRandom();
                    spawnHorseAndRider(configData.npcHorseSpawn.HorseAndNpc[theConfig], spawnPoint, theConfig);
                    yield return CoroutineEx.waitForSeconds(0.5f);
                    total++;
                }
            }
            else {
                foreach (var configs in configData.npcHorseSpawn.HorseAndNpc) {
                    total = 0;
                    yield return CoroutineEx.waitForSeconds(1.0f);
                    while (total < configs.Value.TotalToSpawn) {
                        Vector3 spawnPoint = TropSpawns[configs.Key].GetRandom();
                        spawnHorseAndRider(configData.npcHorseSpawn.HorseAndNpc[configs.Key], spawnPoint, configs.Key);
                        yield return CoroutineEx.waitForSeconds(0.5f);
                        total++;
                    }
                }
            }
            yield return CoroutineEx.waitForSeconds(1.0f);
            if (!ins.booted) {
                PrintWarning($"Spawned a total of {totalHorses} and failed to spawn {failed}");
                ins.booted = true;
                ins.totalHorses = 0;
                ins.failed = 0;
            }
            else {
                PrintWarning($"Spawned a total of {totalHorses} and failed to spawn {failed} Current Horses {HorseAndRider.Count}");
                ins.totalHorses = 0;
                ins.failed = 0;
            }
            StopSpawning();
        }
        private object OnNpcTarget(global : : HumanNPC npc, BaseEntity player) {
            if (npc?.GetMountedVehicle() != null) {
                if (player.IsNpc) return true;
                if (player != null && player is BasePlayer && (player as BasePlayer).InSafeZone()) return true;
                if (!configData.spawnSettings.CanKillSleepers && player != null && player is BasePlayer && (player as BasePlayer).IsSleeping()) return true;
            }
            return null;
        }
        [ChatCommand("horsetest")]
        private void cmdSpawn(BasePlayer player, string command, string[] args) {
            if (!player.IsAdmin) return;
            if (args.Length < 1) {
                SendReply(player, $"Usage: /horsetest <configName>");
                return;
            }
            if (!configData.npcHorseSpawn.HorseAndNpc.ContainsKey(args[0])) {
                SendReply(player, $"The config does not contain {args[0]}");
                return;
            }
            object point = FindPointOnNavmesh(player.transform.position, 10f);
            if (point is Vector3) spawnHorseAndRider(configData.npcHorseSpawn.HorseAndNpc[args[0]], (Vector3)point, args[0]);
        }
        private object OnNpcRadioChatter(ScientistNPC npc) {
            if (_allNpc.ContainsKey(npc.net.ID.Value) && _allNpc[npc.net.ID.Value]) return false;
            return null;
        }
        public void spawnHorseAndRider(horseSpawns theConfig, Vector3 success, string theConfigKey) {
            if (success != Vector3.zero) {
                BaseEntity horseBot = InstantiateEntity("assets/rust.ai/nextai/testridablehorse.prefab", (Vector3)success, Quaternion.Euler(Vector3.zero));
                horseBoxBehavior controller = horseBot.gameObject.AddComponent<horseBoxBehavior>();
                horseBot.enableSaving = false;
                (horseBot as BaseRidableAnimal).startHealth = theConfig.HorseHealth;
                (horseBot as BaseRidableAnimal).SetMaxHealth(theConfig.HorseHealth);
                (horseBot as BaseRidableAnimal).InitializeHealth(theConfig.HorseHealth, theConfig.HorseHealth);
                (horseBot as BaseRidableAnimal)._health = theConfig.HorseHealth;
                horseBot.Spawn();
                global : : HumanNPC horseNpc = InstantiateEntity("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_any.prefab", (Vector3)success, Quaternion.Euler(Vector3.zero)) as global : : HumanNPC;
                if (horseNpc == null) return;
                controller.Npc = horseNpc;
                horseNpc.enableSaving = false;
                horseNpc.startHealth = theConfig.NpcHealth;
                horseNpc.InitializeHealth(theConfig.NpcHealth, theConfig.NpcHealth);
                horseNpc._health = theConfig.NpcHealth;
                horseNpc.health = theConfig.NpcHealth;
                // horseNpc.sightRange = theConfig.VisionRange;
                horseNpc.Spawn();
                _allNpc.Add(horseNpc.net.ID.Value, theConfig.RadioChatter);
                HorseAndRider.Add(horseBot.net.ID.Value, horseNpc.net.ID.Value);
                (horseBot as BaseRidableAnimal).AttemptMount(horseNpc, false);
                if (totalTypes.ContainsKey(theConfigKey)) totalTypes[theConfigKey].Add(horseBot.net.ID.Value);
                else totalTypes.Add(theConfigKey, new List<ulong>() {
                    horseBot.net.ID.Value
                }
                );
                controller.netID = horseBot.net.ID.Value;
                controller.SpawnLocation = (Vector3)success;
                if (theConfig.KitsList.Count > 0) {
                    horseNpc.inventory.Strip();
                    string kitUse = theConfig.KitsList.GetRandom();
                    if (CheckExists(kitUse)) {
                        Kits.Call($"GiveKit", horseNpc, kitUse, false);
                    }
                }
                else {
                    horseNpc.inventory.Strip();
                    switch (UnityEngine.Random.Range(0, 7)) {
                        case 0 : ItemManager.CreateByName("hazmatsuit").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 1 : ItemManager.CreateByName("hazmatsuit_scientist_peacekeeper").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 2 : ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 3 : ItemManager.CreateByName("hazmatsuit").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 4 : ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 5 : ItemManager.CreateByName("hazmatsuit_scientist_peacekeeper").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 6 : ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        case 7 : ItemManager.CreateByName("hazmatsuit").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                        default : ItemManager.CreateByName("hazmatsuit_scientist").MoveToContainer(horseNpc.inventory.containerWear);
                        break;
                    }
                    switch (UnityEngine.Random.Range(0, 3)) {
                        case 0 : ItemManager.CreateByName("rifle.ak").MoveToContainer(horseNpc.inventory.containerBelt, 0);
                        break;
                        case 1 : ItemManager.CreateByName("smg.mp5").MoveToContainer(horseNpc.inventory.containerBelt, 0);
                        break;
                        case 2 : ItemManager.CreateByName("rifle.ak").MoveToContainer(horseNpc.inventory.containerBelt, 0);
                        break;
                        default : ItemManager.CreateByName("rifle.ak").MoveToContainer(horseNpc.inventory.containerBelt, 0);
                        break;
                    }
                }
                controller.SetupConfig(theConfig, theConfigKey);
                if (theConfig.NpcNames != null && theConfig.NpcNames.Count > 0) horseNpc.displayName = theConfig.NpcNames.GetRandom();
                if (theConfig != null && theConfig.HorseItemsConfigs != null && theConfig.HorseItemsConfigs.Count > 0) {
                    string rand = theConfig.HorseItemsConfigs.GetRandom();
                    if (configData.settings != null && configData.settings.HorseItems != null && configData.settings.HorseItems.ContainsKey(rand)) addHorseItems((horseBot as RidableHorse), configData.settings.HorseItems[rand]);
                    else PrintWarning($"HorseItems does not contain {rand}");
                }
                foreach (Item gun in horseNpc.inventory.containerBelt.itemList) {
                    AttackEntity attackEntity = gun.GetHeldEntity() as AttackEntity;
                    if (attackEntity != null && attackEntity is BaseProjectile && attackEntity.effectiveRange <= 1) {
                        attackEntity.effectiveRange = 15f;
                    }
                }
                totalHorses++;
            }
            else failed++;
        }
        private void addHorseItems(RidableHorse horse, List<int> itemList) {
            if (configData.settings.HorseItems.Count > 0) {
                foreach (int itemID in itemList.ToList()) {
                    var itemToCreate = ItemManager.FindItemDefinition(itemID);
                    if (itemToCreate != null) {
                        Item item = ItemManager.Create(itemToCreate, 1, 0);
                        if (!item.MoveToContainer(horse.inventory, 0, false)) {
                            item.Remove();
                            continue;
                        }
                    }
                }
                horse.EquipmentUpdate();
                horse.inventory.SetLocked(true);
            }
        }
        object CanMoveItem(Item item, PlayerInventory playerLoot, uint targetContainer, int targetSlot, int amount) {
            if (item != null && item.parent != null && item.parent.IsLocked()) return false;
            return null;
        }
        private bool CheckExists(string fileName) {
            if (Kits == null) return false;
            return ins.Kits.Call<bool>("isKit", fileName);
        }
        private BaseEntity InstantiateEntity(string type, Vector3 position, Quaternion rotation) {
            var gameObject = Facepunch.Instantiate.GameObject(GameManager.server.FindPrefab(type), position, rotation);
            gameObject.name = type;
            SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
            UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
            if (!gameObject.activeSelf) gameObject.SetActive(true);
            BaseEntity component = gameObject.GetComponent<BaseEntity>();
            return component;
        }
        private static NavMeshHit navmeshHit;
        private static RaycastHit raycastHit;
        private static Collider[] _buffer = new Collider[256];
        private const int WORLD_LAYER = 65536;
        internal static object FindPointOnNavmesh(Vector3 targetPosition, float maxDistance = 50f) {
            if (ins.configData.spawnSettings.NavScanRange > 0) maxDistance = ins.configData.spawnSettings.NavScanRange;
            for (int i = 0; i < 10; i++) {
                Vector3 position = i == 0 ? targetPosition : targetPosition + (UnityEngine.Random.onUnitSphere * maxDistance);
                if (NavMesh.SamplePosition(position, out navmeshHit, maxDistance, 1)) {
                    if (navmeshHit.mask != 1) continue;
                    if (IsInRockPrefab(navmeshHit.position)) continue;
                    if (IsNearWorldCollider(navmeshHit.position)) continue;
                    return navmeshHit.position;
                }
            }
            return null;
        }
        private static bool IsInRockPrefab(Vector3 position) {
            Physics.queriesHitBackfaces = true;
            bool isInRock = Physics.Raycast(position, Vector3.up, out raycastHit, 20f, WORLD_LAYER, QueryTriggerInteraction.Ignore) && blockedColliders.Any(s => raycastHit.collider?.gameObject?.name.ToLower().Contains(s) ?? false);
            Physics.queriesHitBackfaces = false;
            return isInRock;
        }
        private static bool IsNearWorldCollider(Vector3 position) {
            Physics.queriesHitBackfaces = true;
            int count = Physics.OverlapSphereNonAlloc(position, 2f, _buffer, WORLD_LAYER, QueryTriggerInteraction.Ignore);
            Physics.queriesHitBackfaces = false;
            int removed = 0;
            for (int i = 0; i < count; i++) {
                if (acceptedColliders.Any(s => _buffer[i].gameObject.name.Contains(s))) removed++;
            }
            return count - removed > 0;
        }
        private static readonly string[] acceptedColliders = new string[] {
            "road", "carpark", "range", "train_track", "runway", "_grounds", "concrete_slabs", "cave", "walkways"
        }
        ;
        private static readonly string[] blockedColliders = new string[] {
            "rock", "junk", "range", "invisible", "cliff", "prevent_movement", "formation_", "radiation"
        }
        ;
        public class horseBoxBehavior : FacepunchBehaviour {
            private BaseRidableAnimal horse {
                get;
                set;
            }
            public global : : HumanNPC Npc {
                get;
                set;
            }
            public JunkPile junkPile {
                get;
                set;
            }
            public Vector3 SpawnLocation {
                get;
                set;
            }
            public float RomeRange {
                get;
                set;
            }
            public BaseEntity player {
                get;
                set;
            }
            public bool canWander {
                get;
                set;
            }
            public float moveSpeed {
                get;
                set;
            }
            public float nextWanderTime {
                get;
                set;
            }
            private float lastTargetTime {
                get;
                set;
            }
            public Vector3 MoveVector {
                get;
                set;
            }
            public float allowedMoveTime {
                get;
                set;
            }
            public float findingCover {
                get;
                set;
            }
            private bool findCover {
                get;
                set;
            }
            public bool Active {
                get;
                set;
            }
            public ulong netID {
                get;
                set;
            }
            public bool killAi {
                get;
                set;
            }
            private Transform tr {
                get;
                set;
            }
            private InputState aiInputState;
            private NavMeshAgent agent {
                get;
                set;
            }
            private int mountTrys {
                get;
                set;
            }
            private bool isDestroying {
                get;
                set;
            }
            private List<Vector3> roamPosition {
                get;
                set;
            }
            private bool useDormant {
                get;
                set;
            }
            public List<float> waypointSpeed = new List<float>();
            public List<Vector3> waypoint = new List<Vector3>();
            public int currentPoint {
                get;
                set;
            }
            private bool usingWaypoints {
                get;
                set;
            }
            private bool hastarget {
                get;
                set;
            }
            private BaseAIBrain defaultBrain {
                get;
                set;
            }
            public horseSpawns theConfig {
                get;
                set;
            }
            public string theConfigKey {
                get;
                set;
            }
            public BaseEntity currentTarget {
                get;
                private set;
            }
            private void Awake() {
                horse = GetComponent<BaseRidableAnimal>();
                MoveVector = Vector3.zero;
                allowedMoveTime = Time.time;
                tr = horse.transform;
                agent = horse.gameObject.AddComponent<NavMeshAgent>();
                nextWanderTime = Time.time + 30;
                if (ins.debug) ins.NextTick(() => ins.PrintWarning("Spawning NpcHorse at: " + SpawnLocation.ToString()));
                ins.NextTick(() => {
                    if (Npc != null && Npc.Brain != null && Npc.Brain.Senses != null) {
                        Npc.Brain.Senses.Init(Npc, Npc.Brain, 5f, 50f, 60f, Npc.Brain.VisionCone, Npc.Brain.CheckVisionCone, Npc.Brain.CheckLOS, Npc.Brain.IgnoreNonVisionSneakers, Npc.Brain.ListenRange, Npc.Brain.HostileTargetsOnly, false, true, Npc.Brain.SenseTypes, Npc.Brain.RefreshKnownLOS);
                        Npc.Brain.Senses.ignoreSafeZonePlayers = true;
                    }
                    InvokeRepeating("GetBestTarget", 1, 2);
                }
                );
            }
            public void GetBestTarget() {
                if (Npc == null || horse == null || Npc.IsDestroyed || horse.IsDestroyed || Npc.Brain == null || Npc.Brain.Senses == null || Npc.Brain.Senses.Memory == null || Npc.Brain.Senses.Memory.Targets == null) return;
                currentTarget = Npc.GetBestTarget();
            }
            public void SetupConfig(horseSpawns theConfi, string theConfigKe) {
                theConfigKey = theConfigKe;
                theConfig = theConfi;
                useDormant = theConfi.UseDormant;
                moveSpeed = theConfi.speed;
                canWander = theConfi.CanWander;
                RomeRange = theConfi.RomeRange;
                ins.NextTick(() => {
                    if (Npc != null) defaultBrain = Npc.GetComponent<BaseAIBrain>();
                    if (horse != null) netID = horse.net.ID.Value;
                    if (Npc.Brain.Navigator != null) {
                        Npc.Brain.Navigator.CanNavigateMounted = false;
                        Npc.Brain.Navigator.CanUseNavMesh = false;
                    }
                    if (theConfi != null && !string.IsNullOrEmpty(theConfi.WayPoint)) {
                        var cwaypoints = Interface.Oxide.CallHook("GetWaypointsList", theConfi.WayPoint);
                        if (cwaypoints != null) {
                            foreach (var cwaypoint in (List<object>)cwaypoints) {
                                foreach (var pair in (Dictionary<Vector3, float>)cwaypoint) {
                                    if (waypoint.Count <= 0) {
                                        object newPoint = FindPointOnNavmesh(pair.Key, 5f);
                                        if (newPoint is Vector3) {
                                            SpawnLocation = (Vector3)newPoint;
                                            agent.Warp((Vector3)newPoint);
                                            horse.transform.position = (Vector3)newPoint;
                                            agent.enabled = true;
                                            agent.isStopped = false;
                                            destination(horse.transform.position);
                                        }
                                        else {
                                            SpawnLocation = pair.Key;
                                            horse.transform.position = pair.Key;
                                        }
                                    }
                                    horse.SendNetworkUpdate();
                                    waypoint.Add(pair.Key);
                                    waypointSpeed.Add(pair.Value);
                                }
                            }
                            canWander = false;
                            usingWaypoints = true;
                        }
                        else {
                            ins.PrintWarning($"Waypoint name {theConfi.WayPoint} not found.");
                            Destroy(this);
                            return;
                        }
                    }
                    else if (canWander) GenerateRoam();
                    Active = true;
                }
                );
            }
            private void GenerateRoam() {
                if (horse == null || horse.IsDestroyed || horse.transform == null) return;
                roamPosition = FindCoverPoint(horse.transform.position, RomeRange, 60.0f, horse.transform.position.y);
            }
            public void DoDebugMovementFoward(bool run = false) {
                tr.rotation = Quaternion.Lerp(tr.rotation, currentTarget.transform.rotation, 4f * Time.deltaTime);
                aiInputState = new InputState();
                if (run) aiInputState.current.buttons |= 128;
                aiInputState.current.buttons |= 2;
                horse.RiderInput(aiInputState, (BasePlayer)null);
            }
            public void Update() {
                if (!Active || isDestroying) return;
                if (horse == null || horse.IsDestroyed || horse.IsDead() || horse.IsDead() || Npc == null || Npc.IsDestroyed || Npc.IsDead()) {
                    Destroy(this);
                    return;
                }
                else if (!Npc.isMounted) {
                    mountTrys++;
                    if (mountTrys > 5) {
                        if (horse != null || !horse.IsDestroyed || !horse.IsDead()) horse?.Kill();
                        if (ins.debug) ins.PrintWarning("Npc failed to mount horse killing NpcHorse and rider");
                        return;
                    }
                    if (Vector3.Distance(horse.transform.position, Npc.transform.position) > 2f) Npc.transform.position = horse.transform.position;
                    horse.DismountAllPlayers();
                    (horse.children.FirstOrDefault(m => m.PrefabName.Contains("saddle")) as BaseMountable).MountPlayer(Npc);
                    //  horse.AttemptMount(Npc, false);
                    //   Npc.Mount(horse); // Need fix
                    return;
                }
                else if (mountTrys > 0) mountTrys = 0;
                if (currentTarget != null) {
                    hastarget = true;
                    lastTargetTime = Time.time + 180;
                    float distance = Vector3.Distance(horse.transform.position, currentTarget.transform.position);
                    if (!findCover && distance < 9) {
                        findCover = true;
                        ins.timer.Once(8f, () => {
                            findCover = false;
                        }
                        );
                    }
                    if (findCover) {
                        if (findingCover < Time.time) {
                            // object point = FindPointOnNavmesh(Npc.AttackTarget.transform.position, 20f);
                            Vector3 point = FindCoverPoint(currentTarget.transform.position, 20, 60.0f, currentTarget.transform.position.y).GetRandom();
                            if (point != Vector3.zero) {
                                destination(point, moveSpeed);
                            }
                            findingCover = Time.time + 3;
                        }
                    }
                    else if (agent.isOnNavMesh && distance < 13 && distance > 9) {
                        if (tr.rotation != Npc.transform.rotation) tr.rotation = Quaternion.Lerp(tr.rotation, Npc.transform.rotation, 4f * Time.deltaTime);
                        if (!agent.isStopped) agent.isStopped = true;
                    }
                    else if (allowedMoveTime < Time.time) {
                        allowedMoveTime = Time.time + 5;
                        if (agent.isOnNavMesh && Vector3.Distance(horse.transform.position, currentTarget.transform.position) > 13) destination(currentTarget.transform.position, moveSpeed);
                    }
                }
                else if (canWander && canWanderNow())  //Wander
                {
                    nextWanderTime = Time.time + UnityEngine.Random.Range(30, 60);
                    if (useDormant && Npc != null && Npc.IsDormant) return;
                    if (!agent.isOnNavMesh) return;
                    if (roamPosition != null && roamPosition.Count > 0) {
                        Vector3 point = roamPosition.GetRandom();
                        if (point != Vector3.zero) {
                            if (Npc != null) Npc.SetAimDirection(point - Npc.transform.position);
                            destination((Vector3)point, 1f);
                        }
                    }
                }
                else if (usingWaypoints) {
                    if (agent.isOnNavMesh && Vector3.Distance(horse.transform.position, waypoint[currentPoint]) < 0.5f) {
                        if (currentPoint >= waypoint.Count - 1) {
                            waypoint.Reverse();
                            waypointSpeed.Reverse();
                            currentPoint = 0;
                        }
                        currentPoint++;
                        destination((Vector3)waypoint[currentPoint], waypointSpeed[currentPoint] - 0.5f);
                        Npc.SetAimDirection(waypoint[currentPoint] - Npc.transform.position);
                    }
                    else if (hastarget) {
                        hastarget = false;
                        destination((Vector3)waypoint[currentPoint], waypointSpeed[currentPoint] - 0.5f);
                        Npc.SetAimDirection(waypoint[currentPoint] - Npc.transform.position);
                    }
                }
            }
            private bool canWanderNow() {
                if (canWander && Npc != null && nextWanderTime < Time.time && lastTargetTime < Time.time) return true;
                return false;
            }
            private void destination(Vector3 movePoint, float speed = 8f) {
                if (agent.isOnNavMesh) {
                    if (agent.isStopped) agent.isStopped = false;
                    if (agent.speed != speed) agent.speed = speed;
                    if (!isInWater(movePoint)) agent.SetDestination(movePoint);
                }
            }
            private bool isInWater(Vector3 point) {
                if (TerrainMeta.WaterMap.GetHeight(point) - TerrainMeta.HeightMap.GetHeight(point) > 0.6f) return true;
                return false;
            }
            public List<Vector3> FindCoverPoint(Vector3 center, float radius, float next, float y)  // Thanks to ArenaWallGenerator
            {
                List<Vector3> positions = new List<Vector3>();
                float degree = 0f;
                while (degree < 360) {
                    float angle = (float)(2 * Math.PI / 360) * degree;
                    float x = center.x + radius * (float)Math.Cos(angle);
                    float z = center.z + radius * (float)Math.Sin(angle);
                    Vector3 position = new Vector3(3.2009f, 2.639f, 0.2845f);
                    position = new Vector3(x, center.y, z);
                    if (position != Vector3.zero) positions.Add(position);
                    degree += next;
                }
                return positions;
            }
            internal void ClearContainer(ItemContainer container) {
                container.SetLocked(true);
                while (container.itemList.Count > 0) {
                    var item = container.itemList[0];
                    item.RemoveFromContainer();
                    item.Remove(0f);
                }
            }
            private void OnDestroy() {
                CancelInvoke("GetBestTarget");
                if (theConfig.ClearHorseInventoryOnDeath && horse != null && horse.inventory != null) {
                    ClearContainer(horse.inventory);
                    if (theConfig.ClearHorseInventoryOnDeath && !deathLocation.ContainsKey(horse.transform.position)) deathLocation.Add(horse.transform.position, true);
                }
                else if (horse != null && horse.inventory != null) horse.inventory.SetLocked(false);
                if (ins.totalTypes.ContainsKey(theConfigKey)) if (ins.totalTypes[theConfigKey].Contains(netID)) ins.totalTypes[theConfigKey].Remove(netID);
                if (ins.rebooting) {
                    if (Npc != null && !Npc.IsDestroyed) Npc.Kill();
                }
                else if (Npc != null && !Npc.IsDestroyed) Npc.Die();
                if (theConfig.KillHorseOnRiderDeath && !horse.IsDestroyed) {
                    if (theConfig.ClearHorseInventoryOnDeath && !deathLocation.ContainsKey(horse.transform.position)) deathLocation.Add(horse.transform.position, true);
                    horse.Die();
                }
                else if (horse != null && !horse.IsDestroyed) {
                    if (agent != null) UnityEngine.Object.Destroy(agent);
                    if (horse != null && !horse.IsDestroyed) {
                        horse.DismountAllPlayers();
                        horse.transform.position = horse.transform.position + new Vector3(0, -0.01f, 0);
                        if (theConfig.ClearHorseInventoryOnDeath && !deathLocation.ContainsKey(horse.transform.position)) deathLocation.Add(horse.transform.position, true);
                        horse.inventory.SetLocked(false);
                    }
                }
                if (ins.HorseAndRider.ContainsKey(netID)) ins.HorseAndRider.Remove(netID);
                if (!ins.rebooting && !string.IsNullOrEmpty(theConfig.WayPoint) && theConfig.WayPointRespawn > 0) respawnHorse(SpawnLocation, theConfig, theConfig.WayPointRespawn, theConfigKey);
            }
            public void OnKilled() {
                if (theConfig.ClearHorseInventoryOnDeath && horse != null) {
                    if (theConfig.ClearHorseInventoryOnDeath && !deathLocation.ContainsKey(horse.transform.position)) deathLocation.Add(horse.transform.position, true);
                }
            }
        }
        internal void ClearContainer(ItemContainer container) {
            container.SetLocked(true);
            while (container.itemList.Count > 0) {
                var item = container.itemList[0];
                item.RemoveFromContainer();
                item.Remove(0f);
            }
        }
        private void OnEntitySpawned(BaseNetworkable entity) {
            if (entity.name.Contains("horse.co")) {
                BaseCorpse corpse = entity as BaseCorpse;
                NextTick(() => {
                    if (corpse != null) {
                        foreach (var key in deathLocation.ToList()) {
                            if (Vector3.Distance(corpse.transform.position, key.Key) < 1.5f) {
                                LootableCorpse component = corpse.GetComponent<LootableCorpse>();
                                if (component != null) foreach (ItemContainer containers in component.containers) ClearContainer(containers);
                                deathLocation.Remove(key.Key);
                                break;
                            }
                        }
                    }
                }
                );
            }
        }
        public static void respawnHorse(Vector3 success, horseSpawns waypoints, float rTime, string theKey) {
            if (rTime > 0) ins.timer.Once(rTime, () => ins.spawnHorseAndRider(waypoints, success, theKey));
        }
        object OnEntityTakeDamage(global : : HumanNPC entity, HitInfo hitinfo) {
            if (entity == null || hitinfo == null || hitinfo.Initiator == null) return null;
            if (hitinfo.Initiator is global : : HumanNPC && (hitinfo.Initiator as global : : HumanNPC).GetMountedVehicle() != null) {
                return true;
            }
            if (entity.GetMountedVehicle() != null && entity.GetMountedVehicle() is BaseRidableAnimal && hitinfo.damageTypes != null) {
                hitinfo.damageTypes.ScaleAll(10f);
                return null;
            }
            return null;
        }
        object OnEntityTakeDamage(RidableHorse entity, HitInfo hitinfo) {
            if (hitinfo == null || hitinfo.Initiator == null) return null;
            if (hitinfo.Initiator is global : : HumanNPC) {
                global : : HumanNPC scientist = hitinfo.Initiator as global : : HumanNPC;
                if (scientist?.GetMountedVehicle() != 
// ... [Code preview truncated due to length. Full source in attached file] ...

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