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

FREE BotSpawn : 2.2.2 2.2.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using System;
using System.Linq;
using System.Reflection;
using System.Globalization;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Rust.Ai.HTN;
namespace Oxide.Plugins {
    [Info("BotSpawn", "Steenamaroo", "2.2.2", ResourceId = 15)]
    [Description("Spawn tailored AI with kits at monuments, custom locations, or randomly.")]
    class BotSpawn : RustPlugin {
        [PluginReference]
        Plugin Kits, CustomLoot, RustRewards;
        int no_of_AI;
        bool loaded;
        Single currentTime;
        static BotSpawn botSpawn;
        const string permAllowed = "botspawn.allowed";
        static System.Random random = new System.Random();
        int GetRand(int l, int h) => random.Next(l, h);
        public Dictionary<string, List<string>> KitList = new Dictionary<string, List<string>>();
        public Dictionary<string, List<string>> NamesList = new Dictionary<string, List<string>>();
        public Dictionary<string, PopInfo> popinfo = new Dictionary<string, PopInfo>();
        public class PopInfo {
            public int population;
            public int queued;
        }
        public Dictionary<ulong, Timer> weaponCheck = new Dictionary<ulong, Timer>();
        public static string Get(ulong v) => RandomUsernames.Get((int)(v % 2147483647uL));
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
        public Dictionary<string, List<Vector3>> spawnLists = new Dictionary<string, List<Vector3>>();
        public bool IsNight => currentTime > configData.Global.NightStartHour || currentTime < configData.Global.DayStartHour;
        Dictionary<ulong, string> editing = new Dictionary<ulong, string>();
        public static Timer aridTimer, temperateTimer, tundraTimer, arcticTimer;
        public Dictionary<string, Timer> timers = new Dictionary<string, Timer>() {
            {
                "BiomeArid", aridTimer
            }
            , {
                "BiomeTemperate", temperateTimer
            }
            , {
                "BiomeTundra", tundraTimer
            }
            , {
                "BiomeArctic", arcticTimer
            }
        }
        ;
        bool IsAuth(BasePlayer player) => player?.net?.connection?.authLevel == 2;
        public Dictionary<ulong, NPCPlayerApex> NPCPlayers = new Dictionary<ulong, NPCPlayerApex>();
        public Dictionary<string, DataProfile> AllProfiles = new Dictionary<string, DataProfile>();
        void OnServerInitialized() {
            timer.Once(1f, () => {
                botSpawn = this;
                currentTime = TOD_Sky.Instance.Cycle.Hour;
                timer.Repeat(2f, 0, () => currentTime = TOD_Sky.Instance.Cycle.Hour);
                CheckMonuments(false);
                LoadConfigVariables();
                storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"BotSpawn/{configData.DataPrefix}-CustomProfiles");
                defaultData = Interface.Oxide.DataFileSystem.ReadObject<DefaultData>($"BotSpawn/{configData.DataPrefix}-DefaultProfiles");
                spawnsData = Interface.Oxide.DataFileSystem.ReadObject<SpawnsData>($"BotSpawn/{configData.DataPrefix}-SpawnsData");
                var files = Interface.Oxide.DataFileSystem.GetFiles("BotSpawn");
                StoredData storedUpdate;
                UpdateData defaultUpdate;
                string name;
                foreach (var file in files) {
                    name = file.Substring(file.IndexOf("BotSpawn") + 9);
                    name = name.Substring(0, name.Length - 5);
                    if (file.Contains("-CustomProfiles")) {
                        storedUpdate = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"BotSpawn/{name}");
                        Interface.Oxide.DataFileSystem.WriteObject($"BotSpawn/{name}", storedUpdate);
                    }
                    if (file.Contains("-DefaultProfiles")) {
                        defaultUpdate = Interface.Oxide.DataFileSystem.ReadObject<UpdateData>($"BotSpawn/{name}");
                        Interface.Oxide.DataFileSystem.WriteObject($"BotSpawn/{name}", defaultUpdate);
                    }
                }
                SaveData();
                SetupProfiles();
                timer.Once(10, () => timer.Repeat(10, 0, () => AdjustPopulation()));
                foreach (BasePlayer player in UnityEngine.Object.FindObjectsOfType<BasePlayer>()) {
                    foreach (var comp in player?.GetComponents<Component>()) if (comp?.GetType()?.Name == "HumanPlayer") {
                        HumanNPCs.Add(player.userID);
                        break;
                    }
                }
                loaded = true;
            }
            );
        }
        void Init() {
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
                Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            }
            ;
            var filter = RustExtension.Filter.ToList();
            filter.Add("cover points");
            filter.Add("resulted in a conflict");
            RustExtension.Filter = filter.ToArray();
            no_of_AI = 0;
        }
        void Loaded() {
            ConVar.AI.npc_families_no_hurt = false;
            foreach (var entry in timers) spawnLists.Add(entry.Key, new List<Vector3>());
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(permAllowed, this);
        }
        void Unload() {
            foreach (var obj in RemoveObj.ToList()) UnityEngine.Object.DestroyImmediate(obj);
            var filter = RustExtension.Filter.ToList();
            filter.Remove("cover points");
            filter.Remove("resulted in a conflict");
            RustExtension.Filter = filter.ToArray();
            Wipe();
        }
        void Wipe() {
            foreach (var bot in NPCPlayers.ToDictionary(pair => pair.Key, pair => pair.Value).Where(bot => bot.Value != null)) NPCPlayers[bot.Key].Kill();
        }
#region BiomeSpawnsSetup
        void GenerateSpawnPoints(string name, int number, Timer myTimer, int biomeNo) {
            int getBiomeAttempts = 0;
            var spawnlist = spawnLists[name];
            int halfish = Convert.ToInt16((ConVar.Server.worldsize / 2) / 1.1f);
            var rand = UnityEngine.Random.insideUnitCircle * halfish;
            if (AllProfiles[name].Kit.Count > 0 && Kits == null) {
                PrintWarning(lang.GetMessage("nokits", this), name);
                return;
            }
            timers[name] = timer.Repeat(0.01f, 0, () => {
                bool finished = true;
                if (spawnlist.Count < number + 10) {
                    getBiomeAttempts++;
                    if (getBiomeAttempts > 200 && spawnlist.Count == 0) {
                        PrintWarning(lang.GetMessage("noSpawn", this), name);
                        timers[name].Destroy();
                        return;
                    }
                    rand = UnityEngine.Random.insideUnitCircle * halfish;
                    Vector3 randomSpot = new Vector3(rand.x, 0, rand.y);
                    finished = false;
                    if (TerrainMeta.BiomeMap.GetBiome(randomSpot, biomeNo) > 0.5f) {
                        var point = CalculateGroundPos(new Vector3(randomSpot.x, 200, randomSpot.z));
                        if (point != Vector3.zero) spawnlist.Add(CalculateGroundPos(new Vector3(randomSpot.x, 200, randomSpot.z)));
                        ;
                    }
                }
                if (finished) {
                    int i = 0;
                    var target = TargetAmount(AllProfiles[name]);
                    if (target > 0) {
                        int amount = CanRespawn(name, target, false);
                        if (amount > 0) {
                            timer.Repeat(2, amount, () => {
                                if (CanRespawn(name, 1, true) == 1) {
                                    SpawnBots(name, AllProfiles[name], "biome", null, spawnlist[i], -1, true);
                                    i++;
                                }
                            }
                            );
                        }
                    }
                    timers[name].Destroy();
                }
            }
            );
        }
        public bool HasNav(Vector3 pos) {
            NavMeshHit navMeshHit;
            return NavMesh.SamplePosition(pos, out navMeshHit, 2, 1);
        }
        public static Vector3 CalculateGroundPos(Vector3 pos) {
            pos.y = TerrainMeta.HeightMap.GetHeight(pos);
            NavMeshHit navMeshHit;
            if (!NavMesh.SamplePosition(pos, out navMeshHit, 2, 1)) pos = Vector3.zero;
            else if (WaterLevel.GetWaterDepth(pos, true) > 0) pos = Vector3.zero;
            else if (Physics.RaycastAll(navMeshHit.position + new Vector3(0, 100, 0), Vector3.down, 99f, 1235288065).Any()) pos = Vector3.zero;
            else pos = navMeshHit.position;
            return pos;
        }
        Vector3 TryGetSpawn(Vector3 pos, int radius) {
            int attempts = 0;
            var spawnPoint = Vector3.zero;
            Vector2 rand;
            while (attempts < 200 && spawnPoint == Vector3.zero) {
                attempts++;
                rand = UnityEngine.Random.insideUnitCircle * radius;
                spawnPoint = CalculateGroundPos(pos + new Vector3(rand.x, 0, rand.y));
                if (spawnPoint != Vector3.zero) return spawnPoint;
            }
            return spawnPoint;
        }
        int GetNextSpawn(string name, DataProfile profile) {
            if (profile.UseCustomSpawns && spawnsData.CustomSpawnLocations[name].Count > 0) {
                if (availableStatSpawns[name].Count == 0) return -1;
                int spawnnum = availableStatSpawns[name][random.Next(availableStatSpawns[name].Count())];
                availableStatSpawns[name].Remove(spawnnum);
                return spawnnum;
            }
            return -1;
        }
#endregion
#region population
        void AdjustPop(string profile, int num) => popinfo[profile].population += num;
        void AdjustQueue(string profile, int num) {
            popinfo[profile].queued += num;
            //catch, not a fix
            if (popinfo[profile].queued < 0) popinfo[profile].queued = 0;
        }
        int TargetAmount(DataProfile profile) => IsNight ? profile.Night_Time_Spawn_Amount : profile.Day_Time_Spawn_Amount;
        int CanRespawn(string name, int amount, bool second) {
            int response = TargetAmount(AllProfiles[name]) - popinfo[name].population;
            if (!second) response += popinfo[name].queued;
            if (response > 0) {
                if (!second) AdjustQueue(name, Mathf.Min(amount, response));
                return Mathf.Min(amount, response);
            }
            else if (second) {
                AdjustQueue(name, -1);
            }
            return 0;
        }
        Dictionary<string, List<int>> availableStatSpawns = new Dictionary<string, List<int>>();
        void AdjustPopulation() {
            foreach (var profile in AllProfiles.Where(x => x.Value.AutoSpawn == true && x.Key != "AirDrop" && x.Key != "HackableLockedCrate")) {
                int targetAmount = TargetAmount(profile.Value);
                var current = popinfo[profile.Key].population + popinfo[profile.Key].queued;
                AdjustQueue(profile.Key, 0);
                if (current < targetAmount) {
                    if (targetAmount == 0) continue;
                    popinfo[profile.Key].queued += targetAmount - current;
                    timer.Repeat(1f, targetAmount - current, () => {
                        if (profile.Value.UseCustomSpawns && spawnsData.CustomSpawnLocations.ContainsKey(profile.Key)) {
                            int spawnnum = 0, num = spawnsData.CustomSpawnLocations[profile.Key].Count;
                            if (num > 0) {
                                spawnnum = GetNextSpawn(profile.Key, profile.Value);
                                if (spawnnum == -1) {
                                    Puts("ADJUSTPOP FAILING");
                                    return;
                                }
                                SpawnBots(profile.Key, AllProfiles[profile.Key], null, null, new Vector3(), spawnnum, false);
                                if (profile.Value.Announce_Spawn && profile.Value.Announcement_Text != String.Empty) PrintToChat(profile.Value.Announcement_Text);
                            }
                        }
                        else {
                            if (timers.ContainsKey(profile.Key)) {
                                if (spawnLists[profile.Key].Count > 0) SpawnBots(profile.Key, AllProfiles[profile.Key], "biome", null, spawnLists[profile.Key][random.Next(spawnLists[profile.Key].Count)], -1, false);
                            }
                            else {
                                SpawnBots(profile.Key, AllProfiles[profile.Key], null, null, new Vector3(), -1, false);
                                if (profile.Value.Announce_Spawn && profile.Value.Announcement_Text != String.Empty) PrintToChat(profile.Value.Announcement_Text);
                            }
                        }
                    }
                    );
                    continue;
                }
                else {
                    foreach (var npc in NPCPlayers.ToList()) {
                        var bData = npc.Value.GetComponent<BotData>();
                        if (bData.monumentName == profile.Key && bData.respawn) {
                            if (popinfo[profile.Key].population > targetAmount) {
                                DontRespawn.Add(npc.Key);
                                npc.Value.Kill();
                            }
                            if (configData.Global.Staggered_Despawn) break;
                        }
                    }
                }
            }
        }
#endregion
        List<ulong> DontRespawn = new List<ulong>();
#region BotSetup
        void DeployNpcs(Vector3 location, string name, DataProfile profile, string group, int num) => SpawnBots(name, profile, "Attack", group, location, num, true);
        void SpawnBots(string name, DataProfile zone, string type, string group, Vector3 location, int spawnNum, bool initial) {
            bool respawn = type != "Attack" && type != "AirDrop" && type != "HackableLockedCrate";
            var pos = zone.Location;
            var finalPoint = Vector3.zero;
            bool stationary = zone.Stationary;
            float rot = 0;
            if (location == Vector3.zero && type != "AirDrop" && type != "HackableLockedCrate" && zone.UseCustomSpawns && spawnsData.CustomSpawnLocations[name].Count > 0) {
                var customLoc = spawnNum == -1 ? spawnsData.CustomSpawnLocations[name][random.Next(spawnsData.CustomSpawnLocations[name].Count)] : spawnsData.CustomSpawnLocations[name][spawnNum];
                Vector3 loc = s2v(customLoc);
                rot = s2r(customLoc);
                var l = mons.ContainsKey(zone.Parent_Monument) ? mons[zone.Parent_Monument].transform : mons.ContainsKey(name) ? mons[name].transform : null;
                if (l != null) finalPoint = l.TransformPoint(loc);
                if (!HasNav(finalPoint) && !zone.Stationary) {
                    PrintWarning(lang.GetMessage("noNav", this), name, spawnsData.CustomSpawnLocations[name].IndexOf(customLoc)+1);
                    return;
                }
            }
            else stationary = false;
            if (finalPoint == Vector3.zero) {
                if (location != Vector3.zero) pos = location;
                if (type != "biome") finalPoint = TryGetSpawn(pos, zone.Radius);
                else finalPoint = location;
                if (finalPoint == Vector3.zero) {
                    if (initial) Puts($"Can't get spawn point at {name}.Skipping one npc.");
                    AdjustQueue(name, -1);
                    return;
                }
            }
            if (zone.Chute && !stationary) {
                var rand = UnityEngine.Random.insideUnitCircle * zone.Radius;
                finalPoint = type == "AirDrop" ? pos + new Vector3(rand.x, -40, rand.y) : new Vector3(finalPoint.x, 200, finalPoint.z);
            }
            NPCPlayer entity = (NPCPlayer)InstantiateSci(finalPoint, new Quaternion(), zone.Murderer);
            var npc = entity.GetComponent<NPCPlayerApex>();
            npc.Spawn();
            NextTick(() => {
                if (npc == null || npc.IsDestroyed || npc.IsDead()) {
                    if (respawn) AdjustQueue(name, -1);
                    if (spawnNum != -1 && respawn) availableStatSpawns[name].Add(spawnNum);
                    return;
                }
                if (!NPCPlayers.ContainsKey(npc.userID)) NPCPlayers.Add(npc.userID, npc);
                else {
                    npc.Kill();
                    if (respawn) AdjustQueue(name, -1);
                    if (spawnNum != -1 && respawn) availableStatSpawns[name].Add(spawnNum);
                    return;
                }
                npc.EnablePlayerCollider();
                timer.Once(1f, () => {
                    if (npc != null) {
                        var n = mons.ContainsKey(zone.Parent_Monument) ? mons[zone.Parent_Monument].transform : mons.ContainsKey(name) ? mons[name].transform : null;
                        if (n != null) {
                            npc.transform.rotation = Quaternion.Euler(0, n.transform.eulerAngles.y + rot, 0);
                            npc.SetFact(NPCPlayerApex.Facts.IsAggro, 0, false, false);
                        }
                    }
                }
                );
                if (zone.Murderer) {
                    var suit = ItemManager.CreateByName("scarecrow.suit", 1, 0);
                    var eyes = ItemManager.CreateByName("gloweyes", 1, 0);
                    if (!suit.MoveToContainer(npc.inventory.containerWear)) suit.Remove();
                    if (!eyes.MoveToContainer(npc.inventory.containerWear)) eyes.Remove();
                }
                var bData = npc.gameObject.AddComponent<BotData>();
                bData.stationary = stationary;
                string kit = string.Empty;
                string botname = string.Empty;
                if (spawnNum != -1 && respawn) bData.CustomSpawnNum = spawnNum;
                if (configData.Global.Kits_In_Order) {
                    if (KitList[name].Count == 0) KitList[name] = zone.Kit.ToList();
                    if (KitList[name].Count > 0) {
                        kit = KitList[name][0];
                        KitList[name].RemoveAt(0);
                    }
                    if (NamesList[name].Count == 0) NamesList[name] = zone.BotNames.ToList();
                    if (NamesList[name].Count > 0) {
                        botname = NamesList[name][0];
                        NamesList[name].RemoveAt(0);
                    }
                }
                else {
                    if (zone.Kit.Count > 0) kit = zone.Kit[random.Next(zone.Kit.Count)];
                    if (zone.BotNames.Count > 0) botname = zone.BotNames[random.Next(zone.BotNames.Count)];
                }
                bData.monumentName = name;
                no_of_AI++;
                bData.respawn = true;
                bData.profile = zone.Clone();
                bData.group = group ?? null;
                bData.spawnPoint = finalPoint;
                bData.biome = type == "biome";
                npc.startHealth = zone.BotHealth;
                npc.InitializeHealth(zone.BotHealth, zone.BotHealth);
                npc.CommunicationRadius = 0;
                npc.AiContext.Human.NextToolSwitchTime = Time.realtimeSinceStartup * 10;
                npc.AiContext.Human.NextWeaponSwitchTime = Time.realtimeSinceStartup * 10;
                if (zone.Chute && !stationary) AddChute(npc, finalPoint);
                SetName(zone, npc, botname);
                GiveKit(npc, zone, kit);
                npc.clothingMoveSpeedReduction = -zone.Running_Speed_Boost;
                SortWeapons(npc);
                int suicInt = random.Next(zone.Suicide_Timer, zone.Suicide_Timer + 10);
                if (!respawn) {
                    bData.respawn = false;
                    RunSuicide(npc, suicInt);
                }
                else {
                    AdjustPop(name, 1);
                    AdjustQueue(name, -1);
                }
                if (zone.Disable_Radio) npc.RadioEffect = new GameObjectRef();
                ToggleAggro(npc, 0, zone.Aggro_Range);
                npc.Stats.DeaggroChaseTime = 10;
                npc.Stats.Defensiveness = 1;
            }
            );
        }
        BaseEntity InstantiateSci(Vector3 position, Quaternion rotation, bool murd) {
            string type = murd ? "murderer" : "scientist";
            string prefabname = $"assets/prefabs/npc/{type}/{type}.prefab";
            GameObject gameObject = Instantiate.GameObject(GameManager.server.FindPrefab(prefabname), position, rotation);
            gameObject.name = prefabname;
            SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
            if (gameObject.GetComponent<Spawnable>()) UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
            if (!gameObject.activeSelf) gameObject.SetActive(true);
            BaseEntity component = gameObject.GetComponent<BaseEntity>();
            return component;
        }
        void AddChute(NPCPlayerApex npc, Vector3 newPos) {
            float wind = random.Next(0, Mathf.Min(100, configData.Global.Max_Chute_Wind_Speed)) / 40f;
            float fall = random.Next(60, Mathf.Min(100, configData.Global.Max_Chute_Fall_Speed) + 60) / 20f;
            var rb = npc.gameObject.GetComponent<Rigidbody>();
            rb.isKinematic = false;
            rb.useGravity = false;
            rb.drag = 0f;
            npc.gameObject.layer = 0;
            //prevent_build layer fix
            var fwd = npc.transform.forward;
            rb.velocity = new Vector3(fwd.x * wind, 0, fwd.z * wind) - new Vector3(0, fall, 0);
            var col = npc.gameObject.AddComponent<BoxCollider>();
            col.size = new Vector3(1, 1f, 1);
            //feet above ground
            var Chute = GameManager.server.CreateEntity("assets/prefabs/misc/parachute/parachute.prefab", newPos, Quaternion.Euler(0, 0, 0));
            Chute.gameObject.Identity();
            Chute.SetParent(npc);
            Chute.transform.localPosition += new Vector3(0, 1.3f, 0);
            Chute.Spawn();
        }
        void SetName(DataProfile zone, NPCPlayerApex npc, string name) {
            if (name == String.Empty) {
                npc.displayName = Get(npc.userID);
                npc.displayName = char.ToUpper(npc.displayName[0]) + npc.displayName.Substring(1);
            }
            else npc.displayName = name;
            if (zone.BotNamePrefix != String.Empty) npc.displayName = zone.BotNamePrefix + " " + npc.displayName;
            if (npc is Scientist) (npc as Scientist).LootPanelName = npc.displayName;
        }
        void GiveKit(NPCPlayerApex npc, DataProfile zone, string kit) {
            if (npc == null || npc.inventory == null) return;
            var bData = npc.GetComponent<BotData>();
            string type = zone.Murderer ? "Murderer" : "Scientist";
            if (kit != string.Empty) {
                object checkKit = Kits?.CallHook("GetKitInfo", kit, true);
                if (checkKit == null) {
                    PrintWarning($"Kit {kit} does not exist - Spawning default {type}.");
                }
                else {
                    bool weaponInBelt = false;
                    JObject kitContents = checkKit as JObject;
                    if (kitContents != null) {
                        JArray items = kitContents["items"] as JArray;
                        foreach (var weap in items) {
                            JObject item = weap as JObject;
                            if (item["container"].ToString() == "belt") weaponInBelt = true;
                        }
                    }
                    if (!weaponInBelt) {
                        PrintWarning($"Kit {kit} has no items in belt - Spawning default {type}.");
                    }
                    else {
                        if (bData.profile.Keep_Default_Loadout == false) npc.inventory.Strip();
                        Kits?.Call($"GiveKit", npc, kit, true);
                    }
                }
            }
        }
        void SortWeapons(NPCPlayerApex npc) {
            if (npc == null) return;
            var bData = npc.GetComponent<BotData>();
            ItemDefinition fuel = ItemManager.FindItemDefinition("lowgradefuel");
            foreach (var attire in npc.inventory.containerWear.itemList) if (attire.info.shortname.Equals("hat.miner") || attire.info.shortname.Equals("hat.candle")) {
                bData.hasHeadLamp = true;
                Item newItem = ItemManager.Create(fuel, 1);
                attire.contents.Clear();
                if (!newItem.MoveToContainer(attire.contents)) newItem.Remove();
                else {
                    npc.SendNetworkUpdateImmediate();
                    npc.inventory.ServerUpdate(0f);
                }
            }
            foreach (Item item in npc.inventory.containerBelt.itemList) {
                var held = item.GetHeldEntity();
                if (held != null && held as HeldEntity != null) {
                    if (held is FlameThrower || held.name.Contains("launcher")) continue;
                    if (held as BaseMelee != null || held as TorchWeapon != null) {
                        bData.Weapons[1].Add(item);
                        bData.Weapons[0].Add(item);
                    }
                    else if (held as BaseProjectile != null) {
                        bData.Weapons[0].Add(item);
                        if (held.name.Contains("m92") || held.name.Contains("pistol") || held.name.Contains("python") || held.name.Contains("waterpipe")) bData.Weapons[2].Add(item);
                        else if (held.name.Contains("bolt") || held.name.Contains("l96")) bData.Weapons[4].Add(item);
                        else bData.Weapons[3].Add(item);
                    }
                }
            }
            if ((npc is Scientist && (bData.Weapons[0].Count == 0 || (bData.Weapons[0].Count == bData.Weapons[1].Count))) || npc is NPCMurderer && bData.Weapons[0].Count == 0) {
                PrintWarning(lang.GetMessage("noWeapon", this), bData.monumentName);
                bData.noweapon = true;
                return;
            }
            npc.CancelInvoke(npc.EquipTest);
        }
        void RunSuicide(NPCPlayerApex npc, int suicInt) {
            if (!NPCPlayers.ContainsKey(npc.userID)) return;
            timer.Once(suicInt, () => {
                if (npc == null) return;
                if (npc.AttackTarget != null && Vector3.Distance(npc.transform.position, npc.AttackTarget.transform.position) < 10 && npc.GetNavAgent.isOnNavMesh) {
                    var position = npc.AttackTarget.transform.position;
                    npc.svActiveItemID = 0;
                    npc.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                    npc.inventory.UpdatedVisibleHolsteredItems();
                    timer.Repeat(0.05f, 100, () => {
                        if (npc == null) return;
                        npc.SetDestination(position);
                    }
                    );
                }
                timer.Once(4, () => {
                    if (npc == null) return;
                    if (configData.Global.Suicide_Boom) Effect.server.Run("assets/prefabs/weapons/rocketlauncher/effects/rocket_explosion.prefab", npc.transform.position);
                    HitInfo nullHit = new HitInfo();
                    nullHit.damageTypes.Add(Rust.DamageType.Suicide, 10000);
                    npc.IsInvinsible = false;
                    npc.Die(nullHit);
                }
                );
            }
            );
        }
#endregion
        static BasePlayer FindPlayerByName(string name) {
            BasePlayer result = null;
            foreach (BasePlayer current in BasePlayer.activePlayerList) {
                if (current.displayName.Equals(name, StringComparison.OrdinalIgnoreCase) || current.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase) || current.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase)) result = current;
            }
            return result;
        }
#region Hooks
        object OnNpcKits(ulong userID) {
            return NPCPlayers.ContainsKey(userID) ? true : (object)null;
        }
        private object CanBeTargeted(BaseCombatEntity player, BaseEntity entity) {
            NPCPlayer npcPlayer = player as NPCPlayer;
            return (npcPlayer != null && NPCPlayers.ContainsKey(npcPlayer.userID) && configData.Global.Turret_Safe) ? false : (object)null;
        }
        private object CanBradleyApcTarget(BradleyAPC bradley, BaseEntity target) {
            NPCPlayer npcPlayer = target as NPCPlayer;
            return (npcPlayer != null && NPCPlayers.ContainsKey(npcPlayer.userID) && configData.Global.APC_Safe) ? false : (object)null;
        }
        object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            var botMelee = info?.Initiator as BaseMelee;
            bool melee = false;
            if (botMelee != null) {
                melee = true;
                info.Initiator = botMelee.GetOwnerPlayer();
            }
            NPCPlayerApex bot = entity as NPCPlayerApex;
            BotData bData;
            //If victim is one of mine
            if (bot != null && NPCPlayers.ContainsKey(bot.userID)) {
                if (configData.Global.APC_Safe && info?.Initiator is BradleyAPC) return true;
                var attackPlayer = info?.Initiator as BasePlayer;
                bData = bot.GetComponent<BotData>();
                if (configData.Global.Pve_Safe) {
                    if (info.Initiator?.ToString() == null && info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Bullet) return true;
                    //new autoturrets
                    if (info.Initiator?.ToString() == null || info.Initiator.ToString().Contains("cactus") || info.Initiator.ToString().Contains("barricade")) {
                        info.damageTypes.ScaleAll(0);
                        return true;
                    }
                }
                if (attackPlayer != null) {
                    if (NPCPlayers.ContainsKey(attackPlayer.userID)) //and attacker is one of mine
                    if (attackPlayer.GetComponent<BotData>().monumentName == bData.monumentName) return true;
                    //wont attack their own
                    if (configData.Global.PeaceKeepers_Ignore_Melee) {
                        if (bData.profile.Peace_Keeper && (info.Weapon is BaseMelee || info.Weapon is TorchWeapon)) //prevent melee farming with peacekeeper on
                        {
                            info.damageTypes.ScaleAll(0);
                            return true;
                        }
                    }
                    if (info != null && bData.profile.Die_Instantly_From_Headshot && info.isHeadshot) {
                        var weap = info?.Weapon?.ShortPrefabName;
                        var weaps = bData.profile.Instant_Death_From_Headshot_Allowed_Weapons;
                        if (weaps.Count == 0 || (weap != null && weaps.Contains(weap))) {
                            info.damageTypes.Set(0, bot.health);
                            return null;
                        }
                    }
                    if (Vector3.Distance(attackPlayer.transform.position, bot.transform.position) > bot.Stats.AggressionRange) {
                        if (bot.Stats.AggressionRange < 400) {
                            bot.Stats.AggressionRange += 400;
                            bot.Stats.DeaggroRange += 400;
                        }
                        ForceMemory(bot, attackPlayer);
                        timer.Repeat(1f, 20, () => {
                            if (bot != null) {
                                bot.RandomMove();
                                if (bot.AttackTarget != null && bot.AttackTarget.IsVisible(bot.eyes.position, (bot.AttackTarget as BasePlayer).eyes.position, 400)) Rust.Ai.HumanAttackOperator.AttackEnemy(bot.AiContext, Rust.Ai.AttackOperator.AttackType.LongRange);
                            }
                        }
                        );
                        timer.Once(20, () => {
                            if (bot == null) return;
                            ToggleAggro(bot, 0, bData.profile.Aggro_Range);
                        }
                        );
                    }
                    bot.AttackTarget = attackPlayer;
                    bot.lastAttacker = attackPlayer;
                    bData.goingHome = false;
                }
            }
            NPCPlayerApex attackNPC = info?.Initiator as NPCPlayerApex;
            //if attacker is one of mine
            if (attackNPC != null && entity is BasePlayer && NPCPlayers.ContainsKey(attackNPC.userID)) {
                bData = attackNPC.GetComponent<BotData>();
                float rand = GetRand(1, 101);
                float distance = Vector3.Distance(info.Initiator.transform.position, entity.transform.position);
                float newAccuracy = bData.profile.Bot_Accuracy_Percent;
                float newDamage = bData.profile.Bot_Damage_Percent / 100f;
                if (distance > 100f) {
                    newAccuracy = bData.profile.Bot_Accuracy_Percent / (distance / 100f);
                    newDamage = newDamage / (distance / 100f);
                }
                if (!melee && newAccuracy < rand) return true;
                info.damageTypes.ScaleAll(newDamage);
            }
            return null;
        }
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (player == null) return;
            if (HumanNPCs.Contains(player.userID)) HumanNPCs.Remove(player.userID);
            NPCPlayerApex npc = player as NPCPlayerApex;
            if (npc != null) OnEntityKill(npc, info);
        }
        List<ulong> CrateIDs = new List<ulong>();
        void OnEntityKill(NPCPlayerApex npc, HitInfo info) {
            if (npc?.userID != null && NPCPlayers.ContainsKey(npc.userID) && !botInventories.ContainsKey(npc.userID)) {
                var bData = npc.GetComponent<BotData>();
                if (bData == null) return;
                if (!AllProfiles.ContainsKey(bData.monumentName)) return;
                //void OnBotSpawnNpcKilled(string ProfileName, Vector3 position, bool RespawningProfile, bool KilledByBotSpawn)
                Interface.Oxide.CallHook("OnBotSpawnNpcKilled", bData.monumentName, npc.transform.position, bData.respawn, DontRespawn.Contains(npc.userID));
                if (bData.respawn) AdjustPop(bData.monumentName, -1);
                var pos = npc.transform.position;
                if (info?.InitiatorPlayer != null) {
                    if (bData.profile.RustRewardsValue > 0) {
                        var weapon = info?.Weapon?.GetItem()?.info?.shortname ?? info?.WeaponPrefab?.ShortPrefabName;
                        RustRewards?.Call("GiveRustReward", info.InitiatorPlayer, 0, bData.profile.RustRewardsValue, npc, weapon, Vector3.Distance(info.InitiatorPlayer.transform.position, npc.transform.position), null);
                    }
                    if (bData.profile.Spawn_Hackable_Death_Crate_Percent > GetRand(1, 101) && npc.WaterFactor() < 0.1f) {
                        timer.Once(2f, () => {
                            var Crate = GameManager.server.CreateEntity("assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab", pos + new Vector3(1, 2, 0), Quaternion.Euler(0, 0, 0));
                            Crate.Spawn();
                            CrateIDs.Add(Crate.net.ID);
                            (Crate as HackableLockedCrate).hackSeconds = HackableLockedCrate.requiredHackSeconds - bData.profile.Death_Crate_LockDuration;
                            timer.Once(1.4f, () => {
                                if (Crate == null) return;
                                if (CustomLoot && bData.profile.Death_Crate_CustomLoot_Profile != string.Empty) {
                                    var container = Crate?.GetComponent<StorageContainer>();
                                    if (container != null) {
                                        container.inventory.capacity = 36;
                                        container.onlyAcceptCategory = ItemCategory.All;
                                        container.SendNetworkUpdateImmediate();
                                        container.inventory.Clear();
                                        List<Item> loot = (List<Item>)CustomLoot?.Call("MakeLoot", bData.profile.Death_Crate_CustomLoot_Profile);
                                        if (loot != null) foreach (var item in loot) if (!item.MoveToContainer(container.inventory, -1, true)) item.Remove();
                                    }
                                }
                            }
                            );
                        }
                        );
                    }
                }
                Item activeItem = npc.GetActiveItem();
                if (bData.profile.Weapon_Drop_Percent >= GetRand(1, 101) && activeItem != null) {
                    var numb = GetRand(Mathf.Min(bData.profile.Min_Weapon_Drop_Condition_Percent, bData.profile.Max_Weapon_Drop_Condition_Percent), bData.profile.Max_Weapon_Drop_Condition_Percent);
                    numb = Convert.ToInt16((numb / 100f) * activeItem.maxCondition);
                    activeItem.condition = numb;
                    activeItem.Drop(npc.eyes.position, new Vector3(), new Quaternion());
                    npc.svActiveItemID = 0;
                    npc.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                }
                ItemContainer[] source = {
                    npc.inventory.containerMain, npc.inventory.containerWear, npc.inventory.containerBelt
                }
                ;
                Inv botInv = new Inv() {
                    profile = bData.profile
                }
                ;
                botInventories.Add(npc.userID, botInv);
                for (int i = 0; i < source.Length; i++) foreach (var item in source[i].itemList) botInv.inventory[i].Add(new InvContents {
                    ID = item.info.itemid, amount = item.amount, skinID = item.skin,
                }
                );
                if (bData.profile.Disable_Radio == true) npc.DeathEffect = new GameObjectRef();
                DeadNPCPlayerIds.Add(npc.userID);
                no_of_AI--;
                if (bData.respawn == false) return;
                if (bData.biome && spawnLists.ContainsKey(bData.monumentName)) {
                    List<Vector3> spawnList = new List<Vector3>();
                    spawnList = spawnLists[bData.monumentName];
                    int spawnPos = random.Next(spawnList.Count);
                    if (CanRespawn(bData.monumentName, 1, false) == 1) {
                        timer.Once(bData.profile.Respawn_Timer, () => {
                            if (AllProfiles.ContainsKey(bData.monumentName)) {
                                if (CanRespawn(bData.monumentName, 1, true) == 1) {
                                    SpawnBots(bData.monumentName, AllProfiles[bData.monumentName], "biome", null, spawnList[spawnPos], -1, false);
                                    if (bData.profile.Announce_Spawn && bData.profile.Announcement_Text != String.Empty) PrintToChat(bData.profile.Announcement_Text);
                                }
                            }
                        }
                        );
                    }
                    return;
                }
                int num = spawnsData.CustomSpawnLocations[bData.monumentName].Count;
                if (!DontRespawn.Contains(npc.userID) && CanRespawn(bData.monumentName, 1, false) == 1) {
                    timer.Once(bData.profile.Respawn_Timer, () => {
                        int spawnnum = 0;
                        if (AllProfiles.ContainsKey(bData.monumentName)) {
                            if (CanRespawn(bData.monumentName, 1, true) == 1) {
                                if (num > 0 && bData.profile.UseCustomSpawns) {
                                    if (!bData.profile.ChangeCustomSpawnOnDeath) spawnnum = bData.CustomSpawnNum;
                                    else {
                                        availableStatSpawns[bData.monumentName].Add(bData.CustomSpawnNum);
                                        spawnnum = GetNextSpawn(bData.monumentName, bData.profile);
                                    }
                                }
                                SpawnBots(bData.monumentName, AllProfiles[bData.monumentName], null, null, new Vector3(), spawnnum, false);
                                if (bData.profile.Announce_Spawn && bData.profile.Announcement_Text != String.Empty) PrintToChat(bData.profile.Announcement_Text);
                            }
                            else if (bData.profile.UseCustomSpawns) availableStatSpawns[bData.monumentName].Add(bData.CustomSpawnNum);
                        }
                    }
                    );
                }
                else {
                    if (DontRespawn.Contains(npc.userID)) DontRespawn.Remove(npc.userID);
                    if (bData.profile.UseCustomSpawns) availableStatSpawns[bData.monumentName].Add(bData.CustomSpawnNum);
                }
            }
        }
        public static readonly FieldInfo AllScientists = typeof(Scientist).GetField("AllScientists", (BindingFlags.Static | BindingFlags.Public));
        //NRE AskQuestion workaround
        void OnEntitySpawned(Scientist sci) {
            if (loaded && sci != null) AllScientists.SetValue(sci, new HashSet<Scientist>());
            //NRE AskQuestion workaround
        }
        void OnEntitySpawned(DroppedItemContainer container) {
            NextTick(() => {
                if (!loaded || container == null || container.IsDestroyed) return;
                if (container.playerSteamID == 0) return;
                if (configData.Global.Remove_BackPacks_Percent >= GetRand(1, 101)) if (DeadNPCPlayerIds.Contains(container.playerSteamID)) {
                    container.Kill();
                    DeadNPCPlayerIds.Remove(container.playerSteamID);
                    return;
                }
            }
            );
        }
        void OnEntitySpawned(SupplySignal signal) {
            timer.Once(2.3f, () => {
                if (!loaded || signal != null) SmokeGrenades.Add(new Vector3(signal.transform.position.x, 0, signal.transform.position.z));
            }
            );
        }
        void OnEntitySpawned(SupplyDrop drop) {
            if (!loaded || (!drop.name.Contains("supply_drop") && !drop.name.Contains("sleigh/presentdrop"))) return;
            if (!configData.Global.Supply_Enabled) {
                foreach (var location in SmokeGrenades.Where(location => Vector3.Distance(location, new Vector3(drop.transform.position.x, 0, drop.transform.position.z)) < 35f)) {
                    SmokeGrenades.Remove(location);
                    return;
                }
            }
            if (AllProfiles.ContainsKey("AirDrop")) {
                var prof = AllProfiles["AirDrop"];
                if (prof.AutoSpawn == true && prof.Day_Time_Spawn_Amount > 0) {
                    var profile = AllProfiles["AirDrop"];
                    if (profile.Announce_Spawn && profile.Announcement_Text != String.Empty) PrintToChat(profile.Announcement_Text);
                    timer.Repeat(1f, profile.Day_Time_Spawn_Amount, () => {
                        if (drop == null) return;
                        profile.Location = drop.transform.position;
                        SpawnBots("AirDrop", profile, "AirDrop", null, new Vector3(), -1, true);
                    }
                    );
                }
            }
        }
        void OnCrateHack(HackableLockedCrate crate) {
            if (!HasNav(crate.transform.position)) return;
            NextTick(() => {
                if (crate == null || CrateIDs.Contains(crate.net.ID)) return;
                if (CrateIDs.Contains(crate.net.ID)) CrateIDs.Remove(crate.net.ID);
                if (AllProfiles.ContainsKey("HackableLockedCrate")) {
                    var prof = AllProfiles["HackableLockedCrate"];
                    if (prof.AutoSpawn == true && prof.Day_Time_Spawn_Amount > 0) {
                        var profile = AllProfiles["HackableLockedCrate"];
                        if (profile.Announce_Spawn && profile.Announcement_Text != String.Empty) PrintToChat(profile.Announcement_Text);
                        timer.Repeat(1f, profile.Day_Time_Spawn_Amount, () => {
                            if (crate == null) return;
                            profile.Location = crate.transform.position;
                            SpawnBots("HackableLockedCrate", profile, "HackableLockedCrate", null, new Vector3(), -1, true);
                        }
                        );
                    }
                }
            }
            );
        }
        void OnEntitySpawned(NPCPlayerCorpse corpse) {
            if (!loaded || corpse == null) return;
            ulong id = corpse.playerSteamID;
            timer.Once(0.1f, () => {
                if (corpse == null || corpse.IsDestroyed || !botInventories.ContainsKey(id)) return;
                Inv botInv = botInventories[id];
                DataProfile profile = botInv.profile;
                timer.Once(profile.Corpse_Duration, () => {
                    if (corpse != null && !corpse.IsDestroyed) corpse?.Kill();
                }
                );
                timer.Once(2, () => corpse?.ResetRemovalTime(profile.Corpse_Duration));
                List<Item> toDestroy = new List<Item>();
                foreach (var item in corpse.containers[0].itemList) {
                    if (item.ToString().ToLower().Contains("keycard") && configData.Global.Remove_KeyCard) toDestroy.Add(item);
                }
                foreach (var item in toDestroy) item.Remove();
                if (!(profile.Allow_Rust_Loot_Percent >= GetRand(1, 
// ... [Code preview truncated due to length. Full source in attached file] ...

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