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

FREE BotSpawn : 1.8.4 1.8.4

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using Oxide.Game.Rust;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Facepunch;
using Rust;

//Supply signal name fix
namespace Oxide.Plugins 
{
    [Info("BotSpawn", "Steenamaroo", "1.8.4", ResourceId = 2580)]

    [Description("Spawn tailored AI with kits at monuments, custom locations, or randomly.")]

    class BotSpawn : RustPlugin
    {
        [PluginReference]
        Plugin Vanish, Kits; 
        static BotSpawn botSpawn = new BotSpawn();
        const string permAllowed = "botspawn.allowed";
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
        int no_of_AI = 0;
        static System.Random random = new System.Random();
        public List<ulong> coolDownPlayers = new List<ulong>();
        public Dictionary<string, List<Vector3>> spawnLists = new Dictionary<string, List<Vector3>>();
        public Dictionary<ulong, Timer> weaponCheck = new Dictionary<ulong, Timer>();

        public Timer aridTimer;
        public Timer temperateTimer;
        public Timer tundraTimer;
        public Timer arcticTimer;

        bool isBiome(string name)
        {
            if (name == "BiomeArid" || name == "BiomeTemperate" || name == "BiomeTundra" || name == "BiomeArctic")
                return true;
            return false;
        }

        #region Data  
        class StoredData
        {
            public Dictionary<string, DataProfile> DataProfiles = new Dictionary<string, DataProfile>();
            public Dictionary<string, ProfileRelocation> MigrationDataDoNotEdit = new Dictionary<string, ProfileRelocation>();
            public StoredData()
            {
            }
        }

        StoredData storedData;
        #endregion

        void Init()
        {
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                Formatting = Newtonsoft.Json.Formatting.Indented,
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            };
            var filter = RustExtension.Filter.ToList();                                                                                                     //Thanks Fuji.:)
            filter.Add("cover points");
            filter.Add("resulted in a conflict");
            RustExtension.Filter = filter.ToArray();
            no_of_AI = 0;
            LoadConfigVariables();
        }

        void Loaded()
        {
            spawnLists.Add("AridSpawns", new List<Vector3>());
            spawnLists.Add("TemperateSpawns", new List<Vector3>());
            spawnLists.Add("TundraSpawns", new List<Vector3>());
            spawnLists.Add("ArcticSpawns", new List<Vector3>());

            lang.RegisterMessages(messages, this);
            permission.RegisterPermission(permAllowed, this);

            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("BotSpawn");
            SaveData();
        }

        void OnServerInitialized()
        {
            FindMonuments();
        }

        void Unload()
        {
            var filter = RustExtension.Filter.ToList();
            filter.Remove("cover points");
            filter.Remove("resulted in a conflict");
            RustExtension.Filter = filter.ToArray();
            Wipe();
        }

        bool isAuth(BasePlayer player)
        {
            if (player.net.connection != null)
                if (player.net.connection.authLevel < 2)
                    return false;
            return true;
        }

        void UpdateRecords(NPCPlayerApex player)
        {
            if (TempRecord.NPCPlayers.Contains(player))
                TempRecord.NPCPlayers.Remove(player);
            if (weaponCheck.ContainsKey(player.userID))
            {
                weaponCheck[player.userID].Destroy();
                weaponCheck.Remove(player.userID);
            }
        }

        void Wipe()
        {
            foreach (var bot in TempRecord.NPCPlayers)
            {
                if (bot == null)
                    continue;
                else
                    bot.Kill();
            }
            TempRecord.NPCPlayers.Clear();
        }

        // Facepunch.RandomUsernames
        public static string Get(ulong v)                                                                                                                      //credit Fujikura.{
            return Facepunch.RandomUsernames.Get((int)(v % 2147483647uL));
        }

        #region BiomeSpawnsSetup
        void GenerateSpawnPoints(List<Vector3> spawnlist, string name, int number, Timer myTimer, int biomeNo)
        {
            int getBiomeAttempts = 0;
            myTimer = timer.Repeat(0.1f, 0, () =>
            {
                int halfish = Convert.ToInt16((ConVar.Server.worldsize / 2) / 1.1f);

                int x = x = random.Next(-halfish, halfish);
                int z = random.Next(-halfish, halfish);
                Vector3 randomSpot = new Vector3(x, 0, z);
                bool finished = true;

                if (spawnlist.Count < number)
                {
                    getBiomeAttempts++;
                    if (getBiomeAttempts > 50 && spawnlist.Count == 0)
                    {
                        Puts($"Failed to find spawnpoints in {name}.");
                        myTimer.Destroy();
                        return;
                    }

                    finished = false;
                    x = random.Next(-halfish, halfish);
                    z = random.Next(-halfish, halfish);
                    if (TerrainMeta.BiomeMap.GetBiome(randomSpot, biomeNo) > 0.5f
                        && CalculateGroundPos(new Vector3(randomSpot.x, 200, randomSpot.z), true) != new Vector3())
                        spawnlist.Add(CalculateGroundPos(new Vector3(randomSpot.x, 200, randomSpot.z), true));
                }
                if (finished)
                {
                    int i = 0;
                    timer.Repeat(2, number, () =>
                    {
                        SpawnBots(name, TempRecord.AllProfiles[name], "biome", null, spawnlist[i]);
                        i++;
                    });
                    myTimer.Destroy();
                }
            });
        }

        public static Vector3 CalculateGroundPos(Vector3 sourcePos, bool Biome)
        {
            RaycastHit hitInfo;
            var cast = Physics.Raycast(sourcePos, Vector3.down, out hitInfo, 1000f, LayerMask.GetMask("Terrain", "Water", "World"), QueryTriggerInteraction.Ignore);

            if (!hitInfo.collider.name.Contains("rock"))
                cast = Physics.Raycast(sourcePos, Vector3.down, out hitInfo, 1000f, LayerMask.GetMask("Terrain", "Water"), QueryTriggerInteraction.Ignore);

            if (hitInfo.collider.tag == "Main Terrain" || hitInfo.collider.name.Contains("rock"))
            {
                sourcePos.y = hitInfo.point.y;
                return sourcePos;
            }

            return new Vector3();
        }

        Vector3 TryGetSpawn(Vector3 centerPoint, int radius)
        {
            int attempts = 0;
            var spawnPoint = new Vector3();

            while (attempts < 50 && spawnPoint == new Vector3())
            {
                attempts++;
                int X = random.Next((-radius), (radius));
                int Z = random.Next((-radius), (radius));
                Vector3 testPoint = new Vector3((centerPoint.x + X), 200, (centerPoint.z + Z));
                if (CalculateGroundPos(testPoint, false) != new Vector3())
                {
                    spawnPoint = CalculateGroundPos(testPoint, false);
                }
            }
            return spawnPoint;
        }
        #endregion


        #region BotSetup
        void AttackPlayer(Vector3 location, string name, DataProfile profile, string group)
        {
            timer.Repeat(1f, profile.Bots, () => SpawnBots(name, profile, "Attack", group, location));
        }

        void SpawnBots(string name, DataProfile zone, string type, string group, Vector3 location)
        {
            var pos = new Vector3(zone.LocationX, zone.LocationY, zone.LocationZ);
            var finalPoint = new Vector3();
            if (location != new Vector3())
                pos = location;

            var randomTerrainPoint = TryGetSpawn(pos, zone.Radius);
            if (randomTerrainPoint == new Vector3())
            {
                Puts($"Failed to find a suitable spawnpoint : Moving on to next.{name}");
                return;
            }
            else
            {
                finalPoint = randomTerrainPoint + new Vector3(0, 0.5f, 0);
            }

            if (zone.Chute)
            {
                if (type == "AirDrop")
                    finalPoint = (pos - new Vector3(0, 40, 0));
                else
                    finalPoint = new Vector3(randomTerrainPoint.x, 200, (randomTerrainPoint.z));
            }

            NPCPlayer entity = (NPCPlayer)InstantiateSci(finalPoint, Quaternion.Euler(0, 0, 0), zone.Murderer, type);
            var botapex = entity.GetComponent<NPCPlayerApex>();

            TempRecord.NPCPlayers.Add(botapex);
            var bData = botapex.gameObject.AddComponent<botData>();
            bData.monumentName = name;
            botapex.Spawn();
            botapex.AiContext.Human.NextToolSwitchTime = Time.realtimeSinceStartup * 10;
            botapex.AiContext.Human.NextWeaponSwitchTime = Time.realtimeSinceStartup * 10;
            botapex.CommunicationRadius = 0;

            no_of_AI++;

            if (group != null)
                bData.group = group;
            else
                bData.group = null;

            bData.spawnPoint = randomTerrainPoint;
            bData.accuracy = zone.Bot_Accuracy;
            bData.damage = zone.Bot_Damage;
            bData.respawn = true;
            bData.roamRange = zone.Roam_Range;
            bData.dropweapon = zone.Weapon_Drop;
            bData.keepAttire = zone.Keep_Default_Loadout;
            bData.peaceKeeper = zone.Peace_Keeper;
            bData.chute = zone.Chute;
            bData.peaceKeeper_CoolDown = zone.Peace_Keeper_Cool_Down;

            botapex.startHealth = zone.BotHealth;
            botapex.InitializeHealth(zone.BotHealth, zone.BotHealth);  

            if (type == "biome")
                bData.biome = true; 
            if (zone.Chute)
                addChute(botapex, finalPoint);

            int kitRnd;
            kitRnd = random.Next(zone.Kit.Count);

            if (zone.BotNames.Count == zone.Kit.Count && zone.Kit.Count != 0)
                setName(zone, botapex, kitRnd); 
            else
                setName(zone, botapex, random.Next(zone.BotNames.Count));  

            giveKit(botapex, zone, kitRnd);

            sortWeapons(botapex);

            int suicInt = random.Next((zone.Suicide_Timer), (zone.Suicide_Timer + 10));                                        //slightly randomise suicide de-spawn time
            if (type == "AirDrop" || type == "Attack")
            {
                bData.respawn = false;
                runSuicide(botapex, suicInt);
            }

            if (zone.Disable_Radio)
                botapex.RadioEffect = new GameObjectRef();

            botapex.Stats.AggressionRange = zone.Sci_Aggro_Range;
            botapex.Stats.DeaggroRange = zone.Sci_DeAggro_Range;
        }

        BaseEntity InstantiateSci(Vector3 position, Quaternion rotation, bool murd, string type)                                                                            //Spawn population spam fix - credit Fujikura
        {
            string prefabname = "assets/prefabs/npc/scientist/scientist.prefab";
            if (murd)
                prefabname = "assets/prefabs/npc/murderer/murderer.prefab";

            var prefab = GameManager.server.FindPrefab(prefabname);
            GameObject gameObject = Instantiate.GameObject(prefab, 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 botapex, Vector3 newPos)
        {
            float wind = random.Next(0, 50);
            float fall = random.Next(40, 80);
            var rb = botapex.gameObject.GetComponent<Rigidbody>();
            rb.isKinematic = false;
            rb.useGravity = false;
            rb.drag = 0f;
            botapex.gameObject.layer = 3;

            rb.velocity = new Vector3((botapex.transform.forward.x * (wind / 20f)), 0, (botapex.transform.forward * (wind / 20f)).z) - new Vector3(0, (fall / 10f), 0);

            var col = botapex.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(botapex, "parachute");
            Chute.Spawn();
        }

        void setName(DataProfile zone, NPCPlayerApex botapex, int number)
        {
            if (zone.BotNames.Count == 0 || zone.BotNames.Count <= number)
            {
                botapex.displayName = Get(botapex.userID);
                botapex.displayName = char.ToUpper(botapex.displayName[0]) + botapex.displayName.Substring(1);
            }
            else if (zone.BotNames[number] == "")
            {
                botapex.displayName = Get(botapex.userID);
                botapex.displayName = char.ToUpper(botapex.displayName[0]) + botapex.displayName.Substring(1);
            }
            else
                botapex.displayName = zone.BotNames[number];

            if (zone.BotNamePrefix != "")
                botapex.displayName = zone.BotNamePrefix + " " + botapex.displayName;
        }

        void giveKit(NPCPlayerApex botapex, DataProfile zone, int kitRnd)
        {
            var bData = botapex.GetComponent<botData>();

            if (zone.Kit.Count != 0)
            {
                if (zone.Kit[kitRnd] != null)
                {
                    object checkKit = (Kits.CallHook("GetKitInfo", zone.Kit[kitRnd], true));
                    if (checkKit == null)
                    {
                        if (zone.Murderer)
                            PrintWarning($"Kit {zone.Kit[kitRnd]} does not exist - Spawning default Murderer.");
                        else
                            PrintWarning($"Kit {zone.Kit[kitRnd]} does not exist - Spawning default Scientist.");
                    }
                    else
                    {
                        bool weaponInBelt = false;
                        if (checkKit != null && checkKit is JObject)
                        {
                            JObject kitContents = checkKit as JObject;

                            JArray items = kitContents["items"] as JArray;
                            foreach (var weap in items)
                            {
                                JObject item = weap as JObject;
                                if (item["container"].ToString() == "belt")
                                    weaponInBelt = true;                                                                                                    //doesn't actually check for weapons - just any item.}
                        }
                        if (!weaponInBelt)
                        {
                            if (zone.Murderer)
                                PrintWarning($"Kit {zone.Kit[kitRnd]} has no items in belt - Spawning default Murderer.");
                            else
                                PrintWarning($"Kit {zone.Kit[kitRnd]} has no items in belt - Spawning default Scientist.");
                        }
                        else
                        {
                            if (bData.keepAttire == false)
                                botapex.inventory.Strip();
                            Kits.Call($"GiveKit", botapex, zone.Kit[kitRnd], true);
                            if (!(kitList.ContainsKey(botapex.userID)))
                            {
                                kitList.Add(botapex.userID, new kitData
                                {
                                    Kit = zone.Kit[kitRnd],
                                    Wipe_Belt = zone.Wipe_Belt,
                                    Wipe_Clothing = zone.Wipe_Clothing,
                                    Allow_Rust_Loot = zone.Allow_Rust_Loot,
                                });
                            }
                        }
                    }
                }
            }
            else
            {
                if (!(kitList.ContainsKey(botapex.userID)))
                {
                    kitList.Add(botapex.userID, new kitData
                    {
                        Kit = "",
                        Wipe_Belt = zone.Wipe_Belt,
                        Wipe_Clothing = zone.Wipe_Clothing,
                        Allow_Rust_Loot = zone.Allow_Rust_Loot,
                    });
                }
            }
        }

        void sortWeapons(NPCPlayerApex botapex)
        {
            var bData = botapex.GetComponent<botData>();
            foreach (Item item in botapex.inventory.containerBelt.itemList)                                                                                 //store organised weapons lists
            {
                var held = item.GetHeldEntity();
                if (held as HeldEntity != null)
                {
                    if (held.name.Contains("bow") || held.name.Contains("launcher"))
                        continue;
                    if (held as BaseMelee != null || held as TorchWeapon != null)
                        bData.MeleeWeapons.Add(item);
                    else
                    {
                        if (held as BaseProjectile != null)
                        {
                            bData.AllProjectiles.Add(item);
                            if (held.name.Contains("m92") || held.name.Contains("pistol") || held.name.Contains("python") || held.name.Contains("waterpipe"))
                                bData.CloseRangeWeapons.Add(item);
                            else if (held.name.Contains("bolt"))
                                bData.LongRangeWeapons.Add(item);
                            else
                                bData.MediumRangeWeapons.Add(item);
                        }
                    }
                }
            }
            weaponCheck.Add(botapex.userID, timer.Repeat(2, 0, () => SelectWeapon(botapex)));
        }

        void runSuicide(NPCPlayerApex botapex, int suicInt)
        {
            if (TempRecord.NPCPlayers.Contains(botapex))
            {
                timer.Once(suicInt, () =>
                {
                    if (botapex != null)
                    {
                        if (botapex.AttackTarget != null && Vector3.Distance(botapex.transform.position, botapex.AttackTarget.transform.position) < 10 && botapex.GetNavAgent.isOnNavMesh)
                        {
                            if (botapex.AttackTarget != null)
                            {
                                var position = botapex.AttackTarget.transform.position;
                                botapex.svActiveItemID = 0;
                                botapex.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                                botapex.inventory.UpdatedVisibleHolsteredItems();
                                timer.Repeat(0.05f, 100, () =>
                                {
                                    if (botapex == null) return;
                                    botapex.SetDestination(position);
                                });
                            }
                        }
                        timer.Once(4, () =>
                        {
                            if (botapex == null) return;
                            Effect.server.Run("assets/prefabs/weapons/rocketlauncher/effects/rocket_explosion.prefab", botapex.transform.position);
                            HitInfo nullHit = new HitInfo();
                            nullHit.damageTypes.Add(Rust.DamageType.Explosion, 10000);
                            botapex.IsInvinsible = false;
                            botapex.Die(nullHit);
                        }
                        );
                    }
                });
            }
        }
        #endregion

        static BasePlayer FindPlayerByName(string name)
        {
            BasePlayer result = null;
            foreach (BasePlayer current in BasePlayer.activePlayerList)
            {
                if (current.displayName.Equals(name, StringComparison.OrdinalIgnoreCase))
                {
                    BasePlayer result2 = current;
                    return result2;
                }
                if (current.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase))
                {
                    BasePlayer result2 = current;
                    return result2;
                }
                if (current.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase))
                {
                    result = current;
                }
            }
            return result;
        }

        #region Hooks  

        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 = null;

            if (entity is NPCPlayerApex)
            {
                bot = entity as NPCPlayerApex;

                if (!TempRecord.NPCPlayers.Contains(bot))
                    return null;
                var bData = bot.GetComponent<botData>();
                if (info.Initiator?.ToString() == null && configData.Global.Pve_Safe)
                    info.damageTypes.ScaleAll(0);
                if (info.Initiator is BasePlayer && !(info.Initiator is NPCPlayer))
                {
                    var canNetwork = Vanish?.Call("IsInvisible", info.Initiator);                                                                       //bots wont retaliate to vanished players
                    if ((canNetwork is bool))
                        if ((bool)canNetwork)
                            info.Initiator = null;

                    if (bData.peaceKeeper)                                                                                                               //prevent melee farming with peacekeeper on
                    {
                        var heldMelee = info.Weapon as BaseMelee;
                        var heldTorchWeapon = info.Weapon as TorchWeapon;
                        if (heldMelee != null || heldTorchWeapon != null)
                            info.damageTypes.ScaleAll(0);
                    }
                }
                bData.goingHome = false;
            }

            if (info?.Initiator is NPCPlayer && entity is BasePlayer)                                                                                       //add in bot accuracy
            {
                var attacker = info.Initiator as NPCPlayerApex;

                if (TempRecord.NPCPlayers.Contains(attacker))
                {
                    var bData = attacker.GetComponent<botData>();
                    int rand = random.Next(1, 100);
                    float distance = (Vector3.Distance(info.Initiator.transform.position, entity.transform.position));

                    var newAccuracy = (bData.accuracy * 10f);
                    var newDamage = (bData.damage);
                    if (distance > 100f)
                    {
                        newAccuracy = ((bData.accuracy * 10f) / (distance / 100f));
                        newDamage = bData.damage / (distance / 100f);
                    }
                    if (!melee && newAccuracy < rand)                                                                                                          //scale bot attack damage
                        return true;
                    info.damageTypes.ScaleAll(newDamage);
                }
            }
            return null;
        }

        void OnEntityKill(BaseNetworkable entity)
        {
            NPCPlayerApex npc = entity as NPCPlayerApex;
            if (npc != null && TempRecord.NPCPlayers.Contains(npc))
            {
                var bData = npc.GetComponent<botData>();
                Item activeItem = npc.GetActiveItem();

                if (bData.dropweapon == true && activeItem != null)
                {
                    using (TimeWarning timeWarning = TimeWarning.New("PlayerBelt.DropActive", 0.1f))
                    {
                        activeItem.Drop(npc.eyes.position, new Vector3(), new Quaternion());
                        npc.svActiveItemID = 0;
                        npc.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                        kitRemoveList.Add(npc.userID, activeItem.info.name);
                    }
                }
                if (TempRecord.AllProfiles[bData.monumentName].Disable_Radio == true)
                {
                    npc.DeathEffect = new GameObjectRef();                                                                                               //kill radio effects
                }
                DeadNPCPlayerIds.Add(npc.userID);
                no_of_AI--;
                if (bData.respawn == false)
                {
                    UnityEngine.Object.Destroy(npc.GetComponent<botData>());
                    UpdateRecords(npc);
                    return;
                }
                else if (bData.biome)
                {
                    List<Vector3> spawnList = new List<Vector3>();

                    if (spawnLists.ContainsKey(bData.monumentName))
                    {
                        spawnList = spawnLists[bData.monumentName];
                        int spawnPos = random.Next(spawnList.Count);
                        timer.Once(TempRecord.AllProfiles[bData.monumentName].Respawn_Timer, () =>
                        {
                            if (TempRecord.AllProfiles.ContainsKey(bData.monumentName))
                            {
                                SpawnBots(bData.monumentName, TempRecord.AllProfiles[bData.monumentName], "biome", null, spawnList[spawnPos]);
                            }
                        });
                        return;
                    }
                    else return;
                }
                else
                {
                    foreach (var profile in TempRecord.AllProfiles)
                    {
                        timer.Once(profile.Value.Respawn_Timer, () =>
                        {
                            if (profile.Key == bData.monumentName)
                            {
                                SpawnBots(profile.Key, profile.Value, null, null, new Vector3());
                            }
                        });
                    }
                }
                UnityEngine.Object.Destroy(npc.GetComponent<botData>());
                UpdateRecords(npc);
            }
        }

        void OnPlayerDie(BasePlayer player)
        {
            OnEntityKill(player);
        }

        public static readonly FieldInfo AllScientists = typeof(Scientist).GetField("AllScientists", (BindingFlags.Static | BindingFlags.NonPublic)); //NRE AskQuestion workaround

        void OnEntitySpawned(BaseEntity entity) // handles smoke signals, backpacks, corpses(applying kit)
        {
            if (entity as Scientist != null)
                AllScientists.SetValue((entity as Scientist), new HashSet<Scientist>());//NRE AskQuestion workaround
                
            var KitDetails = new kitData();
            if (entity != null)
            {
                var pos = entity.transform.position;
                if (entity is NPCPlayerCorpse)
                {
                    var corpse = entity as NPCPlayerCorpse;
                    corpse.ResetRemovalTime(configData.Global.Corpse_Duration);

                    if (kitList.ContainsKey(corpse.playerSteamID))
                    {
                        KitDetails = kitList[corpse.playerSteamID];
                        NextTick(() =>
                        {
                            if (corpse == null)
                                return;

                            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.RemoveFromContainer();

                            if (!KitDetails.Allow_Rust_Loot)
                            {
                                corpse.containers[0].Clear();
                                corpse.containers[1].Clear();
                                corpse.containers[2].Clear();
                            }
                            if (KitDetails.Kit != "")
                            {
                                var tempbody = GameManager.server.CreateEntity("assets/prefabs/player/player.prefab", (corpse.transform.position - new Vector3(0, -100, 0)), corpse.transform.rotation).ToPlayer();
                                tempbody.Spawn();

                                Kits?.Call($"GiveKit", tempbody, KitDetails.Kit, true);

                                var source = new ItemContainer[] { tempbody.inventory.containerMain, tempbody.inventory.containerWear, tempbody.inventory.containerBelt };

                                for (int i = 0; i < (int)source.Length; i++)
                                {
                                    Item[] array = source[i].itemList.ToArray();
                                    for (int j = 0; j < (int)array.Length; j++)
                                    {
                                        Item item = array[j];
                                        if (!item.MoveToContainer(corpse.containers[i], -1, true))
                                        {
                                            item.Remove(0f);
                                        }
                                    }
                                }
                                tempbody.Kill();
                            }
                            if (kitList[corpse.playerSteamID].Wipe_Belt)
                                corpse.containers[2].Clear();
                            else
                            if (kitRemoveList.ContainsKey(corpse.playerSteamID))
                            {
                                foreach (var thing in corpse.containers[2].itemList)                                                                            //If weapon drop is enabled, this removes the weapon from the corpse's inventory.{
                                    if (kitRemoveList[corpse.playerSteamID] == thing.info.name)
                                    {
                                        thing.Remove();
                                        kitRemoveList.Remove(corpse.playerSteamID);
                                        break;
                                    }
                                }
                            }

                            if (kitList[corpse.playerSteamID].Wipe_Clothing)
                            {
                                corpse.containers[1].Clear();
                            }

                            kitList.Remove(corpse.playerSteamID);
                        });
                    }
                }

                if (entity is DroppedItemContainer)
                {
                    NextTick(() =>
                    {
                        if (entity == null || entity.IsDestroyed) return;
                        var container = entity as DroppedItemContainer;

                        ulong ownerID = container.playerSteamID;
                        if (ownerID == 0) return;
                        if (configData.Global.Remove_BackPacks)
                        {
                            if (DeadNPCPlayerIds.Contains(ownerID))
                            {
                                entity.Kill();
                                DeadNPCPlayerIds.Remove(ownerID);
                                return;
                            }
                        }

                    });
                }

                if (entity.name.Contains("grenade.supplysignal.deployed"))
                    timer.Once(2.3f, () =>
                    {
                        if (entity != null)
                            smokeGrenades.Add(new Vector3(entity.transform.position.x, 0, entity.transform.position.z));
                    });

                if (!(entity.name.Contains("supply_drop")))
                    return;

                Vector3 dropLocation = new Vector3(entity.transform.position.x, 0, entity.transform.position.z);

                if (!(configData.Global.Supply_Enabled))
                {
                    foreach (var location in smokeGrenades)
                    {
                        if (Vector3.Distance(location, dropLocation) < 35f)
                        {
                            smokeGrenades.Remove(location);
                            return;
                        }
                    }
                }
                if (TempRecord.AllProfiles.ContainsKey("AirDrop"))
                {
                    var profile = TempRecord.AllProfiles["AirDrop"];
                    if (profile.AutoSpawn == true)
                    {
                        timer.Repeat(0.1f, profile.Bots, () =>
                        {
                            profile.LocationX = entity.transform.position.x;
                            profile.LocationY = entity.transform.position.y;
                            profile.LocationZ = entity.transform.position.z;
                            SpawnBots("AirDrop", profile, "AirDrop", null, new Vector3());
                        }
                        );
                    }
                }
            }
        }
        #endregion

        #region WeaponSwitching
        void SelectWeapon(NPCPlayerApex npcPlayer)
        {
            if (npcPlayer == null) return;
            var victim = npcPlayer.AttackTarget;
            var bData = npcPlayer.GetComponent<botData>();
            if (bData == null) return;
            if (npcPlayer.svActiveItemID == 0)
                return;

            var active = npcPlayer.GetActiveItem();
            HeldEntity heldEntity1 = null;

            if (active != null)
                heldEntity1 = active.GetHeldEntity() as HeldEntity;

            List<int> weapons = new List<int>();                                                                                                    //check all their weapons
            foreach (Item item in npcPlayer.inventory.containerBelt.itemList)
            {
                var held = item.GetHeldEntity();
                if (held is BaseProjectile || held is BaseMelee || held is TorchWeapon)
                    weapons.Add(Convert.ToInt16(item.position));
            }

            if (weapons.Count == 0)
            {
                PrintWarning(lang.GetMessage("noWeapon", this), bData.monumentName);
                return;
            }
            if (npcPlayer.AttackTarget == null)
            {
                if (active != null) SetRange(npcPlayer);
                int index = random.Next(weapons.Count);
                var currentTime = TOD_Sky.Instance.Cycle.Hour;
                uint UID = 0;
                List<Item> lightList = new List<Item>();
                if (active != null && active.contents != null)
                    lightList = active.contents.itemList;
                if (currentTime > 20 || currentTime < 8)
                {
                    if (active != null && !(active.ToString().Contains("flashlight")))
                    {
                        foreach (var mod in lightList)
                        {
                            if (mod.info.shortname.Contains("flashlight"))
                                return;
                        }
                        foreach (Item item in npcPlayer.inventory.containerBelt.itemList)
                        {
                            if (item.ToString().Contains("flashlight"))
                            {
                                if (heldEntity1 != null)
                                    heldEntity1.SetHeld(false);
                                UID = item.uid;

                            }
                            if (item.contents != null)
                                foreach (var mod in item.contents.itemList)
                                {
                                    if (mod.info.shortname.Contains("flashlight"))
                                        UID = item.uid;
                                }
                            ChangeWeapon(npcPlayer, item);
                        }
                    }
                }
                else
                {
                    if (active != null && active.ToString().Contains("flashlight"))
                    {
                        foreach (Item item in npcPlayer.inventory.containerBelt.itemList)                                                                   //pick one at random to start with
                        {
                            if (item.position == weapons[index])
                            {
                                if (heldEntity1 != null)
                                    heldEntity1.SetHeld(false);
                                ChangeWeapon(npcPlayer, item);
                            }
                        }
                    }
                }
            }
            else
            {
                if (active != null) SetRange(npcPlayer);
                if (heldEntity1 == null)
                    bData.currentWeaponRange = 0;

                float distance = Vector3.Distance(npcPlayer.transform.position, victim.transform.position);
                int newCurrentRange = 0;
                int noOfAvailableWeapons = 0;
                int selectedWeapon;
                Item chosenWeapon = null;
                HeldEntity held = null;


                List<Item> rangeToUse = new List<Item>();
                if (distance < 2f && bData.MeleeWeapons.Count != 0)
                {
                    bData.enemyDistance = 1;
                    rangeToUse = bData.MeleeWeapons;
                    newCurrentRange = 1;
                }
                else if (distance > 1f && distance < 20f)
                {
                    if (bData.CloseRangeWeapons.Count > 0)
                    {
                        bData.enemyDistance = 2;
                        rangeToUse = bData.CloseRangeWeapons;
                        newCurrentRange = 2;
                    }
                    else
                    {
                        rangeToUse = bData.MediumRangeWeapons;
                        newCurrentRange = 3;
                    }
                }
                else if (distance > 19f && distance < 40f && bData.MediumRangeWeapons.Count > 0)
                {
                    bData.enemyDistance = 3;
                    rangeToUse = bData.MediumRangeWeapons;
                    newCurrentRange = 3;
                }
                else if (distance > 39)
                {
                    if (bData.LongRangeWeapons.Count > 0)
                    {
                        bData.enemyDistance = 4;
                        rangeToUse = bData.LongRangeWeapons;
                        newCurrentRange = 4;
                    }
                    else
                    {
                        rangeToUse = bData.MediumRangeWeapons;
                        newCurrentRange = 3;
                    }
                }

                if (rangeToUse.Count > 0)
                {
                    selectedWeapon = random.Next(rangeToUse.Count);
                    chosenWeapon = rangeToUse[selectedWeapon];
                }

                if (chosenWeapon == null)                                                                                                       //if no weapon suited to range, pick any random bullet weapon
                {                                                                                                                               //prevents sticking with melee @>2m when no pistol is available
                    bData.enemyDistance = 5;
                    if (heldEntity1 != null && bData.AllProjectiles.Contains(active))                                                           //prevents choosing a random weapon if the existing one is fine
                        return;
                    foreach (var weap in bData.AllProjectiles)
                    {
                        noOfAvailableWeapons++;
                    }
                    if (noOfAvailableWeapons > 0)
                    {
                        selectedWeapon = random.Next(bData.AllProjectiles.Count);
                        chosenWeapon = bData.AllProjectiles[selectedWeapon];
                        newCurrentRange = 5;
                    }
                }
                if (chosenWeapon == null) return;
                if (newCurrentRange == bData.currentWeaponRange) return;
                bData.currentWeaponRange = newCurrentRange;
                held = chosenWeapon.GetHeldEntity() as HeldEntity;
                if (heldEntity1 != null && heldEntity1.name == held.name)
                    return;
                if (heldEntity1 != null && heldEntity1.name != held.name)
                    heldEntity1.SetHeld(false);
                ChangeWeapon(npcPlayer, chosenWeapon);
            }
        }

        [ConsoleCommand("botspawn")]
        private void cmdBotSpawn(ConsoleSystem.Arg arg)
        {
            if (arg.Args == null || arg.Args.Length != 2) return;
            foreach (var bot in TempRecord.NPCPlayers.Where(bot => bot.GetComponent<botData>().monumentName == arg.Args[0]))
                foreach (var gun in bot.GetComponent<botData>().AllProjectiles.Where(gun=>gun.info.shortname == arg.Args[1]))
                    ChangeWeapon(bot, gun); 
        }
        
        void ChangeWeapon(NPCPlayerApex botapex, Item item)
        {
            Item activeItem1 = botapex.GetActiveItem();
            botapex.svActiveItemID = 0U;
            if (activeItem1 != null)
            {
                HeldEntity heldEntity = activeItem1.GetHeldEntity() as HeldEntity;
                if (heldEntity != null)
                    heldEntity.SetHeld(false);
            }
            botapex.svActiveItemID = item.uid;
            botapex.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            Item activeItem2 = botapex.GetActiveItem();
            if (activeItem2 != null)
            {
                HeldEntity heldEntity = activeItem2.GetHeldEntity() as HeldEntity;
                if (heldEntity != null)
                    heldEntity.SetHeld(true);
            }
            botapex.inventory.UpdatedVisibleHolsteredItems();
            botapex.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            SetRange(botapex);
        }

        void SetRange(NPCPlayerApex npcPlayer)
        {
            if (npcPlayer != null && npcPlayer is NPCMurderer)  
            {
                if (npcPlayer.GetComponent<botData>() == null || npcPlayer.GetHeldEntity() == null || (npcPlayer.GetHeldEntity() as AttackEntity) == null)
                    return;
                var bData = npcPlayer.GetComponent<botData>();
                var held = npcPlayer.GetHeldEntity() as AttackEntity;

                if (bData.currentWeaponRange == 0 || bData.currentWeaponRange == 1)
                    held.effectiveRange = 2;
                else if (bData.currentWeaponRange == 2 || bData.currentWeaponRange == 3)
                    held.effectiveRange = 100;
                else if (bData.currentWeaponRange == 5)
                    held.effectiveRange = 200;
            }
        }
        #endregion

        #region behaviour hooks

        object OnNpcPlayerResume(NPCPlayerApex player)
        {
            if (TempRecord.NPCPlayers.Contains(player))
            {
                var bData = player.GetComponent<botData>(); 
                if (bData.inAir) return false;
            }
            return null;
        }

        object OnNpcDestinationSet(NPCPlayerApex player)
        {
            if (TempRecord.NPCPlayers.Contains(player))
            {
                var bData = player.GetComponent<botData>();
                if (bData.goingHome)
                {
                    player.Destination = bData.spawnPoint;
                    return true;
                }
                return null;
            }
            return null;
        }
        #endregion

        #region OnNpcHooks 
        object OnNpcPlayerTarget(NPCPlayerApex npcPlayer, BaseEntity entity)
        {
            var path = TempRecord.NPCPlayers;
            var conf = configData.Global;

            if (npcPlayer == null || entity == null)
                return null;

            if (entity is NPCPlayer)
            {
                NPCPlayer botVictim = entity as NPCPlayer;

                if (npcPlayer == botVictim) return null;
                if (path.Contains(botVictim) && !(path.Contains(npcPlayer)) && !(conf.NPCs_Attack_BotSpawn))    //stop oustideNPCs attacking BotSpawn bots
                    return true;

                if (!TempRecord.NPCPlayers.Contains(npcPlayer))
                    return null;

                if (!path.Contains(botVictim) && !(conf.BotSpawn_Attacks_NPCs))                                   //stop BotSpawn bots attacking outsideNPCs                                                                                  
                    return true;

                if (path.Contains(botVictim) && !(conf.BotSpawn_Attacks_BotSpawn))                              //stop BotSpawn murd+sci fighting each other 
                    return true;

                if (TempRecord.NPCPlayers.Contains(npcPlayer) && npcPlayer.GetType() == botVictim.GetType())
                    return true;
            }

            if (!TempRecord.NPCPlayers.Contains(npcPlayer))
                return null;
            if (entity is BasePlayer)
            {
                BasePlayer victim = entity as BasePlayer;
                var active = npcPlayer.GetActiveItem();
                var bData =
// ... [Code preview truncated due to length. Full source in attached file] ...

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