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

FREE SpectateRadar : 2.1.0 2.1.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("SpectateRadar", "YourName", "2.1.0")]
    [Description("Жесткая блокировка камеры от 1 лица с возвращением админа на его точку земли")]
    class SpectateRadar : RustPlugin
    {
        private Dictionary<ulong, ulong> adminToTarget = new Dictionary<ulong, ulong>();
        private Dictionary<ulong, Vector3> adminOriginalPositions = new Dictionary<ulong, Vector3>();
        private const string permSpec = "spectateradar.spec";

        void OnServerInitialized()
        {
            permission.RegisterPermission(permSpec, this);
            timer.Every(0.3f, UpdateSpectatorUIs);
        }

        void Unload()
        {
            foreach (var adminId in adminToTarget.Keys)
            {
                BasePlayer admin = BasePlayer.FindByID(adminId);
                if (admin != null)
                {
                    CuiHelper.DestroyUi(admin, "SpectateUI");
                    ResetAdminEntity(admin);
                }
            }
        }

        [ChatCommand("spec")]
        void CmdSpec(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, permSpec))
            {
                SendReply(player, "У вас нет прав для использования этой команды.");
                return;
            }

            if (args.Length == 0)
            {
                if (adminToTarget.ContainsKey(player.userID))
                {
                    StopSpectating(player);
                }
                else
                {
                    SendReply(player, "Использование: /spec <ник / часть ника / SteamID>");
                }
                return;
            }

            string searchArg = string.Join(" ", args);
            BasePlayer target = FindTarget(searchArg);

            if (target == null)
            {
                SendReply(player, $"Игрок \"{searchArg}\" не найден или не в сети.");
                return;
            }

            if (target == player)
            {
                SendReply(player, "Вы не можете следить за самим собой.");
                return;
            }

            StartSpectating(player, target);
        }

        [ChatCommand("specoff")]
        void CmdSpecOff(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, permSpec))
            {
                SendReply(player, "У вас нет прав для использования этой команды.");
                return;
            }

            if (adminToTarget.ContainsKey(player.userID))
            {
                StopSpectating(player);
            }
            else
            {
                SendReply(player, "Вы сейчас ни за кем не следите.");
            }
        }

        private void StartSpectating(BasePlayer admin, BasePlayer target)
        {
            admin.SetParent(null, false, false);
            adminOriginalPositions[admin.userID] = admin.transform.position;

            admin.spectateFilter = target.displayName;
            admin.StartSpectating();
            admin.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, true);

            admin.SetParent(target, uint.MaxValue, false); 
            admin.ClientRPCPlayer(null, admin, "ForceSpectateMode", 1); 
            admin.UpdateNetworkGroup();

            adminToTarget[admin.userID] = target.userID;
            SendReply(admin, $"Вы начали закрепленную слежку за {target.displayName}. Камера заблокирована.");
        }

        private void StopSpectating(BasePlayer admin)
        {
            ResetAdminEntity(admin);
            CuiHelper.DestroyUi(admin, "SpectateUI");
            adminToTarget.Remove(admin.userID);
            SendReply(admin, "Слежка прекращена.");
        }
        private void ResetAdminEntity(BasePlayer admin)
        {
            admin.SetParent(null, false, false);
            admin.StopSpectating();
            admin.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, false);
            admin.spectateFilter = string.Empty;

            Vector3 returnPos = admin.transform.position;
            if (adminOriginalPositions.ContainsKey(admin.userID))
            {
                returnPos = adminOriginalPositions[admin.userID];
                adminOriginalPositions.Remove(admin.userID);
            }
            
            if (TerrainMeta.HeightMap != null)
            {
                float terrainHeight = TerrainMeta.HeightMap.GetHeight(returnPos);
                returnPos.y = terrainHeight + 0.5f; 
            }
            else
            {
                RaycastHit hit;
                int layerMask = LayerMask.GetMask("Terrain", "World", "Construction");
                if (Physics.Raycast(new Vector3(returnPos.x, 400f, returnPos.z), Vector3.down, out hit, 500f, layerMask))
                {
                    returnPos.y = hit.point.y + 0.5f;
                }
            }

            admin.MovePosition(returnPos);
            admin.ClientRPCPlayer(null, admin, "ForcePositionTo", returnPos);
            admin.UpdateNetworkGroup();
        }

        private void UpdateSpectatorUIs()
        {
            List<ulong> toRemove = new List<ulong>();

            foreach (var entry in adminToTarget)
            {
                BasePlayer admin = BasePlayer.FindByID(entry.Key);
                if (admin == null || !admin.IsConnected) continue;

                if (!admin.IsSpectating())
                {
                    toRemove.Add(entry.Key);
                    continue;
                }

                BasePlayer target = BasePlayer.FindByID(entry.Value);
                if (target == null || !target.IsConnected || !target.IsAlive())
                {
                    toRemove.Add(entry.Key);
                    continue;
                }

                DrawSpectateUI(admin, target);
            }

            foreach (var adminId in toRemove)
            {
                BasePlayer admin = BasePlayer.FindByID(adminId);
                if (admin != null) ResetAdminEntity(admin);
            }
        }

        private void DrawSpectateUI(BasePlayer admin, BasePlayer target)
        {
            CuiHelper.DestroyUi(admin, "SpectateUI");

            var container = new CuiElementContainer();

            string panelName = container.Add(new CuiPanel
            {
                Image = { Color = "0.08 0.08 0.08 0.85" },
                RectTransform = { AnchorMin = "0.33 0.03", AnchorMax = "0.67 0.15" }
            }, "Hud", "SpectateUI");

            container.Add(new CuiLabel
            {
                Text = { Text = $"НАБЛЮДЕНИЕ ЗА: {target.displayName.ToUpper()}  |  HP: {target.health:F0}/{target.MaxHealth():F0}", FontSize = 12, Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "0.9 0.2 0.2 1" },
                RectTransform = { AnchorMin = "0.0 0.75", AnchorMax = "1.0 1.0" }
            }, panelName);

            float slotWidth = 0.15f;  
            float spacing = 0.015f;   
            float startPos = 0.01f;   

            for (int i = 0; i < 6; i++)
            {
                float minX = startPos + i * (slotWidth + spacing);
                float maxX = minX + slotWidth;

                string slotPanel = container.Add(new CuiPanel
                {
                    Image = { Color = "0.18 0.18 0.18 0.6" },
                    RectTransform = { AnchorMin = $"{minX} 0.08", AnchorMax = $"{maxX} 0.68" }
                }, panelName);

                Item item = target.inventory.containerBelt.GetSlot(i);
                if (item != null)
                {
                    container.Add(new CuiElement
                    {
                        Parent = slotPanel,
                        Components = {
                            new CuiRawImageComponent { Url = $"https://rustoria.co{item.info.shortname}.png" },
                            new CuiRectTransformComponent { AnchorMin = "0.1 0.1", AnchorMax = "0.9 0.9" }
                        }
                    });

                    if (item.amount > 1)
                    {
                        container.Add(new CuiLabel
                        {
                            Text = { Text = $"x{item.amount}", FontSize = 10, Align = TextAnchor.LowerRight, Color = "1 1 1 0.9" },
                            RectTransform = { AnchorMin = "0.0 0.0", AnchorMax = "0.9 0.25" }
                        }, slotPanel);
                    }
                }
            }

            CuiHelper.AddUi(admin, container);
        }

        private BasePlayer FindTarget(string search)
        {
            if (string.IsNullOrEmpty(search)) return null;

            ulong steamId;
            if (search.Length == 17 && ulong.TryParse(search, out steamId))
            {
                BasePlayer player = BasePlayer.FindByID(steamId);
                if (player != null && player.IsConnected) return player;
            }

            BasePlayer bestMatch = null;
            foreach (var player in BasePlayer.activePlayerList)
            {
                if (player.displayName.Equals(search, StringComparison.OrdinalIgnoreCase))
                    return player;

                if (player.displayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0)
                    bestMatch = player;
            }

            return bestMatch;
        }

        void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (adminToTarget.ContainsKey(player.userID))
                adminToTarget.Remove(player.userID);
            
            if (adminOriginalPositions.ContainsKey(player.userID))
                adminOriginalPositions.Remove(player.userID);
        }
    }
}

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