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

FREE HuntsMan : 1.5.4 1.5.4

Нет прав для скачивания
C#:
using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using Oxide.Core;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Facepunch;
using Rust;
using Rust.Ai;
using Rust.Ai.Gen2;
using HarmonyLib;

namespace Oxide.Plugins
{
    [Info("Huntsman", "Krungh Crow", "1.5.4")]
    [Description("The Hunter hunts you when u kill Game")]

    #region Changelogs and ToDo
    /**********************************************************************
     * 1.5.0    Removed random skins methods
     *          Added skin list to the loottable instead of 1 skin
     *          Assigned skins have to be set again in the cfg
     *          Merged Death triggers
     *          Improved npc/animal lookup
     *          Remade npc base loadout (due to facepunch TOS)
     * 1.5.1    Possible fix for reoccuring nre during startup
     * 1.5.2    Harmony patch
     * 1.5.3     Fix for Facepunch putting the ScientistNPC2 under the Animals.
     **********************************************************************/
    #endregion

    class HuntsMan : RustPlugin
    {
        [PluginReference] Plugin BotReSpawn , ChickenBow, Kits;
        public static Dictionary<BasePlayer, Hunters> SpawnedHunters { get; set; } = new Dictionary<BasePlayer, Hunters>();

        #region Variables

        private bool CanTrigger = true;
        private bool Debug;
        bool BlockSpawn;
        bool IsSpawned;
        bool UseBotRespawn;
        const string hunter = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";
        const ulong chaticon = 76561199188297846;
        const string Trigger_Perm = "huntsman.cantrigger";

        string HunterName;
        string prefix;
        private Dictionary<string, List<ulong>> Skins { get; set; } = new Dictionary<string, List<ulong>>();
        private readonly List<ulong> _Hunter = new List<ulong>();

        public static HuntsMan Instance { get; private set; }

        System.Random Rand;

        #endregion

        #region HarmonyPatching
        private Harmony harmony;

        public static string sTitle = "";
        public static string sNaming = "{Title} {RandomName} {}";

        internal Dictionary<ulong , string> StoredNames = new Dictionary<ulong , string>();

        [HarmonyPatch(typeof(ScientistNPC))]
        [HarmonyPatch("displayName" , MethodType.Getter)]
        public static class DisplayName
        {
            public static bool Prefix(ref string __result , ScientistNPC __instance)
            {
                var plugin = HuntsMan.Instance;
                if (plugin == null || __instance == null) return true;

                if (plugin.StoredNames.ContainsKey(__instance.userID))
                {
                    __result = plugin.HunterName;
                    return false;
                }
                return true;
            }
        }

        #endregion

        #region Mono
        public static HuntsMan instance;

        void OnServerInitialized()
        {
            instance = this;
            permission.RegisterPermission(Trigger_Perm , this);

        }

        public class Hunters : FacepunchBehaviour
        {
            public global::HumanNPC npc;
            public bool ReturningToHome = false;
            public Vector3 SpawnPoint;

            void Start()
            {
                npc = GetComponent<global::HumanNPC>();

                InvokeRepeating("GoHome", 1.0f, 1.0f);//1
                Invoke(nameof(_UseBrain), 0.1f);//0.1
            }
            public void _UseBrain()
            {
                #region navigation
                npc.Brain.Navigator.Agent.agentTypeID = -1372625422;
                npc.Brain.Navigator.DefaultArea = "Walkable";
                npc.Brain.Navigator.enabled = true;
                npc.Brain.Navigator.CanUseNavMesh = true;
                npc.Brain.Navigator.BestCoverPointMaxDistance = instance.configData.HunterData.HunterRoam / 2;//0
                npc.Brain.Navigator.BestRoamPointMaxDistance = instance.configData.HunterData.HunterRoam;//0
                npc.Brain.Navigator.MaxRoamDistanceFromHome = instance.configData.HunterData.HunterRoam;
                npc.Brain.Navigator.Init(npc, npc.Brain.Navigator.Agent);
                npc.Brain.Navigator.SetDestination(SpawnPoint, BaseNavigator.NavigationSpeed.Slow, 0f, 0f);
                #endregion

                #region senses & Targeting
                npc.Brain.ForceSetAge(0);
                npc.Brain.AllowedToSleep = false;
                npc.Brain.sleeping = false;
                npc.Brain.SenseRange = 30f;//30
                npc.Brain.ListenRange = 40f;//40
				npc.Brain.Senses.Init(npc, npc.Brain, 5f, 140f, 140f, -1f, true, true, true, 140f, false, false, true, EntityType.Player, false); 
                npc.Brain.TargetLostRange = 25f;//25
                npc.Brain.HostileTargetsOnly = false;
                npc.Brain.IgnoreSafeZonePlayers = true;
                #endregion
            }

            void GoHome()
            {
                if (npc == null || npc.IsDestroyed || npc.isMounted)
                    return;

                if (!npc.HasBrain)
                    return;
                if (npc.Brain.Senses.Memory.Targets.Count > 0)
                {
                    for (var i = 0; i < npc.Brain.Senses.Memory.Targets.Count; i++)
                    {
                        BaseEntity target = npc.Brain.Senses.Memory.Targets[i];
                        BasePlayer player = target as BasePlayer;

                        if (target == null || !player.IsAlive() || target.limitNetworking)
                        {
                            WipeMemory();
                            ReturningToHome = true;
                            return;
                        }
                        if (npc.Distance(player.transform.position) > 40f)
                        {
                            WipeMemory();
                            SettargetDestination(SpawnPoint);
                            ReturningToHome = true;
                            return;
                        }
                    }
                }

                var distanceHome = Vector3.Distance(npc.transform.position, SpawnPoint);
                if (ReturningToHome == false)
                {
                    if (distanceHome > instance.configData.HunterData.HunterRoam)
                    {
                        ReturningToHome = true;
                        return;
                    }
                    if (distanceHome < instance.configData.HunterData.HunterRoam)
                    {
                        Vector3 random = UnityEngine.Random.insideUnitCircle.normalized * instance.configData.HunterData.HunterRoam;
                        Vector3 newPos = instance.GetNavPoint(SpawnPoint + new Vector3(random.x, 0f, random.y));
                        SettargetDestination(newPos);
                        return;
                    }
                }
                if (ReturningToHome && distanceHome > 2)
                {
                    if (npc.Brain.Navigator.Destination == SpawnPoint)
                    {
                        return;
                    }

                    WipeMemory();
                    SettargetDestination(SpawnPoint);
                    return;
                }
                ReturningToHome = false;
            }
            private void SettargetDestination(Vector3 position)
            {
                npc.Brain.Navigator.Destination = position;
                npc.Brain.Navigator.SetDestination(position, BaseNavigator.NavigationSpeed.Slow, 0f, 0f);
            }
            void WipeMemory()
            {
                if (!npc.HasBrain)
                {
                    return;
                }

                npc.Brain.Senses.Players.Clear();
                npc.Brain.Senses.Memory.Players.Clear();
                npc.Brain.Senses.Memory.Targets.Clear();
                npc.Brain.Senses.Memory.Threats.Clear();
                npc.Brain.Senses.Memory.LOS.Clear();
                npc.Brain.Senses.Memory.All.Clear();
            }

            void OnDestroy()
            {
                if (npc != null && !npc.IsDestroyed)
                {
                    npc.Kill();
                }
                instance._Hunter.Remove(npc.userID);
                CancelInvoke("GoHome");
                CancelInvoke(nameof(_UseBrain));

            }
        }

        #endregion

        #region Configuration
        void Init()
        {
            if (!LoadConfigVariables())
            {
                Puts("Config file issue detected. Please delete file, or check syntax and fix.");
                return;
            }

            Instance = this;
            HunterName = configData.HunterData.Huntername;
            Debug = configData.UseDebug;
            UseBotRespawn = configData.BRS.UseBrs;
            if (Debug) Puts("[Debug] Debug is active");
            prefix = lang.GetMessage("Prefix" , this);

            harmony = new Harmony("krunghcrow.huntsman");

            var getter = AccessTools.PropertyGetter(typeof(ScientistNPC) , "displayName");
            if (getter != null)
            {
                harmony.Patch(getter , prefix: new HarmonyMethod(typeof(DisplayName) , nameof(DisplayName.Prefix)));
            }
            else
            {
                PrintWarning("ScientistNPC.displayName getter not found; skipping name patch.");
            }

            sTitle = configData.HunterData.Huntername;
        }


        private ConfigData configData;

        class ConfigData
        {
            [JsonProperty(PropertyName = "Use Debug")]
            public bool UseDebug = false;
            [JsonProperty(PropertyName = "BotRespawn Settings")]
            public BotrespawnSettings BRS = new BotrespawnSettings();
            [JsonProperty(PropertyName = "Animals to trigger HuntsMan")]
            public AnimalSettings AnimalData = new AnimalSettings();
            [JsonProperty(PropertyName = "Hunter Settings")]
            public SettingsHunter HunterData = new SettingsHunter();
        }

        class BotrespawnSettings
        {
            [JsonProperty(PropertyName = "Use BotReSpawn")]
            public bool UseBrs = false;
            [JsonProperty(PropertyName = "BotReSpawn profile name")]
            public string ProfileBrs = "huntsman";
        }

        class AnimalSettings
        {
            [JsonProperty(PropertyName = "Alpha Animal")]
            public bool AlphaTrigger = true;
            [JsonProperty(PropertyName = "Omega Animal")]
            public bool OmegaTrigger = true;
            [JsonProperty(PropertyName = "Bear")]
            public bool BearTrigger = true;
            [JsonProperty(PropertyName = "Polar Bear")]
            public bool PBearTrigger = true;
            [JsonProperty(PropertyName = "Boar")]
            public bool BoarTrigger = true;
            [JsonProperty(PropertyName = "Chicken")]
            public bool ChickenTrigger = true;
            [JsonProperty(PropertyName = "Stag")]
            public bool StagTrigger = true;
            [JsonProperty(PropertyName = "Wolf2")]
            public bool WolfTrigger2 = true;
            [JsonProperty(PropertyName = "Crocodile")]
            public bool CrocTrigger = false;
            [JsonProperty(PropertyName = "Panther")]
            public bool PantherTrigger = false;
            [JsonProperty(PropertyName = "Snake")]
            public bool SnakeTrigger = false;
            [JsonProperty(PropertyName = "Tiger")]
            public bool TigerTrigger = false;
        }

        class SettingsHunter
        {
            [JsonProperty(PropertyName = "Custom Hunter Name")]
            public string Huntername = "HuntsMan";
            [JsonProperty(PropertyName = "spawn chance (1-100%)")]
            public float HunterSpawnrate = 10f;
            [JsonProperty(PropertyName = "Spawn Amount")]
            public int HunterAmount = 1;
            [JsonProperty(PropertyName = "spawn radius")]
            public int Radius = 15;
            [JsonProperty(PropertyName = "Health")]
            public int HunterHealth = 250;
            [JsonProperty(PropertyName = "Max Roam Distance")]
            public int HunterRoam = 20;
            [JsonProperty(PropertyName = "Damage multiplier")]
            public float HunterDamageScale = 0.6f;
            [JsonProperty(PropertyName = "Lifetime (minutes)")]
            public float HunterLife = 10f;
            [JsonProperty(PropertyName = "Use kit (clothing)")]
            public bool UseKit = false;
            [JsonProperty(PropertyName = "Kit ID")]
            public List<string> KitName = new List<string>();
            [JsonProperty(PropertyName = "Show messages")]
            public bool ShowMsg = true;
            [JsonProperty(PropertyName = "Hunters drop a Backpack with loot")]
            public bool UseLoot = false;
            [JsonProperty(PropertyName = "Spawn Min Amount Items")]
            public int MinAmount { get; set; } = 2;
            [JsonProperty(PropertyName = "Spawn Max Amount Items")]
            public int MaxAmount { get; set; } = 6;
            [JsonProperty(PropertyName = "Loot Table", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public List<LootProfile> Loot { get; set; } = DefaultLoot;
        }

        private bool LoadConfigVariables()
        {
            try
            {
                configData = Config.ReadObject<ConfigData>();
            }
            catch
            {
                return false;
            }
            SaveConf();
            return true;
        }

        protected override void LoadDefaultConfig()
        {
            Puts("Creating new config file.");
            configData = new ConfigData();
            SaveConf();
        }

        void SaveConf() => Config.WriteObject(configData, true);
        #endregion

        #region LanguageAPI
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Hunter_Spawned"] = "You killed the {0} now pay the price !!!!",
                ["Hunter_Spawned_Backpack"] = "{0} Dropped his Backpack !",
                ["Prefix"] = "[<color=green>HuntsMan</color>] : ",
                ["info"] = "\nThe [HuntsMan] Gives u the luck (or not) to spawn a Hunter that wants to kill you for killing Wild Game during offseason",
            }, this);
        }

        #endregion

        #region Commands

        [ChatCommand("hminfo")]
        void cmdhmversion(BasePlayer player, string cmd, string[] args)
        {
            Player.Message(player, string.Format(msg("Current Version v", player.UserIDString)) + this.Version.ToString() + " By : " + this.Author.ToString() + msginfo("info"), chaticon);
        }

        #endregion

        #region External Hooks

        object OnNpcKits(BasePlayer player)
        {
            if (player?.gameObject?.GetComponent<Hunters>() != null)
                return true;
            return null;
        }

        void OnBotReSpawnNPCSpawned(ScientistNPC npc, string profile, string group)
        {
            if (profile == configData.BRS.ProfileBrs)
            {
                npc.displayName = HunterName;
                _Hunter.Add(npc.userID);
                npc.SendNetworkUpdate();
                AddSuicideTimer(npc);
                Effect.server.Run("assets/bundled/prefabs/fx/player/howl.prefab", npc.transform.position);
                if (Debug) Puts($"BotReSpawn spawned {profile} with name ({npc.displayName})");
                Interface.CallHook("OnHuntsmanSpawned", npc);
            }
        }

        #endregion

        #region Oxide Hooks

        void Unload()
        {
            foreach (var hunter in SpawnedHunters.Values)
                UnityEngine.Object.Destroy(hunter);

            SpawnedHunters.Clear();
            BotReSpawn?.Call("RemoveGroupSpawn" , "huntsman");

            harmony?.UnpatchAll(harmony.Id);
        }


        object OnChickenBowHuntsManBlockSpawn(BasePlayer player)
        {
            BlockSpawn = true;
            timer.Once(1 , () => { BlockSpawn = false; });
            return null;
        }
        void OnEntityDeath(BaseAnimalNPC animal , HitInfo info)
        {
            if (animal == null || info?.InitiatorPlayer == null) return;
            HandleAnimalDeath(animal , info.InitiatorPlayer , info);
        }

        void OnEntityDeath(BaseNPC2 animal , HitInfo info)
        {
            if (animal == null || info?.InitiatorPlayer == null || animal is ScientistNPC2) return;
            HandleAnimalDeath(animal , info.InitiatorPlayer , info);
        }

        void OnEntityDeath(SnakeHazard animal , HitInfo info)
        {
            if (animal == null || info?.InitiatorPlayer == null) return;
            HandleAnimalDeath(animal , info.InitiatorPlayer , info);
        }

        private void HandleAnimalDeath(BaseEntity animal , BasePlayer player , HitInfo info)
        {
            if (player.userID.IsSteamId() || info.Initiator is BasePet)
            {
                if (!HasPerm(player , Trigger_Perm)) return;

                if (Interface.CallHook("CanSpawnHuntsman" , animal) != null)
                {
                    return;
                }
                try
                {
                    AnimalCheck(animal);

                    if (UnityEngine.Random.Range(0f , 1f) <= configData.HunterData.HunterSpawnrate / 100)
                    {
                        if (CanTrigger == true)
                        {
                            if (animal is BaseAnimalNPC && BlockSpawn)
                            {
                                if (Debug) Puts($"{player.displayName} shot down a ChickenBow Chicken and a HuntsMan was skipped");
                                return;
                            }

                            for (int i = 0; i < configData.HunterData.HunterAmount; i++)
                            {
                                if (UseBotRespawn)
                                {
                                    Vector3 location = animal.transform.position;
                                    string _Profile = configData.BRS.ProfileBrs;
                                    string[] Spawn = BotReSpawn?.Call("AddGroupSpawn" , location , _Profile , _Profile , 1) as string[];
                                    if (Debug) Puts($"[BotReSpawn] : {Spawn[1]}");
                                    IsSpawned = true;
                                }
                                else if (!UseBotRespawn) Spawnnpc(animal.transform.position);
                            }
                            Puts($"{player.displayName} shot down a {animal.name} and a HuntsMan tried to arrest him/her");

                            if (configData.HunterData.ShowMsg && IsSpawned == true)
                            {
                                string AnimalName = animal.name;
                                if (AnimalName.Contains("assets/rust.ai/agents/") || AnimalName.Contains(".prefab"))
                                {
                                    AnimalName = animal.ShortPrefabName;
                                    if (AnimalName.Contains("wolf2"))
                                    {
                                        AnimalName = "wolf";
                                    }
                                    if (AnimalName.Contains("snake.entity"))
                                    {
                                        AnimalName = "snake";
                                    }
                                }
                                Player.Message(player , string.Format(msg("Hunter_Spawned" , player.UserIDString) , AnimalName) , chaticon);
                            }
                            return;
                        }
                        return;
                    }
                }
                catch
                {
                }
            }
            return;
        }

        void OnEntityDeath(ScientistNPC hunter, HitInfo info)
        {
            if (hunter == null || info?.Initiator == null) return;

            if (_Hunter.Contains(hunter.userID))
            {

                BasePlayer player = info.InitiatorPlayer;
                if (player == null || !player.IsValid()) return;
                if (info.InitiatorPlayer.userID.IsSteamId() || info.Initiator is BasePet) ;
                {
                    if (configData.HunterData.UseLoot)
                    {
                        Player.Message(player, string.Format(msg("Hunter_Spawned_Backpack", player.UserIDString), hunter.displayName), chaticon);
                        string _displayname = hunter.displayName;
                        SpawnHunterLoot(hunter.transform.position + new Vector3(0f, 0.5f, 0f), hunter.transform.rotation, _displayname);
                    }
                }
                Interface.CallHook("OnHuntsmanKilled" , hunter);
            }
        }

        private object OnNpcTarget(BasePlayer attacker, BasePlayer target)
        {
            if (attacker != null && _Hunter.Contains(attacker.userID))
            {
                if (target.IsSleeping() || !target.userID.IsSteamId() || !target is BasePet)
                    return true;
            }
            if (attacker != null && target != null && _Hunter.Contains(target.userID))
            {
                return true;
            }
            return null;
        }

        void OnEntitySpawned(NPCPlayerCorpse corpse)
        {
            if (corpse == null || corpse.IsDestroyed) return;

            ulong id = corpse.playerSteamID;

            if(!(UseBotRespawn) && _Hunter.Contains(corpse.playerSteamID))
            {
                try
                {
                    NextTick(() =>
                    {
                        if (Debug) Puts($"NPC is a {HunterName} so corpse injection is possible");
                        Item hunterskull = ItemManager.CreateByName("skull.human", 1, 0);
                        ItemAmount HunterSkull = new ItemAmount() { itemDef = hunterskull.info, amount = 1, startAmount = 1 };
                        Item hunterflesh = ItemManager.CreateByName("humanmeat.raw", 1, 0);
                        ItemAmount HunterFlesh = new ItemAmount() { itemDef = hunterflesh.info, amount = 6, startAmount = 1 };

                        var dispenser = corpse.GetComponent<ResourceDispenser>();
                        if (dispenser != null)
                        {
                            dispenser.containedItems.Add(HunterSkull);
                            dispenser.containedItems.Add(HunterFlesh);
                            dispenser.Initialize();
                            if (Debug) Puts($"[Debug] Huntsman Corpse was injected with [Skull & Human flesh]");
                        }
                    });
                    return;
                }
                catch
                {
                    return;
                }
            }
            if (Debug && (UseBotRespawn) && _Hunter.Contains(corpse.playerSteamID)) Puts($"[Debug] BotReSpawn will cover the [Skull] injection");
        }

        #endregion

        #region API
        private bool IsHuntsmanNpc(global::HumanNPC npc)
        {
            if (npc != null)
            {
                if (_Hunter.Contains(npc.userID)) return true;
                return false;
            }
            return false;
        }
        #endregion

        #region Event Helpers

        bool HasPerm(BasePlayer player , string perm) { return permission.UserHasPermission(player.UserIDString , perm); }

        public Vector3 GetNavPoint(Vector3 position)
        {
            NavMeshHit hit;
            if (!NavMesh.SamplePosition(position, out hit, 5, -1))
            {
                return position;
            }
            else if (Physics.RaycastAll(hit.position + new Vector3(0, 100, 0), Vector3.down, 99f, 1235288065).Any())
            {
                return position;
            }
            else if (hit.position.y < TerrainMeta.WaterMap.GetHeight(hit.position))
            {
                return position;
            }
            position = hit.position;
            return position;
        }

        public static Vector3 CheckPos(Vector3 pos)
        {
            NavMeshHit navMeshHit;

            if (!NavMesh.SamplePosition(pos, out navMeshHit, 2, 1))
                pos = Vector3.zero;
            else if (WaterLevel.GetWaterDepth(pos, true, false) > 0)
                pos = Vector3.zero;
            else if (Physics.RaycastAll(navMeshHit.position + new Vector3(0, 100, 0), Vector3.down, 99f, 1235288065).Any())
                pos = Vector3.zero;
            else
                pos = navMeshHit.position;
            return pos;
        }

        private void AnimalCheck(object animal)
        {
            CanTrigger = true;

            if (animal is BaseAnimalNPC baseAnimal)
            {
                if (baseAnimal is Bear && !configData.AnimalData.BearTrigger) CanTrigger = false;
                if (baseAnimal is Polarbear && !configData.AnimalData.PBearTrigger) CanTrigger = false;
                if (baseAnimal is Boar && !configData.AnimalData.BoarTrigger) CanTrigger = false;

                if (baseAnimal is Chicken)
                {
                    if (!configData.AnimalData.ChickenTrigger)
                    {
                        CanTrigger = false;
                    }
                    else
                    {
                        if (ChickenBow != null && ChickenBow.Call<bool>("IsSpawnedChicken" , baseAnimal.net.ID))
                            CanTrigger = false;
                    }
                }

                if (baseAnimal is Stag && !configData.AnimalData.StagTrigger) CanTrigger = false;
            }
            else if (animal is BaseNPC2 baseAnimal2)
            {
                if (animal is Crocodile && !configData.AnimalData.CrocTrigger) CanTrigger = false;
                if (animal is Panther && !configData.AnimalData.PantherTrigger) CanTrigger = false;
                if (animal is Tiger && !configData.AnimalData.TigerTrigger) CanTrigger = false;
            }
            else if (animal is SnakeHazard)
            {
                CanTrigger = configData.AnimalData.SnakeTrigger;
            }
            else if (animal is Wolf2)
            {
                CanTrigger = configData.AnimalData.WolfTrigger2;
            }
            else
            {
                CanTrigger = false;
            }

            // Alpha/Omega override
            if (animal is BaseNPC2 npc)
            {
                if (npc.name.Contains("Alpha"))
                {
                    CanTrigger = configData.AnimalData.AlphaTrigger;
                }
                else if (npc.name.Contains("Omega"))
                {
                    CanTrigger = configData.AnimalData.OmegaTrigger;
                }
            }
            else
            {
                CanTrigger = CanTrigger;
            }

            if (Debug) Puts($"[Debug] {animal.GetType().Name} kill was triggered and [CanTrigger] is {CanTrigger}");
        }

        private void GiveLoadout(ScientistNPC npc)
        {
            if (npc != null)
            {
                var inv_belt = npc.inventory.containerBelt;
                var inv_wear = npc.inventory.containerWear;

                Item hat = ItemManager.CreateByName("hat.boonie" , 1 , 3468383925);//checked
                Item hoodie = ItemManager.CreateByName("hoodie" , 1 , 3042985784);//checked
                Item pants = ItemManager.CreateByName("pants" , 1 , 3042985200);//checked
                Item boots = ItemManager.CreateByName("shoes.boots" , 1 , 1464542400);//checked
                Item weapon1 = ItemManager.CreateByName("shotgun.pump" , 1 , 0);

                inv_wear.Clear();
                if (hat != null) hat.MoveToContainer(inv_wear);
                if (hoodie != null) hoodie.MoveToContainer(inv_wear);
                if (pants != null) pants.MoveToContainer(inv_wear);
                if (boots != null) boots.MoveToContainer(inv_wear);
                if (weapon1 != null) weapon1.MoveToContainer(inv_belt);

                npc.inventory.UpdatedVisibleHolsteredItems();
                npc.EquipWeapon();

                string scientistSuitShortname = "hazmatsuit_scientist";
                Item SuitItem = npc.inventory.containerMain.itemList.FirstOrDefault(item => item.info.shortname == scientistSuitShortname);

                if (SuitItem != null)
                {
                    SuitItem.RemoveFromContainer();
                }
            }
            else
            {
                Puts("Huntsman was not fully spawned yet skipping [GiveLoadout]");
            }
        }
        private void Spawnnpc(Vector3 position)
        {
            int radius = configData.HunterData.Radius;
            Vector3 pos = position + UnityEngine.Random.onUnitSphere * radius;
            pos.y = TerrainMeta.HeightMap.GetHeight(pos);
            CheckPos(pos);
            if (pos == Vector3.zero) return;
            ScientistNPC npc = (ScientistNPC)GameManager.server.CreateEntity(hunter , pos , new Quaternion() , true);
            npc.Spawn();
            StoredNames[npc.userID] = HunterName;
            Interface.CallHook("OnHuntsmanSpawn" , npc);
            _Hunter.Add(npc.userID);

            timer.Once(0.3f , () =>
            {
                if (npc == null) return;

                var mono = npc.gameObject.AddComponent<Hunters>();
                mono.SpawnPoint = pos;
                SpawnedHunters[npc] = mono;

                npc.startHealth = configData.HunterData.HunterHealth;
                npc.InitializeHealth(configData.HunterData.HunterHealth , configData.HunterData.HunterHealth);

                npc.damageScale = configData.HunterData.HunterDamageScale;
                (npc as ScientistNPC).radioChatterType = ScientistNPC.RadioChatterType.NONE;
                (npc as ScientistNPC).DeathEffects = new GameObjectRef[0];

                if (configData.HunterData.UseKit && configData.HunterData.KitName.Count > 0)
                {
                    object checkKit = Kits?.CallHook("GetKitInfo" , configData.HunterData.KitName[new System.Random().Next(configData.HunterData.KitName.Count())]);
                    if (checkKit == null)
                    {
                        GiveLoadout(npc);
                        PrintWarning($"Kit for {HunterName} does not exist - Using a default Hunter outfit.");
                    }
                    else
                    {
                        npc.inventory.Strip();
                        Kits?.Call($"GiveKit" , npc , configData.HunterData.KitName[new System.Random().Next(configData.HunterData.KitName.Count())]);
                        npc.inventory.UpdatedVisibleHolsteredItems();
                        npc.EquipWeapon();
                    }
                }
                if (!configData.HunterData.UseKit || configData.HunterData.KitName.Count == 0)
                {
                    GiveLoadout(npc);
                }
                npc.EquipWeapon();
            });
            if (npc.IsHeadUnderwater())
            {
                npc.Kill();
                if (Debug) timer.Once(1f , () => { Puts($"{npc} skipped its spawn (spawned under water)"); });
                IsSpawned = false;
                return;
            }
            if (!npc.IsOutside())
            {
                npc.Kill();
                if (Debug) timer.Once(1f , () => { Puts($"{npc} skipped its spawn (No valid spawnpoint)"); });
                IsSpawned = false;
                return;
            }
            IsSpawned = true;
            Interface.CallHook("OnHuntsmanSpawned" , npc);

            var id = npc.userID;
            timer.Once(1f , () => { Puts($"{npc} spawned"); });
            Effect.server.Run("assets/bundled/prefabs/fx/player/howl.prefab" , npc.transform.position);
            AddSuicideTimer(npc);
        }

        private void AddSuicideTimer(ScientistNPC npc)
        {
            timer.Once(configData.HunterData.HunterLife * 60 , () =>
            {
                if (npc != null)
                {
                    _Hunter.Remove(npc.userID);
                    SpawnedHunters.Remove(npc);
                    npc.Kill();
                    if (Debug) Puts($"{npc} Died of natural causes!!!");
                    return;
                }
                if (Debug) Puts($"{npc} was killed before ending of timer");
                return;
            });
        }

        #endregion

        #region Loot System

        private static List<LootProfile> DefaultLoot
        {
            get
            {
                return new List<LootProfile>
            {
                new LootProfile { probability = 1f, shortname = "ammo.pistol", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "ammo.pistol.fire", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "ammo.rifle.explosive", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() { 0 } },
                new LootProfile { probability = 1f, shortname = "ammo.rifle.hv", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "ammo.rifle.incendiary", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "ammo.shotgun", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "ammo.shotgun", name = "", amountMin = 128, amount = 256, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "explosive.timed", name = "", amountMin = 1, amount = 5, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "explosives", name = "", amountMin = 200, amount = 200, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "pistol.m92", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "shotgun.spas12", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "pickaxe", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() { 3163818649, 1962043729 } },
                new LootProfile { probability = 1f, shortname = "hatchet", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "can.beans", name = "", amountMin = 3, amount = 5, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "can.tuna", name = "", amountMin = 3, amount = 5, skins = new List<ulong>() },
                new LootProfile { probability = 1f, shortname = "black.raspberries", name = "", amountMin = 3, amount = 5, skins = new List<ulong>() },
                new LootProfile { probability = 0.0f, shortname = "box.repair.bench", name = "Recycler", amountMin = 1, amount = 1, skins = new List<ulong>() { 1594245394 } },
                new LootProfile { probability = 0.6f, shortname = "hmlmg", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() },
                new LootProfile { probability = 0.6f, shortname = "supply.signal", name = "", amountMin = 1, amount = 1, skins = new List<ulong>() },
                };
            }
        }
        public class LootProfile
        {
            public float probability { get; set; } = 1f;
            public string shortname { get; set; }
            public string name { get; set; } = "";
            [JsonProperty(PropertyName = "Skin list")]
            public List<ulong> skins { get; set; } = new List<ulong>();
            public int amountMin { get; set; }
            public int amount { get; set; }
        }

        private void SpawnHunterLoot(Vector3 pos, Quaternion rot,string _name)
        {
            var backpack = GameManager.server.CreateEntity(StringPool.Get(545786656) , pos, rot, true) as DroppedItemContainer;

            if (backpack == null) return;

            backpack.inventory = new ItemContainer();
            backpack.inventory.ServerInitialize(null , 36);
            backpack.inventory.GiveUID();
            backpack.inventory.entityOwner = backpack;
            backpack.inventory.SetFlag(ItemContainer.Flag.NoItemInput , true);
            backpack.Spawn();
            SpawnLoot(backpack.inventory, configData.HunterData.Loot.ToList());
        }

        private void SpawnLoot(ItemContainer container , List<LootProfile> loot)
        {
            int total = UnityEngine.Random.Range(Math.Min(loot.Count , configData.HunterData.MinAmount) , Math.Min(loot.Count , configData.HunterData.MaxAmount));

            if (total == 0 || loot.Count == 0)
            {
                return;
            }

            container.capacity = total;
            ItemDefinition def;
            List<ulong> skins; // This variable is no longer needed in this scope
            LootProfile lootItem;

            for (int j = 0; j < total; j++)
            {
                if (loot.Count == 0)
                {
                    break;
                }

                lootItem = loot.GetRandom();

                loot.Remove(lootItem);

                if (lootItem.amount <= 0)
                {
                    continue;
                }

                string shortname = lootItem.shortname;
                if (UnityEngine.Random.value > lootItem.probability)
                {
                    if (!string.IsNullOrEmpty(lootItem.name)) Puts($"Skipping Custom({j + 1}) : {lootItem.name} : probability = {lootItem.probability}");
                    else if (string.IsNullOrEmpty(lootItem.name)) Puts($"Skipping Normal({j + 1}) : {lootItem.shortname} : probability = {lootItem.probability}");
                    j--;
                    continue;
                }
                bool isBlueprint = shortname.EndsWith(".bp");

                if (isBlueprint)
                {
                    shortname = shortname.Replace(".bp" , string.Empty);
                }

                def = ItemManager.FindItemDefinition(shortname);

                if (def == null)
                {
                    Puts("Invalid shortname: {0}" , lootItem.shortname);
                    continue;
                }

                ulong skin = 0;
                if (lootItem.skins != null && lootItem.skins.Count > 0)
                {
                    skin = lootItem.skins.GetRandom();
                }

                int amount = UnityEngine.Random.Range(lootItem.amountMin , lootItem.amount + 1);

                if (amount <= 0)
                {
                    continue;
                }

                Item item;

                if (isBlueprint)
                {
                    item = ItemManager.CreateByItemID(-996920608 , 1 , 0);

                    if (item == null) continue;

                    item.blueprintTarget = def.itemid;
                    item.amount = amount;
                }
                else item = ItemManager.Create(def , amount , skin);

                if (!item.MoveToContainer(container , -1 , false))
                {
                    item.Remove();
                }

                if (!string.IsNullOrEmpty(lootItem.name)) { item.name = lootItem.name; }
                if (Debug)
                {
                    if (string.IsNullOrEmpty(item.name))
                    {
                        Puts($"Normal({j + 1}) : {item.info.shortname} : Amount {item.amount} SkinID : {item.skin}");
                    }
                    if (!string.IsNullOrEmpty(item.name))
                    {
                        Puts($"Custom({j + 1}) : {item.name} : Amount : {item.amount} SkinID : {item.skin}");
                    }
                }
            }
        }

        #endregion

        #region Message helper

        private string msg(string key, string id = null) => prefix + lang.GetMessage(key, this, id);
        private string msginfo(string key, string id = null) => lang.GetMessage(key, this, id);

        #endregion
    }
}

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