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

FREE MonBots : 1.0.27 1.0.27

Нет прав для скачивания
C#:
#region License (GPL v2)
/*
    MonBots - NPC Players that protect monuments, sort of
    Copyright (c) 2021 RFC1920 <desolationoutpostpve@gmail.com>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License v2.0.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

    Optionally you can also view the license at <http://www.gnu.org/licenses/>.
*/
#endregion License (GPL v2)
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.AI;

namespace Oxide.Plugins
{
    [Info("MonBots", "RFC1920", "1.0.27")]
    [Description("Adds interactive NPCs at various monuments")]
    internal class MonBots : RustPlugin
    {
        #region vars
        [PluginReference]
        private readonly Plugin Kits, ZoneManager;

        private ConfigData configData;
        private const string sci = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";
        private List<ulong> isopen = new();

        //private const string permNPCGuiUse = "monbot.use";
        private const string NPCGUI = "monbot.editor";
        private const string NPCGUK = "monbot.kitselect";
        private const string NPCGUM = "monbot.monselect";
        private const string NPCGUN = "monbot.kitsetnames";
        private const string NPCGUP = "monbot.newprofile";
        private readonly List<string> guis = new() { NPCGUI, NPCGUK, NPCGUM, NPCGUN, NPCGUP };

        private bool newsave;
        private bool do1017;

        public static MonBots Instance;
        public SortedDictionary<string, SpawnProfile> spawnpoints = new();
        //        private Dictionary<string, MonBotsZoneMap> zonemaps = new Dictionary<string, MonBotsZoneMap>();
        private Dictionary<ulong, MonBotPlayer> hpcacheid = new();

        private static SortedDictionary<string, Vector3> monPos = new();
        private static SortedDictionary<string, Vector3> monSize = new();
        private static SortedDictionary<string, Vector3> cavePos = new();
        private Dictionary<ulong, Inventories> InvCache = new();

        private readonly static int playerMask = LayerMask.GetMask("Player (Server)");
        #endregion vars

        #region Message
        private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
        private void Message(IPlayer player, string key, params object[] args) => player.Reply(Lang(key, player.Id, args));

        private void DoLog(string message)
        {
            if (configData.Options.debug)
            {
                Interface.GetMod().LogInfo($"{Name}: {message}");
            }
        }
        #endregion Message

        #region global
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["add"] = "Add",
                ["addhere"] = "Add Here",
                ["at"] = "at",
                ["cancel"] = "Cancel",
                ["close"] = "Close",
                ["debug"] = "Debug set to {0}",
                ["delete"] = "DELETE",
                ["detectrange"] = "Detect Range",
                ["dropweapon"] = "DropWeapon",
                ["edit"] = "Edit",
                ["editing"] = "Editing",
                ["end"] = "End",
                ["gotospawn"] = "Go There",
                ["hostile"] = "Hostile",
                ["silent"] = "Silence Effects",
                ["invulnerable"] = "Invulnerable",
                ["kit(s)"] = "Kit(s)",
                ["lootable"] = "Lootable",
                ["wipeclothing"] = "Wipe clothing",
                ["wipebelt"] = "Wipe belt",
                ["wipemain"] = "Wipe main",
                ["wipecorpsemain"] = "Wipe corpse main",
                ["monbots"] = "MonBots",
                ["movehere"] = "Move Here",
                ["name"] = "Name",
                ["name(s)"] = "Name(s)",
                ["needselect"] = "Select NPC",
                ["new"] = "Create New",
                ["none"] = "None",
                ["npcgui"] = "MonBot GUI",
                ["npcguikit"] = "MonBot GUI Kit Select",
                ["npcguimon"] = "MonBot GUI Profile Select",
                ["npcguinames"] = "MonBot GUI Bot Names",
                ["profile"] = "Profile",
                ["respawn"] = "Respawn",
                ["respawntime"] = "Respawn Time",
                ["roamrange"] = "Roam Range",
                ["select"] = "Select",
                ["spawncount"] = "Spawn Count",
                ["spawnrange"] = "Spawn Range",
                ["start"] = "Start"
            }, this);
        }

        private void OnServerInitialized()
        {
            LoadConfigVariables();
            Instance = this;

            AddCovalenceCommand("mb", "cmdMB");

            FindMonuments();
            LoadData();
            LoadBots();

            foreach (KeyValuePair<string, Vector3> mon in monPos)
            {
                if (!spawnpoints.ContainsKey(mon.Key))
                {
                    AddProfile(mon.Value, mon.Key);
                }
            }

            //SaveData();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                foreach (string gui in guis)
                {
                    CuiHelper.DestroyUi(player, gui);
                }

                if (isopen.Contains(player.userID))
                {
                    isopen.Remove(player.userID);
                }
            }
        }

        private void OnNewSave() => newsave = true;

        private void Unload()
        {
            foreach (BasePlayer player in BasePlayer.activePlayerList.Where(x => x.IsAdmin))
            {
                foreach (string gui in guis)
                {
                    CuiHelper.DestroyUi(player, gui);
                }

                if (isopen.Contains(player.userID))
                {
                    isopen.Remove(player.userID);
                }
            }

            //MonBotPlayer[] bots = UnityEngine.Object.FindObjects<MonBotPlayer>();
            MonBotPlayer[] bots = (MonBotPlayer[]) UnityEngine.Object.FindObjectsByType(typeof(MonBotPlayer), FindObjectsSortMode.InstanceID);
            if (bots != null)
            {
                foreach (MonBotPlayer bot in bots)
                {
                    UnityEngine.Object.Destroy(bot);
                }
            }

            foreach (KeyValuePair<string, SpawnProfile> x in new Dictionary<string, SpawnProfile>(spawnpoints))
            {
                x.Value.pos = new List<Vector3>();
                x.Value.ids = new List<ulong>();
            }
            SaveData();
        }

        #region commands
        [Command("mb")]
        private void cmdMB(IPlayer iplayer, string command, string[] args)
        {
            if (!iplayer.IsAdmin) return;
            BasePlayer player = iplayer.Object as BasePlayer;
            if (args.Length > 0)
            {
                DoLog(string.Join(",", args));
                switch (args[0])
                {
                    // The b version of the commands here are for the GUI, the non-B are left behind for command line people, if any
                    case "bsc":
                        {
                            if (args.Length > 2)
                            {
                                int intval = int.Parse(args[2]);
                                string monname = Base64Decode(args[1]);
                                spawnpoints[monname].spawnCount = intval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                        }
                        break;
                    case "sc":
                        {
                            try
                            {
                                int intval = int.Parse(args.Last());
                                List<string> newarg = new(args);
                                newarg.RemoveAt(0);
                                newarg.RemoveAt(newarg.Count - 1);
                                string monname = string.Join(" ", newarg);
                                spawnpoints[monname].spawnCount = intval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                            catch { }
                        }
                        break;
                    case "bsr":
                        {
                            if (args.Length > 2)
                            {
                                int intval = int.Parse(args[2]);
                                string monname = Base64Decode(args[1]);
                                spawnpoints[monname].spawnRange = intval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                        }
                        break;
                    case "sr":
                        {
                            int intval = int.Parse(args.Last());
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(newarg.Count - 1);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].spawnRange = intval;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "brt":
                        {
                            if (args.Length > 2)
                            {
                                int intval = int.Parse(args[2]);
                                string monname = Base64Decode(args[1]);
                                spawnpoints[monname].respawnTime = intval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                        }
                        break;
                    case "rt":
                        {
                            int intval = int.Parse(args.Last());
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(newarg.Count - 1);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].respawnTime = intval;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "bdr":
                        {
                            if (args.Length > 2)
                            {
                                float fval = float.Parse(args[2]);
                                string monname = Base64Decode(args[1]);
                                spawnpoints[monname].detectRange = fval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                        }
                        break;
                    case "dr":
                        {
                            float fval = float.Parse(args.Last());
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(newarg.Count - 1);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].detectRange = fval;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "brr":
                        {
                            if (args.Length > 2)
                            {
                                float fval = float.Parse(args[2]);
                                string monname = Base64Decode(args[1]);
                                spawnpoints[monname].roamRange = fval;
                                SaveData();
                                NPCProfileEditGUI(player, monname);
                            }
                        }
                        break;
                    case "rr":
                        {
                            float fval = float.Parse(args.Last());
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(newarg.Count - 1);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].roamRange = fval;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "rs":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].respawn = !spawnpoints[monname].respawn;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "inv":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].invulnerable = !spawnpoints[monname].invulnerable;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "loot":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].lootable = !spawnpoints[monname].lootable;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "wipec":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].wipeClothing = !spawnpoints[monname].wipeClothing;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "wipeb":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].wipeBelt = !spawnpoints[monname].wipeBelt;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "wipem":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].wipeMain = !spawnpoints[monname].wipeMain;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "wipecm":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].wipeCorpseMain = !spawnpoints[monname].wipeCorpseMain;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "drop":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].dropWeapon = !spawnpoints[monname].dropWeapon;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "hostile":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].hostile = !spawnpoints[monname].hostile;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "silent":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].silent = !spawnpoints[monname].silent;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "names":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);

                            NPCNamesGUI(player, monname);
                        }
                        break;
                    case "name":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(newarg.Count - 1);
                            string monname = string.Join(" ", newarg);
                            SpawnProfile sp = spawnpoints[monname];
                            string botname = args[1];
                            string newname = args.Last();

                            if (sp.names == null || sp.names.Count == 0)
                            {
                                sp.names = new List<string>();
                            }
                            if (botname == "NEW_NAME" && !sp.names.Contains(newname))
                            {
                                sp.names.Add(newname);
                            }
                            else if (sp.names.Contains(botname))
                            {
                                sp.names.Remove(botname);
                                if (newname != "DELETE_ME")
                                {
                                    sp.names.Add(newname);
                                }
                            }
                            SaveData();
                            NPCNamesGUI(player, monname);
                        }
                        break;
                    case "delete":
                        {
                            CuiHelper.DestroyUi(player, NPCGUI);
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);

                            //foreach (MonBotPlayer bot in UnityEngine.Object.FindObjectsOfType<MonBotPlayer>())
                            foreach (MonBotPlayer bot in UnityEngine.Object.FindObjectsByType(typeof(MonBotPlayer), FindObjectsSortMode.InstanceID))
                            {
                                if (bot.info.monument == monname)
                                {
                                    DoLog($"Killing bot {bot.info.displayName} at {monname}");
                                    UnityEngine.Object.Destroy(bot);
                                }
                            }

                            spawnpoints.Remove(monname);
                            SaveData();
                            NPCProfileSelectGUI(player);
                        }
                        break;
                    case "gothere":
                        {
                            CuiHelper.DestroyUi(player, NPCGUI);
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            Vector3 newpos = spawnpoints[monname].monpos;
                            newpos.y = TerrainMeta.HeightMap.GetHeight(newpos);
                            Teleport(player, newpos);
                        }
                        break;
                    case "spawnhere":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            spawnpoints[monname].monpos = player.transform.position;
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "respawn":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);

                            //foreach (MonBotPlayer bot in UnityEngine.Object.FindObjectsOfType<MonBotPlayer>())
                            foreach (MonBotPlayer bot in UnityEngine.Object.FindObjectsByType(typeof(MonBotPlayer), FindObjectsSortMode.InstanceID))
                            {
                                if (bot.info.monument == monname)
                                {
                                    DoLog($"Killing bot {bot.info.displayName} at {monname}");
                                    UnityEngine.Object.Destroy(bot);
                                }
                            }
                            LoadBots(monname);

                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "selkit":
                        {
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            NPCKitSelectGUI(player, monname);
                        }
                        break;
                    case "kitsel":
                        if (args.Length > 2)
                        {
                            CuiHelper.DestroyUi(player, NPCGUK);
                            string kit = args[1];
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            DoLog($"Checking kits for '{monname}'");
                            if (spawnpoints[monname].kits == null || spawnpoints[monname].kits.Count == 0)
                            {
                                spawnpoints[monname].kits = new List<string>();
                            }
                            if (spawnpoints[monname].kits.Contains(kit))
                            {
                                spawnpoints[monname].kits.Remove(kit);
                            }
                            else
                            {
                                spawnpoints[monname].kits.Add(kit);
                            }
                            SaveData();
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "addprofile":
                        {
                            NPCNewProfileGUI(player);
                        }
                        break;
                    case "newprofile":
                        {
                            CuiHelper.DestroyUi(player, NPCGUP);
                            AddProfile(player.transform.position, args[1]);
                            NPCProfileEditGUI(player, args[1]);
                        }
                        break;
                    case "monsel":
                        if (args.Length > 1)
                        {
                            CuiHelper.DestroyUi(player, NPCGUM);
                            List<string> newarg = new(args);
                            newarg.RemoveAt(0);
                            string monname = string.Join(" ", newarg);
                            NPCProfileEditGUI(player, monname);
                        }
                        break;
                    case "newprofileclose":
                        CuiHelper.DestroyUi(player, NPCGUP);
                        break;
                    case "newprofilecancel":
                        CuiHelper.DestroyUi(player, NPCGUP);
                        NPCProfileSelectGUI(player);
                        break;
                    case "namesclose":
                        CuiHelper.DestroyUi(player, NPCGUN);
                        break;
                    case "selkitclose":
                        CuiHelper.DestroyUi(player, NPCGUK);
                        break;
                    case "selmonclose":
                        CuiHelper.DestroyUi(player, NPCGUM);
                        break;
                    case "close":
                        IsOpen(player.userID, false);
                        CuiHelper.DestroyUi(player, NPCGUI);
                        CuiHelper.DestroyUi(player, NPCGUK);
                        CuiHelper.DestroyUi(player, NPCGUM);
                        break;
                }
            }
            else
            {
                foreach (string gui in guis)
                {
                    CuiHelper.DestroyUi(player, gui);
                }
                NPCProfileSelectGUI(player);
            }
        }
        #endregion commands

        private void SpawnBot(ulong userid)
        {
            // Used to identify bot for respawn on death
            if (hpcacheid.ContainsKey(userid))
            {
                DoLog($"{userid} found in cached ids!");
                MonBotPlayer botinfo = hpcacheid[userid];
                SpawnProfile sp = spawnpoints[botinfo.info.monument];
                DoLog($"Respawning bot {botinfo.info.displayName} at {sp.monname}");
                SpawnBot(sp, botinfo.spawnPos, botinfo.info.kit);
            }
            else
            {
                DoLog($"{userid} not found in cached ids :(");
            }
        }

        private void SpawnBot(SpawnProfile sp, Vector3 pos, string kit)
        {
            // Used for initial spawn by LoadBots()
            if (pos == default(Vector3)) return;
            pos = AdjustSpawnPoint(pos, sp.roamRange / 2);
            spawnpoints[sp.monname].pos.Add(pos);
            DoLog($"Spawning bot at {pos}");
            global::HumanNPC bot = (global::HumanNPC)GameManager.server.CreateEntity(sci, pos, new Quaternion(), true);
            bot.Spawn();
            spawnpoints[sp.monname].ids.Add(bot.userID);

            string botname = "Bot";
            if (sp.names != null)
            {
                botname = GetBotName(sp.names.ToArray());
            }

            NextTick(() =>
            {
                DoLog($"Adding Mono to bot {botname} at {sp.monname} ({pos})");
                try
                {
                    MonBotPlayer mono = bot.gameObject.AddComponent<MonBotPlayer>();
                    mono.spawnPos = pos;

                    DoLog("Setting info object");
                    mono.info = new MonBotInfo(bot.userID, bot.transform.position, bot.transform.rotation)
                    {
                        displayName = botname,
                        userid = bot.userID,
                        monument = sp.monname,
                        lootable = sp.lootable,
                        wipeClothing = sp.wipeClothing,
                        wipeBelt = sp.wipeBelt,
                        wipeMain = sp.wipeMain,
                        wipeCorpseMain = sp.wipeCorpseMain,
                        health = sp.startHealth,
                        invulnerable = sp.invulnerable,
                        hostile = sp.hostile,
                        silent = sp.silent,
                        dropWeapon = sp.dropWeapon,
                        detectRange = sp.detectRange,
                        roamRange = sp.roamRange,
                        respawnTimer = sp.respawnTime,
                        respawn = sp.respawn,
                        loc = pos,
                        kit = kit
                    };

                    //mono.UpdateHealth(mono.info);
                    bot.startHealth = sp.startHealth;

                    DoLog("Setting brain object");
                    bot.Brain.Navigator.Agent.agentTypeID = -1372625422;
                    bot.Brain.Navigator.DefaultArea = "Walkable";
                    //bot.Brain.Navigator.Agent.autoRepath = true;
                    bot.Brain.Navigator.Agent.autoBraking = true;
                    bot.Brain.Navigator.enabled = true;
                    bot.Brain.Navigator.CanUseNavMesh = true;
                    bot.Brain.Navigator.BestCoverPointMaxDistance = mono.info.roamRange / 2;
                    bot.Brain.Navigator.BestRoamPointMaxDistance = mono.info.roamRange;
                    bot.Brain.Navigator.MaxRoamDistanceFromHome = mono.info.roamRange;
                    bot.Brain.Navigator.Init(bot, bot.Brain.Navigator.Agent);
                    bot.Brain.Navigator.SetDestination(pos, BaseNavigator.NavigationSpeed.Slow, 0f, 0f);

                    bot.Brain.ForceSetAge(0);
                    bot.Brain.AllowedToSleep = false;
                    bot.Brain.sleeping = false;
                    bot.Brain.SenseRange = mono.info.detectRange;
                    bot.Brain.ListenRange = mono.info.detectRange * 2;
                    bot.Brain.TargetLostRange = mono.info.detectRange;
                    bot.Brain.HostileTargetsOnly = false;
                    bot.Brain.IgnoreSafeZonePlayers = true;

                    //bot.Brain.Navigator.Agent.agentTypeID = -1372625422;
                    //bot.Brain.Navigator.DefaultArea = "Walkable";
                    //bot.Brain.Navigator.enabled = true;
                    //bot.Brain.Navigator.CanUseNavMesh = true;
                    //bot.Brain.Navigator.Agent.autoRepath = true;
                    //bot.Brain.Navigator.Init(bot, bot.Brain.Navigator.Agent);
                    //bot.Brain.Navigator.SetDestination(pos, BaseNavigator.NavigationSpeed.Slow, 0f, 0f);
                    //bot.Brain.ForceSetAge(0);
                    //bot.Brain.TargetLostRange = mono.info.detectRange;
                    //bot.Brain.HostileTargetsOnly = !mono.info.hostile;
                    //bot.Brain.Navigator.BestCoverPointMaxDistance = mono.info.roamRange / 2;
                    //bot.Brain.Navigator.BestRoamPointMaxDistance = mono.info.roamRange;
                    //bot.Brain.Navigator.MaxRoamDistanceFromHome = mono.info.roamRange;
                    //bot.Brain.Senses.Init(bot, bot.Brain, 5f, mono.info.roamRange, mono.info.detectRange, -1f, true, false, true, mono.info.detectRange, !mono.info.hostile, false, true, EntityType.Player, false);
                    //bot.Brain.Navigator.Resume();

                    DoLog("Setting name and inventory");
                    bot.displayName = botname;
                    hpcacheid.Add(bot.userID, mono);
                    if (kit.Length > 0)
                    {
                        bot.inventory.Strip();
                        Kits?.Call("GiveKit", bot, kit);
                    }

                    if (mono.info.silent)
                    {
                        DoLog("Silencing effects");
                        ScientistNPC npc = bot as ScientistNPC;
                        npc.DeathEffects = new GameObjectRef[0];
                        npc.RadioChatterEffects = new GameObjectRef[0];
                        npc.radioChatterType = ScientistNPC.RadioChatterType.NONE;
                        npc.SetChatterType(ScientistNPC.RadioChatterType.NONE);
                    }
                    timer.Once(5f, () => mono.activeItem = bot.GetActiveItem());
                }
                catch //(Exception ex)
                {
                    DoLog($"Unable to setup bot {botname} at {sp.monname} ({pos}) - Possible navmesh issue.");
                }
            });

            if (bot.IsHeadUnderwater())
            {
                bot.Kill();
            }
        }

        private void LoadBots(string profile = "", int quantity = 0)
        {
            DoLog("LoadBots called");
            foreach (KeyValuePair<string, SpawnProfile> sp in new Dictionary<string, SpawnProfile>(spawnpoints))
            {
                if (profile.Length > 0 && !sp.Key.Equals(profile)) continue;

                Vector3 spawnPos = sp.Value.monpos;
                if (newsave && monPos.ContainsKey(sp.Key))
                {
                    DoLog($"Changing {sp.Key} location due to wipe to {spawnPos}");
                    spawnPos = monPos[sp.Key];
                }
                else if (newsave && !monPos.ContainsKey(sp.Key) && sp.Value.spawnCount > 0)
                {
                    Puts($"Server wipe was detected.  Will not spawn bots for profile '{sp.Key}' since it was either custom or the monument does not exist.");
                    continue;
                }

                int spawnqty = quantity > 0 ? quantity : sp.Value.spawnCount;
                if (spawnqty > 0)
                {
                    DoLog($"Working on spawn at {sp.Key}");
                    for (int i = 0; i < spawnqty; i++)
                    {
                        string kit;
                        if (sp.Value.kits == null)
                        {
                            kit = "";
                        }
                        else if (sp.Value.kits.Count == 1)
                        {
                            kit = sp.Value.kits[0];
                        }
                        else
                        {
                            kit = sp.Value.kits.GetRandom() ?? "";
                        }

                        SpawnBot(sp.Value, spawnPos, kit);
                        SaveData();
                    }
                }
            }
            newsave = false;
        }

        private void LoadBots(Vector3 location, string profile, string group, int quantity = 0)
        {
            DoLog("LoadBots by location called");
            foreach (KeyValuePair<string, SpawnProfile> sp in new Dictionary<string, SpawnProfile>(spawnpoints))
            {
                if (!sp.Key.Equals(profile)) continue;

                sp.Value.zonemap.Add(group);
                Vector3 spawnPos = location;

                if (quantity > 0)
                {
                    DoLog($"Working on location spawn at {sp.Key}");
                    for (int i = 0; i < quantity; i++)
                    {
                        string kit;
                        if (sp.Value.kits == null)
                        {
                            kit = "";
                        }
                        else if (sp.Value.kits.Count == 1)
                        {
                            kit = sp.Value.kits[0];
                        }
                        else
                        {
                            kit = sp.Value.kits.GetRandom();
                        }

                        SpawnBot(sp.Value, spawnPos, kit);
                        SaveData();
                    }
                }
            }
        }

        private bool BadLocation(Vector3 location)
        {
            // Avoid placing in a rock or foundation, water, etc.
            int layerMask = LayerMask.GetMask("Construction", "World", "Water");
            RaycastHit hit;
            if (Physics.Raycast(new Ray(location, Vector3.down), out hit, 6f, layerMask))
            {
                return true;
            }
            else if (Physics.Raycast(new Ray(location, Vector3.up), out hit, 6f, layerMask))
            {
                return true;
            }
            else if (Physics.Raycast(new Ray(location, Vector3.forward), out hit, 6f, layerMask))
            {
                return true;
            }
            return false;
            //return (TerrainMeta.HeightMap.GetHeight(location) - TerrainMeta.WaterMap.GetHeight(location)) >= 0;
        }

        private Vector3 AdjustSpawnPoint(Vector3 pos, float radius)
        {
            Vector3 newpos;// = new Vector3() { x = pos.x, y = pos.y, z = pos.z };
            Vector2 rand;
            bool ok = false;
            int i = 0;
            const int max = 250;

            pos.y = TerrainMeta.HeightMap.GetHeight(pos);
            while (!ok)
            {
                i++;
                rand = UnityEngine.Random.insideUnitCircle * radius;
                newpos = pos + new Vector3(rand.x, 0, rand.y);
                ok = !BadLocation(newpos);

                if (ok || i >= max)
                {
                    newpos.y = TerrainMeta.HeightMap.GetHeight(newpos);
                    if (i >= max)
                    {
                        DoLog($"Found meh spawn position after maxing out on checks at {max}");
                    }
                    else
                    {
                        DoLog($"Found adequate spawn position after {i} check(s)");
                    }
                    newpos.y = TerrainMeta.HeightMap.GetHeight(newpos);
                    return newpos;
                }
            }
            return pos;
        }

        private string GetBotName(string[] names)
        {
            if (names.Length == 1 && !string.IsNullOrEmpty(names[0]))
            {
                return names[0];
            }
            else if (names.Length > 1)
            {
                return names.GetRandom();
            }
            return "Bot";
        }
        #endregion global

        #region Oxide Hooks
        private void LoadData()
        {
            spawnpoints = Interface.GetMod().DataFileSystem.ReadObject<SortedDictionary<string, SpawnProfile>>(Name + "/spawnpoints");

            foreach (KeyValuePair<string, SpawnProfile> sp in spawnpoints)
            {
                DoLog($"Loaded profile {sp.Key}");
                if (monPos.ContainsKey(sp.Key))
                {
                    sp.Value.monpos = monPos[sp.Key];
                }
                if (do1017)
                {
                    DoLog("Patching profile for 1.0.17 upgrade");
                    sp.Value.wipeClothing = true;
                    sp.Value.wipeBelt = true;
                }
            }
            do1017 = false;
        }

        private void SaveData()
        {
            Interface.GetMod().DataFileSystem.WriteObject(Name + "/spawnpoints", spawnpoints);
        }
        private object OnServerCommand(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null) return null;

            if (!arg.cmd.FullName.StartsWith("mb") && isopen.Contains(ulong.Parse(player.UserIDString)))
            {
                return false;
            }
            return null;
        }

        private object OnPlayerCommand(IPlayer player, string command, string[] args)
        {
            if (command != "mb" && isopen.Contains(ulong.Parse(player.Id)))
            {
                if (configData.Options.debug) Puts($"OnPlayerCommand: {command} BLOCKED");
                return true;
            }
            return null;
        }
        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (player == null || input == null) return;
            if (!input.WasJustPressed(BUTTON.USE)) return;

            RaycastHit hit;
            if (Physics.Raycast(player.eyes.HeadRay(), out hit, 3f, playerMask))
            {
                BasePlayer pl = hit.GetEntity().ToPlayer();
                MonBotPlayer hp = pl.GetComponent<MonBotPlayer>();

                if (hp == null) return;

                Interface.GetMod().CallHook("OnUseNPC", hp.player, player);
                SaveData();
            }
        }

        private void OnEntityDeath(global::HumanNPC humannpc, HitInfo hitinfo)
        {
            if (humannpc == null) return;
            MonBotPlayer npc = humannpc.GetComponent<MonBotPlayer>();
            if (npc == null) return;
            DoLog("OnEntityDeath: Found MonBot player");

            hpcacheid.Remove((uint)humannpc.net.ID.Value);

            if (npc.info.dropWeapon)
            {
                DoLog("OnEntityDeath: Attempting to drop weapon");
                if (npc.activeItem != null)
                {
                    DoLog($"Dropping {npc.info.displayName}'s activeItem: {npc.activeItem.info.shortname}");
                    Vector3 vector3 = new(UnityEngine.Random.Range(-2f, 2f), 0.2f, UnityEngine.Random.Range(-2f, 2f));
                    npc.activeItem.Drop(humannpc.GetDropPosition(), humannpc.GetInheritedDropVelocity() + (vector3.normalized * 3f));
                    humannpc.svActiveItemID.Value = 0;
                }
            }

            DoLog($"Populating inventory cache for {npc.info.userid}");
            ItemContainer[] sourceinv = { humannpc.inventory.containerMain, humannpc.inventory.containerWear, humannpc.inventory.containerBelt };
            InvCache.Add(humannpc.userID, new Inventories());
            for (int i = 0; i < sourceinv.Length; i++)
            {
                foreach (Item item in sourceinv[i].itemList)
                {
                    InvCache[humannpc.userID].inventory[i].Add(new ItemInfo
                    {
                        ID = item.info.itemid,
                        amount = item.amount,
                        skinID = item.skin
                    });
                }
            }
            DoLog($"DONE populating inventory cache for {npc.info.userid}");

            DoLog("Checking respawn variable");
            if (npc?.info.respawn == true)
            {
                DoLog($"Setting {npc.info.respawnTimer} second respawn timer for {npc.info.displayName} ({npc.info.userid})");
                timer.Once(npc.info.respawnTimer, () => SpawnBot(npc.info.userid));
            }
        }

        private void OnEntitySpawned(NPCPlayerCorpse corpse)
        {
            if (corpse == null) return;
            ulong userid = corpse?.playerSteamID ?? 0;
            if (hpcacheid.ContainsKey(userid))
            {
                MonBotPlayer npc = hpcacheid[userid];
                DoLog($"Setting corpse loot panel name to {npc.info.displayName}");
                corpse._playerName = npc.info.displayName;
                corpse.lootPanelName = npc.info.displayName;

                timer.Once(0.1f, () =>
                {
                    DoLog("Checking corpse lootable flag");
                    if (npc.info.lootable && InvCache.ContainsKey(userid))
                    {
                        for (int i = 0; i < InvCache[userid].inventory.Length; i++)
                        {
                            // For main, if wipe is true, the corpse will get a default loot collection rather than what the NPC had
                            if ((corpse.containers[i].capacity == 24 && !npc.info.wipeMain) ||
                                (corpse.containers[i].capacity == 7 && !npc.info.wipeClothing) ||
                                (corpse.containers[i].capacity == 6 && !npc.info.wipeBelt))
                            {
                                DoLog($"Copying cached items back from live NPC for container {i}");
                                foreach (ItemInfo item in InvCache[userid].inventory[i])
                                {
                                    Item giveItem = ItemManager.CreateByItemID(item.ID, item.amount, item.skinID);
                                    DoLog($"Copying {item.amount} of item {giveItem.info.displayName.english}");
                                    if (!giveItem.MoveToContainer(corpse.containers[i], -1, true))
                                    {
                                        DoLog("Failed to move item :(");
                                        giveItem.Remove();
                                    }
                                }
                            }
                        }
                        if (npc.info.wipeCorpseMain)
                        {
                            DoLog("Wiping corpse main inventory");
                            corpse.containers[0].Clear();
                        }
                        timer.Once(5f, () => InvCache.Remove(userid));
                        ItemManager.DoRemoves();
                        return;
                    }
                    for (int i = 0; i < corpse.containers.Length; i++)
                    {
                        DoLog($"Clearing corpse container {i}");
                        corpse.containers[i].Clear();
                    }
                    ItemManager.DoRemoves();
                });
            }
        }

        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
        {
            if (entity == null) return null;
            if (hitinfo == null) return null;

            MonBotPlayer hp = entity.GetComponent<MonBotPlayer>();
            if (hp != null)
            {
                Interface.GetMod().CallHook("OnHitNPC", entity.GetComponent<BaseCombatEntity>(), hitinfo);
                if (hp.info.invulnerable)
                {
                    //hitinfo.damageTypes = new DamageTypeList();
                    //hitinfo.DoHitEffects = false;
                    //hitinfo.HitMaterial = 0;
                    return true;
                }
                //else
                //{
                //    hp.p
// ... [Code preview truncated due to length. Full source in attached file] ...

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