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

FREE NightZombies : 5.0.2 5.0.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
using Physics = UnityEngine.Physics;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using ConVar;
using Pool = Facepunch.Pool;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("Night Zombies", "0x89A", "5.0.2")]
    [Description("Spawns and kills zombies at set times")]
    class NightZombies : RustPlugin
    {
        private const string DeathSound = "assets/prefabs/npc/murderer/sound/death.prefab";
        private const string RemoveMeMethodName = nameof(DroppedItemContainer.RemoveMe);
        private const int GrenadeItemId = 1840822026;
        
        private static NightZombies _instance;
        private static Configuration _config;
        private DynamicConfigFile _dataFile;
        
        [PluginReference("Kits")]
        private Plugin _kits;
        
        [PluginReference("Vanish")]
        private Plugin _vanish;
        
        // The top-level spawn controller now manages multiple spawn wave controllers.private SpawnController _spawnController;
        // Persistent (monument) zombie controller.private MonumentController _monumentController;
        
        #region -Init-
        
        private void Init()
        {
            _instance = this;
            
            // Register permissions
            permission.RegisterPermission("nightzombies.admin", this);
            permission.RegisterPermission("nightzombies.ignore", this);
            
            // Create our multi-wave controller and persistent zombie controller._spawnController = new SpawnController();
            _monumentController = new MonumentController();
            
            // Read saved number of days since last spawn._dataFile = Interface.Oxide.DataFileSystem.GetFile("NightZombies-daysSinceSpawn");
            try
            {
                _spawnController.DaysSinceLastSpawn = _dataFile.ReadObject<int>();
            }
            catch
            {
                PrintWarning("Failed to load saved days since last spawn, defaulting to 0");
                _spawnController.DaysSinceLastSpawn = 0;
            }
            
            if (_config.Behaviour.SentriesAttackZombies)
                Unsubscribe(nameof(OnTurretTarget));
            if (_config.Destroy.SpawnLoot)
                Unsubscribe(nameof(OnCorpsePopulate));
            if (_config.Behaviour.Ignored.Count == 0 && !_config.Behaviour.IgnoreHumanNpc && _config.Behaviour.AttackSleepers)
                Unsubscribe(nameof(OnNpcTarget));
        }
        
        private void OnServerInitialized()
        {
            if (!_kits?.IsLoaded ?? false)
                PrintWarning("Kits is not loaded, custom kits will not work");
            
            // Start time check for each spawn wave.if (_config.SpawnWaves != null && _config.SpawnWaves.Count > 0)
            {
                TOD_Sky.Instance.Components.Time.OnMinute += _spawnController.TimeTick;
                TOD_Sky.Instance.Components.Time.OnDay += OnDay;
            }
            
            // Initialize persistent monument zombies._monumentController.Initialize();
        }
        
        private void Unload()
        {
            TOD_Sky.Instance.Components.Time.OnMinute -= _spawnController.TimeTick;
            TOD_Sky.Instance.Components.Time.OnDay -= OnDay;
            
            _dataFile.WriteObject(_spawnController.DaysSinceLastSpawn);
            _spawnController?.Shutdown();
            _monumentController?.Shutdown();
            
            _config = null;
            _instance = null;
        }
        
        private void OnDay() => _spawnController.DaysSinceLastSpawn++;
        
        #endregion
        
        #region -Chat Commands-
        
        [ChatCommand("forcespawn")]
        private void ForceSpawnCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, "nightzombies.admin"))
            {
                player.ChatMessage("You do not have permission to use this command.");
                return;
            }
            
            _spawnController.ForceSpawn();
            player.ChatMessage("Forced spawn initiated.Zombies will vanish in 10 minutes.");
        }
        
        [ChatCommand("despawnall")]
        private void DespawnAllCommand(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, "nightzombies.admin"))
            {
                player.ChatMessage("You do not have permission to use this command.");
                return;
            }
            
            _spawnController.DespawnAll();
            _monumentController.DespawnAll();
            player.ChatMessage("All zombies and corpses have been despawned.");
        }
        
        #endregion
        
        #region -Oxide Hooks-
        
        private object OnNpcTarget(ScarecrowNPC npc, BaseEntity target)
        {
            return CanAttack(target);
        }
        
        private object OnTurretTarget(NPCAutoTurret turret, ScarecrowNPC entity)
        {
            if (entity == null)
                return null;
            return true;
        }
        
        private object OnPlayerDeath(ScarecrowNPC scarecrow, HitInfo info)
        {
            Effect.server.Run(DeathSound, scarecrow.transform.position);
            _spawnController.ZombieDied(scarecrow);
            // Monument zombies are persistent and handled separately.if (_config.Destroy.LeaveCorpseKilled)
                return null;
            
            NextTick(() =>
            {
                if (scarecrow == null || scarecrow.IsDestroyed)
                    return;
                scarecrow.AdminKill();
            });
            return true;
        }
        
        private BaseCorpse OnCorpsePopulate(ScarecrowNPC npcPlayer, NPCPlayerCorpse corpse)
        {
            return corpse;
        }
        
        private void OnEntitySpawned(NPCPlayerCorpse corpse)
        {
            // Default to first wave's display name.corpse.playerName = _config.SpawnWaves[0].Zombies.DisplayName;
        }
        
        private void OnEntitySpawned(DroppedItemContainer container)
        {
            if (!_config.Destroy.HalfBodybagDespawn)
                return;
            NextTick(() =>
            {
                if (container != null && container.playerName == _config.SpawnWaves[0].Zombies.DisplayName)
                {
                    container.CancelInvoke(RemoveMeMethodName);
                    container.Invoke(RemoveMeMethodName, container.CalculateRemovalTime() / 2);
                }
            });
        }
        
        #endregion
        
        #region -Helpers-
        
        private object CanAttack(BaseEntity target)
        {
            // If target is a player with the "nightzombies.ignore" permission, never attack them.if (target is BasePlayer player && permission.UserHasPermission(player.UserIDString, "nightzombies.ignore"))
                return true;
            
            if (_config.Behaviour.Ignored.Contains(target.ShortPrefabName) ||
                (_config.Behaviour.IgnoreHumanNpc && HumanNPCCheck(target)) ||
                (!_config.Behaviour.AttackSleepers && target is BasePlayer player2 && player2.IsSleeping()))
                return true;
            
            return null;
        }
        
        private bool HumanNPCCheck(BaseEntity target)
        {
            return target is BasePlayer player && !player.userID.IsSteamId() &&
                   target is not ScientistNPC && target is not ScarecrowNPC;
        }
        
        #endregion
        
        #region -Classes-
        
        // Top-level spawn controller managing multiple spawn wave controllers.private class SpawnController
        {
            public int DaysSinceLastSpawn;
            private List<SpawnWaveController> waveControllers = new List<SpawnWaveController>();
            
            public SpawnController()
            {
                if (_config.SpawnWaves == null || _config.SpawnWaves.Count == 0)
                    _config.SpawnWaves = new List<Configuration.SpawnWave> { new Configuration.SpawnWave() };
                foreach (var wave in _config.SpawnWaves)
                {
                    waveControllers.Add(new SpawnWaveController(wave));
                }
            }
            
            public void TimeTick()
            {
                foreach (var wave in waveControllers)
                    wave.TimeTick();
            }
            
            public void ForceSpawn()
            {
                foreach (var wave in waveControllers)
                    wave.ForceSpawn();
            }
            
            public void DespawnAll()
            {
                foreach (var wave in waveControllers)
                    wave.DespawnAll();
            }
            
            public void ZombieDied(ScarecrowNPC zombie)
            {
                foreach (var wave in waveControllers)
                {
                    if (wave.RemoveZombie(zombie))
                        break;
                }
            }
            
            public void Shutdown()
            {
                foreach (var wave in waveControllers)
                    wave.Shutdown();
            }
        }
        
        // Controller for a single spawn wave.private class SpawnWaveController
        {
            private readonly Configuration.SpawnWave waveConfig;
            private readonly int spawnLayerMask = LayerMask.GetMask("Default", "Tree", "Construction", "World", "Vehicle_Detailed", "Deployed");
            private readonly WaitForSeconds waitTenthSecond = new WaitForSeconds(0.1f);
            private bool _spawned;
            private Coroutine _currentCoroutine;
            private readonly List<ScarecrowNPC> zombies = new List<ScarecrowNPC>();
            
            // Dictionary to track how long each zombie has been fully submerged.private Dictionary<ScarecrowNPC, float> waterTimes = new Dictionary<ScarecrowNPC, float>();
            // Timer to check water status every second.private Timer waterTimer;
            // Head offset used to determine if a zombie is fully underwater.private const float ZombieHeadOffset = 1.8f;
            
            public SpawnWaveController(Configuration.SpawnWave config)
            {
                waveConfig = config;
                waterTimer = _instance.timer.Every(1f, () => CheckWaterStatus());
            }
            
            private bool IsSpawnTime
            {
                get
                {
                    if (waveConfig.SpawnTime > waveConfig.DestroyTime)
                        return Env.time >= waveConfig.SpawnTime || Env.time < waveConfig.DestroyTime;
                    else
                        return Env.time <= waveConfig.SpawnTime || Env.time > waveConfig.DestroyTime;
                }
            }
            
            private bool IsDestroyTime
            {
                get
                {
                    if (waveConfig.SpawnTime > waveConfig.DestroyTime)
                        return Env.time >= waveConfig.DestroyTime && Env.time < waveConfig.SpawnTime;
                    else
                        return Env.time <= waveConfig.DestroyTime && Env.time > waveConfig.SpawnTime;
                }
            }
            
            private bool CanSpawn()
            {
                return !_spawned && Random.Range(0f, 100f) < waveConfig.Chance.Chance;
            }
            
            public void TimeTick()
            {
                if (CanSpawn() && IsSpawnTime)
                    _currentCoroutine = ServerMgr.Instance.StartCoroutine(SpawnZombies());
                else if (zombies.Count > 0 && IsDestroyTime && _spawned)
                    _currentCoroutine = ServerMgr.Instance.StartCoroutine(RemoveZombies());
            }
            
            private IEnumerator SpawnZombies()
            {
                _spawned = true;
                for (int i = 0; i < waveConfig.Zombies.Population; i++)
                {
                    SpawnZombie();
                    yield return waitTenthSecond;
                }
                _currentCoroutine = null;
            }
            
            private IEnumerator RemoveZombies(bool shuttingDown = false)
            {
                if (zombies.Count == 0)
                    yield break;
                if (_currentCoroutine != null)
                    ServerMgr.Instance.StopCoroutine(_currentCoroutine);
                // Iterate backwards for performance.for (int i = zombies.Count - 1; i >= 0; i--)
                {
                    ScarecrowNPC zombie = zombies[i];
                    if (zombie == null || zombie.IsDestroyed)
                        continue;
                    zombie.AdminKill();
                    yield return !shuttingDown ? waitTenthSecond : null;
                }
                zombies.Clear();
                _spawned = false;
                _currentCoroutine = null;
            }
            
            public void ForceSpawn()
            {
                _spawned = true;
                for (int i = 0; i < waveConfig.Zombies.Population; i++)
                    SpawnZombie();
                _instance.timer.Once(600f, () =>
                {
                    for (int i = zombies.Count - 1; i >= 0; i--)
                    {
                        ScarecrowNPC zombie = zombies[i];
                        if (zombie != null && !zombie.IsDestroyed)
                        {
                            zombie.AdminKill();
                            zombies.RemoveAt(i);
                        }
                    }
                    _spawned = false;
                });
            }
            
            public void DespawnAll()
            {
                if (_currentCoroutine != null)
                    ServerMgr.Instance.StopCoroutine(_currentCoroutine);
                for (int i = zombies.Count - 1; i >= 0; i--)
                {
                    ScarecrowNPC zombie = zombies[i];
                    if (zombie != null && !zombie.IsDestroyed)
                        zombie.AdminKill();
                }
                zombies.Clear();
                _spawned = false;
            }
            
            public bool RemoveZombie(ScarecrowNPC zombie)
            {
                if (zombies.Contains(zombie))
                {
                    zombies.Remove(zombie);
                    if (IsSpawnTime)
                        SpawnZombie();
                    return true;
                }
                return false;
            }
            
            public void Shutdown()
            {
                if (waterTimer != null)
                    waterTimer.Destroy();
                ServerMgr.Instance.StartCoroutine(RemoveZombies(true));
            }
            
            #region -Util-
            
            private void SpawnZombie()
            {
                if (zombies.Count >= waveConfig.Zombies.Population)
                    return;
                Vector3 position = (waveConfig.SpawnNearPlayers && BasePlayer.activePlayerList.Count >= waveConfig.MinNearPlayers && GetRandomPlayer(out BasePlayer player))
                    ? GetRandomPositionAroundPlayer(player)
                    : GetRandomPosition();
                ScarecrowNPC zombie = GameManager.server.CreateEntity("assets/prefabs/npc/scarecrow/scarecrow.prefab", position) as ScarecrowNPC;
                if (zombie == null)
                    return;
                zombie.Spawn();
                zombie.displayName = waveConfig.Zombies.DisplayName;
                if (zombie.TryGetComponent(out BaseNavigator navigator))
                {
                    navigator.ForceToGround();
                    navigator.PlaceOnNavMesh(0);
                }
                float health = waveConfig.Zombies.Health;
                zombie.SetMaxHealth(health);
                zombie.SetHealth(health);
                if (_instance._kits != null && waveConfig.Zombies.Kits.Count > 0)
                {
                    zombie.inventory.containerWear.Clear();
                    ItemManager.DoRemoves();
                    _instance._kits.Call("GiveKit", zombie, waveConfig.Zombies.Kits.GetRandom());
                }
                if (!_config.Behaviour.ThrowGrenades)
                {
                    foreach (Item item in zombie.inventory.FindItemsByItemID(GrenadeItemId))
                        item.Remove();
                    ItemManager.DoRemoves();
                }
                zombies.Add(zombie);
            }
            
            private bool GetRandomPlayer(out BasePlayer player)
            {
                List<BasePlayer> players = Pool.GetList<BasePlayer>();
                foreach (BasePlayer bplayer in BasePlayer.activePlayerList)
                {
                    if (bplayer.IsFlying || _instance._vanish?.Call<bool>("IsInvisible", bplayer) == true)
                        continue;
                    players.Add(bplayer);
                }
                player = players.GetRandom();
                Pool.FreeList(ref players);
                return player;
            }
            
            private Vector3 GetRandomPosition()
            {
                Vector3 position = Vector3.zero;
                for (int i = 0; i < 6; i++)
                {
                    float x = Random.Range(-TerrainMeta.Size.x / 2, TerrainMeta.Size.x / 2),
                          z = Random.Range(-TerrainMeta.Size.z / 2, TerrainMeta.Size.z / 2),
                          y = TerrainMeta.HeightMap.GetHeight(new Vector3(x, 0, z));
                    position = new Vector3(x, y + 0.5f, z);
                    if (!AntiHack.TestInsideTerrain(position) && !IsInObject(position) && !IsInOcean(position))
                        break;
                }
                if (position == Vector3.zero)
                    position.y = TerrainMeta.HeightMap.GetHeight(0, 0);
                return position;
            }
            
            private Vector3 GetRandomPositionAroundPlayer(BasePlayer player)
            {
                Vector3 playerPos = player.transform.position;
                Vector3 position = Vector3.zero;
                float maxDist = waveConfig.MaxDistance;
                for (int i = 0; i < 6; i++)
                {
                    position = new Vector3(Random.Range(playerPos.x - maxDist, playerPos.x + maxDist), 0,
                                           Random.Range(playerPos.z - maxDist, playerPos.z + maxDist));
                    position.y = TerrainMeta.HeightMap.GetHeight(position);
                    if (!AntiHack.TestInsideTerrain(position) && !IsInObject(position) && !IsInOcean(position) &&
                        Vector3.Distance(playerPos, position) > waveConfig.MinDistance)
                        break;
                }
                if (position == Vector3.zero)
                    position = GetRandomPosition();
                return position;
            }
            
            private bool IsInObject(Vector3 position)
            {
                return Physics.OverlapSphere(position, 0.5f, spawnLayerMask).Length > 0;
            }
            
            private bool IsInOcean(Vector3 position)
            {
                return WaterLevel.GetWaterDepth(position, true, true) > 0.25f;
            }
            
            private void Broadcast(string key, params object[] values)
            {
                foreach (BasePlayer player in BasePlayer.activePlayerList)
                    player.ChatMessage(string.Format(_instance.GetMessage(key, player.UserIDString), values));
            }
            
            #endregion
            
            // Check water status: if a zombie's head is fully underwater (i.e.water depth at its feet exceeds ZombieHeadOffset)
            // continuously for 10 seconds, despawn it.private void CheckWaterStatus()
            {
                // Iterate backwards to avoid allocation.for (int i = zombies.Count - 1; i >= 0; i--)
                {
                    ScarecrowNPC zombie = zombies[i];
                    if (zombie == null || zombie.IsDestroyed)
                    {
                        waterTimes.Remove(zombie);
                        continue;
                    }
                    
                    if (WaterLevel.GetWaterDepth(zombie.transform.position, true, true) > ZombieHeadOffset)
                    {
                        if (waterTimes.ContainsKey(zombie))
                            waterTimes[zombie] += 1f;
                        else
                            waterTimes[zombie] = 1f;
                        
                        if (waterTimes[zombie] >= 10f)
                        {
                            zombie.AdminKill();
                            zombies.RemoveAt(i);
                            waterTimes.Remove(zombie);
                        }
                    }
                    else
                    {
                        if (waterTimes.ContainsKey(zombie))
                            waterTimes.Remove(zombie);
                    }
                }
            }
        }
        
        // New controller for persistent monument zombies.private class MonumentController
        {
            // Dictionary mapping each monument name to its list of persistent zombies.private Dictionary<string, List<ScarecrowNPC>> monumentZombies = new Dictionary<string, List<ScarecrowNPC>>();
            private Timer checkTimer;
            
            public void Initialize()
            {
                // For each configured monument, spawn the specified number of zombies.foreach (string monument in _config.Monument.Monuments)
                {
                    monumentZombies[monument] = new List<ScarecrowNPC>();
                    for (int i = 0; i < _config.Monument.Population; i++)
                    {
                        SpawnZombieAtMonument(monument);
                    }
                }
                // Check every 60 seconds to ensure persistent zombies are present.checkTimer = _instance.timer.Every(60f, () => CheckMonumentZombies());
            }
            
            private void SpawnZombieAtMonument(string monument)
            {
                Vector3 pos = GetMonumentPosition(monument);
                ScarecrowNPC zombie = GameManager.server.CreateEntity("assets/prefabs/npc/scarecrow/scarecrow.prefab", pos) as ScarecrowNPC;
                if (zombie == null)
                    return;
                zombie.Spawn();
                zombie.displayName = _config.Monument.Zombies.DisplayName;
                float health = _config.Monument.Zombies.Health;
                zombie.SetMaxHealth(health);
                zombie.SetHealth(health);
                if (_instance._kits != null && _config.Monument.Zombies.Kits.Count > 0)
                {
                    zombie.inventory.containerWear.Clear();
                    ItemManager.DoRemoves();
                    _instance._kits.Call("GiveKit", zombie, _config.Monument.Zombies.Kits.GetRandom());
                }
                monumentZombies[monument].Add(zombie);
            }
            
            // Helper to get a spawn position for a monument.private Vector3 GetMonumentPosition(string monument)
            {
                // In a real implementation, you'd use actual monument coordinates.// For this example, we return a random position.float x = Random.Range(-100, 100);
                float z = Random.Range(-100, 100);
                float y = TerrainMeta.HeightMap.GetHeight(new Vector3(x, 0, z)) + 1;
                return new Vector3(x, y, z);
            }
            
            private void CheckMonumentZombies()
            {
                // For each monument, ensure the number of zombies is maintained.foreach (var kvp in monumentZombies)
                {
                    string monument = kvp.Key;
                    List<ScarecrowNPC> zombies = kvp.Value;
                    // Remove null or destroyed zombies.for (int i = zombies.Count - 1; i >= 0; i--)
                    {
                        if (zombies[i] == null || zombies[i].IsDestroyed)
                            zombies.RemoveAt(i);
                    }
                    int missing = _config.Monument.Population - zombies.Count;
                    for (int i = 0; i < missing; i++)
                    {
                        SpawnZombieAtMonument(monument);
                    }
                }
            }
            
            public void DespawnAll()
            {
                foreach (var kvp in monumentZombies)
                {
                    foreach (var zombie in kvp.Value.ToArray())
                    {
                        if (zombie != null && !zombie.IsDestroyed)
                            zombie.AdminKill();
                    }
                    kvp.Value.Clear();
                }
            }
            
            public void Shutdown()
            {
                if (checkTimer != null)
                    checkTimer.Destroy();
                DespawnAll();
            }
        }
        
        #endregion
        
        #region -Configuration-
        
        private class Configuration
        {
            [JsonProperty("Spawn Waves")]
            public List<SpawnWave> SpawnWaves = new List<SpawnWave>();
            
            [JsonProperty("Monument Settings")]
            public MonumentSettings Monument = new MonumentSettings();
            
            [JsonProperty("Destroy Settings")]
            public DestroySettings Destroy = new DestroySettings();
            
            [JsonProperty("Behaviour Settings")]
            public BehaviourSettings Behaviour = new BehaviourSettings();
            
            [JsonProperty("Broadcast Settings")]
            public ChatSettings Broadcast = new ChatSettings();
            
            public class SpawnWave
            {
                [JsonProperty("Wave Name")]
                public string WaveName = "Default Wave";
                
                [JsonProperty("Spawn Time")]
                public float SpawnTime = 19.8f;
                
                [JsonProperty("Destroy Time")]
                public float DestroyTime = 7.3f;
                
                [JsonProperty("Spawn near players")]
                public bool SpawnNearPlayers = false;
                
                [JsonProperty("Min pop for near player spawn")]
                public int MinNearPlayers = 10;
                
                [JsonProperty("Min distance from player")]
                public float MinDistance = 30.0f;
                
                [JsonProperty("Max distance from player")]
                public float MaxDistance = 60.0f;
                
                [JsonProperty("Zombie Settings")]
                public SpawnSettings.ZombieSettings Zombies = new SpawnSettings.ZombieSettings();
                
                [JsonProperty("Chance Settings")]
                public SpawnSettings.ChanceSetings Chance = new SpawnSettings.ChanceSetings();
            }
            
            public class SpawnSettings
            {
                public class ZombieSettings
                {
                    [JsonProperty("Display Name")]
                    public string DisplayName = "Scarecrow";
                    
                    [JsonProperty("Scarecrow Population (total amount)")]
                    public int Population = 50;
                    
                    [JsonProperty("Scarecrow Health")]
                    public float Health = 200f;
                    
                    [JsonProperty("Scarecrow Kits")]
                    public List<string> Kits = new List<string>();
                }
                
                public class ChanceSetings
                {
                    [JsonProperty("Chance per cycle")]
                    public float Chance = 100f;
                    
                    [JsonProperty("Days betewen spawn")]
                    public int Days = 0;
                }
            }
            
            public class MonumentSettings
            {
                [JsonProperty("Monument Zombie Population")]
                public int Population = 3;
                
                [JsonProperty("Monument List")]
                public List<string> Monuments = new List<string>
                {
                    "airfield", "lighthouse", "powerplant", "trainyard", "militarytunnels",
                    "satellitedish", "compound", "oilrig", "submarine", "junkyard",
                    "quarry", "banditcamp", "harbor", "water treatment", "warehouse",
                    "launchsite", "radardome", "mineshaft", "factory", "boathouse",
                    "smokestack", "researchstation", "silobase", "crashsite", "container",
                    "dockyard", "garage", "warehouse2", "blockade"
                };
                
                [JsonProperty("Zombie Settings")]
                public ZombieSettings Zombies = new ZombieSettings();
                
                public class ZombieSettings
                {
                    [JsonProperty("Display Name")]
                    public string DisplayName = "Monument Zombie";
                    
                    [JsonProperty("Scarecrow Health")]
                    public float Health = 300f;
                    
                    [JsonProperty("Scarecrow Kits")]
                    public List<string> Kits = new List<string> { "monumentkit" };
                }
            }
            
            public class DestroySettings
            {
                [JsonProperty("Leave Corpse, when destroyed")]
                public bool LeaveCorpse = false;
                
                [JsonProperty("Leave Corpse, when killed by player")]
                public bool LeaveCorpseKilled = true;
                
                [JsonProperty("Spawn Loot")]
                public bool SpawnLoot = true;
                
                [JsonProperty("Half bodybag despawn time")]
                public bool HalfBodybagDespawn = true;
            }
            
            public class BehaviourSettings
            {
                [JsonProperty("Attack sleeping players")]
                public bool AttackSleepers = false;
                
                [JsonProperty("Zombies attacked by outpost sentries")]
                public bool SentriesAttackZombies = true;
                
                [JsonProperty("Throw Grenades")]
                public bool ThrowGrenades = true;
                
                [JsonProperty("Ignore Human NPCs")]
                public bool IgnoreHumanNpc = true;
                
                [JsonProperty("Ignored entities (full entity shortname)")]
                public List<string> Ignored = new List<string>();
            }
            
            public class ChatSettings
            {
                [JsonProperty("Broadcast spawn amount")]
                public bool DoBroadcast = false;
            }
        }
        
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Failed to load _config, using default values");
                LoadDefaultConfig();
            }
        }
        
        protected override void LoadDefaultConfig() => _config = new Configuration
        {
            Behaviour = new Configuration.BehaviourSettings
            {
                Ignored = new List<string>
                {
                    "scientistjunkpile.prefab",
                    "scarecrow.prefab"
                }
            },
            SpawnWaves = new List<Configuration.SpawnWave>
            {
                // Example wave 1
                new Configuration.SpawnWave
                {
                    WaveName = "Night Wave",
                    SpawnTime = 19.8f,
                    DestroyTime = 7.3f,
                    SpawnNearPlayers = true,
                    MinNearPlayers = 10,
                    MinDistance = 30.0f,
                    MaxDistance = 60.0f,
                    Zombies = new Configuration.SpawnSettings.ZombieSettings
                    {
                        DisplayName = "Scarecrow",
                        Population = 50,
                        Health = 200f,
                        Kits = new List<string> { "defaultkit" }
                    },
                    Chance = new Configuration.SpawnSettings.ChanceSetings
                    {
                        Chance = 100f,
                        Days = 0
                    }
                },
                // Example wave 2
                new Configuration.SpawnWave
                {
                    WaveName = "Dawn Wave",
                    SpawnTime = 6.0f,
                    DestroyTime = 8.0f,
                    SpawnNearPlayers = false,
                    MinNearPlayers = 0,
                    MinDistance = 40.0f,
                    MaxDistance = 80.0f,
                    Zombies = new Configuration.SpawnSettings.ZombieSettings
                    {
                        DisplayName = "Dawn Scarecrow",
                        Population = 30,
                        Health = 150f,
                        Kits = new List<string> { "dawnkit" }
                    },
                    Chance = new Configuration.SpawnSettings.ChanceSetings
                    {
                        Chance = 50f,
                        Days = 1
                    }
                },
                // Additional example wave 3
                new Configuration.SpawnWave
                {
                    WaveName = "Midnight Wave",
                    SpawnTime = 0.0f,
                    DestroyTime = 1.0f,
                    SpawnNearPlayers = true,
                    MinNearPlayers = 5,
                    MinDistance = 20.0f,
                    MaxDistance = 50.0f,
                    Zombies = new Configuration.SpawnSettings.ZombieSettings
                    {
                        DisplayName = "Midnight Scarecrow",
                        Population = 40,
                        Health = 180f,
                        Kits = new List<string> { "midnightkit" }
                    },
                    Chance = new Configuration.SpawnSettings.ChanceSetings
                    {
                        Chance = 75f,
                        Days = 0
                    }
                }
            },
            Monument = new Configuration.MonumentSettings
            {
                Population = 3,
                Monuments = new List<string>
                {
                    "airfield", "lighthouse", "powerplant", "trainyard", "militarytunnels",
                    "satellitedish", "compound", "oilrig", "submarine", "junkyard",
                    "quarry", "banditcamp", "harbor", "water treatment", "warehouse",
                    "launchsite", "radardome", "mineshaft", "factory", "boathouse",
                    "smokestack", "researchstation", "silobase", "crashsite", "container",
                    "dockyard", "garage", "warehouse2", "blockade"
                },
                Zombies = new Configuration.MonumentSettings.ZombieSettings
                {
                    DisplayName = "Monument Zombie",
                    Health = 300f,
                    Kits = new List<string> { "monumentkit" }
                }
            }
        };
        
        protected override void SaveConfig() => Config.WriteObject(_config);
        
        #endregion
        
        #region -Localisation-
        
        private string GetMessage(string key, string userId = null)
        {
            return lang.GetMessage(key, this, userId);
        }
        
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["ChatBroadcast"] = "[Night Zombies] Spawned {0} zombies",
                ["ChatBroadcastSeparate"] = "[Night Zombies] Spawned {0} murderers | Spawned {1} scarecrows"
            }, this);
        }
        
        #endregion
    }
}

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