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

FREE CobaltLaboratory : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Newtonsoft.Json;
namespace Oxide.Plugins {
    [Info("N1KTO COMPANY - Cobalt Laboratory", "RustPlugin", "1.0.0")]
    [Description("Автоматическое событие с ботами и кастомным зданием от N1KTO COMPANY")]
    public class CobaltLaboratory : RustPlugin {
#region Fields
        private Configuration config;
        private const string PermissionUse = "cobaltlaboratory.use";
        private const string PermissionAdmin = "cobaltlaboratory.admin";
        private Timer eventTimer;
        private Timer eventDurationTimer;
        private Timer radiationTimer;
        private Timer autoStartCheckTimer;
        private Vector3 eventPosition;
        private bool isEventActive;
        private List<BasePlayer> activeNPCs = new List<BasePlayer>();
        private List<BaseEntity> spawnedEntities = new List<BaseEntity>();
        private StorageContainer lootBox;
        private BaseEntity radiationEntity;
        private float eventEndTime;
        private string mapMarkerID;
#endregion
#region Configuration
        class Configuration {
            [JsonProperty("Setting up and stopping an event")]
            public EventSettings Event {
                get;
                set;
            }
            [JsonProperty("Configuring notifications")]
            public NotificationSettings Notifications {
                get;
                set;
            }
            [JsonProperty("Setting up radiation in the event area")]
            public RadiationSettings Radiation {
                get;
                set;
            }
            [JsonProperty("Event display on maps")]
            public MapSettings Map {
                get;
                set;
            }
            [JsonProperty("Bot settings")]
            public BotSettings Bots {
                get;
                set;
            }
            [JsonProperty("UI settings")]
            public UISettings UI {
                get;
                set;
            }
            [JsonProperty("Loot settings")]
            public LootSettings Loot {
                get;
                set;
            }
            [JsonProperty("Command settings")]
            public CommandSettings Commands {
                get;
                set;
            }
            public Configuration() {
                Event = new EventSettings();
                Notifications = new NotificationSettings();
                Radiation = new RadiationSettings();
                Map = new MapSettings();
                Bots = new BotSettings();
                UI = new UISettings();
                Loot = new LootSettings();
                Commands = new CommandSettings();
            }
        }
        class EventSettings {
            [JsonProperty("The minimum number of players to start an event")]
            public int MinPlayers {
                get;
                set;
            }
            [JsonProperty("Time before the start of the event (Minimum in seconds)")]
            public int MinStartTime {
                get;
                set;
            }
            [JsonProperty("Time before the start of the event (Maximum in seconds)")]
            public int MaxStartTime {
                get;
                set;
            }
            [JsonProperty("Enable auto-start at specific time")]
            public bool EnableAutoStart {
                get;
                set;
            }
            [JsonProperty("Auto-start time in seconds")]
            public int AutoStartTime {
                get;
                set;
            }
        }
        class NotificationSettings {
            [JsonProperty("Discord WebHook")]
            public string DiscordWebHook {
                get;
                set;
            }
            [JsonProperty("Enable UI Notifications?")]
            public bool EnableUINotifications {
                get;
                set;
            }
            [JsonProperty("Auto hide UI notifications?")]
            public bool AutoHideUI {
                get;
                set;
            }
            [JsonProperty("How long after the show will it hide? (sec)")]
            public float HideDelay {
                get;
                set;
            }
        }
        class RadiationSettings {
            [JsonProperty("Turn on radiation?")]
            public bool EnableRadiation {
                get;
                set;
            }
            [JsonProperty("Number of radiation particles")]
            public int RadiationParticles {
                get;
                set;
            }
        }
        class MapSettings {
            [JsonProperty("Mark the event on the G card")]
            public bool ShowOnMap {
                get;
                set;
            }
            [JsonProperty("Text for map G")]
            public string MapText {
                get;
                set;
            }
        }
        class BotSettings {
            [JsonProperty("Bot types")]
            public List<BotType> Types {
                get;
                set;
            }
            = new List<BotType>();
            [JsonProperty("Enable night vision")]
            public bool EnableNightVision {
                get;
                set;
            }
            [JsonProperty("Enable flashlights at night")]
            public bool EnableFlashlights {
                get;
                set;
            }
            [JsonProperty("Bot behavior settings")]
            public BotBehavior Behavior {
                get;
                set;
            }
            public BotSettings() {
                Types = new List<BotType> {
                    new BotType {
                        Name = "Штурмовик", Health = 150, Accuracy = 0.7f, RoamRange = 30, ChaseRange = 50, Equipment = new Equipment {
                            Weapons = new List<string> {
                                "rifle.ak", "pistol.python"
                            }
                            , Armor = new List<string> {
                                "metal.facemask", "metal.plate.torso"
                            }
                        }
                    }
                    , new BotType {
                        Name = "Снайпер", Health = 100, Accuracy = 0.9f, RoamRange = 50, ChaseRange = 100, Equipment = new Equipment {
                            Weapons = new List<string> {
                                "rifle.bolt", "pistol.revolver"
                            }
                            , Armor = new List<string> {
                                "metal.facemask", "roadsign.jacket"
                            }
                        }
                    }
                    , new BotType {
                        Name = "Медик", Health = 120, Accuracy = 0.6f, RoamRange = 20, ChaseRange = 30, Equipment = new Equipment {
                            Weapons = new List<string> {
                                "smg.mp5", "pistol.semiauto"
                            }
                            , Armor = new List<string> {
                                "coffeecan.helmet", "roadsign.jacket"
                            }
                            , Items = new List<string> {
                                "syringe.medical", "bandage"
                            }
                        }
                    }
                }
                ;
                Behavior = new BotBehavior();
            }
        }
        class BotType {
            [JsonProperty("Bot name")]
            public string Name {
                get;
                set;
            }
            [JsonProperty("Health")]
            public float Health {
                get;
                set;
            }
            [JsonProperty("Accuracy (0.0-1.0)")]
            public float Accuracy {
                get;
                set;
            }
            [JsonProperty("Roam range")]
            public float RoamRange {
                get;
                set;
            }
            [JsonProperty("Chase range")]
            public float ChaseRange {
                get;
                set;
            }
            [JsonProperty("Equipment")]
            public Equipment Equipment {
                get;
                set;
            }
            = new Equipment();
        }
        class Equipment {
            [JsonProperty("Weapons")]
            public List<string> Weapons {
                get;
                set;
            }
            = new List<string>();
            [JsonProperty("Armor")]
            public List<string> Armor {
                get;
                set;
            }
            = new List<string>();
            [JsonProperty("Items")]
            public List<string> Items {
                get;
                set;
            }
            = new List<string>();
        }
        class BotBehavior {
            [JsonProperty("Use cover")]
            public bool UseCover {
                get;
                set;
            }
            = true;
            [JsonProperty("Help wounded allies")]
            public bool HelpAllies {
                get;
                set;
            }
            = true;
            [JsonProperty("Retreat when low health")]
            public bool RetreatWhenLowHealth {
                get;
                set;
            }
            = true;
            [JsonProperty("Low health threshold")]
            public float LowHealthThreshold {
                get;
                set;
            }
            = 0.3f;
        }
        class UISettings {
            [JsonProperty("Event timer color")]
            public string TimerColor {
                get;
                set;
            }
            = "1 1 1 1";
            [JsonProperty("Event notification color")]
            public string NotificationColor {
                get;
                set;
            }
            = "0.7 0.3 0.3 1";
            [JsonProperty("Show event timer")]
            public bool ShowEventTimer {
                get;
                set;
            }
            = true;
            [JsonProperty("Show kill feed")]
            public bool ShowKillFeed {
                get;
                set;
            }
            = true;
            [JsonProperty("Show minimap")]
            public bool ShowMinimap {
                get;
                set;
            }
            = true;
        }
        class LootSettings {
            [JsonProperty("Настройки ящиков")]
            public BoxSettings BoxSettings {
                get;
                set;
            }
            = new BoxSettings();
            [JsonProperty("Категории лута")]
            public List<LootCategory> Categories {
                get;
                set;
            }
            [JsonProperty("Минимум предметов в ящике")]
            public int MinItemsPerBox {
                get;
                set;
            }
            = 6;
            [JsonProperty("Максимум предметов в ящике")]
            public int MaxItemsPerBox {
                get;
                set;
            }
            = 12;
            public LootSettings() {
                BoxSettings = new BoxSettings();
                Categories = new List<LootCategory> {
                    new LootCategory {
                        Name = "Оружие", Weight = 30, Items = new List<LootItem> {
                            new LootItem {
                                ShortName = "rifle.ak", MinAmount = 1, MaxAmount = 1, Chance = 20, Blueprint = true
                            }
                            , new LootItem {
                                ShortName = "rifle.bolt", MinAmount = 1, MaxAmount = 1, Chance = 15, Blueprint = true
                            }
                            , new LootItem {
                                ShortName = "rifle.l96", MinAmount = 1, MaxAmount = 1, Chance = 10, Blueprint = true
                            }
                            , new LootItem {
                                ShortName = "rifle.lr300", MinAmount = 1, MaxAmount = 1, Chance = 20
                            }
                            , new LootItem {
                                ShortName = "smg.mp5", MinAmount = 1, MaxAmount = 1, Chance = 25
                            }
                            , new LootItem {
                                ShortName = "lmg.m249", MinAmount = 1, MaxAmount = 1, Chance = 5
                            }
                            , new LootItem {
                                ShortName = "rocket.launcher", MinAmount = 1, MaxAmount = 1, Chance = 8, Blueprint = true
                            }
                        }
                    }
                    , new LootCategory {
                        Name = "Взрывчатка", Weight = 20, Items = new List<LootItem> {
                            new LootItem {
                                ShortName = "explosive.timed", MinAmount = 1, MaxAmount = 10, Chance = 15
                            }
                            , new LootItem {
                                ShortName = "ammo.rocket.basic", MinAmount = 5, MaxAmount = 15, Chance = 20
                            }
                            , new LootItem {
                                ShortName = "ammo.rocket.hv", MinAmount = 5, MaxAmount = 15, Chance = 15
                            }
                            , new LootItem {
                                ShortName = "ammo.rocket.fire", MinAmount = 5, MaxAmount = 15, Chance = 10
                            }
                            , new LootItem {
                                ShortName = "rocket.launcher", MinAmount = 1, MaxAmount = 1, Chance = 8, Blueprint = true
                            }
                        }
                    }
                    , new LootCategory {
                        Name = "Боеприпасы", Weight = 50, Items = new List<LootItem> {
                            new LootItem {
                                ShortName = "ammo.rifle", MinAmount = 120, MaxAmount = 240, Chance = 50
                            }
                            , new LootItem {
                                ShortName = "ammo.rifle.hv", MinAmount = 60, MaxAmount = 120, Chance = 30
                            }
                            , new LootItem {
                                ShortName = "ammo.rifle.explosive", MinAmount = 20, MaxAmount = 40, Chance = 15
                            }
                            , new LootItem {
                                ShortName = "ammo.rocket.basic", MinAmount = 2, MaxAmount = 4, Chance = 10
                            }
                            , new LootItem {
                                ShortName = "ammo.rocket.hv", MinAmount = 2, MaxAmount = 4, Chance = 8
                            }
                        }
                    }
                    , new LootCategory {
                        Name = "Компоненты", Weight = 40, Items = new List<LootItem> {
                            new LootItem {
                                ShortName = "explosives", MinAmount = 20, MaxAmount = 50, Chance = 30
                            }
                            , new LootItem {
                                ShortName = "targeting.computer", MinAmount = 1, MaxAmount = 2, Chance = 20
                            }
                            , new LootItem {
                                ShortName = "rifle.body", MinAmount = 1, MaxAmount = 3, Chance = 40
                            }
                            , new LootItem {
                                ShortName = "tech.trash", MinAmount = 5, MaxAmount = 10, Chance = 50
                            }
                        }
                    }
                    , new LootCategory {
                        Name = "Ресурсы", Weight = 70, Items = new List<LootItem> {
                            new LootItem {
                                ShortName = "sulfur", MinAmount = 2000, MaxAmount = 4000, Chance = 60
                            }
                            , new LootItem {
                                ShortName = "metal.refined", MinAmount = 200, MaxAmount = 500, Chance = 40
                            }
                            , new LootItem {
                                ShortName = "gunpowder", MinAmount = 1000, MaxAmount = 2000, Chance = 50
                            }
                            , new LootItem {
                                ShortName = "metal.fragments", MinAmount = 2000, MaxAmount = 4000, Chance = 60
                            }
                            , new LootItem {
                                ShortName = "charcoal", MinAmount = 2000, MaxAmount = 4000, Chance = 70
                            }
                        }
                    }
                }
                ;
            }
        }
        class BoxSettings {
            [JsonProperty("Тип ящика (large.wooden/elite/military/...)")]
            public string BoxType {
                get;
                set;
            }
            = "box.wooden.large";
            [JsonProperty("Высота спавна ящика над землей")]
            public float BoxHeight {
                get;
                set;
            }
            = 1.0f;
            [JsonProperty("Можно ли подбирать ящик")]
            public bool IsPickupable {
                get;
                set;
            }
            = false;
            [JsonProperty("Время жизни ящика (в минутах, 0 = бесконечно)")]
            public float BoxLifetime {
                get;
                set;
            }
            = 0f;
            [JsonProperty("Защита ящика (0-1000)")]
            public float BoxHealth {
                get;
                set;
            }
            = 500f;
            [JsonProperty("Создавать несколько ящиков")]
            public bool EnableMultipleBoxes {
                get;
                set;
            }
            = false;
            [JsonProperty("Минимум ящиков")]
            public int MinBoxes {
                get;
                set;
            }
            = 1;
            [JsonProperty("Максимум ящиков")]
            public int MaxBoxes {
                get;
                set;
            }
            = 3;
            [JsonProperty("Радиус спавна ящиков")]
            public float BoxSpawnRadius {
                get;
                set;
            }
            = 10f;
        }
        class LootCategory {
            [JsonProperty("Category name")]
            public string Name {
                get;
                set;
            }
            [JsonProperty("Category weight (higher = more common)")]
            public int Weight {
                get;
                set;
            }
            [JsonProperty("Items in category")]
            public List<LootItem> Items {
                get;
                set;
            }
            = new List<LootItem>();
        }
        class LootItem {
            [JsonProperty("Item shortname")]
            public string ShortName {
                get;
                set;
            }
            [JsonProperty("Minimum amount")]
            public int MinAmount {
                get;
                set;
            }
            [JsonProperty("Maximum amount")]
            public int MaxAmount {
                get;
                set;
            }
            [JsonProperty("Drop chance (0-100)")]
            public float Chance {
                get;
                set;
            }
            [JsonProperty("Is blueprint")]
            public bool Blueprint {
                get;
                set;
            }
            [JsonProperty("Custom skin ID")]
            public ulong SkinID {
                get;
                set;
            }
        }
        class CommandSettings {
            [JsonProperty("Основная команда")]
            public string MainCommand {
                get;
                set;
            }
            = "cobaltlab";
            [JsonProperty("Команда старта")]
            public string StartCommand {
                get;
                set;
            }
            = "start";
            [JsonProperty("Команда остановки")]
            public string StopCommand {
                get;
                set;
            }
            = "stop";
            [JsonProperty("Команда статуса")]
            public string StatusCommand {
                get;
                set;
            }
            = "status";
            [JsonProperty("Команда настройки времени")]
            public string TimeCommand {
                get;
                set;
            }
            = "time";
            [JsonProperty("Команда настройки вебхука")]
            public string WebhookCommand {
                get;
                set;
            }
            = "webhook";
            [JsonProperty("Команда автостарта")]
            public string AutoStartCommand {
                get;
                set;
            }
            = "autostart";
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) LoadDefaultConfig();
            }
            catch {
                LoadDefaultConfig();
            }
            SaveConfig();
        }
        protected override void LoadDefaultConfig() {
            config = new Configuration {
                Event = new EventSettings {
                    MinPlayers = 0, MinStartTime = 3000, MaxStartTime = 7200
                }
                , Notifications = new NotificationSettings {
                    DiscordWebHook = "", EnableUINotifications = true, AutoHideUI = true, HideDelay = 15.0f
                }
                , Radiation = new RadiationSettings {
                    EnableRadiation = true, RadiationParticles = 20
                }
                , Map = new MapSettings {
                    ShowOnMap = true, MapText = "Cobalt lab"
                }
                , Bots = new BotSettings {
                    Types = new List<BotType> {
                        new BotType {
                            Name = "Штурмовик", Health = 150, Accuracy = 0.7f, RoamRange = 30, ChaseRange = 50, Equipment = new Equipment {
                                Weapons = new List<string> {
                                    "rifle.ak", "pistol.python"
                                }
                                , Armor = new List<string> {
                                    "metal.facemask", "metal.plate.torso"
                                }
                            }
                        }
                        , new BotType {
                            Name = "Снайпер", Health = 100, Accuracy = 0.9f, RoamRange = 50, ChaseRange = 100, Equipment = new Equipment {
                                Weapons = new List<string> {
                                    "rifle.bolt", "pistol.revolver"
                                }
                                , Armor = new List<string> {
                                    "metal.facemask", "roadsign.jacket"
                                }
                            }
                        }
                        , new BotType {
                            Name = "Медик", Health = 120, Accuracy = 0.6f, RoamRange = 20, ChaseRange = 30, Equipment = new Equipment {
                                Weapons = new List<string> {
                                    "smg.mp5", "pistol.semiauto"
                                }
                                , Armor = new List<string> {
                                    "coffeecan.helmet", "roadsign.jacket"
                                }
                                , Items = new List<string> {
                                    "syringe.medical", "bandage"
                                }
                            }
                        }
                    }
                    , Behavior = new BotBehavior {
                        UseCover = true, HelpAllies = true, RetreatWhenLowHealth = true, LowHealthThreshold = 0.3f
                    }
                }
                , UI = new UISettings {
                    TimerColor = "1 1 1 1", NotificationColor = "0.7 0.3 0.3 1", ShowEventTimer = true, ShowKillFeed = true, ShowMinimap = true
                }
                , Loot = new LootSettings {
                    BoxSettings = new BoxSettings(), Categories = new List<LootCategory> {
                        new LootCategory {
                            Name = "Оружие", Weight = 30, Items = new List<LootItem> {
                                new LootItem {
                                    ShortName = "rifle.ak", MinAmount = 1, MaxAmount = 1, Chance = 20, Blueprint = true
                                }
                                , new LootItem {
                                    ShortName = "rifle.bolt", MinAmount = 1, MaxAmount = 1, Chance = 15, Blueprint = true
                                }
                                , new LootItem {
                                    ShortName = "rifle.l96", MinAmount = 1, MaxAmount = 1, Chance = 10, Blueprint = true
                                }
                                , new LootItem {
                                    ShortName = "rifle.lr300", MinAmount = 1, MaxAmount = 1, Chance = 20
                                }
                                , new LootItem {
                                    ShortName = "smg.mp5", MinAmount = 1, MaxAmount = 1, Chance = 25
                                }
                                , new LootItem {
                                    ShortName = "lmg.m249", MinAmount = 1, MaxAmount = 1, Chance = 5
                                }
                                , new LootItem {
                                    ShortName = "rocket.launcher", MinAmount = 1, MaxAmount = 1, Chance = 8, Blueprint = true
                                }
                            }
                        }
                        , new LootCategory {
                            Name = "Взрывчатка", Weight = 20, Items = new List<LootItem> {
                                new LootItem {
                                    ShortName = "explosive.timed", MinAmount = 1, MaxAmount = 10, Chance = 15
                                }
                                , new LootItem {
                                    ShortName = "ammo.rocket.basic", MinAmount = 5, MaxAmount = 15, Chance = 20
                                }
                                , new LootItem {
                                    ShortName = "ammo.rocket.hv", MinAmount = 5, MaxAmount = 15, Chance = 15
                                }
                                , new LootItem {
                                    ShortName = "ammo.rocket.fire", MinAmount = 5, MaxAmount = 15, Chance = 10
                                }
                                , new LootItem {
                                    ShortName = "rocket.launcher", MinAmount = 1, MaxAmount = 1, Chance = 8, Blueprint = true
                                }
                            }
                        }
                        , new LootCategory {
                            Name = "Боеприпасы", Weight = 50, Items = new List<LootItem> {
                                new LootItem {
                                    ShortName = "ammo.rifle", MinAmount = 120, MaxAmount = 240, Chance = 50
                                }
                                , new LootItem {
                                    ShortName = "ammo.rifle.hv", MinAmount = 60, MaxAmount = 120, Chance = 30
                                }
                                , new LootItem {
                                    ShortName = "ammo.rifle.explosive", MinAmount = 20, MaxAmount = 40, Chance = 15
                                }
                                , new LootItem {
                                    ShortName = "ammo.rocket.basic", MinAmount = 2, MaxAmount = 4, Chance = 10
                                }
                                , new LootItem {
                                    ShortName = "ammo.rocket.hv", MinAmount = 2, MaxAmount = 4, Chance = 8
                                }
                            }
                        }
                        , new LootCategory {
                            Name = "Компоненты", Weight = 40, Items = new List<LootItem> {
                                new LootItem {
                                    ShortName = "explosives", MinAmount = 20, MaxAmount = 50, Chance = 30
                                }
                                , new LootItem {
                                    ShortName = "targeting.computer", MinAmount = 1, MaxAmount = 2, Chance = 20
                                }
                                , new LootItem {
                                    ShortName = "rifle.body", MinAmount = 1, MaxAmount = 3, Chance = 40
                                }
                                , new LootItem {
                                    ShortName = "tech.trash", MinAmount = 5, MaxAmount = 10, Chance = 50
                                }
                            }
                        }
                        , new LootCategory {
                            Name = "Ресурсы", Weight = 70, Items = new List<LootItem> {
                                new LootItem {
                                    ShortName = "sulfur", MinAmount = 2000, MaxAmount = 4000, Chance = 60
                                }
                                , new LootItem {
                                    ShortName = "metal.refined", MinAmount = 200, MaxAmount = 500, Chance = 40
                                }
                                , new LootItem {
                                    ShortName = "gunpowder", MinAmount = 1000, MaxAmount = 2000, Chance = 50
                                }
                                , new LootItem {
                                    ShortName = "metal.fragments", MinAmount = 2000, MaxAmount = 4000, Chance = 60
                                }
                                , new LootItem {
                                    ShortName = "charcoal", MinAmount = 2000, MaxAmount = 4000, Chance = 70
                                }
                            }
                        }
                    }
                }
                , Commands = new CommandSettings {
                    MainCommand = "cobaltlab", StartCommand = "start", StopCommand = "stop", StatusCommand = "status", TimeCommand = "time", WebhookCommand = "webhook", AutoStartCommand = "autostart"
                }
            }
            ;
        }
        protected override void SaveConfig() => Config.WriteObject(config);
#endregion
#region Oxide Hooks
        private void Init() {
            permission.RegisterPermission(PermissionUse, this);
            permission.RegisterPermission(PermissionAdmin, this);
            cmd.AddChatCommand(config.Commands.MainCommand, this, nameof(CmdCobaltLab));
            // Запускаем таймер для проверки автозапуска
            if (config.Event.EnableAutoStart) {
                autoStartCheckTimer = timer.Every(60f, CheckAutoStart);
            }
        }
        private void OnServerInitialized(bool initial) {
            if (initial) ScheduleNextEvent();
        }
        void Unload() {
            // Принудительно останавливаем событие перед выгрузкой
            isEventActive = false;
            // Очищаем все таймеры
            eventTimer?.Destroy();
            eventDurationTimer?.Destroy();
            radiationTimer?.Destroy();
            autoStartCheckTimer?.Destroy();
            // Очищаем все сущности
            foreach (var npc in activeNPCs.ToList()) {
                if (npc != null && !npc.IsDestroyed) npc.Kill();
            }
            activeNPCs.Clear();
            foreach (var entity in spawnedEntities.ToList()) {
                if (entity != null && !entity.IsDestroyed) entity.Kill();
            }
            spawnedEntities.Clear();
            // Очищаем UI у всех игроков
            foreach (var player in BasePlayer.activePlayerList) {
                if (player != null && player.IsConnected) CuiHelper.DestroyUi(player, "CobaltLabNotification");
            }
            // Очищаем маркер на карте
            RemoveMapMarker();
        }
        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
            var npc = entity as BasePlayer;
            if (npc == null || !activeNPCs.Contains(npc)) return;
            activeNPCs.Remove(npc);
            if (info?.InitiatorPlayer != null) {
                var killer = info.InitiatorPlayer;
                BroadcastKill(killer, npc.displayName);
            }
            // Если все боты мертвы, завершаем событие
            if (activeNPCs.Count == 0) {
                timer.Once(30f, () => StopEvent());
            }
        }
#endregion
#region Commands
        [Command("cobaltlab")]
        private void CmdCobaltLab(BasePlayer player, string command, string[] args) {
            if (!permission.UserHasPermission(player.UserIDString, PermissionAdmin)) {
                SendMessage(player, "У вас нет прав на использование этой команды");
                return;
            }
            if (args.Length == 0) {
                SendMessage(player, $"Используйте: /{config.Commands.MainCommand} {config.Commands.StartCommand}|{config.Commands.StopCommand}|{config.Commands.StatusCommand}|{config.Commands.TimeCommand}|{config.Commands.WebhookCommand}|{config.Commands.AutoStartCommand}");
                SendMessage(player, $"{config.Commands.StartCommand} [время_в_секундах] - Запустить событие");
                SendMessage(player, $"{config.Commands.StopCommand} - Остановить текущее событие");
                SendMessage(player, $"{config.Commands.StatusCommand} - Показать статус события");
                SendMessage(player, $"{config.Commands.TimeCommand} <min> <max> - Установить интервал появления (в секундах)");
                SendMessage(player, $"{config.Commands.WebhookCommand} <url> - Установить Discord webhook URL");
                SendMessage(player, $"{config.Commands.AutoStartCommand} <время_в_секундах> - Установить время автозапуска");
                SendMessage(player, $"{config.Commands.AutoStartCommand} disable - Отключить автозапуск");
                return;
            }
            switch (args[0].ToLower()) {
                case var cmd when cmd == config.Commands.StartCommand.ToLower() : if (args.Length > 1 && int.TryParse(args[1], out int delay)) {
                    if (eventTimer != null) eventTimer.Destroy();
                    eventTimer = timer.Once(delay, StartEvent);
                    SendMessage(player, $"Событие запустится через {delay} секунд");
                }
                else {
                    StartEvent();
                }
                break;
                case var cmd when cmd == config.Commands.StopCommand.ToLower() : StopEvent();
                SendMessage(player, "Событие остановлено");
                break;
                case var cmd when cmd == config.Commands.StatusCommand.ToLower() : ShowEventStatus(player);
                if (eventTimer != null) {
                    var nextEvent = config.Event.MinStartTime;
                    SendMessage(player, $"Следующее событие через: {nextEvent} секунд");
                }
                break;
                case var cmd when cmd == config.Commands.TimeCommand.ToLower() : if (args.Length >= 3 && int.TryParse(args[1], out int min) && int.TryParse(args[2], out int max)) {
                    if (min > max) {
                        SendMessage(player, "Минимальное время не может быть больше максимального");
                        return;
                    }
                    config.Event.MinStartTime = min;
                    config.Event.MaxStartTime = max;
                    SaveConfig();
                    SendMessage(player, $"Интервал появления установлен: {min}-{max} секунд");
                    ScheduleNextEvent();
                }
                else {
                    SendMessage(player, $"Используйте: /{config.Commands.MainCommand} {config.Commands.TimeCommand} <min> <max>");
                }
                break;
                case var cmd when cmd == config.Commands.WebhookCommand.ToLower() : if (args.Length >= 2) {
                    string url = args[1];
                    config.Notifications.DiscordWebHook = url;
                    SaveConfig();
                    SendDiscordMessage(":white_check_mark: **Webhook успешно настроен!**");
                    SendMessage(player, "Discord webhook URL обновлен и протестирован");
                }
                else {
                    SendMessage(player, $"Используйте: /{config.Commands.MainCommand} {config.Commands.WebhookCommand} <url>");
                }
                break;
                case var cmd when cmd == config.Commands.AutoStartCommand.ToLower() : if (args.Length >= 2) {
                    if (args[1].ToLower() == "disable") {
                        config.Event.EnableAutoStart = false;
                        config.Event.AutoStartTime = 0;
                        SaveConfig();
                        SendMessage(player, "Автозапуск отключен");
                    }
                    else if (int.TryParse(args[1], out int autoStartTime)) {
                        config.Event.EnableAutoStart = true;
                        config.Event.AutoStartTime = autoStartTime;
                        SaveConfig();
                        SendMessage(player, $"Время автозапуска установлено на {autoStartTime} секунд");
                    }
                    else {
                        SendMessage(player, $"Используйте: /{config.Commands.MainCommand} {config.Commands.AutoStartCommand} <время_в_секундах> или disable");
                    }
                }
                else {
                    SendMessage(player, $"Используйте: /{config.Commands.MainCommand} {config.Commands.AutoStartCommand} <время_в_секундах> или disable");
                }
                break;
                default : SendMessage(player, $"Неизвестная команда.Используйте: /{config.Commands.MainCommand} {config.Commands.StartCommand}|{config.Commands.StopCommand}|{config.Commands.StatusCommand}|{config.Commands.TimeCommand}|{config.Commands.WebhookCommand}|{config.Commands.AutoStartCommand}");
                break;
            }
        }
#endregion
#region Core Methods
        private void ScheduleNextEvent() {
            if (eventTimer != null) eventTimer.Destroy();
            float delay = UnityEngine.Random.Range(config.Event.MinStartTime, config.Event.MaxStartTime);
            eventTimer = timer.Once(delay, StartEvent);
        }
        private void StartEvent() {
            if (isEventActive) return;
            if (BasePlayer.activePlayerList.Count < config.Event.MinPlayers) return;
            isEventActive = true;
            eventEndTime = Time.time + 900f;
            // 15 минут на событие
            FindEventPosition();
            SpawnBuilding();
            SpawnNPCs();
            CreateLootBox();
            if (config.Radiation.EnableRadiation) CreateRadiation();
            if (config.Map.ShowOnMap) CreateMapMarker();
            // Запускаем таймер события
            eventDurationTimer = timer.Once(900f, () => StopEvent());
            BroadcastEventStart();
        }
        private void StopEvent() {
            if (!isEventActive) return;
            // Отправляем сообщение в Discord
            var message = ":stop_sign: **Событие Cobalt Laboratory завершено!**";
            if (activeNPCs.Count == 0) message += "\nВсе боты были уничтожены!";
            SendDiscordMessage(message);
            CleanupEvent();
            ScheduleNextEvent();
        }
        private void CleanupEvent() {
            isEventActive = false;
            // Очищаем таймеры безопасно
            if (radiationTimer != null && !radiationTimer.Destroyed) {
                radiationTimer.Destroy();
                radiationTimer = null;
            }
            if (eventDurationTimer != null && !eventDurationTimer.Destroyed) {
                eventDurationTimer.Destroy();
                eventDurationTimer = null;
            }
            if (eventTimer != null && !eventTimer.Destroyed) {
                eventTimer.Destroy();
                eventTimer = null;
            }
            // Очищаем сущности с проверками
            if (activeNPCs != null) {
                foreach (var npc in activeNPCs.ToList()) {
                    try {
                        if (npc != null && !npc.IsDestroyed) {
                            npc.Kill();
                            PrintWarning($"Удален бот: {npc.displayName}");
                        }
                    }
                    catch (Exception ex) {
                        PrintError($"Ошибка при удалении бота: {ex.Message}");
                    }
                }
                activeNPCs.Clear();
            }
            if (spawnedEntities != null) {
                foreach (var entity in spawnedEntities.ToList()) {
                    try {
                        if (entity != null && !entity.IsDestroyed) {
                            entity.Kill();
                            PrintWarning($"Удалена сущность: {entity.ShortPrefabName}");
                        }
                    }
                    catch (Exception ex) {
                        PrintError($"Ошибка при удалении сущности: {ex.Message}");
                    }
                }
                spawnedEntities.Clear();
            }
            // Очищаем UI у всех игроков безопасно
            foreach (var player in BasePlayer.activePlayerList.ToList()) {
                try {
                    if (player != null && player.IsConnected) {
                        CuiHelper.DestroyUi(player, "CobaltLabNotification");
                        CuiHelper.DestroyUi(player, "CobaltLabMinimap");
                        CuiHelper.DestroyUi(player, "CobaltLabCompass");
                    }
                }
                catch (Exception ex) {
                    PrintError($"Ошибка при очистке UI у игрока {player?.displayName}: {ex.Message}");
                }
            }
            // Очищаем маркер на карте
            RemoveMapMarker();
            // Сбрасываем переменные
            eventPosition = Vector3.zero;
            lootBox = null;
            radiationEntity = null;
            eventEndTime = 0f;
            PrintWarning("Событие успешно очищено");
        }
        private void FindEventPosition() {
            var attempts = 0;
            const int maxAttempts = 100;
            const float minDistanceFromMonument = 50f;
            const float maxDistanceFromMonument = 150f;
            while (attempts < maxAttempts) {
                // Получаем случайную позицию на карте (исключая края)
                var randomPos = TerrainMeta.Position + new Vector3(UnityEngine.Random.Range(TerrainMeta.Size.x * 0.2f, TerrainMeta.Size.x * 0.8f), 0f, UnityEngine.Random.Range(TerrainMeta.Size.z * 0.2f, TerrainMeta.Size.z * 0.8f) );
                // Получаем высоту в этой точке
                var height = TerrainMeta.HeightMap.GetHeight(randomPos);
                randomPos.y = height;
                // Проверяем, что позиция не в воде
                if (WaterLevel.GetWaterDepth(randomPos, true, true, null) > 0.1f) {
                    attempts++;
                    continue;
                }
                // Проверяем уклон поверхности
                if (TerrainMeta.HeightMap.GetSlope(randomPos) > 40f) {
                    attempts++;
                    continue;
                }
                // Проверяем, что рядом нет построек
                var entities = Physics.OverlapSphere(randomPos, 20f, LayerMask.GetMask("Construction", "Deployed"));
                if (entities.Length > 0) {
                    attempts++;
                    continue;
                }
                // Проверяем расстояние до монументов
                bool validPosition = true;
                foreach (var monument in TerrainMeta.Path.Monuments) {
                    float distance = Vector3.Distance(randomPos, monument.transform.position);
                    if (distance < minDistanceFromMonument || distance > maxDistanceFromMonument) {
                        validPosition = false;
                        break;
                    }
                }
                if (!validPosition) {
                    attempts++;
                    continue;
                }
                // Проверяем, что на этом месте можно строить
                var ray = new Ray(randomPos + new Vector3(0f, 5f, 0f), Vector3.down);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit, 10f, LayerMask.GetMask("Terrain", "World"))) {
                    if (hit.GetEntity() == null) {
                        eventPosition = hit.point;
                        PrintWarning($"Найдена подходящая позиция: {eventPosition}");
                        return;
                    }
                }
                attempts++;
            }
            // Если не нашли позицию, используем центр карты
            eventPosition = TerrainMeta.Position + TerrainMeta.Size / 2f;
            eventPosition.y = TerrainMeta.HeightMap.GetHeight(eventPosition);
            PrintWarning($"Используем центр карты как позицию: {eventPosition}");
        }
        private void SpawnBuilding() {
            var building = GameManager.server.CreateEntity("assets/prefabs/building core/foundation/foundation.prefab", eventPosition);
            if (building == null) return;
            building.Spawn();
            spawnedEntities.Add(building);
        }
        private void SpawnNPCs() {
            if (config?.Bots?.Types == null) {
                PrintError("Ошибка: Конфигурация ботов отсутствует");
                return;
            }
            foreach (var botType in config.Bots.Types) {
                try {
                    if (string.IsNullOrEmpty(botType?.Name)) {
                        PrintError("Оши
// ... [Code preview truncated due to length. Full source in attached file] ...

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