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

FREE RaidBlock : 1.0.0 1.0.0

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

namespace Oxide.Plugins
{
    [Info("Raid Block", "BlackWolf", "1.0.0")]
    public class RaidBlock : RustPlugin
    {
        #region Fields
        private const string PermissionAdmin = "raidblock.admin";
        private const float RAID_BLOCK_TIME = 120f; // 2 minutes in seconds
        private Dictionary<ulong, Timer> raidBlockTimers = new();
        private Dictionary<ulong, string> activeCui = new();
        private Dictionary<ulong, float> blockStartTimes = new();
        
        // Configuration
        private Configuration config;

        // Lists of items that trigger raid block
        private readonly HashSet<string> raidItems = new HashSet<string>
        {
            "explosive.timed", // C4
            "ammo.rocket.basic", // Regular Rocket
            "ammo.rocket.fire", // Incendiary Rocket
            "ammo.rocket.hv", // High Velocity Rocket
            "ammo.rocket.smoke", // Smoke Rocket
            "grenade.f1", // F1 Grenade
            "grenade.beancan", // Beancan Grenade
            "grenade.satchel", // Satchel Charge
            "ammo.rifle.explosive", // Explosive Ammo
            "surveycharge", // Survey Charge
            "explosive.underwater", // Underwater Explosive
            "ammo.shotgun", // Shotgun Ammo
            "ammo.handmade.shell", // Handmade Shells
            "ammo.rifle", // Rifle Ammo
            "ammo.pistol" // Pistol Ammo
        };

        private readonly HashSet<string> raidTools = new HashSet<string>
        {
            "hammer.salvaged",
            "axe.salvaged",
            "pickaxe",
            "jackhammer",
            "explosive.timed.underwater",
            "chainsaw",
            "hammer",
            "icepick.salvaged",
            "axe",
            "mace",
            "machete",
            "salvaged.sword",
            "longsword",
            "spear.stone",
            "spear.wooden"
        };
        #endregion

        #region Configuration
        private class Configuration
        {
            [JsonProperty("Enable sound effects")]
            public bool EnableSoundEffects = true;

            [JsonProperty("Block message color (hex)")]
            public string MessageColor = "#FF4444";

            [JsonProperty("Timer color (hex)")]
            public string TimerColor = "#FFFFFF";

            [JsonProperty("Show block message to nearby players")]
            public bool ShowToNearbyPlayers = true;

            [JsonProperty("Nearby players notification range")]
            public float NotificationRange = 30f;

            [JsonProperty("Block combat between raid blocked players")]
            public bool BlockPvPBetweenBlocked = true;

            public static Configuration DefaultConfig()
            {
                return new Configuration();
            }
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null) LoadDefaultConfig();
            }
            catch
            {
                PrintError("Configuration file is corrupt! Loading default config...");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void LoadDefaultConfig()
        {
            config = Configuration.DefaultConfig();
        }

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

        #region Plugin Lifecycle
        private void Init()
        {
            // Register permissions
            permission.RegisterPermission(PermissionAdmin, this);
            
            // Register commands
            cmd.AddChatCommand("raidblock", this, CmdRaidBlock);
            
            // Clean up any existing data
            raidBlockTimers.Clear();
            activeCui.Clear();
        }

        private void OnServerInitialized()
        {
            // Load configuration
            LoadConfig();
        }

        private void Unload()
        {
            // Clean up timers and CUI
            foreach (var timer in raidBlockTimers.Values)
                timer?.Destroy();
            
            foreach (var player in BasePlayer.activePlayerList)
                DestroyUI(player);
        }
        #endregion

        #region Combat Events
        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            try
            {
                // Check if it's building damage
                bool isRaidableEntity = entity is BuildingBlock || 
                                      entity is Door || 
                                      entity is AutoTurret || 
                                      entity is StorageContainer ||
                                      entity is BuildingPrivlidge ||
                                      entity is BaseOven ||
                                      entity is LootContainer;
                
                if (!isRaidableEntity) return;
                
                // Get the attacker
                BasePlayer attacker = info?.InitiatorPlayer;
                if (attacker == null) return;

                // Check damage type
                bool isRaidDamage = false;

                // Check weapon/tool
                Item weapon = attacker.GetActiveItem();
                if (weapon != null)
                {
                    isRaidDamage = raidItems.Contains(weapon.info.shortname) ||
                                  raidTools.Contains(weapon.info.shortname);

                    // If using a tool on a building, it's raid damage
                    if (!isRaidDamage && entity is BuildingBlock && raidTools.Contains(weapon.info.shortname))
                    {
                        isRaidDamage = true;
                    }
                }

                // Check damage types
                if (!isRaidDamage && info.damageTypes != null)
                {
                    isRaidDamage = info.damageTypes.Has(Rust.DamageType.Explosion) ||
                                  info.damageTypes.Has(Rust.DamageType.AntiVehicle) ||
                                  info.damageTypes.Has(Rust.DamageType.Bullet) ||
                                  info.damageTypes.Has(Rust.DamageType.Blunt) ||
                                  info.damageTypes.Has(Rust.DamageType.Slash) ||
                                  info.damageTypes.Has(Rust.DamageType.Stab);
                }

                if (!isRaidDamage) return;

                ApplyRaidBlockToPlayer(attacker);
            }
            catch (Exception ex)
            {
                PrintError($"Error in OnEntityTakeDamage: {ex.Message}");
            }
        }

        // Handle explosive ammo and rockets
        private void OnWeaponFired(BaseProjectile projectile, BasePlayer player, ItemModProjectile mod, ProtoBuf.ProjectileShoot projectileShoot)
        {
            try
            {
                if (player == null || projectile == null) return;

                var heldItem = player.GetActiveItem();
                if (heldItem?.info == null) return;

                // Check if the weapon uses raid ammo
                var ammoType = heldItem.GetHeldEntity()?.GetComponent<BaseProjectile>()?.primaryMagazine?.ammoType;
                if (ammoType == null) return;

                if (raidItems.Contains(ammoType.shortname))
                {
                    ApplyRaidBlockToPlayer(player);
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error in OnWeaponFired: {ex.Message}");
            }
        }

        // Handle thrown explosives (Satchels, Beancans, etc.)
        private void OnExplosiveThrown(BasePlayer player, BaseEntity entity, ThrownWeapon weapon)
        {
            try
            {
                if (player == null || entity == null) return;

                string itemName = entity.ShortPrefabName;
                if (raidItems.Contains(itemName))
                {
                    ApplyRaidBlockToPlayer(player);
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error in OnExplosiveThrown: {ex.Message}");
            }
        }

        // Handle C4 placement
        private void OnExplosiveDropped(BasePlayer player, BaseEntity entity, ThrownWeapon weapon)
        {
            try
            {
                if (player == null || entity == null) return;

                if (entity is TimedExplosive)
                {
                    ApplyRaidBlockToPlayer(player);
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error in OnExplosiveDropped: {ex.Message}");
            }
        }

        // Helper method to apply raid block
        private void ApplyRaidBlockToPlayer(BasePlayer player)
        {
            // Check if player is already raid blocked
            if (IsRaidBlocked(player.userID))
            {
                // Refresh the timer
                RefreshRaidBlock(player);
                return;
            }

            // Apply raid block
            ApplyRaidBlock(player);

            // Notify nearby players if enabled
            if (config.ShowToNearbyPlayers)
                NotifyNearbyPlayers(player);

            // Play sound if enabled
            if (config.EnableSoundEffects)
                player.Command("note.raid", 1, 1, 0);
        }

        private object OnPlayerAttack(BasePlayer attacker, HitInfo info)
        {
            try
            {
                if (!config.BlockPvPBetweenBlocked) return null;

                // Check if both players are raid blocked
                if (info?.HitEntity is BasePlayer victim)
                {
                    if (IsRaidBlocked(attacker.userID) && IsRaidBlocked(victim.userID))
                    {
                        SendReply(attacker, "You cannot PvP while raid blocked!");
                        return true; // Cancel the attack
                    }
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error in OnPlayerAttack: {ex.Message}");
            }
            return null;
        }
        #endregion

        #region Helper Methods
        private void ApplyRaidBlock(BasePlayer player)
        {
            try
            {
                ulong userId = player.userID;

                // Initialize dictionaries if needed
                if (!raidBlockTimers.ContainsKey(userId))
                    raidBlockTimers[userId] = null;
                if (!blockStartTimes.ContainsKey(userId))
                    blockStartTimes[userId] = 0f;

                // Destroy existing timer if any
                raidBlockTimers[userId]?.Destroy();

                // Store start time
                blockStartTimes[userId] = Time.realtimeSinceStartup;

                // Create new timer
                raidBlockTimers[userId] = timer.Once(RAID_BLOCK_TIME, () => RemoveRaidBlock(player));

                // Show UI
                CreateUI(player, RAID_BLOCK_TIME);

                // Notify player
                SendReply(player, $"You are now raid blocked for {RAID_BLOCK_TIME} seconds!");
            }
            catch (Exception ex)
            {
                PrintError($"Error in ApplyRaidBlock: {ex.Message}\nStack: {ex.StackTrace}");
            }
        }

        private void RefreshRaidBlock(BasePlayer player)
        {
            try
            {
                ulong userId = player.userID;

                // Initialize dictionaries if needed
                if (!raidBlockTimers.ContainsKey(userId))
                    raidBlockTimers[userId] = null;
                if (!blockStartTimes.ContainsKey(userId))
                    blockStartTimes[userId] = 0f;

                // Reset timer
                raidBlockTimers[userId]?.Destroy();
                blockStartTimes[userId] = Time.realtimeSinceStartup;
                raidBlockTimers[userId] = timer.Once(RAID_BLOCK_TIME, () => RemoveRaidBlock(player));

                // Update UI
                CreateUI(player, RAID_BLOCK_TIME);
            }
            catch (Exception ex)
            {
                PrintError($"Error in RefreshRaidBlock: {ex.Message}\nStack: {ex.StackTrace}");
            }
        }

        private void RemoveRaidBlock(BasePlayer player)
        {
            try
            {
                ulong userId = player.userID;

                // Clean up
                if (raidBlockTimers.ContainsKey(userId))
                {
                    raidBlockTimers[userId]?.Destroy();
                    raidBlockTimers.Remove(userId);
                }
                
                if (blockStartTimes.ContainsKey(userId))
                    blockStartTimes.Remove(userId);

                DestroyUI(player);

                // Notify player
                if (player != null && player.IsConnected)
                {
                    SendReply(player, "Your raid block has expired!");

                    // Play sound if enabled
                    if (config.EnableSoundEffects)
                        player.Command("note.raid", 1, 0.5f, 0);
                }
            }
            catch (Exception ex)
            {
                PrintError($"Error in RemoveRaidBlock: {ex.Message}\nStack: {ex.StackTrace}");
            }
        }

        private bool IsRaidBlocked(ulong userId)
        {
            return raidBlockTimers.ContainsKey(userId) && raidBlockTimers[userId] != null;
        }

        private float GetRemainingBlockTime(ulong userId)
        {
            if (!blockStartTimes.ContainsKey(userId)) return 0f;
            float elapsed = Time.realtimeSinceStartup - blockStartTimes[userId];
            return Math.Max(0f, RAID_BLOCK_TIME - elapsed);
        }

        private void NotifyNearbyPlayers(BasePlayer attacker)
        {
            try
            {
                var nearbyPlayers = new List<BasePlayer>();
                var entities = new List<BaseEntity>();
                Vis.Entities(attacker.transform.position, config.NotificationRange, entities);
                
                foreach (var entity in entities)
                {
                    if (entity is BasePlayer player && player != attacker && player.IsConnected)
                        nearbyPlayers.Add(player);
                }

                foreach (var player in nearbyPlayers)
                    SendReply(player, $"{attacker.displayName} has started raiding nearby!");
            }
            catch (Exception ex)
            {
                PrintError($"Error in NotifyNearbyPlayers: {ex.Message}");
            }
        }
        #endregion

        #region UI Methods
        private void CreateUI(BasePlayer player, float duration)
        {
            DestroyUI(player);

            var elements = new CuiElementContainer();

            // Main panel - centered at top
            elements.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform = { AnchorMin = "0.35 0.85", AnchorMax = "0.65 0.95" },
                CursorEnabled = false
            }, "Overlay", "RaidBlock_UI");

            // Background panel with gradient
            elements.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0.9", Material = "assets/content/ui/uibackgroundblur-ingame.mat" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" }
            }, "RaidBlock_UI", "RaidBlock_BG");

            // Red warning bar at top
            elements.Add(new CuiPanel
            {
                Image = { Color = "0.8 0 0 0.8" },
                RectTransform = { AnchorMin = "0 0.8", AnchorMax = "1 1" }
            }, "RaidBlock_UI");

            // Warning icon (⚠)
            elements.Add(new CuiLabel
            {
                Text = 
                {
                    Text = "⚠",
                    FontSize = 20,
                    Font = "robotocondensed-bold.ttf",
                    Color = "1 1 1 1",
                    Align = TextAnchor.MiddleCenter
                },
                RectTransform = { AnchorMin = "0 0.8", AnchorMax = "0.2 1" }
            }, "RaidBlock_UI");

            // Raid block text
            elements.Add(new CuiLabel
            {
                Text = 
                {
                    Text = "RAID BLOCKED",
                    FontSize = 24,
                    Font = "robotocondensed-bold.ttf",
                    Color = "1 0 0 1",
                    Align = TextAnchor.MiddleCenter
                },
                RectTransform = { AnchorMin = "0.2 0.8", AnchorMax = "0.8 1" }
            }, "RaidBlock_UI");

            // Timer text with glow
            elements.Add(new CuiLabel
            {
                Text = 
                {
                    Text = $"{duration:F0}s",
                    FontSize = 32,
                    Font = "robotocondensed-bold.ttf",
                    Color = "1 1 1 1",
                    Align = TextAnchor.MiddleCenter
                },
                RectTransform = { AnchorMin = "0 0.2", AnchorMax = "1 0.8" }
            }, "RaidBlock_UI", "RaidBlock_Timer");

            // Bottom text
            elements.Add(new CuiLabel
            {
                Text = 
                {
                    Text = "NO PVP ALLOWED",
                    FontSize = 16,
                    Font = "robotocondensed-regular.ttf",
                    Color = "1 0.3 0.3 1",
                    Align = TextAnchor.MiddleCenter
                },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0.2" }
            }, "RaidBlock_UI");

            // Store and send UI
            var json = CuiHelper.ToJson(elements);
            activeCui[player.userID] = json;
            CuiHelper.AddUi(player, json);

            // Start timer updates
            timer.Every(1f, () =>
            {
                if (!player.IsConnected || !IsRaidBlocked(player.userID))
                {
                    DestroyUI(player);
                    return;
                }

                float remaining = GetRemainingBlockTime(player.userID);
                UpdateTimerText(player, remaining);
            });
        }

        private void UpdateTimerText(BasePlayer player, float remaining)
        {
            var elements = new CuiElementContainer();
            elements.Add(new CuiLabel
            {
                Text = 
                {
                    Text = $"{remaining:F0}s",
                    FontSize = 32,
                    Font = "robotocondensed-bold.ttf",
                    Color = "1 1 1 1",
                    Align = TextAnchor.MiddleCenter
                },
                RectTransform = { AnchorMin = "0 0.2", AnchorMax = "1 0.8" }
            }, "RaidBlock_UI", "RaidBlock_Timer");

            CuiHelper.DestroyUi(player, "RaidBlock_Timer");
            CuiHelper.AddUi(player, CuiHelper.ToJson(elements));
        }

        private void DestroyUI(BasePlayer player)
        {
            if (activeCui.ContainsKey(player.userID))
            {
                CuiHelper.DestroyUi(player, "RaidBlock_UI");
                activeCui.Remove(player.userID);
            }
        }
        #endregion

        #region Commands
        private void CmdRaidBlock(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermissionAdmin))
            {
                SendReply(player, "You don't have permission to use this command!");
                return;
            }

            if (args.Length == 0)
            {
                SendReply(player, "Usage: /raidblock <check/clear> [player name]");
                return;
            }

            switch (args[0].ToLower())
            {
                case "check":
                    if (args.Length < 2)
                    {
                        SendReply(player, "Usage: /raidblock check <player name>");
                        return;
                    }
                    var targetPlayer = BasePlayer.Find(args[1]);
                    if (targetPlayer == null)
                    {
                        SendReply(player, "Player not found!");
                        return;
                    }
                    SendReply(player, IsRaidBlocked(targetPlayer.userID) 
                        ? $"{targetPlayer.displayName} is raid blocked!" 
                        : $"{targetPlayer.displayName} is not raid blocked.");
                    break;

                case "clear":
                    if (args.Length < 2)
                    {
                        SendReply(player, "Usage: /raidblock clear <player name>");
                        return;
                    }
                    var clearPlayer = BasePlayer.Find(args[1]);
                    if (clearPlayer == null)
                    {
                        SendReply(player, "Player not found!");
                        return;
                    }
                    if (IsRaidBlocked(clearPlayer.userID))
                    {
                        RemoveRaidBlock(clearPlayer);
                        SendReply(player, $"Removed raid block from {clearPlayer.displayName}");
                    }
                    else
                    {
                        SendReply(player, $"{clearPlayer.displayName} is not raid blocked!");
                    }
                    break;

                default:
                    SendReply(player, "Usage: /raidblock <check/clear> [player name]");
                    break;
            }
        }
        #endregion
    }
}

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