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

FREE RaidBlock : 1.0.7 1.0.7

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

namespace Oxide.Plugins
{
    [Info("RaidBlock", "RustGPT", "1.0.7")]
    [Description(
        "Adds a raid block system with a UI component to show the block duration, applying to all players in the raid zone."
    )]
    public class RaidBlock : RustPlugin
    {
        [PluginReference]
        private readonly Plugin? CombatBlock;

        private readonly Dictionary<ulong, Dictionary<Vector3, Timer>> raidTimers = new();
        private readonly Dictionary<ulong, HashSet<Vector3>> playerZones = new();
        private readonly List<RaidZone> activeRaidZones = new();
        private readonly List<SphereEntity> activeDomes = new();
        private readonly Dictionary<ulong, RaidBlockUIManager> uiManagers = new();
        private readonly Dictionary<ulong, Dictionary<Vector3, float>> savedBlockTimes = new();
        private readonly Dictionary<ulong, Dictionary<Vector3, float>> remainingTimes = new();

        private sealed class PluginConfig
        {
            public float BlockDuration { get; set; }
            public bool BlockOnReceiveRaidDamage { get; set; }
            public bool RemoveBlockOnDeath { get; set; }
            public required List<string> BlockedCommands { get; set; }
            public float RaidZoneRadius { get; set; }
            public bool IsSphereEnabled { get; set; }
            public int SphereType { get; set; }
            public int DomeTransparencyLevel { get; set; }
            public float VisualMultiplier { get; set; }
            public bool DebugMode { get; set; }
        }

        private PluginConfig config = new() { BlockedCommands = new List<string>() };

        private sealed class RaidZone
        {
            public Vector3 Position { get; set; }
            public float ExpirationTime { get; set; }
        }

        private sealed class RaidBlockUIManager
        {
            private const string UIPanel = "RaidBlock.UI";
            private const string UILabel = "RaidBlock.UI.Label";
            private const string UIProgress = "RaidBlock.UI.Progress";

            private readonly RaidBlock plugin;
            private readonly BasePlayer player;
            private readonly float maxDuration;

            public RaidBlockUIManager(RaidBlock plugin, BasePlayer player, float maxDuration)
            {
                this.plugin = plugin;
                this.player = player;
                this.maxDuration = maxDuration;
            }

            private (string min, string max) GetUIPosition()
            {
                try
                {
                    bool hasCombatBlock = false;
                    if (plugin?.CombatBlock != null)
                    {
                        try
                        {
                            // Проверяем наличие UI и активного блока
                            object? hasUI = plugin.CombatBlock.Call(
                                "HasCombatBlockUI",
                                player.userID
                            );
                            object? hasBlock = plugin.CombatBlock.Call(
                                "HasCombatBlock",
                                player.userID
                            );
                            if (hasUI is bool hasUIValue && hasBlock is bool hasBlockValue)
                            {
                                hasCombatBlock = hasUIValue && hasBlockValue;
                            }
                        }
                        catch (Exception)
                        {
                            // Игнорируем ошибки при вызове CombatBlock, так как плагин может быть недоступен
                            plugin?.Puts("[RaidBlock] Error checking CombatBlock status");
                        }
                    }

                    // Если есть активный CombatBlock UI, размещаем наш UI ниже
                    if (hasCombatBlock)
                    {
                        return ("0.3447913 0.0735", "0.640625 0.1035");
                    }

                    // Стандартная позиция
                    return ("0.3447913 0.1135", "0.640625 0.1435");
                }
                catch (Exception)
                {
                    return ("0.3447913 0.1135", "0.640625 0.1435");
                }
            }

            public void Create(float duration)
            {
                try
                {
                    if (player?.IsConnected != true)
                    {
                        plugin?.Puts("[RaidBlock] Player is not connected");
                        return;
                    }

                    Destroy();

                    CuiElementContainer container = new();
                    if (container == null || plugin == null)
                    {
                        plugin?.Puts("[RaidBlock] Container or plugin is null");
                        return;
                    }

                    (string anchorMin, string anchorMax) = GetUIPosition();

                    // Background panel
                    _ = container.Add(
                        new CuiPanel
                        {
                            Image = { Color = "0.97 0.92 0.88 0.16" },
                            RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax },
                            CursorEnabled = false,
                        },
                        "Hud",
                        UIPanel
                    );

                    AddLabel(container, duration);
                    AddProgressBar(container, duration);

                    _ = CuiHelper.AddUi(player, container);
                }
                catch (Exception ex)
                {
                    plugin?.Puts($"[RaidBlock] Error creating UI: {ex.Message}");
                }
            }

            public void Update(float duration)
            {
                if (player?.IsConnected != true)
                {
                    return;
                }

                try
                {
                    CuiElementContainer container = new();
                    if (container == null || plugin == null)
                    {
                        plugin?.Puts("[RaidBlock] Container or plugin is null");
                        return;
                    }

                    (string anchorMin, string anchorMax) = GetUIPosition();

                    // Обновляем позицию панели
                    _ = CuiHelper.DestroyUi(player, UIPanel);
                    _ = container.Add(
                        new CuiPanel
                        {
                            Image = { Color = "0.97 0.92 0.88 0.16" },
                            RectTransform = { AnchorMin = anchorMin, AnchorMax = anchorMax },
                            CursorEnabled = false,
                        },
                        "Hud",
                        UIPanel
                    );

                    AddLabel(container, duration);
                    AddProgressBar(container, duration);

                    _ = CuiHelper.DestroyUi(player, UIProgress);
                    _ = CuiHelper.DestroyUi(player, UILabel);
                    _ = CuiHelper.AddUi(player, container);
                }
                catch (Exception ex)
                {
                    plugin?.Puts($"[RaidBlock] Error updating UI: {ex.Message}");
                }
            }

            public void Destroy()
            {
                if (player?.IsConnected != true)
                {
                    return;
                }

                _ = CuiHelper.DestroyUi(player, UIProgress);
                _ = CuiHelper.DestroyUi(player, UILabel);
                _ = CuiHelper.DestroyUi(player, UIPanel);
            }

            private void AddLabel(CuiElementContainer container, float duration)
            {
                if (container == null || plugin == null)
                {
                    return;
                }

                try
                {
                    string message = plugin.GetMessage("RaidBlock.Active", player, (int)duration);
                    container.Add(
                        new CuiElement
                        {
                            Name = UILabel,
                            Parent = UIPanel,
                            Components =
                            {
                                new CuiTextComponent
                                {
                                    Text = message,
                                    FontSize = 15,
                                    Align = TextAnchor.MiddleCenter,
                                    Color = "1 1 1 0.5",
                                },
                                new CuiRectTransformComponent
                                {
                                    AnchorMin = "0 0",
                                    AnchorMax = "1 1",
                                },
                            },
                        }
                    );
                }
                catch (ArgumentException ex)
                {
                    plugin.Puts($"[RaidBlock] Invalid label parameters: {ex.Message}");
                }
                catch (InvalidOperationException ex)
                {
                    plugin.Puts($"[RaidBlock] Label operation error: {ex.Message}");
                }
            }

            private void AddProgressBar(CuiElementContainer container, float duration)
            {
                float progress = Mathf.Clamp01(duration / maxDuration);
                container.Add(
                    new CuiElement
                    {
                        Name = UIProgress,
                        Parent = UIPanel,
                        Components =
                        {
                            new CuiImageComponent { Color = "0.60 0.80 0.20 0.5" },
                            new CuiRectTransformComponent
                            {
                                AnchorMin = "0 0",
                                AnchorMax = $"{progress} 0.1",
                            },
                        },
                    }
                );
            }
        }

        private RaidBlockUIManager GetOrCreateUIManager(BasePlayer player)
        {
            if (!uiManagers.TryGetValue(player.userID, out RaidBlockUIManager? ui))
            {
                ui = new RaidBlockUIManager(this, player, config.BlockDuration);
                uiManagers[player.userID] = ui;
            }
            return ui;
        }

        private void UpdateRaidBlockUI(BasePlayer player, float duration)
        {
            try
            {
                if (player?.IsConnected != true)
                {
                    return;
                }

                if (
                    !playerZones.TryGetValue(player.userID, out HashSet<Vector3>? zones)
                    || zones == null
                    || zones.Count == 0
                )
                {
                    DestroyRaidBlockUI(player);
                    return;
                }

                RaidBlockUIManager ui = GetOrCreateUIManager(player);
                ui.Update(duration);
            }
            catch (Exception ex)
            {
                Puts($"[RaidBlock] Error updating UI: {ex.Message}");
            }
        }

        private void DestroyRaidBlockUI(BasePlayer player)
        {
            if (player?.IsConnected != true)
            {
                return;
            }

            if (uiManagers.TryGetValue(player.userID, out RaidBlockUIManager? ui))
            {
                ui.Destroy();
                _ = uiManagers.Remove(player.userID);
            }
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null)
            {
                return;
            }

            RemoveAllRaidBlocks(player);
            _ = uiManagers.Remove(player.userID);
        }

        protected override void LoadDefaultConfig()
        {
            config = new PluginConfig
            {
                BlockDuration = 300.0f,
                BlockOnReceiveRaidDamage = true,
                RemoveBlockOnDeath = true,
                BlockedCommands = new List<string> { "/tpr", "/tpa", "/home" },
                RaidZoneRadius = 50.0f,
                IsSphereEnabled = true,
                SphereType = 0,
                DomeTransparencyLevel = 7,
                VisualMultiplier = 1.0f,
                DebugMode = false,
            };
            SaveConfig();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            config = Config.ReadObject<PluginConfig>();
            if (config == null)
            {
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(config);
        }

        private void Init()
        {
            ClearAllRaidBlockUI();
        }

        private void Unload()
        {
            ClearAllRaidZonesAndDomes();
        }

        protected override void LoadDefaultMessages()
        {
            try
            {
                lang.RegisterMessages(
                    new Dictionary<string, string>
                    {
                        ["RaidBlock.Active"] = "Блокировка рейда: {0} сек",
                        ["RaidBlock.BlockedCommand"] =
                            "Вы не можете использовать эту команду во время блокировки рейда",
                        ["RaidBlock.UIMessage"] =
                            "Вы не можете использовать эту команду во время блокировки рейда",
                        ["RaidBlock.NoBuild"] = "Вы не можете строить в зоне рейда",
                    },
                    this,
                    "ru"
                );

                lang.RegisterMessages(
                    new Dictionary<string, string>
                    {
                        ["RaidBlock.Active"] = "Raid Block: {0} sec",
                        ["RaidBlock.BlockedCommand"] =
                            "You cannot use this command while in raid block",
                        ["RaidBlock.UIMessage"] = "You cannot use this command while in raid block",
                        ["RaidBlock.NoBuild"] = "You cannot build in the raid zone",
                    },
                    this,
                    "en"
                );
            }
            catch (ArgumentException ex)
            {
                Puts($"[RaidBlock] Invalid message format: {ex.Message}");
            }
            catch (InvalidOperationException ex)
            {
                Puts($"[RaidBlock] Message registration error: {ex.Message}");
            }
            catch (KeyNotFoundException ex)
            {
                Puts($"[RaidBlock] Message key not found: {ex.Message}");
            }
        }

        private string GetMessage(string key, BasePlayer? player = null, params object[] args)
        {
            return string.Format(
                CultureInfo.InvariantCulture,
                lang.GetMessage(key, this, player?.UserIDString),
                args
            );
        }

        private void ClearAllRaidBlockUI()
        {
            foreach (BasePlayer? player in BasePlayer.activePlayerList)
            {
                DestroyRaidBlockUI(player);
            }
        }

        private void ClearAllRaidZonesAndDomes()
        {
            foreach (SphereEntity dome in activeDomes)
            {
                if (dome?.IsDestroyed == false)
                {
                    dome.Kill();
                }
            }
            activeDomes.Clear();
            activeRaidZones.Clear();
        }

        private void RemoveRaidBlock(BasePlayer player, Vector3 zonePosition, bool saveTime = false)
        {
            if (player == null)
            {
                return;
            }

            ulong playerId = player.userID;

            if (raidTimers.TryGetValue(playerId, out Dictionary<Vector3, Timer>? timers))
            {
                if (timers.TryGetValue(zonePosition, out Timer? timer))
                {
                    timer.Destroy();
                    _ = timers.Remove(zonePosition);
                }

                if (timers.Count == 0)
                {
                    _ = raidTimers.Remove(playerId);
                }
            }

            if (playerZones.TryGetValue(playerId, out HashSet<Vector3>? zones))
            {
                _ = zones.Remove(zonePosition);

                if (zones.Count == 0)
                {
                    _ = playerZones.Remove(playerId);
                }
            }

            if (
                saveTime
                && remainingTimes.TryGetValue(playerId, out Dictionary<Vector3, float>? times)
            )
            {
                if (times.TryGetValue(zonePosition, out float remainingTime))
                {
                    if (
                        !savedBlockTimes.TryGetValue(
                            playerId,
                            out Dictionary<Vector3, float>? savedTimes
                        )
                    )
                    {
                        savedTimes = new Dictionary<Vector3, float>();
                        savedBlockTimes[playerId] = savedTimes;
                    }
                    savedTimes[zonePosition] = remainingTime;
                }
                _ = times.Remove(zonePosition);
                if (times.Count == 0)
                {
                    _ = remainingTimes.Remove(playerId);
                }
            }

            if (!playerZones.TryGetValue(playerId, out HashSet<Vector3>? value) || value.Count == 0)
            {
                DestroyRaidBlockUI(player);
            }
        }

        private void AddRaidBlock(
            BasePlayer player,
            Vector3 zonePosition,
            float duration,
            bool checkSaved = true
        )
        {
            try
            {
                if (player == null)
                {
                    return;
                }

                ulong playerId = player.userID;

                if (
                    checkSaved
                    && savedBlockTimes.TryGetValue(
                        playerId,
                        out Dictionary<Vector3, float>? savedTimes
                    )
                    && savedTimes.TryGetValue(zonePosition, out float savedDuration)
                )
                {
                    duration = savedDuration;
                    _ = savedTimes.Remove(zonePosition);
                    if (savedTimes.Count == 0)
                    {
                        _ = savedBlockTimes.Remove(playerId);
                    }
                }

                if (!raidTimers.TryGetValue(playerId, out Dictionary<Vector3, Timer>? timers))
                {
                    timers = new Dictionary<Vector3, Timer>();
                    raidTimers[playerId] = timers;
                }

                if (timers.TryGetValue(zonePosition, out Timer? existingTimer))
                {
                    existingTimer.Destroy();
                    _ = timers.Remove(zonePosition);
                }

                if (!playerZones.TryGetValue(playerId, out HashSet<Vector3>? zones))
                {
                    zones = new HashSet<Vector3>();
                    playerZones[playerId] = zones;
                }

                _ = zones.Add(zonePosition);

                if (!remainingTimes.TryGetValue(playerId, out Dictionary<Vector3, float>? times))
                {
                    times = new Dictionary<Vector3, float>();
                    remainingTimes[playerId] = times;
                }

                times[zonePosition] = duration;

                timers[zonePosition] = timer.Every(
                    1f,
                    () =>
                    {
                        try
                        {
                            if (player?.IsConnected != true)
                            {
                                if (timers.TryGetValue(zonePosition, out Timer? timer))
                                {
                                    timer.Destroy();
                                    _ = timers.Remove(zonePosition);
                                }
                                return;
                            }

                            if (times.TryGetValue(zonePosition, out float remainingTime))
                            {
                                remainingTime--;
                                times[zonePosition] = remainingTime;

                                if (remainingTime <= 0)
                                {
                                    RemoveRaidBlock(player, zonePosition);
                                    if (timers.TryGetValue(zonePosition, out Timer? timer))
                                    {
                                        timer.Destroy();
                                        _ = timers.Remove(zonePosition);
                                    }
                                }
                                else
                                {
                                    UpdateRaidBlockUI(player, remainingTime);
                                }
                            }
                            else if (timers.TryGetValue(zonePosition, out Timer? timer))
                            {
                                timer.Destroy();
                                _ = timers.Remove(zonePosition);
                            }
                        }
                        catch (Exception ex)
                        {
                            Puts($"[RaidBlock] Timer error: {ex.Message}");
                        }
                    }
                );
                UpdateRaidBlockUI(player, duration);
            }
            catch (Exception ex)
            {
                Puts($"[RaidBlock] Error adding raid block: {ex.Message}");
            }
        }

        private void IsPlayerInRaidZone(BasePlayer player, out HashSet<Vector3> activeZones)
        {
            activeZones = new HashSet<Vector3>();

            if (player == null)
            {
                return;
            }

            Vector3 playerPosition = player.transform.position;
            foreach (RaidZone raidZone in activeRaidZones)
            {
                if (Time.realtimeSinceStartup > raidZone.ExpirationTime)
                {
                    continue;
                }

                float distance = Vector3.Distance(playerPosition, raidZone.Position);
                if (distance <= config.RaidZoneRadius / 2)
                {
                    _ = activeZones.Add(raidZone.Position);
                }
            }
        }

        private void CheckPlayerInZone(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            IsPlayerInRaidZone(player, out HashSet<Vector3> activeZones);

            ulong playerId = player.userID;

            if (!playerZones.TryGetValue(playerId, out HashSet<Vector3>? zones))
            {
                zones = new HashSet<Vector3>();
                playerZones[playerId] = zones;
            }

            foreach (
                Vector3 zonePos in activeZones.Where(zonePos =>
                    !zones.Any(playerZonePos =>
                        Vector3.Distance(playerZonePos, zonePos) <= config.RaidZoneRadius / 2
                    )
                )
            )
            {
                AddRaidBlock(player, zonePos, config.BlockDuration);
            }

            List<Vector3> zonesToRemove = zones.Where(playerZonePos =>
                    !activeZones.Any(activeZonePos =>
                        Vector3.Distance(playerZonePos, activeZonePos) <= config.RaidZoneRadius / 2
                    )
                ).ToList();

            foreach (Vector3 zonePos in zonesToRemove)
            {
                RemoveRaidBlock(player, zonePos, true);
            }
        }

        private void CreateRaidZone(Vector3 position)
        {
            // Проверяем, находится ли новая точка в радиусе существующей зоны
            RaidZone? existingZone = null;
            foreach (RaidZone zone in activeRaidZones)
            {
                if (Vector3.Distance(zone.Position, position) <= config.RaidZoneRadius / 2)
                {
                    existingZone = zone;
                    break;
                }
            }

            if (existingZone != null)
            {
                // Обновляем время существующей зоны
                existingZone.ExpirationTime = Time.realtimeSinceStartup + config.BlockDuration;
                return;
            }

            RaidZone raidZone = new()
            {
                Position = position,
                ExpirationTime = Time.realtimeSinceStartup + config.BlockDuration,
            };

            activeRaidZones.Add(raidZone);

            if (config.IsSphereEnabled)
            {
                bool isInExistingDome = false;
                foreach (SphereEntity dome in activeDomes)
                {
                    if (
                        dome?.IsDestroyed == false
                        && Vector3.Distance(dome.transform.position, position)
                            <= config.RaidZoneRadius / 2
                    )
                    {
                        isInExistingDome = true;
                        break;
                    }
                }

                if (!isInExistingDome)
                {
                    CreateDome(position);
                }
            }
        }

        private void CreateDome(Vector3 position)
        {
            // Проверяем, находится ли новая точка в радиусе существующего купола
            foreach (SphereEntity dome in activeDomes)
            {
                if (dome?.IsDestroyed == false)
                {
                    float distance = Vector3.Distance(dome.transform.position, position);
                    if (distance <= config.RaidZoneRadius / 2)
                    {
                        return;
                    }
                }
            }

            string spherePrefab =
                config.SphereType == 0
                    ? "assets/prefabs/visualization/sphere.prefab"
                    : "assets/prefabs/visualization/sphere_battleroyale.prefab";

            SphereEntity? sphere =
                GameManager.server.CreateEntity(spherePrefab, position) as SphereEntity;
            if (sphere != null)
            {
                sphere.enableSaving = false;
                // Возвращаем оригинальный размер купола
                sphere.currentRadius = config.RaidZoneRadius;
                sphere.lerpRadius = config.RaidZoneRadius;
                sphere.lerpSpeed = 1f;

                // Возвращаем оригинальный визуальный размер
                float visualScale = config.RaidZoneRadius * 2f * config.VisualMultiplier;
                sphere.transform.localScale = Vector3.one * visualScale;
                sphere.UpdateScale();

                sphere.Spawn();
                activeDomes.Add(sphere);
            }
        }

        private void OnPlayerDeath(BasePlayer player, HitInfo info)
        {
            if (player == null || player.userID == 0 || string.IsNullOrEmpty(player.displayName))
            {
                return;
            }

            if (config.RemoveBlockOnDeath)
            {
                RemoveAllRaidBlocks(player);
            }
        }

        private void RemoveAllRaidBlocks(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            ulong playerId = player.userID;

            if (playerZones.TryGetValue(playerId, out HashSet<Vector3>? zones))
            {
                foreach (Vector3 zonePos in new HashSet<Vector3>(zones))
                {
                    RemoveRaidBlock(player, zonePos, false);
                }
            }

            DestroyRaidBlockUI(player);
        }

        private bool OnPlayerChat(
            BasePlayer player,
            string message,
            ConVar.Chat.ChatChannel channel
        )
        {
            if (player == null || string.IsNullOrEmpty(message))
            {
                return true;
            }

            if (
                playerZones.TryGetValue(player.userID, out HashSet<Vector3>? zones)
                && zones.Count > 0
                && config.BlockedCommands.Exists(cmd =>
                    cmd != null && message.StartsWith(cmd, StringComparison.OrdinalIgnoreCase)
                )
            )
            {
                player.ChatMessage(GetMessage("RaidBlock.BlockedCommand", player));
                return false;
            }

            return true;
        }

        private bool OnUserCommand(IPlayer player, string command, string[] args)
        {
            if (player?.Object is not BasePlayer basePlayer)
            {
                return true;
            }

            if (
                playerZones.TryGetValue(basePlayer.userID, out HashSet<Vector3>? zones)
                && zones.Count > 0
            )
            {
                command = "/" + command.ToUpperInvariant();
                if (config.BlockedCommands.Contains(command))
                {
                    basePlayer.ChatMessage(GetMessage("RaidBlock.UIMessage", basePlayer));
                    return false;
                }
            }

            return true;
        }

        [HookMethod("HasRaidBlock")]
        public bool HasRaidBlock(ulong playerID)
        {
            return remainingTimes.ContainsKey(playerID);
        }

        private void OnServerInitialized(bool initial)
        {
            LoadConfig();
            if (config.RaidZoneRadius <= 0)
            {
                config.RaidZoneRadius = 50.0f;
                SaveConfig();
            }
            if (config.BlockDuration <= 0)
            {
                config.BlockDuration = 300.0f;
                SaveConfig();
            }
            if (config.VisualMultiplier <= 0)
            {
                config.VisualMultiplier = 1.0f;
                SaveConfig();
            }

            if (CombatBlock == null)
            {
                PrintError("CombatBlock plugin not found!");
            }

            _ = timer.Every(
                1f,
                () =>
                {
                    _ = activeRaidZones.RemoveAll(zone =>
                        Time.realtimeSinceStartup > zone.ExpirationTime
                    );

                    foreach (BasePlayer? player in BasePlayer.activePlayerList)
                    {
                        if (player == null)
                        {
                            continue;
                        }

                        CheckPlayerInZone(player);
                    }
                }
            );
        }

        [HookMethod("HasRaidBlockUI")]
        public bool HasRaidBlockUI(ulong playerID)
        {
            return uiManagers.ContainsKey(playerID);
        }

        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (info?.damageTypes?.GetMajorityDamageType() == DamageType.Decay)
            {
                return;
            }

            if (
                entity == null
                || info?.Initiator == null
                || info?.damageTypes == null
                || entity.transform == null
            )
            {
                return;
            }

            if (info.Initiator is not BasePlayer attacker)
            {
                return;
            }

            if (
                entity.OwnerID != 0
                && entity.Health() <= info.damageTypes.Total()
                && (
                    info.damageTypes.Has(DamageType.Explosion)
                    || info.damageTypes.Has(DamageType.Bullet)
                )
            )
            {
                BasePlayer? victim = entity as BasePlayer;
                Vector3 damagePosition = entity.transform.position;

                RaidZone? existingZone = null;
                foreach (RaidZone zone in activeRaidZones)
                {
                    float distance = Vector3.Distance(zone.Position, damagePosition);
                    if (distance <= config.RaidZoneRadius / 2)
                    {
                        existingZone = zone;
                        zone.ExpirationTime = Time.realtimeSinceStartup + config.BlockDuration;
                        break;
                    }
                }

                if (existingZone == null)
                {
                    CreateRaidZone(damagePosition);
                    existingZone = activeRaidZones[activeRaidZones.Count - 1];
                }

                AddRaidBlock(attacker, existingZone.Position, config.BlockDuration, false);

                if (victim != null && config.BlockOnReceiveRaidDamage)
                {
                    AddRaidBlock(victim, existingZone.Position, config.BlockDuration, false);
                }
            }
        }

        private bool CanBuild(Planner planner, Construction prefab, Construction.Target target)
        {
            try
            {
                BasePlayer? player = planner?.GetOwnerPlayer();
                if (player == null)
                {
                    return true;
                }

                // Проверяем активные зоны рейда
                bool isInAnyRaidZone = false;
                foreach (RaidZone raidZone in activeRaidZones)
                {
                    if (Time.realtimeSinceStartup > raidZone.ExpirationTime)
                    {
                        continue;
                    }

                    float distance = Vector3.Distance(target.position, raidZone.Position);
                    if (distance <= config.RaidZoneRadius / 2)
                    {
                        isInAnyRaidZone = true;
                        break;
                    }
                }

                if (isInAnyRaidZone)
                {
                    player.ChatMessage(GetMessage("RaidBlock.NoBuild", player));
                    return false;
                }

                return true;
            }
            catch (Exception)
            {
                return true;
            }
        }

        private bool OnStructureUpgrade(
            BuildingBlock block,
            BasePlayer player,
            BuildingGrade.Enum grade,
            ulong skinID
        )
        {
            try
            {
                if (player == null || block == null)
                {
                    return true;
                }

                // Проверяем активные зоны рейда
                bool isInAnyRaidZone = false;
                foreach (RaidZone raidZone in activeRaidZones)
                {
                    if (Time.realtimeSinceStartup > raidZone.ExpirationTime)
                    {
                        continue;
                    }

                    float distance = Vector3.Distance(block.transform.position, raidZone.Position);
                    if (distance <= config.RaidZoneRadius / 2)
                    {
                        isInAnyRaidZone = true;
                        break;
                    }
                }

                if (isInAnyRaidZone)
                {
                    player.ChatMessage(GetMessage("RaidBlock.BlockedUpgrade", player));
                    return false;
                }

                return true;
            }
            catch (Exception)
            {
                return true;
            }
        }
    }
}

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