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

FREE MBKits : 1.0.0 1.0.0

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



namespace Oxide.Plugins
{
    [Info("MBKits", "Barry_Allenn", "1.0.0")]
    [Description("MBKits")]
    public class MBKits : RustPlugin
    {
        [PluginReference] private Plugin ImageLibrary, MBMainMenu;
        

        private ImageUI imageUI = new ImageUI();

        private Dictionary<string, KitData> kits = new();
        private Dictionary<string, string> kitContainerNames = new();

        private Dictionary<ulong, List<ChatErrorEntry>> playerErrors = new();


        private string kitsFile => $"{Name}/kits";

        private Dictionary<ulong, Dictionary<string, double>> kitCooldowns = new();
        private string cooldownFile => $"{Name}/cooldowns";

        private class KitData
        {
            public string Name;
            public string ImageUrl = "https://i.postimg.cc/tJrNqhNX/42808.png";
            public string Permission = "";
            public string CooldownText = "1h"; // Строка вида "1h30m" вместо числа
            public List<ItemData> Items = new();
        }

        private class ItemData
        {
            public string ShortName;
            public int Amount;
            public ulong SkinID = 0;         // ← используем только это
            public int AmmoAmount;
            public string Container; // "main", "belt", "wear"
        }

        private class ChatErrorEntry
        {
            public string Text;
            public string ImageKey;
            public DateTime Timestamp;
        }


        private double GetCooldownSeconds(string text)
        {
            if (TryParseTime(text.ToLower(), out var ts))
                return ts.TotalSeconds;

            return 0;
        }

        private static bool TryParseTime(string input, out TimeSpan result)
        {
            int d = 0, h = 0, m = 0, s = 0;
            Match matchD = Regex.Match(input, @"(\d+?)d");
            Match matchH = Regex.Match(input, @"(\d+?)h");
            Match matchM = Regex.Match(input, @"(\d+?)m");
            Match matchS = Regex.Match(input, @"(\d+?)s");

            if (matchD.Success) d = int.Parse(matchD.Groups[1].Value);
            if (matchH.Success) h = int.Parse(matchH.Groups[1].Value);
            if (matchM.Success) m = int.Parse(matchM.Groups[1].Value);
            if (matchS.Success) s = int.Parse(matchS.Groups[1].Value);

            if (!matchD.Success && !matchH.Success && !matchM.Success && !matchS.Success)
            {
                result = TimeSpan.Zero;
                return false;
            }

            result = new TimeSpan(d, h, m, s);
            return true;
        }

        private void LoadKits()
        {
            kits = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<string, KitData>>(kitsFile) ?? new();
        }

        private void SaveKits()
        {
            Interface.Oxide.DataFileSystem.WriteObject(kitsFile, kits);
        }

        private void LoadCooldowns()
        {
            kitCooldowns = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Dictionary<string, double>>>(cooldownFile) ?? new();
        }

        private void SaveCooldowns()
        {
            Interface.Oxide.DataFileSystem.WriteObject(cooldownFile, kitCooldowns);
        }

        void Init()
        {
            LoadKits();
            LoadCooldowns();
            permission.RegisterPermission("mbkits.admin", this); // ← один общий
        }

        private void OnServerInitialized()
        {
            imageUI = new ImageUI();
            imageUI.DownloadImages();

            ImageLibrary.Call("AddImage", "https://i.postimg.cc/8cN7k8kD/Group-4.png", "error_icon_invalid_kits");
            ImageLibrary.Call("AddImage", "https://i.postimg.cc/GpRw5bXc/Group-1-3.png", "success_icon_kits");

            foreach (var kit in kits.Values)
            {
                if (!string.IsNullOrEmpty(kit.ImageUrl) &&
                    (kit.ImageUrl.StartsWith("http://") || kit.ImageUrl.StartsWith("https://")))
                {
                    ImageLibrary?.Call("AddImage", kit.ImageUrl, kit.ImageUrl);
                }

                // Регистрируем permission, если нужно
                if (!string.IsNullOrEmpty(kit.Permission) && !permission.PermissionExists(kit.Permission))
                {
                    permission.RegisterPermission(kit.Permission, this);
                }
            }
        }

        void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
            {
                CuiHelper.DestroyUi(player, "MBKits_UI");
                CuiHelper.DestroyUi(player, "MBKits_Inv_UI");
            }

            imageUI?.UnloadImages();
        }

        private void OnPlayerConnected(BasePlayer player)
        {

            ShowIntroImage(player); // ← Добавлено
        }
        
        private void ShowIntroImage(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "MBKits_IntroUI");

            var container = new CuiElementContainer();

            string imageId = imageUI?.GetImage("MBWelcome_Four_Os");
            if (string.IsNullOrEmpty(imageId))
            {
                PrintWarning("[MBKits] Intro image not loaded");
                return;
            }

            container.Add(new CuiElement
            {
                Name = "MBKits_IntroUI",
                Parent = "Overlay",
                Components =
        {
            new CuiRawImageComponent
            {
                Png = imageId,
                Color = "1 1 1 0", // полная непрозрачность картинки
                Sprite = "assets/content/textures/generic/fulltransparent.tga"
            },
            new CuiRectTransformComponent
            {
                AnchorMin = "0 0",
                AnchorMax = "1 0.5"
            }
        }
            });

            CuiHelper.AddUi(player, container);

            timer.Once(0.5f, () =>
            {
                CuiHelper.DestroyUi(player, "MBKits_IntroUI");
            });
        }

        #region MBKitsUI

        [HookMethod("OpenMBKitsForPlayer")]
        private void ShowKitsUI(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "MBKits_UI");

            var container = new CuiElementContainer();

            string root = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                CursorEnabled = true
            }, "Overlay", "MBKits_UI");

            string backgroundPanel = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0.7", Material = "assets/content/ui/uibackgroundblur.mat" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                CursorEnabled = true
            }, root);

            string imageId = imageUI?.GetImage("MBWelcome_Four_Os");
            if (!string.IsNullOrEmpty(imageId))
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = root,
                    Components =
                    {
                        new CuiRawImageComponent { Png = imageId },
                        new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-558 -314", OffsetMax = "558 315" }
                    }
                });
            }

            // Добавляем кнопку закрытия UI
            container.Add(new CuiButton
            {
                Button = { Color = "0 0 0 0", Close = "MBKits_UI" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                Text = { Text = "", FontSize = 0 }
            }, root);

            string centerPanel = container.Add(new CuiPanel
            {
                Image = { Color = "0.1 0.1 0.1 0" },
                RectTransform = {
                    AnchorMin = "0.5 0.5",
                    AnchorMax = "0.5 0.5",
                    OffsetMin = "-438 -265", // ширина 800, высота 600
                    OffsetMax = "440 265"
                },
                CursorEnabled = true
            }, root);

            container.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0.341 0.86", AnchorMax = "0.75 0.955" },
                Text = { Text = Msg("MB_Kits_Player", player.userID.ToString()), Color = "1 1 1 0.9", Align = TextAnchor.MiddleLeft, FontSize = 30 }
            }, centerPanel);

            container.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0.341 0.8", AnchorMax = "0.9 0.868" },
                Text = { Text = Msg("MB_Kits_Player_2", player.userID.ToString()), Color = "1 1 1 0.9", Align = TextAnchor.MiddleLeft, FontSize = 21, Font = "permanentmarker.ttf" }
            }, centerPanel);

            container.Add(new CuiLabel
            {
                Text = { Text = Msg("MB_Close_Kits", player.userID.ToString()), FontSize = 13, Color = "1 1 1 0.4", Align = TextAnchor.MiddleCenter },
                RectTransform = { AnchorMin = "0.2 -0.06", AnchorMax = "0.8 -0.02" }
            }, centerPanel);

            container.Add(new CuiButton
            {
                Button = {
                    Command = "mbkits.back",  // кастомная команда
                    Color = "0.2 0.5 0.8 0"
                },
                RectTransform = { AnchorMin = "0.865 0.04", AnchorMax = "0.947 0.12" },
                Text = {
                    Text = Msg("MB_Back", player.UserIDString),
                    FontSize = 15,
                    Align = TextAnchor.MiddleCenter,
                    Color = "1 1 1 1"
                }
            }, centerPanel);

            // Прокрутка
            float blockHeight = 242f;
            float blockMargin = 8f;
            float verticalShift = 3f;

            var kitList = kits.Values.ToList();
            int total = kitList.Count;
            int rowCount = Mathf.CeilToInt(total / 3f);
            float totalHeight = rowCount * (blockHeight + blockMargin);
            float minVisibleHeight = 300f;
            float scrollContentHeight = Mathf.Max(totalHeight, minVisibleHeight);

            container.Add(new CuiElement
            {
                Name = "MBMenuScrollableKits",
                Parent = centerPanel,
                Components =
                {
                    new CuiScrollViewComponent
                    {
                        Vertical = true,
                        Horizontal = false,
                        Inertia = true,
                        Elasticity = 0.2f,
                        DecelerationRate = 0.2f,
                        ScrollSensitivity = 30f,
                        ContentTransform = new CuiRectTransform
                        {
                            AnchorMin = "0 1",
                            AnchorMax = "1 1",
                            OffsetMin = $"0 -{scrollContentHeight}",
                            OffsetMax = "0 0"
                        },
                        VerticalScrollbar = new CuiScrollbar
                        {
                            Size = 4f,
                            AutoHide = false,
                            HandleColor = "0.3 0.6 0.9 0.7",
                            TrackColor = "0.1 0.1 0.1 0.6"
                        }
                    },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0.34 0.285",
                        AnchorMax = "0.96 0.75"
                    },
                    new CuiNeedsCursorComponent()
                }
            });

            container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform =
                {
                    AnchorMin = "0 1",
                    AnchorMax = "1 1",
                    OffsetMin = $"0 -{scrollContentHeight}",
                    OffsetMax = "0 0"
                }
            }, "MBMenuScrollableKits", "MBMenuKitsContent");

            // Отображаем наборы
            for (int i = 0; i < total; i++)
            {
                var kit = kitList[i];

                int row = i / 3;
                int col = i % 3;

                float topOffset = -(row * (blockHeight + blockMargin)) - verticalShift;
                float bottomOffset = topOffset - blockHeight;

                float left = col switch
                {
                    0 => 0f,
                    1 => 0.333f,
                    2 => 0.666f,
                    _ => 0f
                };
                float right = col == 2 ? left + 0.31f : left + 0.32f;

                string bgImg = imageUI.GetImage("MBKitsBG_Default");
                string containerName = $"KitContainer_{i}";
                kitContainerNames[kit.Name.ToLower()] = containerName;


                container.Add(new CuiPanel
                {
                    Image = { Color = "0 0 0 0" },
                    RectTransform =
                    {
                        AnchorMin = $"{left} 1",
                        AnchorMax = $"{right} 1",
                        OffsetMin = $"0 {bottomOffset}",
                        OffsetMax = $"0 {topOffset}"
                    }
                }, "MBMenuKitsContent", containerName);

                // Фон
                if (!string.IsNullOrEmpty(bgImg))
                {
                    container.Add(new CuiElement
                    {
                        Name = $"KitBG_{i}",
                        Parent = containerName,
                        Components =
                        {
                            new CuiRawImageComponent
                            {
                                Png = bgImg,
                                Sprite = "assets/content/textures/generic/fulltransparent.tga"
                            },
                            new CuiRectTransformComponent
                            {
                                AnchorMin = "0 0",
                                AnchorMax = "1 1"
                            }
                        }
                    });
                }

                string kitImg = (string)ImageLibrary.Call("GetImage", kit.ImageUrl);
                if (!string.IsNullOrEmpty(kitImg))
                {
                    container.Add(new CuiElement
                    {
                        Parent = containerName,
                        Components =
                        {
                            new CuiRawImageComponent
                            {
                                Png = kitImg,
                                Sprite = "assets/content/textures/generic/fulltransparent.tga"
                            },
                            new CuiRectTransformComponent
                            {
                                AnchorMin = "0.1 0.2",
                                AnchorMax = "0.9 0.8"
                            }
                        }
                    });
                }

                // Название набора
                container.Add(new CuiLabel
                {
                    Text =
                    {
                        Text = kit.Name.ToUpper(),
                        FontSize = 17,
                        Align = TextAnchor.MiddleCenter,
                        Color = "1 1 1 0.9"
                    },
                    RectTransform = { AnchorMin = "0.05 0.85", AnchorMax = "0.95 0.98" }
                }, containerName);

                bool hasPermission = string.IsNullOrEmpty(kit.Permission) || permission.UserHasPermission(player.UserIDString, kit.Permission);

                double cooldownUntil = 0;
                bool isOnCooldown = kitCooldowns.TryGetValue(player.userID, out var cooldowns) &&
                    cooldowns.TryGetValue(kit.Name.ToLower(), out cooldownUntil) &&
                    cooldownUntil > Facepunch.Math.Epoch.Current;


                if (!hasPermission)
                {
                    // Нет прав — серая неактивная кнопка
                    container.Add(new CuiButton
                    {
                        Button = { Color = "0.3 0.3 0.3 0" }, // тёмно-серая
                        RectTransform = { AnchorMin = "0.05 0.04", AnchorMax = "0.72 0.18" },
                        Text = {
                            Text = Msg("MB_NoAccess", player.UserIDString),
                            FontSize = 14,
                            Align = TextAnchor.MiddleCenter,
                            Color = "0.8 0.8 0.8 1" // светло-серый текст
                        }
                    }, containerName);
                }
                else if (isOnCooldown)
                {
                    double timeLeft = cooldownUntil - Facepunch.Math.Epoch.Current;
                    if (timeLeft < 0) timeLeft = 0;
                    TimeSpan ts = TimeSpan.FromSeconds(timeLeft);
                    string cooldownText = string.Format("{0:D2}h {1:D2}m", ts.Hours, ts.Minutes);


                    // Кулдаун — жёлтая неактивная кнопка
                    container.Add(new CuiButton
                    {
                        Button = { Color = "0.8 0.6 0.1 0" }, // жёлтый фон
                        RectTransform = { AnchorMin = "0.05 0.04", AnchorMax = "0.72 0.18" },
                        Text = {
                            Text = cooldownText,
                            FontSize = 14,
                            Align = TextAnchor.MiddleCenter,
                            Color = "1 0.4 0.4 1"
                        }
                    }, containerName);
                }
                else
                {
                    // Кнопка "ПОЛУЧИТЬ"
                    container.Add(new CuiButton
                    {
                        Button =
                        {
                            Color = "0.2 0.6 0.2 0",
                            Command = $"mbkits.givekit {kit.Name}"
                        },
                        RectTransform = { AnchorMin = "0.05 0.04", AnchorMax = "0.72 0.18" },
                        Text =
                        {
                            Text = Msg("MB_Claim", player.UserIDString),
                            FontSize = 14,
                            Align = TextAnchor.MiddleCenter,
                            Color = "1 1 1 1"
                        }
                    }, containerName, $"KitButton_{kit.Name}");
                }

                // Кнопка "ПРОСМОТР"
                container.Add(new CuiButton
                {
                    Button =
                    {
                        Color = "0.2 0.2 0.8 0",
                        Command = $"mbkits.viewkit {kit.Name}"
                    },
                    RectTransform = { AnchorMin = "0.75 0.04", AnchorMax = "0.948 0.18" },
                }, containerName);

            }

            CuiHelper.AddUi(player, container);
        }
        #endregion

        #region MBKitsInvUI

        private void ShowKitsInvUI(BasePlayer player, KitData kit)
        {
            CuiHelper.DestroyUi(player, "MBKits_Inv_UI");
            CuiHelper.DestroyUi(player, "MBKits_UI");

            var container = new CuiElementContainer();

            string root = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                CursorEnabled = true
            }, "Overlay", "MBKits_Inv_UI");

            string backgroundPanel = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0.7", Material = "assets/content/ui/uibackgroundblur.mat" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                CursorEnabled = true
            }, root);

            // Картинка фону
            string imageId = imageUI?.GetImage("MBKits_inv");
            if (!string.IsNullOrEmpty(imageId))
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = root,
                    Components =
                    {
                        new CuiRawImageComponent { Png = imageId },
                        new CuiRectTransformComponent { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-558 -314", OffsetMax = "558 315" }
                    }
                });
            }

            // Закриття
            container.Add(new CuiButton
            {
                Button = { Color = "0 0 0 0", Close = "MBKits_Inv_UI" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                Text = { Text = "", FontSize = 0 }
            }, root);

            string centerPanel = container.Add(new CuiPanel
            {
                Image = { Color = "0.1 0.1 0.1 0" },
                RectTransform = {
                    AnchorMin = "0.5 0.5",
                    AnchorMax = "0.5 0.5",
                    OffsetMin = "-438 -265",
                    OffsetMax = "440 265"
                },
                CursorEnabled = true
            }, root);

            container.Add(new CuiLabel
            {
                Text = { Text = Msg("MB_Close_Kits", player.userID.ToString()), FontSize = 13, Color = "1 1 1 0.4", Align = TextAnchor.MiddleCenter },
                RectTransform = { AnchorMin = "0.2 -0.06", AnchorMax = "0.8 -0.02" }
            }, centerPanel);

            container.Add(new CuiButton
            {
                Button = {
                    Command = "mbkits_inv.back",  // кастомная команда
                    Color = "0.2 0.5 0.8 0"
                },
                RectTransform = { AnchorMin = "0.865 0.04", AnchorMax = "0.947 0.12" },
                Text = {
                    Text = Msg("MB_Back", player.UserIDString),
                    FontSize = 15,
                    Align = TextAnchor.MiddleCenter,
                    Color = "1 1 1 1"
                }
            }, centerPanel);

            // Название
            container.Add(new CuiLabel
            {
                Text = {
                    Text = $"{kit.Name.ToUpper()}",
                    FontSize = 15,
                    Align = TextAnchor.MiddleCenter,
                    Color = "1 1 1 0.9"
                },
                RectTransform = { AnchorMin = "0.411 0.8411", AnchorMax = "0.5345 0.897" }
            }, centerPanel);

            // Получаем локализованные строки через Msg
            string textPrefix = Msg("CooldownPrefix", player.UserIDString);
            string textPrefix_2 = Msg("CooldownPrefix_2", player.UserIDString);
            string textH = Msg("TimeHours", player.UserIDString);
            string textM = Msg("TimeMinutes", player.UserIDString);
            string textS = Msg("TimeSeconds", player.UserIDString);

            // Форматирование: всегда H M S, даже если 0
            string FormatCooldown(TimeSpan time)
            {
                return $"{(int)time.TotalHours}{textH} {(int)time.Minutes}{textM} {(int)time.Seconds}{textS}";
            }



            // Проверка кулдауна
            double cooldownUntil = 0;
            bool isOnCooldown = kitCooldowns.TryGetValue(player.userID, out var cooldowns) &&
                cooldowns.TryGetValue(kit.Name.ToLower(), out cooldownUntil) &&
                cooldownUntil > Facepunch.Math.Epoch.Current;

            string cooldownText;

            if (isOnCooldown)
            {
                double remaining = cooldownUntil - Facepunch.Math.Epoch.Current;

                if (remaining < 0) remaining = 0;
                TimeSpan remainingTime = TimeSpan.FromSeconds(remaining);
                cooldownText = $"{textPrefix}: {FormatCooldown(remainingTime)}";
            }
            else
            {
                TimeSpan fullTime = TimeSpan.FromSeconds(GetCooldownSeconds(kit.CooldownText));
                cooldownText = $"{textPrefix_2}: {FormatCooldown(fullTime)}";

            }

            // Вывод в UI
            container.Add(new CuiLabel
            {
                Text = {
                    Text = cooldownText,
                    FontSize = 13,
                    Align = TextAnchor.MiddleLeft,
                    Color = isOnCooldown ? "1 0.4 0.4 1" : "1 1 1 0.7"
                },
                RectTransform = { AnchorMin = "0.547 0.8411", AnchorMax = "0.792 0.897" }
            }, centerPanel);

            // Слоты main — 6x4
            var main = kit.Items.Where(i => i.Container == "main").ToList();
            for (int i = 0; i < 24; i++)
            {
                int row = i / 6;
                int col = i % 6;

                float xMin = 0.412f + col * 0.0645f;
                float yMax = 0.827f - row * 0.1075f;
                float xMax = xMin + 0.0585f;
                float yMin = yMax - 0.0955f;

                AddItemSlot(container, centerPanel, $"Main_{i}", xMin, yMin, xMax, yMax, i < main.Count ? main[i] : null);
            }

            // Слоты wear — 7 ячеек
            var wear = kit.Items.Where(i => i.Container == "wear").ToList();
            for (int i = 0; i < 7; i++)
            {
                float xMin = 0.38f + i * 0.0645f;
                float yMin = 0.298f;
                float xMax = xMin + 0.0585f;
                float yMax = yMin + 0.0955f;

                AddItemSlot(container, centerPanel, $"Wear_{i}", xMin, yMin, xMax, yMax, i < wear.Count ? wear[i] : null);
            }

            // Слоты belt — 6 ячеек
            var belt = kit.Items.Where(i => i.Container == "belt").ToList();
            for (int i = 0; i < 6; i++)
            {
                float xMin = 0.412f + i * 0.0645f;
                float yMin = 0.187f;
                float xMax = xMin + 0.0585f;
                float yMax = yMin + 0.0955f;

                AddItemSlot(container, centerPanel, $"Belt_{i}", xMin, yMin, xMax, yMax, i < belt.Count ? belt[i] : null);
            }

            CuiHelper.AddUi(player, container);
        }


        #endregion

        private void AddErrorMessage(BasePlayer player, string text, string imageKey)
        {
            ulong id = player.userID;

            if (!playerErrors.ContainsKey(id))
                playerErrors[id] = new List<ChatErrorEntry>();

            var entry = new ChatErrorEntry
            {
                Text = text,
                ImageKey = imageKey,
                Timestamp = DateTime.UtcNow
            };

            playerErrors[id].Add(entry);

            if (playerErrors[id].Count > 5)
                playerErrors[id].RemoveAt(0);

            RedrawErrorUI(player);

            timer.Once(3f, () =>
            {
                if (playerErrors.TryGetValue(id, out var list) && list.Contains(entry))
                {
                    list.Remove(entry);
                    RedrawErrorUI(player);
                }
            });
        }

        private void RedrawErrorUI(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "MB_ErrorChatUI");

            if (!playerErrors.TryGetValue(player.userID, out var messages) || messages.Count == 0)
                return;

            var container = new CuiElementContainer();

            string parent = container.Add(new CuiPanel
            {
                Image = { Color = "0 0 0 0" },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "5 96", OffsetMax = "200 500" }
            }, "Overlay", "MB_ErrorChatUI");

            float blockHeight = 50f;
            float spacing = 5f;
            float yStart = 0f;

            for (int i = 0; i < messages.Count; i++)
            {
                var error = messages[messages.Count - 1 - i];
                float offsetY = yStart + i * (blockHeight + spacing);

                string panel = container.Add(new CuiPanel
                {
                    Image = { Color = "0 0 0 0" },
                    RectTransform = {
                        AnchorMin = "0 0",
                        AnchorMax = "1 0",
                        OffsetMin = $"0 {offsetY}",
                        OffsetMax = $"0 {offsetY + blockHeight}"
                    }
                }, parent);

                container.Add(new CuiElement
                {
                    Parent = panel,
                    Components =
                    {
                        new CuiRawImageComponent
                        {
                            Png = (string)ImageLibrary?.Call("GetImage", error.ImageKey),
                            Color = "1 1 1 1"
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = "0 0",
                            AnchorMax = "1 1",
                        }
                    }
                });

                string titleKey = error.ImageKey switch
                {
                    "success_icon_kits" => "SuccessTitle",
                    "error_icon_invalid_kits" => "ErrorTitle",
                    "error_icon_expired" => "ErrorTitle",
                    _ => "ErrorTitle"
                };

                string title = Msg(titleKey, player.UserIDString);

                container.Add(new CuiLabel
                {
                    RectTransform = { AnchorMin = "0.31 0.56", AnchorMax = "1 0.9" },
                    Text = {
                        Text = title,
                        Align = TextAnchor.MiddleLeft,
                        FontSize = 12,
                        Color = "1 1 1 0.9"
                    }
                }, panel);

                container.Add(new CuiLabel
                {
                    RectTransform = { AnchorMin = "0.31 0", AnchorMax = "0.98 0.54" },
                    Text = {
                        Text = error.Text,
                        Align = TextAnchor.UpperLeft,
                        FontSize = 9,
                        Color = "1 1 1 0.8"
                    }
                }, panel);
            }

            CuiHelper.AddUi(player, container);
        }

        #region Command

        // [ChatCommand("kit")]
        // private void CmdKits(BasePlayer player, string command, string[] args)
        // {
        //     ShowKitsUI(player);
        // }

        [ConsoleCommand("mbkits.viewkit")]
        private void CmdViewKit(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !arg.HasArgs()) return;

            string kitName = arg.Args[0].ToLower();
            if (!kits.TryGetValue(kitName, out var kit)) return;

            ShowKitsInvUI(player, kit);
        }


        [ConsoleCommand("mbkits.givekit")]
        private void CmdGiveKit(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player == null || !arg.HasArgs()) return;

            string kitName = arg.Args[0].ToLower();
            if (!kits.TryGetValue(kitName, out var kit))
                return;

            if (!string.IsNullOrEmpty(kit.Permission) && !permission.UserHasPermission(player.UserIDString, kit.Permission))
                return;

            // --- Проверка отката ---
            double now = Facepunch.Math.Epoch.Current;
            double cooldownUntil = 0;
            if (kitCooldowns.TryGetValue(player.userID, out var cooldowns))
            {
                cooldowns.TryGetValue(kitName, out cooldownUntil);
            }

            if (cooldownUntil > now)
            {
                double remaining = cooldownUntil - now;
                TimeSpan remainingTime = TimeSpan.FromSeconds(remaining);
                AddErrorMessage(player, string.Format(Msg("CooldownPrefix", player.UserIDString) + ": {0:D2}м {1:D2}с", remainingTime.Minutes, remainingTime.Seconds), "error_icon_expired");
                return;
            }

            // ✅ Проверка на заполненность до выдачи!
            if (!CanFitAllItems(player, kit))
            {
                AddErrorMessage(player, Msg("KitInventoryFull", player.UserIDString), "error_icon_invalid_kits");
                return;
            }

            // --- Выдача набора ---
            GiveKitToPlayer(player, kit);

            AddErrorMessage(player, Msg("KitSuccess", player.UserIDString), "success_icon_kits");

            // 🔊 Звук
            EffectNetwork.Send(new Effect("assets/prefabs/misc/xmas/presents/effects/unwrap.prefab", player, 0, Vector3.up, Vector3.zero)
            {
                scale = UnityEngine.Random.Range(0f, 1f)
            });

            // --- Запись нового времени ---
            if (!kitCooldowns.TryGetValue(player.userID, out cooldowns))
            {
                cooldowns = new Dictionary<string, double>();
                kitCooldowns[player.userID] = cooldowns;
            }

            double cooldownSec = GetCooldownSeconds(kit.CooldownText);
            cooldowns[kitName.ToLower()] = now + cooldownSec;
            SaveCooldowns();

            UpdateKitButton(player, kitName);
        }


        private void UpdateKitButton(BasePlayer player, string kitName)
        {

            var kit = kits[kitName];
            string containerName = kitContainerNames[kitName.ToLower()];

            CuiHelper.DestroyUi(player, $"KitButton_{kitName}");

            var container = new CuiElementContainer();

            double now = Facepunch.Math.Epoch.Current;
            double cooldownUntil = 0;
            bool isOnCooldown = kitCooldowns.TryGetValue(player.userID, out var cooldowns) &&
                cooldowns.TryGetValue(kitName.ToLower(), out cooldownUntil) &&
                cooldownUntil > now;

            if (isOnCooldown)
            {
                double remaining = cooldownUntil - now;
                if (remaining < 1) remaining = 1; // минимум 1 секунда, чтобы избежать 00:00

                TimeSpan ts = TimeSpan.FromSeconds(remaining);
                string cooldownText = FormatShortTime(ts, player); // Используем форматированный вывод

                container.Add(new CuiButton
                {
                    Button = { Color = "0.8 0.6 0.1 0" },
                    RectTransform = { AnchorMin = "0.05 0.04", AnchorMax = "0.72 0.18" },
                    Text = {
                        Text = cooldownText,
                        FontSize = 14,
                        Align = TextAnchor.MiddleCenter,
                        Color = "1 0.4 0.4 1"
                    }
                }, containerName, $"KitButton_{kitName}");
            }

            CuiHelper.AddUi(player, container);
        }

        [ConsoleCommand("mbkits.back")]
        private void CmdKitsBack(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection?.player as BasePlayer;
            if (player == null) return;

            CuiHelper.DestroyUi(player, "MBKits_UI");

            MBMainMenu?.Call("ShowMainMenu", player);
        }

        [ConsoleCommand("mbkits_inv.back")]
        private void CmdKitsBackInv(ConsoleSystem.Arg arg)
        {
            var player = arg.Connection?.player as BasePlayer;
            if (player == null) return;

            CuiHelper.DestroyUi(player, "MBKits_Inv_UI");
            ShowKitsUI(player);
        }



        [ChatCommand("kit")]
        private void CmdKit(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                ShowKitsUI(player);
                return;
            }

            switch (args[0].ToLower())
            {
                case "add":
                {
                    if (!permission.UserHasPermission(player.UserIDString, "mbkits.admin"))
                    {
                        player.ChatMessage(Msg("NoAdminPermission", player.UserIDString));
                        return;
                    }

                    if (args.Length < 2)
                    {
                        player.ChatMessage(Msg("KitAddUsage", player.UserIDString));
                        return;
                    }

                    string kitName = args[1].ToLower();
                    string permName = args.Length >= 3 ? args[2].ToLower() : $"mbkits.{kitName}";

                    if (!string.IsNullOrEmpty(permName) && !permission.PermissionExists(permName))
                        permission.RegisterPermission(permName, this);

                    var kit = new KitData
                    {
                        Name = kitName,
                        Permission = permName,
                        CooldownText = "1h"
                    };

                    foreach (var item in player.inventory.containerMain.itemList)
                    {
                        if (item == null) continue;
                        kit.Items.Add(CreateItemData(item, "main"));
                    }
                    foreach (var item in player.inventory.containerBelt.itemList)
                    {
                        if (item == null) continue;
                        kit.Items.Add(CreateItemData(item, "belt"));
                    }
                    foreach (var item in player.inventory.containerWear.itemList)
                    {
                        if (item == null) continue;
                        kit.Items.Add(CreateItemData(item, "wear"));
                    }

                    kits[kitName] = kit;
                    SaveKits();
                    player.ChatMessage(string.Format(Msg("KitAdded", player.UserIDString), kitName, permName));
                    break;
                }

                case "remove":
                {
                    if (!permission.UserHasPermission(player.UserIDString, "mbkits.admin"))
                    {
                        player.ChatMessage(Msg("NoAdminPermission", player.UserIDString));
                        return;
                    }

                    if (args.Length < 2)
                    {
                        player.ChatMessage(Msg("KitRemoveUsage", player.UserIDString));
                        return;
                    }

                    string kitName = args[1].ToLower();

                    if (!kits.Remove(kitName))
                    {
                        player.ChatMessage(string.Format(Msg("KitNotFound", player.UserIDString), kitName));
                        return;
                    }

                    int count = 0;
                    foreach (var entry in kitCooldowns)
                    {
                        if (entry.Value.Remove(kitName))
                            count++;
                    }

                    SaveKits();
                    SaveCooldowns();

                    player.ChatMessage(string.Format(Msg("KitRemoved", player.UserIDString), kitName, count));
                    break;
                }

                default:
                {
                    ShowKitsUI(player);
                    break;
                }
            }
        }



        #endregion
        
        private ItemData CreateItemData(Item item, string container)
        {
            return new ItemData
            {
                ShortName = item.info.shortname,
                Amount = item.amount,
                SkinID = item.skin, // сохраняем оригинальный SkinID
                AmmoAmount = item.contents?.itemList?.FirstOrDefault()?.amount ?? 0,
                Container = container
            };
        }

        private string FormatShortTime(TimeSpan time, BasePlayer player)
        {
            string result = "";
            if (time.Days > 0) result += $"{time.Days}{Msg("TimeDays", player.UserIDString)} ";
            if (time.Hours > 0) result += $"{time.Hours}{Msg("TimeHours", player.UserIDString)} ";
            if (time.Minutes > 0) result += $"{time.Minutes}{Msg("TimeMinutes", player.UserIDString)} ";
            if (time.Seconds > 0) result += $"{time.Seconds}{Msg("TimeSeconds", player.UserIDString)}";
            return result.Trim();
        }

        private bool CanFitAllItems(BasePlayer player, KitData kit)
        {
            int totalAvailable = player.inventory.containerMain.capacity - player.inventory.containerMain.itemList.Count
                            + player.inventory.containerBelt.capacity - player.inventory.containerBelt.itemList.Count
                            + player.inventory.containerWear.capacity - player.inventory.containerWear.itemList.Count;

            int totalItems = kit.Items.Count;

            return totalAvailable >= totalItems;
        }

        private void GiveKitToPlayer(BasePlayer player, KitData kit)
        {
            foreach (var entry in kit.Items)
            {
                var definition = ItemManager.FindItemDefinition(entry.ShortName);
                if (definition == null) continue;

                // Используем только SkinID
                var item = ItemManager.Create(definition, entry.Amount, entry.SkinID);
                if (item == null) continue;

                // Если это оружие с патронами
                if (item.contents != null && entry.AmmoAmount > 0)
                {
                    var ammoDef = ItemManager.FindItemDefinition("ammo.pistol");
                    if (ammoDef != null)
                    {
                        var ammo = ItemManager.Create(ammoDef, entry.AmmoAmount);
                        ammo?.MoveToContainer(item.contents);
                    }
                }

                // Куда положить предмет
                ItemContainer primary = entry.Container switch
                {
                    "belt" => player.inventory.containerBelt,
                    "wear" => player.inventory.containerWear,
                    _ => player.inventory.containerMain
                };

                // Альтернативы, если не влезло
                ItemContainer[] fallback =
                {
                    player.inventory.containerMain,
                    player.inventory.containerBelt,
                    player.inventory.containerWear
                };

                // Пытаемся положить в основную цель
                if (item.MoveToContainer(primary)) continue;

                // Пытаемся в альтернативные
                bool moved = false;
                foreach (var alt in fallback)
                {
                    if (alt == primary) continue;
                    if (item.MoveToContainer(alt))
                    {
                        moved = true;
                        break;
                    }
                }

            }
        }


        private void AddItemSlot(CuiElementContainer container, string parent, string name, float xMin, float yMin, float xMax, float yMax, ItemData item)
        {
            container.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = $"{xMin} {yMin}", AnchorMax = $"{xMax} {yMax}" },
                Image = { Color = "0 0 0 0" }
            }, parent, name);

            if (item == null) return;

            int itemId = ItemManager.FindItemDefinition(item.ShortName)?.itemid ?? 0;
            ulong skinId = item.SkinID;


            container.Add(new CuiElement
            {
                Parent = name,
                Components =
                {
                    new CuiImageComponent { ItemId = itemId, SkinId = skinId },
                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 0",
                        AnchorMax = "1 1",
                        OffsetMin = "4 4",
                        OffsetMax = "-4 -4"
                    }
                }
            });

            container.Add(new CuiLabel
            {
                Text = {
                    Text = $"x{item.Amount}",
                    FontSize = 10,
                    Align = TextAnchor.LowerRight,
                    Color = "1 1 1 0.7"
                },
                RectTransform = { AnchorMin = "0 0.05", AnchorMax = "0.9 1" }
            }, name);
        }

        #region ImageUI

        private class ImageUI
        {
            private const string PathFolder = "MBSystem/MBKits/Images/";
            private readonly Dictionary<string, ImageData> _images = new()
            {
                { "MBWelcome_Four_Os", new ImageData() },
                { "MBKitsBG_Default", new ImageData() },
                { "MBKits_inv", new ImageData() },

            };

            private enum ImageStatus { NotLoaded, Loaded, Failed }

            private class ImageData
            {
                public ImageStatus Status = ImageStatus.NotLoaded;
                public string Id { get; set; }
            }

            public string GetImage(string name)
            {
                if (_images.TryGetValue(name, out var image) && image.Status == ImageStatus.Loaded)
                    return image.Id;
                return null;
            }

            public void DownloadImages()
            {
                string fullPath = Interface.Oxide.DataDirectory + System.IO.Path.DirectorySeparatorChar + PathFolder;
                if (!System.IO.Directory.Exists(fullPath))
                {
                    System.IO.Directory.CreateDirectory(fullPath);
                    Interface.Oxide.LogInfo($"[MBKits] Создана папка: {fullPath}");
                }

                var nextImage = _images.FirstOrDefault(img => img.Value.Status == ImageStatus.NotLoaded);
                if (!string.IsNullOrEmpty(nextImage.Key))
                    ServerMgr.Instance.StartCoroutine(LoadImage(nextImage));
                else
                    Interface.Oxide.LogInfo("[MBKits] Все изображения загружены!");
            }

            private IEnumerator LoadImage(KeyValuePair<string, ImageData> image)
            {
                string filePath = "file://" + Interface.Oxide.DataDirectory + System.IO.Path.DirectorySeparatorChar + PathFolder + image.Key + ".png";
                using (var www = UnityEngine.Networking.UnityWebRequestTexture.GetTexture(filePath))
                {
                    yield return www.SendWebRequest();

                    if (www.result != UnityEngine.Networking.UnityWebRequest.Result.Success)
                    {
          
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху