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

FREE BotReSpawn : 1.1.7 1.1.7

Нет прав для скачивания
C#:
using Facepunch;
using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using UnityEngine.AI;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Game.Rust.Cui;
namespace Oxide.Plugins {
    [Info("BotReSpawn", "Sempai#3239", "1.1.7", ResourceId = 0)]
    [Description("Spawn tailored AI with kits at monuments, custom locations, or randomly.")]
    class BotReSpawn : RustPlugin {
        [PluginReference]
        Plugin NoSash, Kits, CustomLoot, RustRewards, XPerience;
        int halfish, no_of_AI;
        bool loaded;
        static BotReSpawn bs;
        static System.Random random = new System.Random();
        public static string Get(ulong v) => RandomUsernames.Get((int)(v % 2147483647uL));
        public static bool IsNight => bs.configData.Global.UseServerTime == true ? TOD_Sky.Instance.IsNight : TOD_Sky.Instance.Cycle.Hour > bs.configData.Global.NightStartHour || TOD_Sky.Instance.Cycle.Hour < bs.configData.Global.DayStartHour;
        int GetRand(int l, int h) => random.Next(l, h);
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
        const string permAllowed = "BotReSpawn.allowed";
        const string huff = "assets/prefabs/npc/murderer/sound/breathing.prefab";
        const string Parachute = "assets/prefabs/misc/parachute/parachute.prefab";
        const string RocketExplosion = "assets/prefabs/weapons/rocketlauncher/effects/rocket_explosion.prefab";
        const string LockedCrate = "assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab";
        ItemDefinition fuel = ItemManager.FindItemDefinition("lowgradefuel");
        public List<ulong> HumanNPCs = new List<ulong>();
        public List<Vector3> protect = new List<Vector3>();
        public Dictionary<string, Profile> Profiles = new Dictionary<string, Profile>();
        Dictionary<string, LootContainer> Containers = new Dictionary<string, LootContainer>() {
            {
                "Default NPC", null
            }
        }
        ;
        LootContainer.LootSpawnSlot[] sc;
        public Dictionary<ulong, ScientistNPC> NPCPlayers = new Dictionary<ulong, ScientistNPC>();
        ItemDefinition scrap;
#region Setup + TakeDown
        void Init() {
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
                Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            }
            ;
            no_of_AI = 0;
        }
        void Loaded() {
            ConVar.AI.npc_families_no_hurt = false;
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(permAllowed, this);
        }
        bool Unloading = false;
        void Unload() {
            Unloading = true;
            DestroySpawnGroups();
            foreach (BasePlayer player in BasePlayer.activePlayerList) DestroyMenu(player, true);
            foreach (var obj in UnityEngine.Object.FindObjectsOfType(typeof(MonoBehaviour)).ToList()) if (obj?.ToString() != null && obj.ToString().Contains("BotData") && !(obj is BotData)) UnityEngine.Object.Destroy(obj);
        }
        int test = 0;
        void OnServerInitialized() {
            PrintWarning("\n-----------------------------\n" + "     Author - Sempai#3239\n" + "     VK - https://vk.com/rustnastroika\n" + "     Discord - https://discord.gg/5DPTsRmd3G\n" + "-----------------------------");
            scrap = ItemManager.FindItemDefinition("scrap");
            sc = GameManager.server.FindPrefab("assets/prefabs/npc/scarecrow/scarecrow.prefab")?.GetComponent<ScarecrowNPC>()?.LootSpawnSlots;
            foreach (BasePlayer player in BaseNetworkable.serverEntities.OfType<BasePlayer>()) ProcessHumanNPC(player);
            halfish = Convert.ToInt16((ConVar.Server.worldsize / 2) / 1.1f);
            timer.Once(1f, () => {
                if (NoSash) {
                    PrintWarning("NoSash plugin is installed");
                    PrintWarning("Target_Noobs option is now disabled.");
                    PrintWarning("BotReSpawn NPCs will target noob players.");
                }
                bs = this;
                GetBiomePoints();
                CheckMonuments(false);
                LoadConfigVariables();
                ImportFiles();
                loaded = true;
                SaveData();
                SetupProfiles();
                CheckKits();
                SetupLootSources();
                newsave = false;
                timer.Once(0.1f, () => CreateSpawnGroups());
                foreach (BradleyAPC apc in BaseNetworkable.serverEntities.OfType<BradleyAPC>()) SetupAPC(apc);
            }
            );
            // Remove in V1.1.0
            BaseEntity.saveList.RemoveWhere(p => !p);
            BaseEntity.saveList.RemoveWhere(p => p == null);
        }
        void ProcessHumanNPC(BasePlayer player) {
            NextTick(() => {
                if (player == null) return;
                foreach (var comp in player.GetComponents<Component>()) if (comp?.GetType()?.Name == "HumanPlayer") {
                    HumanNPCs.Add(player.userID);
                    break;
                }
            }
            );
        }
#endregion
#region Setup Methods
        void GetBiomePoints() {
            var trees = BaseNetworkable.serverEntities.OfType<ResourceEntity>().Where(x => x is TreeEntity || x.ShortPrefabName.Contains("cactus"));
            string biomename = "";
            List<string> names = new List<string>();
            int biome = -1;
            Vector3 point = Vector3.zero;
            foreach (var tree in trees.ToList()) {
                biome = TerrainMeta.BiomeMap.GetBiomeMaxType(tree.transform.position, -1);
                point = CalculateGroundPos(tree.transform.position + Vector3.forward / 2f, false, false);
                if (point != Vector3.zero) {
                    biomename = $"Biome{Enum.GetName(typeof(TerrainBiome.Enum), biome)}";
                    if (BiomeSpawns.ContainsKey(biomename)) BiomeSpawns[biomename].Add(point);
                    else BiomeSpawns.Add(biomename, new List<Vector3> {
                        point
                    }
                    );
                }
            }
        }
        void CheckMonuments(bool add) {
            GameObject gobject;
            Vector3 pos;
            float rot;
            foreach (var monumentInfo in TerrainMeta.Path.Monuments.OrderBy(x => x.displayPhrase.english)) {
                var displayPhrase = monumentInfo.displayPhrase.english.Replace("\n", String.Empty);
                if (displayPhrase.Contains("Oil Rig") || displayPhrase.Contains("Water Well")) continue;
                if (monumentInfo?.gameObject?.name != null) displayPhrase = ProcessName(monumentInfo.gameObject.name, displayPhrase);
                gobject = monumentInfo.gameObject;
                pos = gobject.transform.position;
                rot = gobject.transform.eulerAngles.y;
                int counter = 0;
                if (displayPhrase != String.Empty) {
                    if (add) {
                        foreach (var entry in Profiles.Where(x => x.Key.Contains(displayPhrase) && x.Key.Length == displayPhrase.Length + 2)) counter++;
                        if (counter < 10) AddProfile(gobject, $"{displayPhrase} {counter}", null, pos);
                    }
                    else {
                        foreach (var entry in GotMonuments.Where(x => x.Key.Contains(displayPhrase) && x.Key.Length == displayPhrase.Length + 2)) counter++;
                        if (counter < 10) GotMonuments.Add($"{displayPhrase} {counter}", new Profile(ProfileType.Monument));
                    }
                }
            }
        }
        List<string> numerical = new List<string>() {
            "mountain_", "power_sub_big_", "power_sub_small_", "ice_lake_"
        }
        ;
        string ProcessName(string name, string displayPhrase) {
            foreach (var n in numerical) {
                int num;
                if (name.Length > n.Length && int.TryParse(name.Substring(name.IndexOf(n) + n.Length, 1), out num)) {
                    if (name.Contains("sub_big_")) displayPhrase += "_Large";
                    if (name.Contains("sub_small_")) displayPhrase += "_Small";
                    return displayPhrase + $"_{num}";
                }
            }
            if (displayPhrase == "Harbor") {
                if (name.Contains("_1")) displayPhrase += "_Small";
                else displayPhrase += "_Large";
            }
            else if (displayPhrase == "Fishing Village" || displayPhrase == "Wild Swamp") {
                if (name.Contains("_a")) displayPhrase += "_A";
                else if (name.Contains("_b")) displayPhrase += "_B";
                else displayPhrase += "_C";
            }
            return displayPhrase;
        }
        void ImportFiles() {
            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>($"BotReSpawn/{configData.DataPrefix}-CustomProfiles");
            defaultData = Interface.Oxide.DataFileSystem.ReadObject<DefaultData>($"BotReSpawn/{configData.DataPrefix}-DefaultProfiles");
            defaultData.Events = defaultData.Events.Where(x => x.Key != "CH47").ToDictionary(pair => pair.Key, pair => pair.Value);
            spawnsData = Interface.Oxide.DataFileSystem.ReadObject<SpawnsData>($"BotReSpawn/{configData.DataPrefix}-SpawnsData");
            templateData = Interface.Oxide.DataFileSystem.ReadObject<TemplateData>("BotReSpawn/TemplateData");
        }
        Dictionary<string, List<Vector3>> BiomeSpawns = new Dictionary<string, List<Vector3>>() {
            {
                "BiomeArid", new List<Vector3>()
            }
            , {
                "BiomeTemperate", new List<Vector3>()
            }
            , {
                "BiomeTundra", new List<Vector3>()
            }
            , {
                "BiomeArctic", new List<Vector3>()
            }
        }
        ;
        private void SetupProfiles() {
            CheckMonuments(true);
            foreach (var biome in defaultData.Biomes) AddProfile(new GameObject(), biome.Key, biome.Value, new Vector3());
            foreach (var e in defaultData.Events) AddProfile(new GameObject(), e.Key, e.Value, new Vector3());
            foreach (var profile in storedData.Profiles) AddData(profile.Key, profile.Value);
            SaveData();
            SetupSpawnsFile();
            foreach (var profile in Profiles.Where(x => x.Value.type == ProfileType.Custom || x.Value.type == ProfileType.Monument)) if (profile.Value.Spawn.Kit.Count > 0 && Kits == null) PrintWarning(lang.GetMessage("nokits", this), profile.Key);
        }
        void CheckKits() {
            ValidKits.Clear();
            Kits?.Call("GetKitNames", new object[] {
                ValidKits
            }
            );
            var names = Kits?.Call("GetAllKits");
            if (names != null) ValidKits.AddRange((string[])names);
            ValidKits = ValidKits.Distinct().ToList();
            foreach (var kit in ValidKits.ToList()) {
                object checkKit = Kits?.CallHook("GetKitInfo", kit, true);
                bool weaponInKit = 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 (Isweapon(item["itemid"].ToString(), null)) {
                            weaponInKit = true;
                            break;
                        }
                    }
                }
                if (!weaponInKit) ValidKits.Remove(kit);
            }
            if (Kits) foreach (var profile in Profiles) profile.Value.Spawn.Kit = profile.Value.Spawn.Kit.Where(x => ValidKits.Contains(x)).ToList();
            ValidKits = ValidKits.OrderBy(x => x.ToString()).ToList();
        }
        void SetupLootSources() {
            List<string> ignore = Pool.GetList<string>();
            ignore.AddRange("hidden,test,shelves,stocking,mission".Split(','));
            Containers.Add("ScarecrowNPC", null);
            Containers.Add("Random", null);
            foreach (var entry in Resources.FindObjectsOfTypeAll<LootContainer>().Where(x => x != null && !x.isSpawned).ToList()) {
                bool skip = false;
                foreach (var i in ignore) if (entry.PrefabName.Contains(i)) skip = true;
                if (skip) continue;
                string name = GetLootName(entry.PrefabName, entry.ShortPrefabName);
                if (Containers.ContainsKey(name)) continue;
                Containers.Add(name, entry);
            }
            Pool.FreeList<string>(ref ignore);
        }
#endregion
#region Helpers
        public string GetLootName(string name, string name2) => name.Contains("underwater_labs") ? "underwater_labs_" + name2 : name2;
        public void PopulateLoot(LootContainer source, ItemContainer container) {
            LootContainer.LootSpawnSlot[] lootSpawnSlots = source == null ? sc : source.LootSpawnSlots;
            if (lootSpawnSlots.Length != 0) {
                for (int i = 0; i < lootSpawnSlots.Length; i++) {
                    LootContainer.LootSpawnSlot lootSpawnSlot = lootSpawnSlots[i];
                    for (int j = 0; j < lootSpawnSlot.numberToSpawn; j++) if (UnityEngine.Random.Range(0f, 1f) <= lootSpawnSlot.probability) lootSpawnSlot.definition.SpawnIntoContainer(container);
                }
            }
            else if (source?.lootDefinition != null) for (int k = 0; k < source.maxDefinitionsToSpawn; k++) source.lootDefinition.SpawnIntoContainer(container);
            if (source?.SpawnType == LootContainer.spawnType.ROADSIDE || source?.SpawnType == LootContainer.spawnType.TOWN) foreach (Item item in container.itemList) if (item.hasCondition) item.condition = UnityEngine.Random.Range(item.info.condition.foundCondition.fractionMin, item.info.condition.foundCondition.fractionMax) * item.info.condition.max;
            if (source != null && source.scrapAmount > 0) {
                var sc = ItemManager.Create(scrap, source.scrapAmount, 0);
                if (sc.MoveToContainer(container)) sc.Remove(0f);
            }
        }
        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;
        }
        public bool Isweapon(string i, Item item) {
            if (i != string.Empty) item = ItemManager.CreateByItemID(Convert.ToInt32(i), 1);
            var held = item?.GetHeldEntity();
            bool weapon = item?.info?.category == ItemCategory.Weapon || (held != null && (held as ThrownWeapon || held as BaseMelee || held as TorchWeapon));
            if (i != string.Empty && item != null) item.Remove();
            return weapon;
        }
#endregion
#region Hooks
        bool newsave = false;
        void OnNewSave(string filename) => newsave = true;
        object OnNpcKits(ulong userID) => NPCPlayers.ContainsKey(userID) ? true : (object)null;
        object OnNpcDuck(global : : HumanNPC npc) => NPCPlayers.ContainsKey(npc.userID) ? true : (object)null;
        private object CanEntityBeHostile(ScientistNPC npc) => npc != null && NPCPlayers.ContainsKey(npc.userID) ? true : (object)null;
        private object CanBeTargeted(NPCPlayer npc, BaseEntity entity) => (npc != null && NPCPlayers.ContainsKey(npc.userID) && configData.Global.Turret_Safe) ? false : (object)null;
        private object CanBradleyApcTarget(BradleyAPC bradley, NPCPlayer npc) => npc == null ? null : NPCPlayers.ContainsKey(npc.userID) ? !configData.Global.APC_Safe : (object)null;
        private void OnEntitySpawned(BradleyAPC apc) => SetupAPC(apc);
        void OnEntitySpawned(BasePlayer player) => ProcessHumanNPC(player);
        void SetupAPC(BradleyAPC apc) => apc.InvokeRepeating(() => UpdateTargetList(apc), 0f, 2f);
        public void UpdateTargetList(BradleyAPC apc) {
            List<BasePlayer> list = Pool.GetList<BasePlayer>();
            Vis.Entities<BasePlayer>(apc.transform.position, apc.searchRange, list, 133120, QueryTriggerInteraction.Collide);
            foreach (var player in list) {
                if (!player.GetComponent<BotData>() || !apc.VisibilityTest(player)) continue;
                bool flag = false;
                foreach (BradleyAPC.TargetInfo targetInfo in apc.targetList) {
                    if (targetInfo.entity == player) {
                        targetInfo.lastSeenTime = Time.time;
                        flag = true;
                        break;
                    }
                }
                if (flag) continue;
                BradleyAPC.TargetInfo targetInfo1 = Pool.Get<BradleyAPC.TargetInfo>();
                targetInfo1.Setup(player, Time.time);
                apc.targetList.Add(targetInfo1);
            }
            Pool.FreeList<BasePlayer>(ref list);
        }
        object OnEntityTakeDamage(BasePlayer player, HitInfo info) {
            if (player == null || info == null) return null;
            var bData1 = player.GetComponent<BotData>();
            if (bData1 != null) {
                if (info?.Initiator == player || info?.InitiatorPlayer == player) return true;
                if (info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Heat && bData1.profile.Other.Fire_Safe) return true;
                if (info.InitiatorPlayer != null) {
                    if (info.InitiatorPlayer == player) return true;
                    var brain = bData1.GetComponent<BaseAIBrain>();
                    if (brain != null) {
                        if (bData1.inAir && bData1.profile.Other.Invincible_Whilst_Chuting) return true;
                        if (bData1.profile.Behaviour.Respect_Safe_Zones && player.InSafeZone()) return true;
                        if (info.InitiatorPlayer != bData1.CurrentTarget && Vector3.Distance(info.InitiatorPlayer.transform.position, player.transform.position) >= bData1.profile.Other.Immune_From_Damage_Beyond) return true;
                        if (info.InitiatorPlayer == bData1.CurrentTarget || bData1.Targets.ContainsKey(info.InitiatorPlayer)) SetTarget(bData1, brain, info.InitiatorPlayer);
                        else if (bData1.WantsAttack(info.InitiatorPlayer, true)) {
                            SetTarget(bData1, brain, info.InitiatorPlayer);
                            if (configData.Global.NPCs_Assist_NPCs) {
                                var weapon = info?.Weapon as BaseProjectile;
                                List<BotData> bDatas = Pool.GetList<BotData>();
                                Vis.Components<BotData>(player.transform.position, (weapon != null && weapon.IsSilenced() ? 3 : Mathf.Max(50, bData1.profile.Behaviour.Assist_Sense_Range)), bDatas);
                                foreach (var bData in bDatas) {
                                    brain = bData.GetComponent<BaseAIBrain>();
                                    if (brain == null || bData == bData1) continue;
                                    if (info.InitiatorPlayer != bData.CurrentTarget && Vector3.Distance(info.InitiatorPlayer.transform.position, player.transform.position) >= bData.profile.Other.Immune_From_Damage_Beyond) continue;
                                    if (info.InitiatorPlayer == bData.CurrentTarget || bData.Targets.ContainsKey(info.InitiatorPlayer) || bData.WantsAttack(info.InitiatorPlayer, true)) {
                                        timer.Once(Vector3.Distance(bData.transform.position, bData1.transform.position) / 5f, () => {
                                            if (bData?.profile != null && brain?.Senses != null && info.InitiatorPlayer != null && !info.InitiatorPlayer.IsDead()) SetTarget(bData, brain, info.InitiatorPlayer);
                                        }
                                        );
                                    }
                                    //else
                                    //{
                                    //    No LOS? SetDestination(...//}
                                }
                                Pool.FreeList<BotData>(ref bDatas);
                            }
                        }
                    }
                    if (info != null && bData1.profile.Other.Die_Instantly_From_Headshot && info.isHeadshot) {
                        var weap = info?.Weapon?.GetItem()?.info?.shortname;
                        var weaps = bData1.profile.Other.Instant_Death_From_Headshot_Allowed_Weapons;
                        if (weaps.Count == 0 || weap != null && weaps.Contains(weap)) {
                            info.damageTypes.Set(0, player.health);
                            return null;
                        }
                    }
                }
                if (configData.Global.APC_Safe && info?.Initiator is BradleyAPC) return true;
                if (info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Heat) return null;
                if (configData.Global.Pve_Safe) {
                    if (info.Initiator?.ToString() == null && info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Bullet) return true;
                    if (info.Initiator?.ToString() == null || info.Initiator.ToString().Contains("cactus") || info.Initiator.ToString().Contains("barricade")) return true;
                }
            }
            return null;
        }
        void SetTarget(BotData bData, BaseAIBrain brain, BasePlayer target) {
            bData.Addto(bData.Players, target);
            bData.Addto(bData.Targets, target);
            bData.CurrentTarget = target;
            brain.Navigator.SetFacingDirectionEntity(target);
        }
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (player == null) return;
            if (HumanNPCs.Contains(player.userID)) HumanNPCs.Remove(player.userID);
            if (player?.net?.connection != null) DestroyMenu(player, true);
            ScientistNPC npc = player as ScientistNPC;
            if (npc != null) OnEntityKill(npc, info, info?.InitiatorPlayer != null);
        }
        List<uint> BSCrates = new List<uint>();
        object OnEntityKill(ScientistNPC npc) {
            if (npc == null || npc.IsDestroyed) return null;
            return !Unloading && npc?.gameObject?.name == "BotReSpawn" ? true : (object)null;
        }
        void OnEntityKill(ScientistNPC npc, HitInfo info, bool killed) {
            if (npc?.userID != null && NPCPlayers.ContainsKey(npc.userID) && !botInventories.ContainsKey(npc.userID)) {
                botInventories.Add(npc.userID, null);
                foreach (var child in npc.children.Where(child => child.name.Contains("parachute"))) {
                    child.SetParent(null);
                    child.Kill();
                    break;
                }
                var bData = npc.GetComponent<BotData>();
                if (bData == null || !Profiles.ContainsKey(bData?.profilename)) return;
                if (!bData.temporary) timer.Once(Mathf.Max(1, bData.profile.Death.Respawn_Timer * 60), () => bData.sg?.SpawnBot(1, bData.profile.type == ProfileType.Biome || bData.profile.Spawn.ChangeCustomSpawnOnDeath ? null : bData.sp));
                if (killed) {
                    if (!info.InitiatorPlayer.IsNpc) {
                        if (bData.profile.Death.RustRewardsValue > 0) {
                            var weapon = info?.Weapon?.GetItem()?.info?.shortname ?? info?.WeaponPrefab?.ShortPrefabName;
                            RustRewards?.Call("GiveRustReward", info.InitiatorPlayer, 0, bData.profile.Death.RustRewardsValue, npc, weapon, Vector3.Distance(info.InitiatorPlayer.transform.position, npc.transform.position), null);
                        }
                        if (bData.profile.Death.XPerienceValue > 0) XPerience?.Call("GiveXP", info.InitiatorPlayer, bData.profile.Death.XPerienceValue);
                    }
                    if (bData.profile.Death.Spawn_Hackable_Death_Crate_Percent > GetRand(1, 101) && npc.WaterFactor() < 0.1f) {
                        var pos = npc.transform.position;
                        timer.Once(2f, () => {
                            if (bData?.profile == null) return;
                            var Crate = GameManager.server.CreateEntity(LockedCrate, pos + new Vector3(1, 2, 0), Quaternion.Euler(0, 0, 0));
                            Crate.Spawn();
                            BSCrates.Add(Crate.net.ID);
                            (Crate as HackableLockedCrate).hackSeconds = HackableLockedCrate.requiredHackSeconds - bData.profile.Death.Death_Crate_LockDuration * 60;
                            timer.Once(1.4f, () => {
                                if (Crate == null || bData?.profile == null) return;
                                if (CustomLoot && bData.profile.Death.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.Death_Crate_CustomLoot_Profile);
                                        if (loot != null) foreach (var item in loot) if (!item.MoveToContainer(container.inventory, -1, true)) item.Remove();
                                    }
                                }
                            }
                            );
                        }
                        );
                    }
                    Interface.CallHook("OnBotReSpawnNPCKilled", npc, bData.profilename, bData.group, info);
                }
                Item activeItem = npc.GetActiveItem();
                if (bData.profile.Death.Weapon_Drop_Percent >= GetRand(1, 101) && activeItem != null) {
                    var numb = GetRand(Mathf.Min(bData.profile.Death.Min_Weapon_Drop_Condition_Percent, bData.profile.Death.Max_Weapon_Drop_Condition_Percent), bData.profile.Death.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, name = npc.displayName,
                }
                ;
                botInventories[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,
                    }
                    );
                }
                DeadNPCPlayerIds.Add(npc.userID, bData.profile.Other.Backpack_Duration * 60);
                no_of_AI--;
            }
        }
#endregion
#region Events
        void OnEntitySpawned(HackableLockedCrate crate) {
            NextTick(() => {
                if (crate == null || !loaded || (configData.Global.Ignore_HackableCrates_With_OwnerID && crate.OwnerID != 0) || BSCrates.Contains(crate.net.ID) || Interface.CallHook("OnBotReSpawnCrateDropped", crate) != null) return;
                if (configData.Global.Ignore_Parented_HackedCrates && crate.HasParent() || crate.transform?.parent != null) return;
                DoEvent("LockedCrate_Spawn", crate.transform.position);
            }
            );
        }
        void OnCrateHack(HackableLockedCrate crate) {
            NextTick(() => {
                if (crate == null || (configData.Global.Ignore_HackableCrates_With_OwnerID && crate.OwnerID != 0)) return;
                if (configData.Global.Ignore_Parented_HackedCrates && crate.HasParent() || crate.transform?.parent != null) return;
                if (Interface.CallHook("OnBotReSpawnCrateHackBegin", crate) != null) return;
                DoEvent("LockedCrate_HackStart", crate.transform.position);
            }
            );
        }
        void OnEntityDeath(BaseEntity entity) {
            if (entity?.transform?.position == null) return;
            string prof = string.Empty;
            if (entity is BradleyAPC) {
                if (Interface.CallHook("OnBotReSpawnAPCKill", entity) != null) return;
                prof = "APC_Kill";
            }
            if (entity?.GetComponent<PatrolHelicopterAI>()) {
                if (Interface.CallHook("OnBotReSpawnPatrolHeliKill", entity) != null) return;
                prof = "PatrolHeli_Kill";
            }
            if (entity.GetComponent<CH47HelicopterAIController>()) {
                if (Interface.CallHook("OnBotReSpawnCH47Kill", entity) != null) return;
                prof = "CH47_Kill";
            }
            if (prof != string.Empty) DoEvent(prof, entity.transform.position);
        }
        void DoEvent(string name, Vector3 pos) {
            Profile profile = Profiles[name];
            if (profile.Spawn.AutoSpawn == true && GetPop(profile) > 0) {
                if (profile.Spawn.Announce_Spawn && profile.Spawn.Announcement_Text != String.Empty) PrintToChat(profile.Spawn.Announcement_Text);
                int quantity = GetPop(profile);
                if (profile.Spawn.AutoSpawn == true && quantity > 0) {
                    profile.Other.Location = pos;
                    CreateTempSpawnGroup(pos, name, profile, string.Empty, quantity);
                }
            }
        }
#endregion
#region SpawningHooks
        void OnEntitySpawned(DroppedItemContainer container) {
            NextTick(() => {
                if (!loaded || container == null || container.IsDestroyed || container.playerSteamID == 0) return;
                if (DeadNPCPlayerIds.ContainsKey(container.playerSteamID)) {
                    if (configData.Global.Remove_BackPacks_Percent >= GetRand(1, 101)) {
                        if (container != null && !container.IsDestroyed) container.Kill();
                    }
                    else {
                        container.CancelInvoke(container.RemoveMe);
                        timer.Once(DeadNPCPlayerIds[container.playerSteamID], () => {
                            if (container != null && !container.IsDestroyed) container?.Kill();
                        }
                        );
                    }
                    DeadNPCPlayerIds.Remove(container.playerSteamID);
                }
            }
            );
        }
        void OnEntitySpawned(SupplySignal signal) {
            if (configData.Global.Ignore_Skinned_Supply_Grenades && signal.skinID != 0) return;
            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 (Interface.CallHook("OnBotReSpawnAirdrop", drop) != null) 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;
                }
            }
            Profile profile = null;
            Profiles.TryGetValue("AirDrop", out profile);
            if (profile != null) DoEvent("AirDrop", drop.transform.position);
        }
        object CanPopulateLoot(ScientistNPC entity, NPCPlayerCorpse corpse) => !configData.Global.Allow_AlphaLoot && botInventories.ContainsKey(corpse.playerSteamID) ? true : (object)null;
        void OnEntitySpawned(NPCPlayerCorpse corpse) {
            if (!loaded || corpse == null) return;
            Inv botInv = new Inv();
            ulong id = corpse.playerSteamID;
            timer.Once(0.1f, () => {
                if (corpse == null || corpse.IsDestroyed || !botInventories.ContainsKey(id)) return;
                botInv = botInventories[id];
                if (botInv == null) return;
                Profile profile = botInv.profile;
                timer.Once(profile.Death.Corpse_Duration * 60, () => {
                    if (corpse != null && !corpse.IsDestroyed) corpse?.Kill();
                }
                );
                timer.Once(2, () => {
                    if (profile != null) corpse?.ResetRemovalTime(profile.Death.Corpse_Duration * 60);
                }
                );
                if (!(profile.Death.Allow_Rust_Loot_Percent >= GetRand(1, 101))) corpse.containers[0].Clear();
                else {
                    if (profile.Death.Rust_Loot_Source != "Default NPC") {
                        LootContainer container = null;
                        if (profile.Death.Rust_Loot_Source == "Random") container = Containers.ElementAt(random.Next(0, Containers.Count)).Value;
                        else Containers.TryGetValue(profile.Death.Rust_Loot_Source, out container);
                        corpse.containers[0].Clear();
                        PopulateLoot(container, corpse.containers[0]);
                    }
                    foreach (var item in corpse.containers[0].itemList.ToList()) if ((item.info.shortname.Contains("keycard") && configData.Global.Remove_KeyCard) || (item.info.shortname.Contains("frankensteins.") && configData.Global.Remove_Frankenstein_Parts)) item.Remove();
                }
                Item playerSkull = ItemManager.CreateByName("skull.human", 1);
                playerSkull.name = string.Concat($"Skull of {botInv.name}");
                ItemAmount SkullInfo = new ItemAmount() {
                    itemDef = playerSkull.info, amount = 1, startAmount = 1
                }
                ;
                var dispenser = corpse.GetComponent<ResourceDispenser>();
                if (dispenser != null) {
                    dispenser.containedItems.Add(SkullInfo);
                    dispenser.Initialize();
                }
                for (int i = 0; i < botInv.inventory.Length; i++) {
                    if (i == 1) continue;
                    foreach (var item in botInv.inventory[i]) {
                        var giveItem = ItemManager.CreateByItemID(item.ID, item.amount, item.skinID);
                        if (!giveItem.MoveToContainer(corpse.containers[i], -1, true)) giveItem.Remove();
                    }
                }
                timer.Once(5f, () => botInventories?.Remove(id));
                if (profile.Death.Wipe_Belt_Percent >= GetRand(1, 101)) corpse.containers[2].Clear();
                if (profile.Death.Wipe_Clothing_Percent >= GetRand(1, 101)) corpse.containers[1].Clear();
                ItemManager.DoRemoves();
                corpse.containers = new ItemContainer[] {
                    corpse.containers[0], new ItemContainer(), new ItemContainer(), corpse.containers[1], corpse.containers[2]
                }
                ;
                corpse._playerName = botInv.name;
                corpse.lootPanelName = botInv.name;
            }
            );
        }
#endregion
#region WeaponSwitching
        void SelectWeapon(ScientistNPC npc, BotData bData, BaseAIBrain brain) {
            if (npc == null) {
                TidyUp(npc, bData);
                return;
            }
            if (bData == null || bData.throwing || bData.healing || brain?.Senses == null || npc?.inventory?.containerBelt == null) return;
            if (bData.CurrentTarget == null || !bData.Targets.ContainsKey(bData.CurrentTarget) || !brain.Senses.Memory.IsLOS(bData.CurrentTarget)) bData.GetNearest();
            Range enemyrange = bData.CurrentTarget == null ? TargetRange(41) : TargetRange(Vector3.Distance(npc.transform.position, bData.CurrentTarget.transform.position));
            Range bestrange = BestRange(bData, enemyrange);
            bData.canFire = !(configData.Global.Limit_ShortRange_Weapon_Use && bestrange == Range.Close && enemyrange == Range.Long);
            if (bestrange == bData.currentRange) {
                SetLights(bData, npc.GetHeldEntity());
                return;
            }
            bData.currentRange = bestrange;
            UpdateActiveItem(npc, bData.Weaps[bestrange].GetRandom(), bData);
        }
        void SetLights(BotData bData, HeldEntity held) {
            bData.torch = held as TorchWeapon;
            if (bData.torch != null) {
                bData.torch.fuelTickAmount = 0;
                bData.torch.SetIsOn(bData.profile.Behaviour.AlwaysUseLights ? true : IsNight);
            }
            else {
                bData.gun = held as BaseProjectile;
                if (bData.gun != null) bData.gun.SetLightsOn(bData.profile.Behaviour.AlwaysUseLights ? true : IsNight);
            }
            if (bData.hasHeadLamp) HeadLampToggle(bData.npc, bData.profile.Behaviour.AlwaysUseLights ? true : IsNight);
        }
        void UpdateActiveItem(ScientistNPC npc, HeldEntity held, BotData bData) {
            if (held == null) {
                npc.CancelInvoke("SelectWeapon");
                return;
            }
            var activeItem = npc.GetHeldEntity();
            npc.svActiveItemID = 0U;
            if (activeItem != null) activeItem.SetHeld(false);
            npc.svActiveItemID = held.GetItem().uid;
            npc.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
            SetRange(npc, held, bData);
            if (held != null) held.SetHeld(true);
            npc.inventory.UpdatedVisibleHolsteredItems();
            var cs = held as Chainsaw;
            if (cs != null) {
                if (cs.HasFlag(BaseEntity.Flags.On)) return;
                cs.SetEngineStatus(true);
                cs.SendNetworkUpdateImmediate(false);
            }
            var cs1 = held as Jackhammer;
            if (cs1 != null) {
                if (cs1.HasFlag(BaseEntity.Flags.On)) return;
                cs1.SetEngineStatus(true);
                cs1.SendNetworkUpdateImmediate(false);
            }
        }
        void SetRange(ScientistNPC npc, HeldEntity held, BotData bData) {
            var weapon = held as AttackEntity;
            if (bData != null && weapon != null) weapon.effectiveRange = bData.Weaps[Range.Melee].Contains(held) ? 2 : 410;
        }
        void HeadLampToggle(ScientistNPC npc, bool NewState) {
            foreach (var item in npc.inventory.containerWear.itemList.Where(item => item.info.shortname.Equals("hat.miner") || item.info.shortname.Equals("hat.candle"))) {
                if ((NewState && !item.IsOn()) || (!NewState && item.IsOn())) {
                    item.SwitchOnOff(NewState);
                    npc.inventory.ServerUpdate(0f);
                    break;
                }
            }
        }
        void TidyUp(ScientistNPC npc, BotData bData) {
            if (npc != null && !npc.IsDestroyed) npc.Kill();
            if (bData != null) UnityEngine.Object.DestroyImmediate(bData);
        }
#endregion
#region SetUpLocations
        public Dictionary<string, Profile> GotMonuments = new Dictionary<string, Profile>();
        public Dictionary<string, List<SpawnerInfo>> Spawners = new Dictionary<string, List<SpawnerInfo>>();
        public class SpawnerInfo {
            public bool Destroy = false;
            public GameObject go;
            public Profile profile;
        }
        void AddProfile(GameObject go, string name, Profile monument, Vector3 pos) {
            if (monument == null && defaultData.Monuments.ContainsKey(name)) monument = defaultData.Monuments[name];
            else if (monument == null) monument = new Profile(ProfileType.Monument);
            Spawners[name] = new List<SpawnerInfo>() {
                new SpawnerInfo() {
                    go = go, profile = monument
                }
            }
            ;
            Profiles[name] = monument;
            Profiles[name].Other.Location = pos;
            foreach (var custom in storedData.Profiles) {
                if (custom.Value.Other.Parent_Monument == name && storedData.MigrationDataDoNotEdit.ContainsKey(custom.Key)) {
                    var path = storedData.MigrationDataDoNotEdit[custom.Key];
                    if (path.ParentMonument == new Vector3()) {
                        Puts($"Parent_Monument added for {custom.Key}.Removing any existing custom spawn points");
                        spawnsData.CustomSpawnLocations[custom.Key].Clear();
                        SaveSpawns();
                        path.ParentMonument = pos;
                        path.Offset = Spawners[name][0].go.transform.InverseTransformPoint(custom.Value.Other.Location);
                    }
                }
                else {
                    if (!storedData.MigrationDataDoNotEdit.ContainsKey(custom.Key)) storedData.MigrationDataDoNotEdit.Add(custom.Key, new ProfileRelocation());
                    if (custom.Value.Other.Parent_Monument == "" && storedData.MigrationDataDoNotEdit[custom.Key].ParentMonument != new Vector3()) {
                        Puts($"Parent_Monument removed for {custom.Key}.Removing any existing custom spawn points");
                        spawnsData.CustomSpawnLocations[custom.Key].Clear();
                        storedData.MigrationDataDoNotEdit[custom.Key] = new ProfileRelocation();
                        SaveSpawns();
                    }
                }
            }
        }
        void AddData(string name, Profile profile) {
            if (!storedData.MigrationDataDoNotEdit.ContainsKey(name)) storedData.MigrationDataDoNotEdit.Add(name, new ProfileRelocation());
            var path = storedData.MigrationDataDoNotEdit[name];
            if (profile.Other.Parent_Monument != String.Empty) {
                if (Profiles.ContainsKey(profile.Other.Parent_Monument)) {
                    if (path.ParentMonument != Profiles[profile.Other.Parent_Monument].Other.Location) {
                        bool userChanged = false;
                        foreach (var monument in Profiles) if (monument.Value.Other.Location == Profiles[profile.Other.Parent_Monument].Other.Location && monument.Key != profile.Other.Parent_Monument) {
                            userChanged = true;
                            break;
                        }
                        profile.Other.Location = Spawners[profile.Other.Parent_Monument][0].go.transform.TransformPoint(path.Offset);
                        if (userChanged) {
                            Puts($"Parent_Monument change detected for {name}.Removing any existing custom spawn points");
                            spawnsData.CustomSpawnLocations[name].Clear();
                            SaveSpawns();
                        }
                        path.ParentMonument = Profiles[profile.Other.Parent_Monument].Other.Location;
                        path.Offset = Spawners[profile.Other.Parent_Monument][0].go.transform.InverseTransformPoint(profile.Other.Location);
                    }
                }
                else if (profile.Spawn.AutoSpawn == true) Puts($"Parent monument {profile.Other.Parent_Monument} does not exist for custom profile {name}");
            }
            else if (newsave && configData.Global.Disable_Non_Parented_Custom_Profiles_After_Wipe) profile.Spawn.AutoSpawn = false;
            Profiles[name] = profile;
            GameObject obj = new GameObject();
            obj.transform.position = profile.Other.Location;
            List<SpawnerInfo> parent;
            Spawners.TryGetValue(profile.Other.Parent_Monument, out parent);
            if (parent?[0]?.go) obj.transform.rotation = parent[0].go.transform.rotation;
            Spawners[name] = new List<SpawnerInfo>() {
                new SpawnerInfo() {
                    go = obj, profile = profile, Destroy = true
                }
            }
            ;
        }
        void SetupSpawnsFile() {
            bool flag = false;
            foreach (var entry in Profiles.Where(entry => entry.Value.type != ProfileType.Biome && entry.Value.type != ProfileType.Event)) {
                if (!spawnsData.CustomSpawnLocations.ContainsKey(entry.Key)) {
                    spawnsData.CustomSpawnLocations.Add(entry.Key, new List<SpawnData>());
                    flag = true;
                }
                if (entry.Value.Spawn.AutoSpawn && entry.Value.Spawn.UseCustomSpawns && spawnsData.CustomSpawnLocations[entry.Key].Count == 0) PrintWarning(lang.GetMessage("nospawns", this), entry.Key);
            }
            if (flag) SaveSpawns();
        }
#endregion
#region SpawnGroups
        void DestroySpawnGroups(GameObject gameObject = null) {
            foreach (var entry in Spawners.ToList()) {
                if (entry.Value == null) continue;
                foreach (var go in Spawners[entry.Key].ToList()) {
                    if (gameObject == null || go?.go == gameObject) {
                        if (go?.go != null) {
                            var sg = go.go.GetComponent<CustomGroup>();
                            if (sg == null) continue;
                            SpawnHandler.Instance.SpawnGroups.Remove(sg);
                            UnityEngine.Object.Destroy(sg);
                            if (go.Destroy) UnityEngine.Object.Destroy(go.go);
                        }
                    }
                }
            }
        }
        void RemoveTemp(GameObject gameObject = null) {
            foreach (var entry in Spawners.ToList()) {
                if (entry.Value == null) continue;
                foreach (var go in entry.Value) {
                    if (gameObject == null || go?.go == gameObject) {
                        if (go?.go != null) {
                            var sg = go.go.GetComponent<CustomGroup>();
             
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху