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

FREE WalkingDead : 1.2.2 1.2.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

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 Oxide.Core.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Facepunch;
using Rust;
using Rust.Ai;


#region Changelogs and ToDo
/*************************************************************
* 
* Thx Steenamaroo for the coding assistance :)
*
* 1.0.9     :   Added additional checks
*           :   Possible fix for msg nre in console
* 1.0.10    :   Added check for chat message timer (hopefully fixes the nre)
* 1.0.11    :   Removed Gametip messages
* 1.0.12    :   Walkers will not spawn on foundations
* 1.1.0     :   Walkers dont attack animals/npc true/false to config
* 1.1.1     :   Fix for NRE
* 1.1.2     :   Added ResourceId for dev API
*           :   Added simple debug through cfg settings
*           :   Possible fix for NextTick issue
* 1.1.3     :   Fix for Kits NRE
* 1.1.4     :   Added option to block spawn if player suicided
*           :   Added test for single zoneblock
* 1.1.5     :   Added watercheck and suicide when walking under water
*           :   Improved NPC targetinging eachother
* 1.1.6     :   Patched for December 2nd rust update
*           :   Removed murderer which is removed by Facepunch
*           :   NPC are now scientists (working on mellee part)
*           :   Fixed walkers not spawning with suit if no clothing or kits
*           :   Walkers now wield a eoka waterpipe or double barrel by default
*           :   Fixed oxide mixing up HumanNPC plugin(same name) and npc type
* 1.2.0     :   NPC is now a melee type again (scarecrow)
*           :   Added various Behaviours for melee attack
*           :   Small coding cleanup
* 1.2.1     :   Added safezonecheck (including custom safezone triggers)
*           :   Zones (old test) is now a list
* 1.2.2     :   Fix for compile issues
* 
**************************************************************/
#endregion

namespace Oxide.Plugins
{
    [Info("Walking Dead", "Krungh Crow", "1.2.2", ResourceId = 280)]
    [Description("Spawns a real zombie after you die")]

    class WalkingDead : RustPlugin
    {
        [PluginReference] Plugin Kits, ZoneManager;

        #region Variables
        Dictionary<string, Timer> CoolDowns = new Dictionary<string, Timer>();
        public static WalkingDead instance;

        const string zombie = "assets/prefabs/npc/scarecrow/scarecrow.prefab";
        const string fireball1 = "assets/bundled/prefabs/fireball.prefab";
        const ulong chaticon = 76561199087926121;
        bool Debug = false;

        #endregion

        #region Behaviour
        public class Walkers : FacepunchBehaviour
        {
            private ScarecrowNPC npc;
            public bool ReturningToHome = false;
            public bool isRoaming = true;
            public Vector3 SpawnPoint;

            private void Awake()
            {
                npc = GetComponent<ScarecrowNPC>();
                Invoke(nameof(_UseBrain), 0.1f);
                InvokeRepeating(Attack, 1.2f, 2.0f);
                InvokeRepeating(GoHome, 2.0f, 4.5f);
            }

            public void _UseBrain()
            {
                #region navigation
                npc.Brain.Navigator.Agent.agentTypeID = -1372625422;
                npc.Brain.Navigator.DefaultArea = "Walkable";
                npc.Brain.Navigator.Agent.autoRepath = true;
                npc.Brain.Navigator.enabled = true;
                npc.Brain.Navigator.CanUseNavMesh = true;
                npc.Brain.Navigator.BestRoamPointMaxDistance = instance.configData.ZombieData.ZombieRoam;
                npc.Brain.Navigator.MaxRoamDistanceFromHome = instance.configData.ZombieData.ZombieRoam;
                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;
                npc.Brain.ListenRange = 40f;
                npc.Brain.Senses.Init(npc, npc.Brain, 5f, 140f, 140f, -1f, true, false, true, 60f, false, false, false, EntityType.Player, false);
                npc.Brain.TargetLostRange = 25f;
                npc.Brain.HostileTargetsOnly = false;
                npc.Brain.IgnoreSafeZonePlayers = true;
                #endregion
            }

            private void Attack()
            {
                BaseEntity entity = npc.Brain.Senses.GetNearestTarget(40);

                if (entity != null && Vector3.Distance(entity.transform.position, npc.transform.position) < 2.0f)
                {
                    npc.StartAttacking(entity);
                    npc.Brain.Navigator.SetFacingDirectionEntity(entity);
                }
            }

            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())
                        {
                            WipeMemory();
                            ReturningToHome = true;
                            isRoaming = false;
                            return;
                        }
                        if (npc.Distance(player.transform.position) > 25f)
                        {
                            WipeMemory();
                            ReturningToHome = true;
                            isRoaming = false;
                            return;
                        }
                    }
                }

                var distanceHome = Vector3.Distance(npc.transform.position, SpawnPoint);
                if (ReturningToHome == false)
                {
                    if (isRoaming == true && distanceHome > instance.configData.ZombieData.ZombieRoam)
                    {
                        ReturningToHome = true;
                        isRoaming = false;
                        return;
                    }
                    if (isRoaming == true && distanceHome < instance.configData.ZombieData.ZombieRoam)
                    {
                        Vector3 random = UnityEngine.Random.insideUnitCircle.normalized * instance.configData.ZombieData.ZombieRoam;
                        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;
                isRoaming = true;
            }

            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();
                }
                CancelInvoke(GoHome);
                CancelInvoke(Attack);
                CancelInvoke(nameof(_UseBrain));
            }
        }

        void Unload()
        {
            Walkers[] walkers = UnityEngine.Object.FindObjectsOfType<Walkers>();
            if (walkers != null)
            {
                foreach (Walkers walker in walkers)
                    UnityEngine.Object.Destroy(walker);
                if (Debug) Puts($"[Debug] All Walkers where destroyed on Plugin Un/Reload");
            }
        }

        #endregion

        #region Configuration
        void Init()
        {
            if (!LoadConfigVariables())
            {
                Puts("Config file issue detected.Please delete file, or check syntax and fix.");
                return;
            }
            Debug = configData.PlugCFG.Debug;
            if (Debug) Puts($"[Debug] is activated");
        }

        private ConfigData configData;

        class ConfigData
        {
            [JsonProperty(PropertyName = "Settings Plugin")]
            public SettingsPlugin PlugCFG = new SettingsPlugin();
            [JsonProperty(PropertyName = "Settings Player")]
            public SettingsPlayer PlayerCFG = new SettingsPlayer();
            [JsonProperty(PropertyName = "Zombie Settings")]
            public SettingsZombie ZombieData = new SettingsZombie();
            [JsonProperty(PropertyName = "Zombie Targeting")]
            public SettingsTarget ZombieTarget = new SettingsTarget();
        }

        class SettingsPlugin
        {
            [JsonProperty(PropertyName = "Debug")]
            public bool Debug = false;
        }

        class SettingsPlayer
        {
            [JsonProperty(PropertyName = "Suicide block")]
            public bool SuicideBlock = false;
            [JsonProperty(PropertyName = "Zone block")]
            public bool ZoneBlock = false;
            [JsonProperty(PropertyName = "Zone ID's")]
            public List<string> ZoneID = new List<string>();

        }

        class SettingsZombie
        {
            [JsonProperty(PropertyName = "Zombie spawn delay (seconds)")]
            public int SpawnTime = 5;
            [JsonProperty(PropertyName = "Zombie spawn cooldown (seconds)")]
            public int Cooldown = 300;
            [JsonProperty(PropertyName = "Zombie Show cooldown chat messages")]
            public bool ShowCooldownMsg = false;
            [JsonProperty(PropertyName = "Zombie Prefix Title")]
            public string ZombiePrefix = "Walker";
            [JsonProperty(PropertyName = "Zombie spawn amount")]
            public int SpawnAmount = 1;
            [JsonProperty(PropertyName = "Zombie Health")]
            public int ZombieHealth = 250;
            [JsonProperty(PropertyName = "Zombie spawn radius")]
            public int Radius = 5;
            [JsonProperty(PropertyName = "Zombie Max Roam Distance")]
            public int ZombieRoam = 20;
            [JsonProperty(PropertyName = "Zombie Damage multiplier")]
            public float ZombieDamageScale = 0.6f;
            [JsonProperty(PropertyName = "Zombie Lifetime (minutes)")]
            public float ZombieLife = 30f;
            [JsonProperty(PropertyName = "Zombie Spawns on fire")]
            public bool FromHell = false;
            [JsonProperty(PropertyName = "Zombie Kit ID")]
            public List<string> KitName = new List<string>();
            [JsonProperty(PropertyName = "Zombie Show chat messages")]
            public bool ShowMsg = false;
        }

        class SettingsTarget
        {
            [JsonProperty(PropertyName = "Zombie Can target other npc")]
            public bool TargetNPC = false;
            [JsonProperty(PropertyName = "Zombie Can target animals")]
            public bool TargetAnimal = false;
        }


        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>
            {
                ["Cooldown"] = "You have a cooldown and didnt ressurect a walker!!",
                ["Zombie_Spawn"] = "You died and resurrected a Walker!",
                ["Prefix"] = "<color=green>Walking Dead : </color>",
                ["info"] = "\nThe [Walking Dead] will resurrect players as Walkers\nThese are aggressive and attack anything on sight !!\nUsing their melee weapons they can and will go after you !!",
            }, this);
        }

        #endregion

        #region Commands

        [ChatCommand("wdinfo")]
        void cmdwdversion(BasePlayer player, string cmd, string[] args)
        {
            string prefix = lang.GetMessage("Prefix", this);
            {
                Player.Message(player, prefix + string.Format(msg("Current Version v", player.UserIDString)) + this.Version.ToString() + " By : " + this.Author.ToString() + msg("info"), chaticon);
            }
        }

        #endregion

        #region Hooks

        void OnServerInitialized()
        {
            instance = this;

            if (ZoneManager)
            {
                Puts("Check for [ZoneManager] dependency : Installed");
            }
            else
            {
                Puts("Check for [ZoneManager] dependency : Not Installed");
            }

        }

        private object OnNpcTarget(BaseEntity attacker, BaseEntity target)
        {
            if (attacker?.gameObject?.GetComponent<Walkers>())
            {
                if (target is NPCPlayer && configData.ZombieTarget.TargetNPC == false)
                {
                    if (Debug) Puts($"[Debug] NPC targeting is false ignore NPC {target}");
                    return true;
                }

                if (target is TunnelDweller || target is UnderwaterDweller && configData.ZombieTarget.TargetNPC == false)
                {
                    if (Debug) Puts($"[Debug] NPC targeting is false ignoring Dweller {target}");
                    return true;
                }

                if (target is BaseNpc && (configData.ZombieTarget.TargetAnimal == false))
                {
                    if (Debug) Puts($"[Debug] Animal targeting is false ignoring {target}");
                    return true;
                }
                return null;

                if (target?.gameObject?.GetComponent<Walkers>() && (attacker.IsNpc || attacker is NPCPlayer))
                {
                    return true;
                }
                return null;
            }
            return null;
        }

        private object OnNpcTarget(BaseEntity attacker, BasePlayer target)
        {
            if (attacker?.gameObject?.GetComponent<Walkers>())
            {
                if (target.InSafeZone() || target.HasPlayerFlag(BasePlayer.PlayerFlags.SafeZone)) return true;
                if (target.IsSleeping() || target.IsFlying || !(target.userID.IsSteamId())) return true;
            }
            return null;
        }

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

        void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player.userID.IsSteamId())
            {
                if (!ZoneManager)
                {
                    if (Debug) Puts($"[Debug] Zonemanager not installed skipping ZoneCheck");
                }
                else
                {
                    var zoneIds = ZoneManager?.Call("GetZoneIDs") as string[];

                    if (zoneIds == null)
                    {
                        if (Debug) Puts($"[Debug] No ZoneId's are listed");
                        return;
                    }

                    bool IsInZone = false;

                    foreach (string zoneId in zoneIds)

                    {
                        if ((bool)ZoneManager?.Call("isPlayerInZone", zoneId, player) && zoneId.Contains(configData.PlayerCFG.ZoneID.ToString()) && configData.PlayerCFG.ZoneBlock)
                        {
                            IsInZone = true;
                            if (Debug) Puts($"[Debug] {player} is in excluded Zone:[{zoneId}] skipping Walker spawn");
                            return;
                        }
                    }
                }

                if (player.InSafeZone() || player.HasPlayerFlag(BasePlayer.PlayerFlags.SafeZone))
                {
                    if (Debug) Puts($"[Debug] {player} was in a safezone skipping walker spawn");
                    return;
                }

                if (configData.PlayerCFG.SuicideBlock && info != null && info.damageTypes.GetMajorityDamageType() == Rust.DamageType.Suicide)
                {
                    if (Debug) Puts($"[Debug] {player} was suicideblocked skipping walker spawn");
                    return;
                }

                if (CoolDowns.ContainsKey(player.UserIDString))
                {
                    if (configData.ZombieData.ShowCooldownMsg == true)
                    {
                        if (Debug) Puts($"[Debug] Player had cooldown message triggered");
                        string prefix = lang.GetMessage("Prefix", this);
                        Player.Message(player, prefix + string.Format(msg("Cooldown", player.UserIDString)), chaticon);
                    }
                    return;
                }
                else
                {
                    string id = player.UserIDString;
                    Timer Cooldown = timer.Once((float)configData.ZombieData.Cooldown, () =>
                    {
                        if (Debug) Puts($"[Debug] {player} cooldown ended");
                        CoolDowns.Remove(id);
                    });

                    CoolDowns.Add(id, Cooldown);
                    if (Debug) Puts($"[Debug] {player} cooldown started");
                }

                var loc = player.transform.position;
                string name = player.displayName;

                List<ClothingItems> clothes = new List<ClothingItems>();

                foreach (var item in player.inventory.containerWear.itemList)
                {
                    clothes.Add(new ClothingItems() { ItemId = item.info.itemid, SkinId = item.skin });
                }

                timer.Once(configData.ZombieData.SpawnTime, () =>
                {
                    for (int i = 0; i < configData.ZombieData.SpawnAmount; i++)
                        Spawnnpc(loc, name, clothes);
                    if (Debug) Puts($"[Debug] Walker ({name}) spawned at {loc}");
                });

                if (configData.ZombieData.ShowMsg)
                {
                    if (!player.userID.IsSteamId())
                    {
                        return;
                    }

                    if (player == null)
                    {
                        return;
                    }

                    if (player != null) ;
                    {
                        string prefix = lang.GetMessage("Prefix", this);
                        Player.Message(player, prefix + string.Format(msg("Zombie_Spawn", player.UserIDString)), chaticon);
                        if (Debug) Puts($"[Debug] {player} recieved a spawn message");
                    }

                }
            }
        }

        #endregion

        #region Event Helpers

        public class ClothingItems
        {
            public int ItemId;
            public ulong SkinId;
        }
         
        private void Spawnnpc(Vector3 pos, string name, List<ClothingItems> clothes)
        {
            int radius = configData.ZombieData.Radius;
            int x = UnityEngine.Random.Range(-radius, radius);
            int z = UnityEngine.Random.Range(-radius, radius);
            pos += new Vector3(x, 0.1f, z);

            ScarecrowNPC npc = (ScarecrowNPC)GameManager.server.CreateEntity(zombie, pos, new Quaternion(), true);
            npc.Spawn();
            if (npc == null)
                return;

            var inv_wear = npc.inventory.containerWear;
            var inv_belt = npc.inventory.containerBelt;

            NextTick(() =>
            {
                if (npc == null)
                    return;

                var mono = npc.gameObject.AddComponent<Walkers>();
                mono.SpawnPoint = pos;

                string Zombieprefix = configData.ZombieData.ZombiePrefix;

                int HealtH = configData.ZombieData.ZombieHealth;

                npc.startHealth = HealtH;
                npc.InitializeHealth(HealtH, HealtH);
                npc.displayName = Zombieprefix + (" ") + name;

                if (configData.ZombieData.FromHell)
                {
                    var Fire = GameManager.server.CreateEntity(fireball1, new Vector3(0, 1, 0), Quaternion.Euler(0, 0, 0));
                    Fire.gameObject.Identity();
                    Fire.SetParent(npc);
                    Fire.Spawn();
                    if (Debug) Puts($"[Debug] Walker ({name}) spawned From Hell (on Fire)");
                    timer.Once(1f, () =>
                    {
                        if (Fire != null) Fire.Kill();
                    });
                }
                npc.damageScale = configData.ZombieData.ZombieDamageScale;

                if (clothes.Count != 0)
                {
                    inv_wear.Clear();

                    foreach (var item in clothes)
                    {
                    var item1 = ItemManager.CreateByItemID(item.ItemId, 1, item.SkinId);
                    if (item1 == null)
                    Puts("Failed to create item.");
                    if (!item1.MoveToContainer(npc.inventory.containerWear))
                        {
                            Puts("Failed to move item to zombie inventory.");
                            item1.Remove();
                        }
                    }
                }
                else if (clothes.Count == 0 && configData.ZombieData.KitName.Count > 0)
                {
                    object checkKit = Kits?.CallHook("GetKitInfo", configData.ZombieData.KitName[new System.Random().Next(configData.ZombieData.KitName.Count())]);
                    if (checkKit == null)
                    {
                        Item eyes = ItemManager.CreateByName("gloweyes", 1, 0);
                        if (eyes != null) eyes.MoveToContainer(inv_wear);
                    }
                    else
                    {
                        npc.inventory.Strip();
                        Kits?.Call($"GiveKit", npc, configData.ZombieData.KitName[new System.Random().Next(configData.ZombieData.KitName.Count())]);
                    }
                }
                else
                {
                    Item eyes = ItemManager.CreateByName("gloweyes", 1, 0);
                    if (eyes != null) eyes.MoveToContainer(inv_wear);
                }
            });

            if (npc.IsHeadUnderwater())
            {
                npc.Kill();
                if (Debug) Puts($"[Debug] Walker ({name}) spawned under water killing walker ({name})");
                return;
            }

            if (!npc.IsOutside())
            {
                npc.Kill();
                Puts("walker[" + npc.userID + "] was not spawned beceause it wanted to spawn inside");
                return;
            }

            var id = npc.userID;

            timer.Once(configData.ZombieData.ZombieLife * 60, () =>
            {
                if (npc != null)
                    npc.Hurt(configData.ZombieData.ZombieHealth + 100);

                Puts("Walker [" + id + "] Died of unnatural causes!!!");
            });

        }

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

        #endregion

        #region Message Helper

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

        #endregion
    }
}

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