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

FREE NPCGrenades : 1.2.2 1.2.2

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

namespace Oxide.Plugins
{
    [Info("NPC Grenades", "Sempai#3239", "1.2.2")]
    [Description("F1 grenades spawn various NPCs when thrown.")]
    public class NPCGrenades: CovalencePlugin
    {
        #region plugin refs

        [PluginReference]
        private Plugin Friends, Clans, Kits;

        #endregion

        #region Consts

        private static NPCGrenades plugin;
        private static System.Random random = new System.Random();
        private static VersionNumber previousVersion;

        public const int f1GrenadeId = 143803535;
        public const ulong scientistSkinID = 2640541557;
        public const ulong heavySkinID = 2640541496;
        public const ulong juggernautSkinID = 2647297156;
        public const ulong tunnelSkinID = 2676146196;
        public const ulong underwaterSkinID = 2676146329;
        public const ulong murdererSkinID = 2643502595;
        public const ulong scarecrowSkinID = 2647297210;
        public const ulong mummySkinID = 2643385137;
        public const ulong bearSkinID = 2647301111;
        public const ulong polarbearSkinID = 2868239755;
        public const ulong wolfSkinID = 2647303718;
        public const ulong boarSkinID = 2643502513;
        public const ulong stagSkinID = 2647297256;
        public const ulong chickenSkinID = 2647297056;
        public const ulong bradleySkinID = 2643385052;
        
        public const string scientistPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam.prefab";
        public const string heavyPrefab = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_heavy.prefab";
        public const string scarecrowPrefab = "assets/prefabs/npc/scarecrow/scarecrow.prefab";
        public const string bearPrefab = "assets/rust.ai/agents/bear/bear.prefab";
        public const string polarbearPrefab = "assets/rust.ai/agents/bear/polarbear.prefab";
        public const string wolfPrefab = "assets/rust.ai/agents/wolf/wolf.prefab";
        public const string boarPrefab = "assets/rust.ai/agents/boar/boar.prefab";
        public const string stagPrefab = "assets/rust.ai/agents/stag/stag.prefab";
        public const string chickenPrefab = "assets/rust.ai/agents/chicken/chicken.prefab";
        public const string bradleyPrefab = "assets/prefabs/npc/m2bradley/bradleyapc.prefab";
        
        public const string murdererChatter = "assets/prefabs/npc/murderer/sound/breathing.prefab";
        public const string murdererDeath = "assets/prefabs/npc/murderer/sound/death.prefab";
        public const string fleshBloodImpact = "assets/bundled/prefabs/fx/impacts/slash/flesh/fleshbloodimpact.prefab";
        public const string explosionSound = "assets/prefabs/weapons/f1 grenade/effects/f1grenade_explosion.prefab";
        public const string bradleyExplosion = "assets/prefabs/npc/m2bradley/effects/bradley_explosion.prefab";

        public const string permScientist = "npcgrenades.scientist";
        public const string permHeavy = "npcgrenades.heavy";
        public const string permJuggernaut = "npcgrenades.juggernaut";
        public const string permTunnel = "npcgrenades.tunnel";
        public const string permUnderwater = "npcgrenades.underwater";
        public const string permMurderer = "npcgrenades.murderer";
        public const string permScarecrow = "npcgrenades.scarecrow";
        public const string permMummy = "npcgrenades.mummy";
        public const string permBear = "npcgrenades.bear";
        public const string permPolarbear = "npcgrenades.polarbear";
        public const string permWolf = "npcgrenades.wolf";
        public const string permBoar = "npcgrenades.boar";
        public const string permStag = "npcgrenades.stag";
        public const string permChicken = "npcgrenades.chicken";
        public const string permBradley = "npcgrenades.bradley";
        public const string permAdmin = "npcgrenades.admin";

        #endregion

        #region Language

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Syntax"] = "Invalid syntax, use: /npcnade.give <type> <SteamID/PlayerName>",
                ["WrongType"] = "Grenade type \"{0}\" not recognised, please check & try again.",
                ["Received"] = "You received a {0}!",
                ["PlayerReceived"] = "Player {0} ({1}) received a {2}!",
                ["Permission"] = "You do not have permission to use {0}!",
                ["NotEnabled"] = "{0} is not enabled!",
                ["NotAdmin"] = "You do not have permission to use that command!",
                ["PlayerNotFound"] = "Can't find a player with the name or ID: {0}",
                ["PlayersFound"] = "Multiple players found, please be more specific: {0}",
                ["UnderWater"] = "{0} ({1}) spawned under water and was killed.",
                ["InSafeZone"] = "{0} ({1}) spawned in as Safe Zone and was killed.",
                ["Outside"] = "{0} ({1}) spawned inside and was killed.",
                ["OnStructure"] = "{0} ({1}) spawned on a building and was killed.",
                ["IsInRock"] = "{0} ({1}) spawned inside terrain and was killed.",
                ["ConsoleSyntax"] = "Invalid syntax, use: npcnade.give <type> <SteamID/PlayerName>",
                ["InvalidNade"] = "Grenade type \"{0}\" not recognised, please check and try again!"
            }, this);
        }

        private string GetMessage(string messageKey, string playerID, params object[] args) {
            return string.Format(lang.GetMessage(messageKey, this, playerID), args);
        }

        private void Message(IPlayer player, string messageKey, params object[] args)
        {
            var message = GetMessage(messageKey, player.Id, args);
            if (config.options.usePrefix)
            {
                player.Reply(config.options.chatPrefix + message);
            }
            else
            {
                player.Reply(message);
            }
        }

        private void Message(BasePlayer player, string messageKey, params object[] args)
        {
            if (player is NPCPlayer)
            {
                return;
            }
            var message = GetMessage(messageKey, player.UserIDString, args);
            if (config.options.usePrefix && config.options.chatPrefix != string.Empty)
            {
                player.ChatMessage(config.options.chatPrefix + message);
            }
            else
            {
                player.ChatMessage(message);
            }
        }

        #endregion

        #region Oxide Hooks

        private void OnServerInitialized()
        {
            plugin = this;
        }

        private void Init()
        {
            LoadNadeInfo();
            permission.RegisterPermission(permAdmin, this);
            foreach (var item in NadeInfo.Keys)
            {
                permission.RegisterPermission(NadeInfo[item].Perm, this);
            }
            try
            {
                storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
                if (storedData == null)
                {
                    Puts("Data file is blank.Creating default data file.");
                    LoadDefaultData();
                }
            }
            catch (Exception ex)
            {
                if (ex is JsonSerializationException || ex is NullReferenceException || ex is JsonReaderException)
                {
                    Puts($"Exception Type: {ex.GetType()}");
                    Puts("Data file contains errors.Either fix the errors or delete the data file and reload the plugin for default values.");
                    return;
                }
                throw;
            }
            LoadDefaultData();
        }

        private void Unload()
        {
            plugin = null;
            NadeInfo = null;
            GrenadeNPCData = null;
            BaseNpcData = null;
            BradleyAPCData = null;
            NPCInventories = null;
        }

        private void OnServerSave()
        {
            int delay  = random.Next(10, 30);
            timer.Once(delay, () =>
            {
                SaveData();
            });
        }

        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            if (IsNpcGrenade(entity.skinID))
            {
                NPCPlayer npc = entity as NPCPlayer;
                if (npc is ScientistNPC || npc is ScarecrowNPC)
                {
                    if (npc?.userID != null && GrenadeNPCData.ContainsKey(npc.userID) && !NPCInventories.ContainsKey(npc.userID)) 
                    {
                        npc.children.Clear();
                        ItemContainer[] source = { npc.inventory.containerMain, npc.inventory.containerWear, npc.inventory.containerBelt };
                        Inv npcInv = new Inv() { name = npc.displayName, };
                        NPCInventories.Add(npc.userID, npcInv);
                        for (int i = 0; i < source.Length; i++)
                        {
                            foreach (var item in source[i].itemList)
                            {
                                npcInv.inventory[i].Add(new InvContents
                                {
                                    ID = item.info.itemid,
                                    amount = item.amount,
                                    skinID = item.skin,
                                });
                            }
                        }
                    }
                    timer.Once(5.0f, () =>
                    {
                        RemoveNpcData(npc.userID);
                    });
                }
                else
                {
                    RemoveNpcData(entity.net.ID);
                }
            }
        }

        // Below adds proper grenade names to items added via kits/loadouts by plugins which don't specify a name
        // in the config.This means when players click on the item in inventory it keeps the NPC Nade name.// It is also needed for checks later on.private void OnItemAddedToContainer(ItemContainer container, Item item)
        {
            if (IsNpcGrenade(item.skin))
            {
                if (item.name == null)
                {
                    if (NadeInfo.ContainsKey(item.skin))
                    {
                        item.name = NadeInfo[item.skin].Name;
                    }
                }
            }
        }

        // This hook works regardless of whether player or NPC player.OnExplosiveThrown only hooks for players.private void OnExplosiveFuseSet(TimedExplosive explosive, float fuseLength)
        {
            var npc = explosive.creatorEntity as BasePlayer;
            if (npc == null || !npc.IsAlive())
                return;

            var item = npc.GetActiveItem();
            if (item == null || explosive == null)
                return;

            if (IsNpcGrenade(item.skin))
            {
                OnNpcNadeThrown(npc, explosive, item);
            }
        }

        // Changed to a custom call due to OnExplosiveThrown not hooking NPC throws
        private void OnNpcNadeThrown(BaseEntity thrower, BaseEntity entity, Item npcNade)
        {
            var player = thrower as BasePlayer;
            if (!IsNpcGrenade(npcNade.skin))
            {
                return;
            }
            else if (!NadeInfo[npcNade.skin].Enabled)
            {
                NextTick(() => {
                    entity.Kill();
                });
                if (player is NPCPlayer)
                {
                    Puts($"An NPC player is trying to throw an NPCGrenade which is not enabled in the config: {npcNade.name}");
                    return;
                }
                else
                {
                    GiveNade(player, npcNade.skin, npcNade.name, "refund");
                    Message(player, "NotEnabled", npcNade.name);
                    return;
                }
            }
            if (config.options.usePerms && !HasPermission(player, npcNade))
            {
                NextTick(() => {
                    entity.Kill();
                });
                GiveNade(player, npcNade.skin, npcNade.name, "refund");
                Message(player, "Permission", npcNade.name);
                return;
            }
            timer.Once(2.4f, () =>
            {
                if (entity != null)
                {
                    var position = entity.transform.position;
                    NextTick(() => {
                        entity.Kill();
                    });
                    if (player == null || !player.IsAlive())
                    {
                        return;
                    }
                    if (storedData.HumanNPC.ContainsKey(npcNade.name))
                    {
                        NPCPlayerData settings = new NPCPlayerData
                        {
                            Name = storedData.HumanNPC[npcNade.name].Name,
                            Prefab = storedData.HumanNPC[npcNade.name].Prefab,
                            Health = storedData.HumanNPC[npcNade.name].Health,
                            MaxRoamRange = storedData.HumanNPC[npcNade.name].MaxRoamRange,
                            SenseRange = storedData.HumanNPC[npcNade.name].SenseRange,
                            ListenRange = storedData.HumanNPC[npcNade.name].ListenRange,
                            AggroRange = storedData.HumanNPC[npcNade.name].AggroRange,
                            DeAggroRange = storedData.HumanNPC[npcNade.name].DeAggroRange,
                            TargetLostRange = storedData.HumanNPC[npcNade.name].TargetLostRange,
                            MemoryDuration = storedData.HumanNPC[npcNade.name].MemoryDuration,
                            VisionCone = storedData.HumanNPC[npcNade.name].VisionCone,
                            CheckVisionCone = storedData.HumanNPC[npcNade.name].CheckVisionCone,
                            CheckLOS = storedData.HumanNPC[npcNade.name].CheckLOS,
                            IgnoreNonVisionSneakers = storedData.HumanNPC[npcNade.name].IgnoreNonVisionSneakers,
                            DamageScale = storedData.HumanNPC[npcNade.name].DamageScale,
                            PeaceKeeper = storedData.HumanNPC[npcNade.name].PeaceKeeper,
                            IgnoreSafeZonePlayers = storedData.HumanNPC[npcNade.name].IgnoreSafeZonePlayers,
                            RadioChatter = storedData.HumanNPC[npcNade.name].RadioChatter,
                            DeathSound = storedData.HumanNPC[npcNade.name].DeathSound,
                            NumberToSpawn = storedData.HumanNPC[npcNade.name].NumberToSpawn,
                            SpawnRadius = storedData.HumanNPC[npcNade.name].SpawnRadius,
                            DespawnTime = storedData.HumanNPC[npcNade.name].DespawnTime,
                            KillInSafeZone = storedData.HumanNPC[npcNade.name].KillInSafeZone,
                            StripCorpseLoot = storedData.HumanNPC[npcNade.name].StripCorpseLoot,
                            KitList = storedData.HumanNPC[npcNade.name].KitList,
                            Speed = storedData.HumanNPC[npcNade.name].Speed,
                            Acceleration = storedData.HumanNPC[npcNade.name].Acceleration,
                            FastSpeedFraction = storedData.HumanNPC[npcNade.name].FastSpeedFraction,
                            NormalSpeedFraction = storedData.HumanNPC[npcNade.name].NormalSpeedFraction,
                            SlowSpeedFraction = storedData.HumanNPC[npcNade.name].SlowSpeedFraction,
                            SlowestSpeedFraction = storedData.HumanNPC[npcNade.name].SlowestSpeedFraction,
                            LowHealthMaxSpeedFraction = storedData.HumanNPC[npcNade.name].LowHealthMaxSpeedFraction,
                            TurnSpeed = storedData.HumanNPC[npcNade.name].TurnSpeed,
                            ExplosionSound = storedData.HumanNPC[npcNade.name].ExplosionSound
                        };
                        if (settings.Prefab.Contains("scarecrow"))
                        {
                            SpawnScarecrow(player, npcNade, position, settings);
                            return;
                        }
                        else
                        {
                            SpawnScientist(player, npcNade, position, settings);
                            return;
                        }
                    }
                    else if (storedData.AnimalNPC.ContainsKey(npcNade.name))
                    {
                        SpawnAnimal(player, npcNade, position);
                        return;
                    }
                    else if (storedData.BradleyNPC.ContainsKey(npcNade.name))
                    {
                        SpawnBradley(player, npcNade, position);
                        return;
                    }
                }
            });
        }

        private void OnExplosiveDropped(BasePlayer player, BaseEntity entity, Item item)
        {
            if (item.skin == null)
            {
                return;
            }
            else if (!IsNpcGrenade(item.skin))
            {
                return;
            }
            OnNpcNadeThrown(player, entity, item);
        }

        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (entity == null || info == null)
            {
                return null;
            }
            if (IsNpcGrenade(entity.skinID))
            {
                // Stop melee armed NPC injuring themselves which happens when their swing misses the target
                if (info.Initiator == info.HitEntity)
                {
                    return true;
                }
            }
            if (!config.bradley.bradleyBaseDamage)
            {
                var damageType = info.damageTypes.GetMajorityDamageType();
                if (entity is BasePlayer)
                {
                    return null;
                }
                else if (damageType == DamageType.Blunt)
                {
                    if(entity.GetBuildingPrivilege() && info.WeaponPrefab.name == "MainCannonShell")
                    {
                        // Blunt damage from APC cannon shells blocked
                        CancelHit(info);
                        return true;
                    }
                }
                else if (damageType == DamageType.Bullet && info.Initiator is BradleyAPC)
                {
                    // Bullet damage from APC machine gun bullets blocked
                    CancelHit(info);
                    return true;
                }
            }

            return null;
        }

        private object OnNpcTarget(BaseEntity entity, BaseEntity target)
        {
            if (entity != null && target != null)
            {
                var isEntityNade = IsNpcGrenade(entity.skinID);
                var isTargetNade = IsNpcGrenade(target.skinID);

                if (isEntityNade && isTargetNade)
                {
                    return true;
                }
                else if (isEntityNade && !isTargetNade)
                {
                    // Target is Player
                    if (target is BasePlayer)
                    {
                        var player = target as BasePlayer;
                        if (player.IsSleeping() && config.options.sleeperSafe)
                        {
                            return true;
                        }
                        if (!config.options.attackOwner && entity.OwnerID == player.userID)
                        {
                            return true;
                        }
                        if (config.options.useFriends || config.options.useClans || config.options.useTeams)
                        {
                            if (entity.OwnerID != player.userID && IsFriend(entity.OwnerID, player.userID))
                            {
                                return true;
                            }
                            return null;
                        }
                    }
                    else if (target is NPCPlayer)
                    {
                        if (config.options.npcSafe)
                        {
                            return true;
                        }
                    }
                    else if (target is BaseNpc)
                    {
                        if (config.options.npcSafe)
                        {
                            return true;
                        }
                    }
                }
                else if (!isEntityNade && isTargetNade)
                {
                    if (entity is NPCPlayer && config.options.npcSafe)
                    {
                        return true;
                    }
                    else if (entity is BaseNpc && config.options.animalSafe)
                    {
                        return true;
                    }
                }
            }
            return null;
        }

        private object OnTurretTarget(AutoTurret turret, BaseEntity target)
        {
            if (target != null)
            {
                if (config.options.turretSafe && IsNpcGrenade(target.skinID))
                {
                    return true;
                }
            }
            return null;
        }

        private object CanBradleyApcTarget(BradleyAPC bradley, BaseEntity target)
        {
            if (target != null)
            {
                if (IsNpcGrenade(target.skinID))
                {
                    if (config.options.bradleySafe)
                    {
                        return false;
                    }
                }
                var player = target as BasePlayer;
                if (IsNpcGrenade(bradley.skinID))
                {
                    if (player.IsSleeping() && config.options.sleeperSafe)
                    {
                        return false;
                    }
                    if (!config.options.attackOwner && bradley.OwnerID == player.userID)
                    {
                        return false;
                    }
                    if (config.options.useFriends || config.options.useClans || config.options.useTeams)
                    {
                        if (bradley.OwnerID != player.userID && IsFriend(bradley.OwnerID, player.userID))
                        {
                            return true;
                        }
                    }
                }
            }
            return null;
        }

        private object OnBradleyApcInitialize(BradleyAPC bradley)
        {
            if (!IsNpcGrenade(bradley.skinID))
            {
                return null;
            }
            else
            {
                var key = "Bradley Grenade";
                bradley.health = storedData.BradleyNPC[key].Health;
                bradley._maxHealth = storedData.BradleyNPC[key].Health;
                bradley.searchRange = storedData.BradleyNPC[key].SearchRange;
                bradley.viewDistance = storedData.BradleyNPC[key].ViewDistance;
                bradley.maxCratesToSpawn = storedData.BradleyNPC[key].CratesToSpawn;
                bradley.throttle = storedData.BradleyNPC[key].ThrottleResponse;
                bradley.leftThrottle = bradley.throttle;
                bradley.rightThrottle = bradley.throttle;
                bradley.ClearPath();
                bradley.currentPath.Clear();
                bradley.currentPathIndex = 0;
                bradley.DoAI = true;
                bradley.DoSimpleAI();

                var position = bradley.transform.position;
                for (int i = 0; i < storedData.BradleyNPC[key].PatrolPathNodes; i++)
                {
                    position = position + UnityEngine.Random.onUnitSphere * storedData.BradleyNPC[key].PatrolRange;
                    position.y = TerrainMeta.HeightMap.GetHeight(position);
                    bradley.currentPath.Add(position);
                }
                return true;
            }
            return null;
        }

        void OnEntitySpawned(NPCPlayerCorpse corpse)
        {
            if (corpse == null)
            {
                return;
            }

            Inv npcInv = new Inv();
            timer.Once(0.2f, () =>
            {

                if (corpse == null || corpse.IsDestroyed)
                {
                    return;
                }
                ulong id = corpse.playerSteamID;
                if (!NPCInventories.ContainsKey(id))
                {
                    return;
                }
                npcInv = NPCInventories[id];

                corpse._playerName = npcInv.name;
                corpse.lootPanelName = npcInv.name;

                var key = corpse._playerName + " Grenade";
                if (storedData.HumanNPC[key].StripCorpseLoot)
                {
                    corpse.containers[0].Clear();
                }
                else
                {
                    for (int i = 0; i < npcInv.inventory.Length; i++)
                    {
                        foreach (var item in npcInv.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, () => NPCInventories?.Remove(id));
            });
        }

        #endregion

        #region Main

        private void SpawnScientist(BasePlayer player, Item npcNade, Vector3 position, NPCPlayerData settings)
        {
            if (player == null || npcNade == null || position == null || settings == null)
            {
                return;
            }
            DoExplosion(settings.ExplosionSound, position);
            for (int i = 0; i < settings.NumberToSpawn; i++)
            {
                if (settings.NumberToSpawn > 1)
                {
                    position = position + UnityEngine.Random.onUnitSphere * settings.SpawnRadius;
                    position.y = TerrainMeta.HeightMap.GetHeight(position);
                }
                var npc = (ScientistNPC)GameManager.server.CreateEntity(settings.Prefab, position + new Vector3(0, 0.1f, 0), new Quaternion(), true);
                if (npc == null)
                {
                    return;
                }
                npc.Spawn();

                var nav = npc.GetComponent<BaseNavigator>(); 
                if (nav == null)
                {
                    return;
                }
                npc.NavAgent.enabled = true;
                nav.CanUseNavMesh = true; 
                nav.DefaultArea = "Walkable";
                npc.NavAgent.areaMask = 1;
                npc.NavAgent.agentTypeID = -1372625422;  
                npc.NavAgent.autoTraverseOffMeshLink = true; 
                npc.NavAgent.autoRepath = true;
                nav.CanUseCustomNav = true; 
                npc.NavAgent.baseOffset = -0.1f;
                nav.PlaceOnNavMesh();

                var brain = npc.gameObject.AddComponent<ScientistAI>();
                brain.Settings = settings;

                var move = npc.gameObject.AddComponent<ScientistMovement>();
                move.HomeLoc = position;
                move.Settings = settings;

                npc.enableSaving = false;
                npc.skinID = npcNade.skin;
                npc.OwnerID = player.userID;
                npc.displayName = settings.Name;
                npc.damageScale = settings.DamageScale;
                npc.startHealth = settings.Health;
                npc.InitializeHealth(settings.Health, settings.Health);
                npc.EnablePlayerCollider();

                timer.Once(0.2f, () =>
                {
                    if (npc == null || npc.IsDestroyed)
                    {
                        return;
                    }
                    if (SpawnAborted(player, npc, npcNade, position, npc.userID))
                    {
                        return;
                    }
                    GiveGrenadeNpcKit(npc, npcNade);
                    if (settings.DespawnTime > 0)
                    {
                        DespawnNPC(npc, npc.userID, settings.DespawnTime);
                    }
                    GrenadeNPCData.Add(npc.userID, npc);
                });
            }
        }

        private void SpawnScarecrow(BasePlayer player, Item npcNade, Vector3 position, NPCPlayerData settings)
        {
            if (player == null || npcNade == null || position == null || settings == null)
            {
                return;
            }
            DoExplosion(settings.ExplosionSound, position);
            for (int i = 0; i < settings.NumberToSpawn; i++)
            {
                if (settings.NumberToSpawn > 1)
                {
                    position = position + UnityEngine.Random.onUnitSphere * settings.SpawnRadius;
                    position.y = TerrainMeta.HeightMap.GetHeight(position);
                }

                var npc = (ScarecrowNPC)GameManager.server.CreateEntity(settings.Prefab, position + new Vector3(0, 0.1f, 0), new Quaternion(), true);
                
                if (npc == null)
                {
                    return;
                }
                npc.Spawn();

                var nav = npc.GetComponent<BaseNavigator>(); 
                if (nav == null)
                {
                    return;
                }
                npc.NavAgent.enabled = true;
                nav.CanUseNavMesh = true; 
                nav.DefaultArea = "Walkable";
                npc.NavAgent.areaMask = 1;
                npc.NavAgent.agentTypeID = -1372625422;  
                npc.NavAgent.autoTraverseOffMeshLink = true; 
                npc.NavAgent.autoRepath = true;
                nav.CanUseCustomNav = true; 
                npc.NavAgent.baseOffset = -0.1f;
                nav.PlaceOnNavMesh();

                var brain = npc.gameObject.AddComponent<ScarecrowAI>();
                brain.Settings = settings;

                var move = npc.gameObject.AddComponent<ScarecrowMovement>();
                move.HomeLoc = position;
                move.Settings = settings;

                npc.enableSaving = false;
                npc.skinID = npcNade.skin;
                npc.OwnerID = player.userID;
                npc.displayName = settings.Name;
                npc.damageScale = settings.DamageScale;
                npc.startHealth = settings.Health;
                npc.InitializeHealth(settings.Health, settings.Health);
                npc.EnablePlayerCollider();

                timer.Once(0.2f, () =>
                {
                    if (npc == null || npc.IsDestroyed)
                    {
                        return;
                    }
                    if (SpawnAborted(player, npc, npcNade, position, npc.userID))
                    {
                        return;
                    }
                    GiveGrenadeNpcKit(npc, npcNade);

                    if (settings.DespawnTime > 0)
                    {
                        DespawnNPC(npc, npc.userID, settings.DespawnTime);
                    }
                    GrenadeNPCData.Add(npc.userID, npc);
                });
            }
        }

        private void SpawnAnimal(BasePlayer player, Item npcNade, Vector3 position)
        {
            if (storedData.AnimalNPC.ContainsKey(npcNade.name))
            {
                string npcPrefab = storedData.AnimalNPC[npcNade.name].Prefab;
                string npcName = storedData.AnimalNPC[npcNade.name].Name;
                int spawnAmount = storedData.AnimalNPC[npcNade.name].NumberToSpawn;
                string exploSound = storedData.AnimalNPC[npcNade.name].ExplosionSound;

                DoExplosion(exploSound, position);

                for (int i = 0; i < spawnAmount; i++)
                {
                    if (spawnAmount > 1)
                    {
                        position = position + UnityEngine.Random.onUnitSphere * storedData.AnimalNPC[npcNade.name].SpawnRadius;
                        position.y = TerrainMeta.HeightMap.GetHeight(position);
                    }
                    BaseNpc npc = (BaseNpc)GameManager.server.CreateEntity(npcPrefab, position);
                    npc.Spawn();

                    npc.startHealth = storedData.AnimalNPC[npcNade.name].Health;
                    npc.InitializeHealth(storedData.AnimalNPC[npcNade.name].Health, storedData.AnimalNPC[npcNade.name].Health);
                    npc.OwnerID = player.userID;
                    npc.skinID = npcNade.skin;
                    npc.CurrentBehaviour = BaseNpc.Behaviour.Attack;
                    npc.SetFact(BaseNpc.Facts.CanTargetEnemies, 1, true, true);
                    npc.SetFact(BaseNpc.Facts.IsAggro, 1, true, true);

                    if (SpawnAborted(player, npc, npcNade, position, npc.net.ID))
                    {
                        return;
                    }
                    float despawnTime = storedData.AnimalNPC[npcNade.name].DespawnTime;
                    if (despawnTime > 0)
                    {
                        DespawnNPC(npc, npc.net.ID, despawnTime);
                    }
                    BaseNpcData.Add(npc.net.ID, npc);
                }
            }
        }
            
        private void SpawnBradley(BasePlayer player, Item npcNade, Vector3 position)
        {
            if (storedData.BradleyNPC.ContainsKey(npcNade.name))
            {
                string npcPrefab = storedData.BradleyNPC[npcNade.name].Prefab;
                string npcName = storedData.BradleyNPC[npcNade.name].Name;
                int spawnAmount = storedData.BradleyNPC[npcNade.name].NumberToSpawn;
                string exploSound = storedData.BradleyNPC[npcNade.name].ExplosionSound;

                DoExplosion(exploSound, position);

                for (int i = 0; i < spawnAmount; i++)
                {
                    if (spawnAmount > 1)
                    {
                        position = position + UnityEngine.Random.onUnitSphere * storedData.BradleyNPC[npcNade.name].SpawnRadius;
                        position.y = TerrainMeta.HeightMap.GetHeight(position);
                    }

                    BradleyAPC npc = (BradleyAPC)GameManager.server.CreateEntity(npcPrefab, position);
                    npc.OwnerID = player.userID;
                    npc.skinID = npcNade.skin;
                    npc.Spawn();

                    if (SpawnAborted(player, npc, npcNade, position, npc.net.ID))
                    {
                        return;
                    }
                    float despawnTime = storedData.BradleyNPC[npcNade.name].DespawnTime;
                    if (despawnTime > 0)
                    {
                        DespawnNPC(npc, npc.net.ID, despawnTime);
                    }
                    BradleyAPCData.Add(npc.net.ID, npc);
                }
            }
        }

        private void DespawnNPC(BaseEntity npc, ulong botId, float despawnTime)
        {
            timer.Once(despawnTime, () =>
            {
                if (npc != null && !npc.IsDestroyed)
                {
                    NextTick(() =>
                    {
                        npc.Kill();
                        RemoveNpcData(botId);
                    });
                    return;
                }
            });
        }

        #endregion

        #region Helpers

        private void CancelHit(HitInfo info)
        {
            info.damageTypes = new DamageTypeList();
            info.DidHit = false;
            info.DoHitEffects = false;
        }

        private object OnNpcKits(ulong npcUserID) // Prevents conflict with NPCKits.{
            return GrenadeNPCData.ContainsKey(npcUserID) ? true : (object)null;
        }

        private void GiveNade(BasePlayer player, ulong skinId, string nadeName, string reason)
        {
            if (player == null && skinId == null || nadeName == null || reason == null)
            {
                return;
            }
            Item npcNade = ItemManager.CreateByItemID(f1GrenadeId, 1, skinId);
            npcNade.name = nadeName;

            if (reason == "give")
            {
                player.inventory.GiveItem(npcNade);
                Message(player, "Received", nadeName);
            }
            else if (reason == "refund")
            {
                player.inventory.GiveItem(npcNade);
            }
        }

        public Item GiveInventoryItem(ItemContainer itemContainer, string shortName, int itemAmount, ulong skinId)
        {
            Item item = ItemManager.CreateByName(shortName, itemAmount, skinId);
            if (item == null) return null;
            if (!item.MoveToContainer(itemContainer))
            {
                item.Remove(0f);
                return null;
            }
            return item;
        }

        private bool HasPermission(BasePlayer player, Item npcNade)
        {
            if (player == null || npcNade == null)
            {
                return false;
            }
            if (player is NPCPlayer)
            {
                // Allow NPCs spawned by plugins which arm with NPCGrenades to work regardless of perms
                return true;
            }
            else if (storedData.HumanNPC.ContainsKey(npcNade.name))
            {
                string humanPerm = storedData.HumanNPC[npcNade.name].Permission;
                if (permission.UserHasPermission(player.UserIDString, humanPerm))
                {
                    return true;
                }
            }
            else if (storedData.AnimalNPC.ContainsKey(npcNade.name))
            {
                string animalPerm = storedData.AnimalNPC[npcNade.name].Permission;
                if (permission.UserHasPermission(player.UserIDString, animalPerm))
                {
                    return true;
                }
            }
            else if (storedData.BradleyNPC.ContainsKey(npcNade.name))
            {
                string apcPerm = storedData.BradleyNPC[npcNade.name].Permission;
                if (permission.UserHasPermission(player.UserIDString, apcPerm))
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsNpcGrenade(ulong skinId)
        {
            if(NadeInfo.ContainsKey(skinId))
            {
                return true;
            }
            return false;
        }

        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;
        }

        private bool IsInSafeZone(Vector3 position)
        {
            int loop = Physics.OverlapSphereNonAlloc(position, 1f, Vis.colBuffer, 1 << 18, QueryTriggerInteraction.Collide);
            for (int i = 0; i < loop; i++)
            {
                Collider collider = Vis.colBuffer[i];
                if (collider.GetComponent<TriggerSafeZone>())
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsOnStructure(Vector3 position)
        {
            RaycastHit hit;
            var heightOffset = new Vector3(0, 0.1f, 0);
            if (Physics.Raycast(position + heightOffset, Vector3.down,
                    out hit, 4f, LayerMask.GetMask("Construction")) && hit.GetEntity().IsValid())
            {
                if (hit.GetEntity().name.Contains("building"))
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsInRock(Vector3 position)
        {
            RaycastHit hit;
            string[] colliders = new string[] { "rock", "cliff", "junk", "range", "invisible" };
            Physics.queriesHitBackfaces = true;
            if (Physics.Raycast(position, Vector3.up, out hit, 25f, 65536, QueryTriggerInteraction.Ignore))
            {
                if (colliders.Any(x => hit.collider?.gameObject?.name.Contains(x, CompareOptions.OrdinalIgnoreCase) != null))
                {
                    return true;
                }
            }
            Physics.queriesHitBackfaces = false;
            return false;
        }

        private void DoExplosion(string sound, Vector3 position)
        {
            try
            {
                Effect.server.Run(sound, position);
            }
            catch
            {
                Puts($"Invalid explosion effect path specified.");
            }
        }

        private IPlayer FindPlayer(string nameOrIdOrIp)
        {
            foreach (var activePlayer in covalence.Players.Connected)
            {
                if (activePlayer.Id == nameOrIdOrIp)
                    return activePlayer;
                if (activePlayer.Name.Contains(nameOrIdOrIp))
                    return activePlayer;
                if (activePlayer.Name.ToLower().Contains(nameOrIdOrIp.ToLower()))
                    return activePlayer;
                if (activePlayer.Address == nameOrIdOrIp)
                    return activePlayer;
            }
            return null;
        }

        private bool IsFriend(ulong playerId, ulong targetId)
        {
            if (playerId == 0 || targetId == 0)
            {
                return false;
            }
            if (playerId == targetId)
            {
                return true;
            }
            if (Clans)
            {
                var result = Clans?.Call("IsMemberOrAlly", playerId, targetId);
                if (result != null && Convert.ToBoolean(result))
                {
                    return true;
                }
            }
            if (Friends)
            {
                var result = Friends?.Call("AreFriends", playerId, targetId);
                if (result != null && Convert.ToBoolean(result))
                {
                    return true;
                }
            }
            RelationshipManager.PlayerTeam team;
            RelationshipManager.ServerInstance.playerToTeam.TryGetValue(playerId, out team);
            if (team == null)
            {
                return false;
            }
            if (team.members.Contains(targetId))
            {
                return true;
            }
            return false;
        }

        private bool SpawnAborted(BasePlayer player, BaseEntity npc, Item npcNade, Vector3 position, ulong npcId)
        {
            if (npc == null || npc.IsDestroyed)
            {
                return true;
            }
            if (npc.WaterFactor() > 0.7f)
            {
                npc.Kill();
                Message(player, "UnderWater", npcNade.name, npcId);
                return true;
            }
            else if (IsInSafeZone(position))
            {
                npc.Kill();
                Message(player, "InSafeZone", npcNade.name, npcId);
                return true;
            }
            else if (!npc.IsOutside())
            {
                npc.Kill();
                Message(player, "Outside", npcNade.name, npcId);
                return true;
            }
            else if (IsOnStructure(position))
            {
                npc.Kill();
                Message(player, "OnStructure", npcNade.name, npcId);
                return true;
            }
            else if (IsInRock(position))
            {
                npc.Kill();
                Message(player, "IsInRock", npcNade.name, npcId);
                return true;
            }
            return false;
        }

        private void RemoveNpcData(ulong npcId)
        {
            if (GrenadeNPCData.ContainsKey(npcId))
            {
                GrenadeNPCData.Remove(npcId);
            }
            else if (BaseNpcData.ContainsKey(npcId))
            {
                BaseNpcData.Remove(npcId);
            }
            else if (BradleyAPCData.ContainsKey(npcId))
            {
                BradleyAPCData.Remove(npcId);
            }
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(Name, storedData);
        }
        #endregion

        #region Kits

        private void GiveGrenadeNpcKit(NPCPlayer npc, Item npcNade)
        {
            if (storedData.HumanNPC.ContainsKey(npcNade.name))
            {
                int kitCount = storedData.HumanNPC[npcNade.name].KitList.Count();
                if (Kits)
                {
                    if (kitCount > 0)
                    {
                        var kit = storedData.HumanNPC[npcNade.name].KitList[random.Next(kitCount)];
                        object kitCheck = Kits?.CallHook("GetKitInfo", kit, true);
                        if (kitCheck == null)
                        {
                            Puts($"Kit: \"{kit}\" does not exist, using default kit.");
                        }
                        else
                        {
                            npc.inventory.Strip();
                            Kits?.Call($"GiveKit", npc, kit, true);
                            return;
                        }
                    }
                }

                if (npc == null) return;
                npc.inventory.Strip();

                foreach (var item in storedData.HumanNPC[npcNade.name].DefaultLoadout)
                {
                    var container = item.Container.ToLower();
                    if (container == "belt")
                    {
                        GiveInventoryItem(npc.inventory.containerBelt, item.Shortname, item.Amount, item.SkinID);
                    }
                    else if (container == "wear")
                    {
                        GiveInventoryItem(npc.inventory.containerWear, item.Shortname, item.Amount, item.SkinID);
                    }
                    else
                    {
                        GiveInventoryItem(npc.inventory.containerMain, item.Shortname, item.Amount, item.SkinID);
                    }
                }
            }
        }

        #endregion

        #region Commands

        [Command("npcnade.give")]
        private void CmdGiveNpcNade(IPlayer player, string command, string[] args)
        {
            if (!player.HasPermission(permAdmin))
            {
                Message(player, "NotAdmin");
                return;
            }
            else if (args.Length < 2)
            {
     
// ... [Code preview truncated due to length. Full source in attached file] ...

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