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

FREE UAVSignal : 1.4.4 1.4.4

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

namespace Oxide.Plugins
{
    [Info("UAVSignal", "Yac Vaguer", "1.4.4")]
    [Description("Call a UAV to detect nearby players and NPCs.")]
    public class UAVSignal : RustPlugin
    {
        #region Fields

        private const string PermissionUse = "uavsignal.use";
        private const string SupplySignalShortname = "supply.signal";
        private const string F15Prefab = "assets/scripts/entity/misc/f15/f15e.prefab";
        private HashSet<BasePlayer> playersWithUI = new HashSet<BasePlayer>();
        private HashSet<BasePlayer> currentPlayersInRadius = new HashSet<BasePlayer>();

        private Configuration config;
        private HashSet<BasePlayer> trackedPlayers = new HashSet<BasePlayer>();
        private Timer markingPlayersTimer;
        private Timer playersInRadiusTimer;
        private BasePlayer caller;
        private bool isActive = false;

        private List<LootContainer> processedContainers = new List<LootContainer>();

        #endregion

        #region Initialization

        private void Init()
        {
            permission.RegisterPermission(PermissionUse, this);
            LoadDefaultMessages();
        }

        private void OnServerInitialized()
        {
            LoadConfigValues();
        }

        private void Unload()
        {
            DestroyUAV();
        }

        #endregion

        #region Commands

        [ChatCommand("uav")]
        private void UAVCommand(BasePlayer player, string command, string[] args)
        {
            if (!HasPermission(player))
            {
                player.ChatMessage(GetMessage("NoPermission", player.UserIDString));
                return;
            }

            if (args.Length == 1)
            {
                var targetPlayer = FindPlayer(args[0]);
                if (targetPlayer != null)
                {
                    GiveUAVSignal(targetPlayer);
                    player.ChatMessage(
                        string.Format(
                            GetMessage("UAVGiven", player.UserIDString),
                            targetPlayer.displayName
                        )
                    );
                }
                else
                {
                    player.ChatMessage(
                        string.Format(GetMessage("PlayerNotFound", player.UserIDString), args[0])
                    );
                }
            }
            else
            {
                GiveUAVSignal(player);
                player.ChatMessage(GetMessage("UAVReceived", player.UserIDString));
            }
        }

        [ConsoleCommand("uav")]
        private void UAVConsoleCommand(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();

            if (player != null && !HasPermission(player))
            {
                arg.ReplyWith(GetMessage("NoPermission", player.UserIDString));
                return;
            }

            if (arg.Args == null || arg.Args.Length == 0)
            {
                arg.ReplyWith("Usage: uav <player name or ID>");
                return;
            }

            var targetPlayer = FindPlayer(arg.Args[0]);
            if (targetPlayer != null)
            {
                GiveUAVSignal(targetPlayer);
                arg.ReplyWith($"UAV signal given to {targetPlayer.displayName}");
            }
            else
            {
                arg.ReplyWith($"Player '{arg.Args[0]}' not found.");
            }
        }

        #endregion

        #region Event Hooks

        private void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
        {
            if (entity is SupplySignal signal && signal.skinID == config.UAV.SkinID)
            {
                ThrowUAV(signal, player);
            }
        }

        private void OnExplosiveDropped(BasePlayer player, BaseEntity entity, ThrownWeapon item)
        {
            if (entity is SupplySignal signal && signal.skinID == config.UAV.SkinID)
            {
                ThrowUAV(signal, player);
            }
        }

        private void ThrowUAV(SupplySignal signal, BasePlayer player)
        {
            signal.CancelInvoke(signal.Explode);
            signal.CancelInvoke(signal.KillMessage);
            signal.Kill();
            StartUAV(player);
        }

        private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
        {
            if (entity is BasePlayer player)
            {
                if (playersWithUI.Contains(player))
                {
                    HideTrackedIcon(player);
                }

                if (player == caller)
                {
                    DestroyUAV();
                }
            }
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (playersWithUI.Contains(player))
            {
                HideTrackedIcon(player);
            }

            if (player == caller)
            {
                DestroyUAV();
            }
        }

        private object CanLootEntity(BasePlayer player, LootContainer container)
        {
            if (container == null || !config.Loot.Enabled)
                return null;

            if (processedContainers.Contains(container))
                return null;

            processedContainers.Add(container);

            string containerName = container.ShortPrefabName;
            float dropChance;

            if (config.Loot.Containers.TryGetValue(containerName, out dropChance))
            {
                if (RollChance(dropChance))
                {
                    var item = ItemManager.CreateByName(
                        SupplySignalShortname,
                        1,
                        config.UAV.SkinID
                    );
                    if (item != null)
                    {
                        item.name = config.UAV.ItemName;
                        container.inventory.capacity++;
                        container.inventorySlots++;
                        item.MoveToContainer(container.inventory);
                    }
                }
            }

            return null;
        }

        private void OnEntityKill(LootContainer container)
        {
            if (container != null)
            {
                processedContainers.Remove(container);
            }
        }

        #endregion

        #region UAV Logic

        private void StartUAV(BasePlayer player)
        {
            if (isActive)
            {
                player.ChatMessage(GetMessage("UAVAlreadyActive", player.UserIDString));
                GiveUAVSignal(player);
                return;
            }

            isActive = true;
            caller = player;

            SpawnJet(player);
            player.ChatMessage(GetMessage("UAVCalled", player.UserIDString));
            DebugLog(
                $"UAV started by {player.displayName} at position {player.transform.position}"
            );
        }

        private void SpawnJet(BasePlayer player)
        {
            Vector3 targetPosition = player.transform.position;
            Vector3 spawnPosition =
                targetPosition + player.transform.forward.normalized * config.Jet.SpawnDistance;

            var jet = GameManager.server.CreateEntity(F15Prefab, spawnPosition) as F15;
            if (jet == null)
            {
                PrintError("Failed to create F15 entity.");
                isActive = false;
                return;
            }

            jet.transform.position = spawnPosition;
            jet.transform.forward = (targetPosition - spawnPosition).normalized;
            jet.movePosition = targetPosition;
            jet.defaultAltitude = config.Jet.Altitude;
            jet.Spawn();

            jet.Invoke(() => jet.Kill(), config.Jet.Duration);

            timer.Once(config.UAV.Warmup, () => ActivateUAV(player));
            DebugLog("Jet spawned and moving to target position");
        }

        private void ActivateUAV(BasePlayer player)
        {
            player.ChatMessage(GetMessage("UAVActive", player.UserIDString));
            UpdatePlayersInRadius();

            markingPlayersTimer = timer.Every(3f, () => MarkPlayers(player));
            playersInRadiusTimer = timer.Every(3f, UpdatePlayersInRadius);

            timer.Once(config.UAV.Duration, DestroyUAV);
            DebugLog("UAV activated and timers started");
        }

        private void DestroyUAV()
        {
            if (markingPlayersTimer != null && !markingPlayersTimer.Destroyed)
            {
                markingPlayersTimer.Destroy();
            }

            if (playersInRadiusTimer != null && !playersInRadiusTimer.Destroyed)
            {
                playersInRadiusTimer.Destroy();
            }

            isActive = false;
            currentPlayersInRadius.Clear();
            trackedPlayers.Clear();

            foreach (var player in playersWithUI.ToList())
            {
                HideTrackedIcon(player);
            }

            if (caller != null)
            {
                caller.ChatMessage(GetMessage("UAVEnded", caller.UserIDString));
                DebugLog($"UAV ended for {caller.displayName}");
                caller = null;
            }
        }

        private void UpdatePlayersInRadius()
        {
            if (caller == null || !caller.IsConnected)
            {
                DestroyUAV();
                return;
            }

            currentPlayersInRadius.Clear();

            var players = new List<BasePlayer>();
            Vis.Entities<BasePlayer>(
                caller.transform.position,
                config.UAV.Radius,
                players,
                Rust.Layers.Mask.Player_Server
            );

            var validPlayers = players.Where(player =>
                    player != null &&
                    player != caller &&
                    (!player.userID.Get().IsSteamId() || player.IsConnected)).ToList();

            var playersToRemove = trackedPlayers.Except(validPlayers).ToList();
            
            foreach (var player in playersToRemove)
            {
                trackedPlayers.Remove(player);
                DebugLog($"Stopped tracking {(player.IsNpc ? "NPC" : "Player")} '{player.displayName}'");
            }

            foreach (var player in validPlayers)
            {
                currentPlayersInRadius.Add(player);

                if (!playersWithUI.Contains(player))
                {
                    ShowTrackedIcon(player);

                    if (!trackedPlayers.Contains(player))
                    {
                        trackedPlayers.Add(player);

                        if (player.IsNpc)
                        {
                            DebugLog(
                                $"UAV has detected NPC '{player.ShortPrefabName}' at position {player.transform.position}"
                            );
                        }
                        else
                        {
                            DebugLog(
                                $"UAV has detected player '{player.displayName}' (ID: {player.UserIDString}) at position {player.transform.position}"
                            );
                        }
                    }
                }
            }
            HideUIForPlayersThatAreNotInRadius();
        }

        private void HideUIForPlayersThatAreNotInRadius()
        {
            foreach (var player in playersWithUI.ToList())
            {
                if (!currentPlayersInRadius.Contains(player))
                {
                    HideTrackedIcon(player);
                }
            }
        }

        private void MarkPlayers(BasePlayer player)
        {
            if (player == null || !player.IsConnected)
            {
                DestroyUAV();
                DebugLog("Destroying UAV due to error with the player throwing the Signal");
                return;
            }

            foreach (var target in currentPlayersInRadius)
            {
                if (target == null || target.IsDead())
                {
                    DebugLog("Target is null or dead");
                    continue;
                }

                BasePlayer.PingType type = BasePlayer.PingType.Hostile;

                if (player.Team != null && player.Team.members.Contains(target.userID))
                {
                    DebugLog($"Target is part of the team {target.displayName}");
                    continue;
                }

                if (!target.userID.IsSteamId())
                {
                    type = BasePlayer.PingType.Gun;
                }

                Vector3 pingPosition = target.transform.position + Vector3.up * 2f;

                player.AddPingAtLocation(type, pingPosition, 3f, target.net.ID);
                DebugLog(
                    $"Added ping for {(target.IsNpc ? "NPC" : "Player")} '{target.displayName}' level {type} at position {pingPosition}"
                );
            }
        }

        private void ShowTrackedIcon(BasePlayer player)
        {
            if (player == null || !player.IsConnected)
                return;

            if (playersWithUI.Contains(player))
                return;

            CuiElementContainer elements = new CuiElementContainer();

            string panelName = "UAVTrackedPanel";

            elements.Add(
                new CuiPanel
                {
                    Image = { Color = config.UAV.PanelColor },
                    RectTransform =
                    {
                        AnchorMin = config.UAV.TrackedCUIAnchorMin,
                        AnchorMax = config.UAV.TrackedCUIAnchorMax,
                    },
                    CursorEnabled = false,
                },
                "Hud",
                panelName
            );

            elements.Add(
                new CuiLabel
                {
                    Text =
                    {
                        Color = config.UAV.TextColor,
                        FontSize = 15,
                        Align = TextAnchor.MiddleCenter,
                        Text = GetMessage("BeingTracked", player.UserIDString),
                    },
                    RectTransform = { AnchorMin = "0.205 0.314", AnchorMax = "0.979 0.8" },
                },
                panelName
            );

            elements.Add(
                new CuiElement
                {
                    Parent = panelName,
                    Components =
                    {
                        new CuiRawImageComponent
                        {
                            Color = "1 1 1 1",
                            Url = config.UAV.TrackedIconUrl,
                        },
                        new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "0.184 1" },
                    },
                }
            );

            CuiHelper.AddUi(player, elements);
            playersWithUI.Add(player);
        }

        private void HideTrackedIcon(BasePlayer player)
        {
            if (player == null || !player.IsConnected)
                return;

            if (!playersWithUI.Contains(player))
                return;

            CuiHelper.DestroyUi(player, "UAVTrackedPanel");
            playersWithUI.Remove(player);
        }

        #endregion

        #region Helpers

        private bool HasPermission(BasePlayer player)
        {
            return permission.UserHasPermission(player.UserIDString, PermissionUse)
                || player.IsAdmin;
        }

        private BasePlayer FindPlayer(string nameOrId)
        {
            var players = BasePlayer.activePlayerList.Where(p =>
                    p.displayName.Contains(nameOrId, StringComparison.OrdinalIgnoreCase)
                    || p.UserIDString == nameOrId
                ).ToList();

            if (players.Count == 1)
                return players[0];

            return null;
        }

        private void GiveUAVSignal(BasePlayer player)
        {
            var item = ItemManager.CreateByName(SupplySignalShortname, 1, config.UAV.SkinID);
            if (item != null)
            {
                item.name = config.UAV.ItemName;
                player.GiveItem(item);
                DebugLog($"Gave UAV signal to {player.displayName}");
            }
        }

        private bool RollChance(float chance)
        {
            return UnityEngine.Random.Range(0f, 100f) <= chance;
        }

        private void DebugLog(string message)
        {
            if (config.DebugMode)
            {
                Puts(message);
            }
        }

        #endregion

        #region Configuration

        private class Configuration
        {
            [JsonProperty("UAV Settings")]
            public UAVSettings UAV { get; set; } = new UAVSettings();

            [JsonProperty("Jet Settings")]
            public JetSettings Jet { get; set; } = new JetSettings();

            [JsonProperty("Loot Settings")]
            public LootSettings Loot { get; set; } = new LootSettings();

            [JsonProperty("Debug Mode")]
            public bool DebugMode { get; set; } = false;
        }

        private class UAVSettings
        {
            [JsonProperty("Duration (seconds)")]
            public float Duration { get; set; } = 180f;

            [JsonProperty("Radius")]
            public float Radius { get; set; } = 40f;

            [JsonProperty("Skin ID")]
            public ulong SkinID { get; set; } = 3248057023;

            [JsonProperty("Warmup Time (seconds)")]
            public float Warmup { get; set; } = 5f;

            [JsonProperty("Item Name")]
            public string ItemName { get; set; } = "UAV Signal";

            [JsonProperty("Tracked Icon URL")]
            public string TrackedIconUrl { get; set; } =
                "https://cdn.rustpluginshub.com/unsafe/50x50/https://rustpluginshub.com/icons/location.png";

            [JsonProperty("Tracked Icon Position (AnchorMin)")]
            public string TrackedCUIAnchorMin { get; set; } = "0.006 0.485";

            [JsonProperty("Tracked Icon Position (AnchorMax)")]
            public string TrackedCUIAnchorMax { get; set; } = "0.105 0.518";

            [JsonProperty("Panel Color")]
            public string PanelColor { get; set; } = "0.96 0.31 0.26 0.47";

            [JsonProperty("Text Color")]
            public string TextColor { get; set; } = "1 1 1 1";
        }

        private class JetSettings
        {
            [JsonProperty("Altitude")]
            public float Altitude { get; set; } = 200f;

            [JsonProperty("Spawn Distance")]
            public float SpawnDistance { get; set; } = 500f;

            [JsonProperty("Duration (seconds)")]
            public float Duration { get; set; } = 15f;
        }

        private class LootSettings
        {
            [JsonProperty("Enable Loot Drops")]
            public bool Enabled { get; set; } = true;

            [JsonProperty("Loot Containers and Drop Chances")]
            public Dictionary<string, float> Containers { get; set; } =
                new Dictionary<string, float>
                {
                    { "crate_normal", 0f },
                    { "crate_normal_2", 0f },
                    { "crate_elite", 2f },
                    { "heli_crate", 5f },
                    { "bradley_crate", 5f },
                };
        }

        protected override void LoadDefaultConfig()
        {
            config = new Configuration();
            SaveConfig();
            Puts("Default configuration file created.");
        }

        private void LoadConfigValues()
        {
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    LoadDefaultConfig();
                }
                else
                {
                    SaveConfig();
                }
            }
            catch
            {
                PrintError("Configuration file is corrupt; loading default configuration.");
                LoadDefaultConfig();
            }
        }

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

        #endregion

        #region Localization

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["NoPermission"] = "You do not have permission to use this command.",
                    ["PlayerNotFound"] = "Player '{0}' not found.",
                    ["UAVGiven"] = "UAV Signal given to {0}.",
                    ["UAVReceived"] = "You have received a UAV Signal.",
                    ["UAVCalled"] = "UAV has been called to your area.",
                    ["UAVAlreadyActive"] = "A UAV is already active.",
                    ["UAVActive"] = "UAV is now active.",
                    ["UAVEnded"] = "UAV has ended.",
                    ["BeingTracked"] = "You are being tracked",
                },
                this
            );
        }

        private string GetMessage(string key, string userId = null)
        {
            return lang.GetMessage(key, this, userId);
        }

        #endregion
    }
}

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