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

FREE PluginInfo : 1.0.1 1.0.1

Нет прав для скачивания
C#:
/*
███████╗██╗     ███████╗██╗    ██╗ ███████╗ ██████╗ 
██╔════╝██║     ██╔════╝ ██║  ██╔╝ ██╔════╝ ██╔══██╗
█████╗  ██║     █████╗    █████╔╝  █████╗   ██████╔╝
██╔══╝  ██║     ██╔══╝   ██╔═ ██╗  ██╔══╝   ██╔══██╗
██║     ███████╗███████╗██║    ██╗ ███████╗ ██║  ██║
╚═╝     ╚══════╝╚══════╝╚═╝    ╚═╝ ╚══════╝ ╚═╝  ╚═╝
*                 Flexer
*        Copyright © Flexer. All rights reserved.
*/
using System.Collections.Generic;
using System.Globalization;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Oxide.Core;
namespace Oxide.Plugins {
    [Info("PluginInfo", "Flexer", "1.0.1")]
    [Description("Displays rotating informational messages below the hotbar. Movable per player with interactive panel.")]
    public class PluginInfo : RustPlugin {
        private ConfigData config;
        private int messageIndex = 0;
        private const string panelName = "InfoPanelUI";
        private System.Random rng = new System.Random();
        private Dictionary<ulong, Vector2> playerOffsets = new Dictionary<ulong, Vector2>();
        private Dictionary<ulong, Vector2> playerScales = new Dictionary<ulong, Vector2>();
        private class ConfigData {
            public float IntervalSeconds {
                get;
                set;
            }
            public string RotationMode {
                get;
                set;
            }
            public string PanelColor {
                get;
                set;
            }
            public string TextColor {
                get;
                set;
            }
            public int FontSize {
                get;
                set;
            }
            public string AnchorMin {
                get;
                set;
            }
            public string AnchorMax {
                get;
                set;
            }
            public float MoveIncrement {
                get;
                set;
            }
            public string MoveUIAnchorMin {
                get;
                set;
            }
            // fixed location for controller
            public string MoveUIAnchorMax {
                get;
                set;
            }
            public List<string> Messages {
                get;
                set;
            }
        }
        protected override void LoadDefaultConfig() {
            config = new ConfigData {
                IntervalSeconds = 15f, RotationMode = "Sequential", PanelColor = "0.1 0.1 0.1 0.75", TextColor = "1 1 1 1", FontSize = 15, AnchorMin = "0.345 0.110", AnchorMax = "0.64 0.150", MoveIncrement = 0.005f, MoveUIAnchorMin = "0.05 0.70", MoveUIAnchorMax = "0.45 0.94", Messages = new List<string> {
                    "<size=24><b>Flexer</b></size>", "Press <color=#ffd479>/home</color> to teleport!", "Vote daily to get rewards at <color=#aaffaa>example.com/vote</color>", "Need help? Type <color=#ffaaaa>/help</color>", "Join our Discord at <color=#7289da>discord.gg/yourserver</color>", "Check out the shop: <color=#ffcc00>www.yourserver.com/shop</color>"
                }
            }
            ;
            SaveConfig();
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            config = Config.ReadObject<ConfigData>() ?? new ConfigData();
            if (config.IntervalSeconds <= 0f) config.IntervalSeconds = 15f;
            if (string.IsNullOrEmpty(config.RotationMode)) config.RotationMode = "Sequential";
            if (string.IsNullOrEmpty(config.PanelColor)) config.PanelColor = "0.1 0.1 0.1 0.75";
            if (string.IsNullOrEmpty(config.TextColor)) config.TextColor = "1 1 1 1";
            if (config.FontSize <= 0) config.FontSize = 15;
            if (string.IsNullOrEmpty(config.AnchorMin)) config.AnchorMin = "0.345 0.110";
            if (string.IsNullOrEmpty(config.AnchorMax)) config.AnchorMax = "0.64 0.150";
            if (config.MoveIncrement <= 0f) config.MoveIncrement = 0.005f;
            if (string.IsNullOrEmpty(config.MoveUIAnchorMin)) config.MoveUIAnchorMin = "0.05 0.70";
            if (string.IsNullOrEmpty(config.MoveUIAnchorMax)) config.MoveUIAnchorMax = "0.45 0.94";
            if (config.Messages == null || config.Messages.Count == 0) {
                PrintWarning("No messages found in config, loading defaults.");
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() => Config.WriteObject(config, true);
        void Init() {
            permission.RegisterPermission("plugininfo.move", this);
        }
        void OnServerInitialized() {
            LoadPlayerOffsets();
            LoadPlayerScales();
            timer.Every(config.IntervalSeconds, RotateMessage);
            foreach (var player in BasePlayer.activePlayerList) {
                var offset = playerOffsets.ContainsKey(player.userID) ? playerOffsets[player.userID] : Vector2.zero;
                CreateUI(player, GetCurrentMessage(), offset);
            }
        }
        void OnPlayerInit(BasePlayer player) {
            var offset = playerOffsets.ContainsKey(player.userID) ? playerOffsets[player.userID] : Vector2.zero;
            CreateUI(player, GetCurrentMessage(), offset);
        }
        void OnPlayerDisconnected(BasePlayer player) {
            DestroyMovementPanel(player);
            DestroyUI(player);
        }
        void Unload() {
            foreach (var player in BasePlayer.activePlayerList) {
                DestroyUI(player);
                DestroyMovementPanel(player);
            }
        }
        private void RotateMessage() {
            if (config.Messages == null || config.Messages.Count == 0) return;
            var mode = (config.RotationMode ?? "Sequential").Trim().ToLowerInvariant();
            if (mode == "random") messageIndex = rng.Next(config.Messages.Count);
            else messageIndex = (messageIndex + 1) % config.Messages.Count;
            string message = config.Messages[messageIndex];
            foreach (var player in BasePlayer.activePlayerList) {
                DestroyUI(player);
                var offset = playerOffsets.ContainsKey(player.userID) ? playerOffsets[player.userID] : Vector2.zero;
                CreateUI(player, message, offset);
            }
        }
        private string GetCurrentMessage() {
            if (config.Messages == null || config.Messages.Count == 0) return "No messages configured.";
            return config.Messages[messageIndex];
        }
        private bool TryParseAnchorPair(string s, out Vector2 v) {
            v = Vector2.zero;
            if (string.IsNullOrWhiteSpace(s)) return false;
            var parts = s.Split(' ');
            if (parts.Length != 2) return false;
            if (!float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var x)) return false;
            if (!float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var y)) return false;
            v = new Vector2(x, y);
            return true;
        }
        private float Clamp01(float f) => Mathf.Clamp01(f);
        private Vector2 Clamp01(Vector2 v) => new Vector2(Clamp01(v.x), Clamp01(v.y));
        private void CreateUI(BasePlayer player, string text, Vector2 offset) {
            var container = new CuiElementContainer();
            Vector2 min, max;
            if (!TryParseAnchorPair(config.AnchorMin, out min)) min = new Vector2(0.345f, 0.110f);
            if (!TryParseAnchorPair(config.AnchorMax, out max)) max = new Vector2(0.64f, 0.150f);
            var size = max - min;
            var scale = playerScales.ContainsKey(player.userID) ? playerScales[player.userID] : Vector2.one;
            var scaledMax = min + new Vector2(size.x * Mathf.Clamp(scale.x, 0.25f, 3f), size.y * Mathf.Clamp(scale.y, 0.25f, 3f));
            var minWith = Clamp01(min + offset);
            var maxWith = Clamp01(scaledMax + offset);
            if (maxWith.x <= minWith.x) maxWith.x = Mathf.Min(1f, minWith.x + (scaledMax.x - min.x));
            if (maxWith.y <= minWith.y) maxWith.y = Mathf.Min(1f, minWith.y + (scaledMax.y - min.y));
            var panel = container.Add(new CuiPanel {
                Image = {
                    Color = config.PanelColor
                }
                , RectTransform = {
                    AnchorMin = $"{minWith.x.ToString(CultureInfo.InvariantCulture)} {minWith.y.ToString(CultureInfo.InvariantCulture)}", AnchorMax = $"{maxWith.x.ToString(CultureInfo.InvariantCulture)} {maxWith.y.ToString(CultureInfo.InvariantCulture)}"
                }
                , CursorEnabled = false
            }
            , "Hud", panelName);
            container.Add(new CuiLabel {
                Text = {
                    Text = text, FontSize = config.FontSize, Align = TextAnchor.MiddleCenter, Color = config.TextColor
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
            }
            , panel);
            CuiHelper.AddUi(player, container);
        }
        private void DestroyUI(BasePlayer player) => CuiHelper.DestroyUi(player, panelName);
        private const string movePanelName = "MovePanelUI";
        private readonly Dictionary<ulong, float> playerMoveStep = new Dictionary<ulong, float>();
        private readonly Dictionary<ulong, bool> playerSizeMode = new Dictionary<ulong, bool>();
        [ChatCommand("panelmove")]
        private void cmdShowMovePanel(BasePlayer player, string command, string[] args) {
            if (!permission.UserHasPermission(player.UserIDString, "plugininfo.move")) {
                SendReply(player, "You don't have permission to move this panel.");
                return;
            }
            if (args != null && args.Length > 0 && args[0].Equals("off", System.StringComparison.OrdinalIgnoreCase)) {
                DestroyMovementPanel(player);
                return;
            }
            ShowMovementPanel(player);
        }
        private void ShowMovementPanel(BasePlayer player) {
            DestroyMovementPanel(player);
            if (!playerMoveStep.ContainsKey(player.userID)) playerMoveStep[player.userID] = (config?.MoveIncrement > 0 ? config.MoveIncrement : 0.005f);
            if (!playerSizeMode.ContainsKey(player.userID)) playerSizeMode[player.userID] = false;
            if (!playerScales.ContainsKey(player.userID)) playerScales[player.userID] = Vector2.one;
            Vector2 mvMin, mvMax;
            if (!TryParseAnchorPair(config.MoveUIAnchorMin, out mvMin)) mvMin = new Vector2(0.05f, 0.70f);
            if (!TryParseAnchorPair(config.MoveUIAnchorMax, out mvMax)) mvMax = new Vector2(0.45f, 0.94f);
            mvMin = Clamp01(mvMin);
            mvMax = Clamp01(mvMax);
            var ui = new CuiElementContainer();
            var root = ui.Add(new CuiPanel {
                Image = {
                    Color = "0 0 0 0.88"
                }
                , RectTransform = {
                    AnchorMin = $"{mvMin.x} {mvMin.y}", AnchorMax = $"{mvMax.x} {mvMax.y}"
                }
                , CursorEnabled = true
            }
            , "Hud", movePanelName);
            ui.Add(new CuiPanel {
                Image = {
                    Color = "0.15 0.15 0.15 1"
                }
                , RectTransform = {
                    AnchorMin = "0 0.78", AnchorMax = "1 1"
                }
            }
            , root);
            ui.Add(new CuiLabel {
                Text = {
                    Text = "Move Panel", FontSize = 14, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
                }
                , RectTransform = {
                    AnchorMin = "0.03 0.80", AnchorMax = "0.7 0.99"
                }
            }
            , root);
            AddBtn(ui, "X", "movepanel close", "0.92 0.80", "0.985 0.99", 14, "0.85 0.3 0.3 1", root);
            float step = playerMoveStep[player.userID];
            bool sizeMode = playerSizeMode[player.userID];
            string modeText = sizeMode ? "Mode: Size" : "Mode: Move";
            ui.Add(new CuiLabel {
                Text = {
                    Text = $"Step: {step:0.###}", FontSize = 12, Align = TextAnchor.MiddleLeft, Color = "1 1 1 1"
                }
                , RectTransform = {
                    AnchorMin = "0.03 0.58", AnchorMax = "0.20 0.74"
                }
            }
            , root);
            AddBtn(ui, "–", "movepanel stepdec", "0.21 0.60", "0.26 0.72", 16, "0.6 0.6 0.6 1", root);
            AddBtn(ui, "+", "movepanel stepinc", "0.27 0.60", "0.32 0.72", 16, "0.6 0.6 0.6 1", root);
            AddBtn(ui, modeText, "movepanel modetoggle", "0.33 0.60", "0.60 0.72", 12, "0.35 0.55 0.9 1", root);
            AddBtn(ui, "Reset", "movepanel reset", "0.03 0.40", "0.19 0.56", 12, "0.5 0.5 0.5 1", root);
            AddBtn(ui, "Center", "movepanel center", "0.21 0.40", "0.37 0.56", 12, "0.5 0.5 0.5 1", root);
            AddBtn(ui, "SizeReset", "movepanel sizereset", "0.39 0.40", "0.57 0.56", 12, "0.5 0.5 0.5 1", root);
            AddBtn(ui, "↑", "movepanel up", "0.73 0.58", "0.81 0.74", 18, "0.85 0.85 0.85 1", root);
            AddBtn(ui, "←", "movepanel left", "0.64 0.42", "0.72 0.58", 18, "0.85 0.85 0.85 1", root);
            AddBtn(ui, "→", "movepanel right", "0.82 0.42", "0.90 0.58", 18, "0.85 0.85 0.85 1", root);
            AddBtn(ui, "↓", "movepanel down", "0.73 0.26", "0.81 0.42", 18, "0.85 0.85 0.85 1", root);
            CuiHelper.AddUi(player, ui);
        }
        private void AddBtn(CuiElementContainer c, string text, string cmd, string min, string max, int font, string color, string parent) {
            c.Add(new CuiButton {
                Button = {
                    Command = cmd, Color = color
                }
                , RectTransform = {
                    AnchorMin = min, AnchorMax = max
                }
                , Text = {
                    Text = text, FontSize = font, Align = TextAnchor.MiddleCenter
                }
            }
            , parent);
        }
        private void DestroyMovementPanel(BasePlayer player) => CuiHelper.DestroyUi(player, movePanelName);
        [ConsoleCommand("movepanel")]
        private void cmdMovePanel(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, "plugininfo.move")) return;
            var a = arg.Args;
            if (a == null || a.Length == 0) {
                ShowMovementPanel(player);
                return;
            }
            if (!playerOffsets.ContainsKey(player.userID)) playerOffsets[player.userID] = Vector2.zero;
            if (!playerScales.ContainsKey(player.userID)) playerScales[player.userID] = Vector2.one;
            if (!playerMoveStep.ContainsKey(player.userID)) playerMoveStep[player.userID] = (config?.MoveIncrement > 0 ? config.MoveIncrement : 0.005f);
            if (!playerSizeMode.ContainsKey(player.userID)) playerSizeMode[player.userID] = false;
            var offset = playerOffsets[player.userID];
            var scale = playerScales[player.userID];
            float step = Mathf.Max(0.0005f, playerMoveStep[player.userID]);
            bool sizeMode = playerSizeMode[player.userID];
            bool refreshUI = true;
            void SaveOffset(Vector2 o) {
                playerOffsets[player.userID] = o;
                SavePlayerOffsets();
                DestroyUI(player);
                CreateUI(player, GetCurrentMessage(), o);
            }
            void SaveScale(Vector2 s) {
                s.x = Mathf.Clamp(s.x, 0.25f, 3f);
                s.y = Mathf.Clamp(s.y, 0.25f, 3f);
                playerScales[player.userID] = s;
                SavePlayerScales();
                DestroyUI(player);
                CreateUI(player, GetCurrentMessage(), offset);
            }
            switch (a[0].ToString().ToLowerInvariant()) {
                case "up" : if (sizeMode) SaveScale(new Vector2(scale.x, scale.y + step));
                else SaveOffset(new Vector2(offset.x, offset.y + step));
                break;
                case "down" : if (sizeMode) SaveScale(new Vector2(scale.x, scale.y - step));
                else SaveOffset(new Vector2(offset.x, offset.y - step));
                break;
                case "left" : if (sizeMode) SaveScale(new Vector2(scale.x - step, scale.y));
                else SaveOffset(new Vector2(offset.x - step, offset.y));
                break;
                case "right" : if (sizeMode) SaveScale(new Vector2(scale.x + step, scale.y));
                else SaveOffset(new Vector2(offset.x + step, offset.y));
                break;
                case "stepinc" : playerMoveStep[player.userID] = Mathf.Min(step * 2f, 0.1f);
                break;
                case "stepdec" : playerMoveStep[player.userID] = Mathf.Max(step * 0.5f, 0.0005f);
                break;
                case "modetoggle" : playerSizeMode[player.userID] = !playerSizeMode[player.userID];
                break;
                case "reset" : offset = Vector2.zero;
                SaveOffset(offset);
                break;
                case "center" : Vector2 min, max;
                if (!TryParseAnchorPair(config.AnchorMin, out min)) min = new Vector2(0.345f, 0.110f);
                if (!TryParseAnchorPair(config.AnchorMax, out max)) max = new Vector2(0.64f, 0.150f);
                var size = max - min;
                var desiredMin = new Vector2(0.5f - size.x * 0.5f, 0.5f - size.y * 0.5f);
                offset = desiredMin - min;
                SaveOffset(offset);
                break;
                case "sizereset" : SaveScale(Vector2.one);
                break;
                case "close" : DestroyMovementPanel(player);
                refreshUI = false;
                break;
                default : break;
            }
            if (refreshUI) {
                DestroyMovementPanel(player);
                ShowMovementPanel(player);
            }
        }
        private void SavePlayerOffsets() => Interface.Oxide.DataFileSystem.WriteObject("PluginInfoOffsets", playerOffsets);
        private void LoadPlayerOffsets() => playerOffsets = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Vector2>>("PluginInfoOffsets") ?? new Dictionary<ulong, Vector2>();
        private void SavePlayerScales() => Interface.Oxide.DataFileSystem.WriteObject("PluginInfoScales", playerScales);
        private void LoadPlayerScales() => playerScales = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Vector2>>("PluginInfoScales") ?? new Dictionary<ulong, Vector2>();
    }
}

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