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

FREE FoundationDrop : 0.0.81 0.0.81

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

namespace Oxide.Plugins
{  
    [Info("Foundation Drop", "Server-rust.ru", "0.0.81")]
    public class FoundationDrop : RustPlugin
    {
        #region References

        [PluginReference] private Plugin Backpack;

        #endregion
        
        #region Classes

        private class Event
        {
            public double StartTime;
            public bool Started = false;
            public bool Finished = false;
            public int Received = 0;
            

            public Timer StartTimer;
            public Timer DestroyTimer;
            
            public Dictionary<ulong, Vector3> PlayerConnected = new Dictionary<ulong, Vector3>();
            public List<List<BaseEntity>> BlockList = new List<List<BaseEntity>>();
            public int EventHashID = 12;

            public void JoinEvent(BasePlayer player)
            {
                if (Started)
                {
                    SendMessage(player, $"Мероприятие уже началось, вы <color=#538fef>не успели</color>!");
                    return;
                }
                else
                {
                    if (PlayerConnected.ContainsKey(player.userID))
                    {
                        SendMessage(player, $"Вы уже участник мероприятия!");
                        return;
                    }
                    if (player.inventory.AllItems().Length != 0)
                    {
                        SendMessage(player, $"На мероприятие можно попасть только <color=#538fef><b>полностью голым</b></color>");
                        return;
                    }
                    
                    CuiHelper.DestroyUi(player, CONF_UI_MainLayer);
                    player.inventory.Strip();
                    player.SendNetworkUpdate();
                    
                    PlayerConnected.Add(player.userID, player.transform.position);
                    ClearTeleport(player, EventPosition + new Vector3(0, 5, 0));
                    player.SetPlayerFlag(BasePlayer.PlayerFlags.ChatMute, true);
                    
                    UI_DrawInfo(player);
                }
            }

            public void LeftEvent(BasePlayer player, bool external = false)
            {
                player.SetPlayerFlag(BasePlayer.PlayerFlags.ChatMute, false);
                player.inventory.Strip();
                player.StartSleeping();
                
                ClearTeleport(player, PlayerConnected[player.userID]);

                PlayerConnected.Remove(player.userID);
                if ((PlayerConnected.Count == 0 || Finished) && !external)
                {
                    if (Received < instance.config.CONF_MaxWinners)
                    {
                        SendMessage(player, $"Вы стали <b><color=#538fef>победителем</color></b> этого мероприятия!");
                        var finish = instance.config.RewardList.ToList().GetRandom();
                        
                        if (finish.Key.StartsWith("command"))
                        {
                            string workingPart = finish.Key.Split('+')[1];
                            instance.Server.Command(workingPart.Replace("%STEAMID%", player.UserIDString));
                        }
                        else if (finish.Key.StartsWith("item"))
                        {
                            string itemName = finish.Key.Split('+')[1];
                            int itemAmount = finish.Value;

                            Item prize = ItemManager.CreateByPartialName(itemName, itemAmount);
                            prize.MoveToContainer(player.inventory.containerMain);

                            player.Command("note.inv", new object[] {prize.info.itemid, prize.amount});
                            Received++;
                        }
                    }
                }
            }

            public void HandlePlayers()
            {
                if (Finished)
                    return;
                
                List<ulong> copyList = PlayerConnected.Keys.ToList();
                foreach (var check in copyList)
                {
                    BasePlayer target = BasePlayer.FindByID(check);
                    if (target == null)
                    {
                        PlayerConnected.Remove(check);
                    }
                    else
                    {
                        if (target.IsSwimming())
                            LeftEvent(target);
                    }
                }

                if (PlayerConnected.Count == 1)
                {
                    instance.StopEvent();
                    return;
                }

                StartTimer = instance.timer.Once(1, HandlePlayers);
            }

            public void StartEvent(int startDelay)
            {
                Interface.Oxide.LogWarning($"Foundation Drop announced!");
                BasePlayer.activePlayerList.ForEach(p => SendMessage(p, "Началась регистрация на мероприятие, нажмите на кнопку <b><color=#538fef>зарегистрироваться</color></b>"));
                StartTimer = instance.timer.Once(startDelay, () =>
                {
                    BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_MainLayer));
                    BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_SideLayer));
                    
                    List<ulong> removeKeys = new List<ulong>();
                    foreach (var check in PlayerConnected)
                    {
                        BasePlayer target = BasePlayer.FindByID(check.Key);
                        if (target != null)
                        {
                            CuiHelper.DestroyUi(target, CONF_UI_SideLayer);
                            continue;
                        }
                        else
                        {
                            removeKeys.Add(check.Key);
                        }
                    }

                    foreach (var check in removeKeys)
                        PlayerConnected.Remove(check);
                    
                    
                    if (PlayerConnected.Count <= 1)
                    {
                        instance.StopEvent(true);
                        return;
                    }
                    
                    BasePlayer.activePlayerList.ForEach(p =>
                    {
                        if (!PlayerConnected.ContainsKey(p.userID))
                            return;
                        
                        if (instance.config.CONF_GivePistol)
                        {
                            Item item = ItemManager.CreateByPartialName("pistol.m92", 1);
                            item.name = $"Опасное оружие";

                            item.GetHeldEntity().GetComponent<BaseProjectile>().primaryMagazine.capacity = instance.config.CONF_GivePistolAmount;
                            item.GetHeldEntity().GetComponent<BaseProjectile>().primaryMagazine.contents = instance.config.CONF_GivePistolAmount;
                        
                            item.MoveToContainer(p.inventory.containerBelt);
                        }
                    });
                    
                    instance.DropFoundation();
                    HandlePlayers();
                });
            }
            
            public void InitializeEvent(int startDelay)
            {
                Started = false;
                StartTime = CurrentTime() + startDelay;
                ServerMgr.Instance.StartCoroutine(instance.InitializeFoundation(startDelay));
            }

            public void FinishEvent(bool external = false)
            {
                Finished = true;

                StartTimer?.Destroy();
                DestroyTimer?.Destroy();
               
                BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_MainLayer));
                BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_SideLayer));
                BasePlayer.activePlayerList.ForEach(p => p.SetPlayerFlag(BasePlayer.PlayerFlags.ChatMute, false));
                var listPredicted = BasePlayer.activePlayerList.Where(p => cEvent.PlayerConnected.ContainsKey(p.userID));
                foreach (var check in listPredicted)
                    LeftEvent(check, external);
                
                foreach (var check in BlockList.SelectMany(p => p))
                    check?.Kill();

                string message = external ? "Мероприятие закончено по <b><color=#538fef>техническим причинам</color></b>!" : "Мероприятие окончено, всем <b><color=#538fef>спасибо</color></b> за участие!";
                BasePlayer.activePlayerList.ForEach(p => SendMessage(p, message)); 
            }
        }

        private class Configuration
        {
            [JsonProperty("Размер арены в квадратах")]
            public int CONF_ArenaSize = 10;
            [JsonProperty("Выдавать ли специальный пистолет для разрушения блоков")]
            public bool CONF_GivePistol = true;
            [JsonProperty("Количество патронов в пистолете")]
            public int CONF_GivePistolAmount = 1;
            [JsonProperty("Интвервал между удалениями блоков")]
            public float CONF_DelayDestroy = 0.1f;
            [JsonProperty("Время ожидания игроков с момента объявления ивента")]
            public int CONF_WaitTime = 30;
            [JsonProperty("Максимальное количество победителей")]
            public int CONF_MaxWinners = 1;
            
            [JsonProperty("Список наград (выбирается случайно)")]
            public Dictionary<string, int> RewardList;

            public static Configuration GetConfiguration()
            {
                return new Configuration()
                {
                    RewardList = new Dictionary<string, int>
                    {
                        ["item+rifle.ak"] = 1,
                        ["command+ownerid 76561190000000000"] = 1 
						/* 
						 * Пример: command+ownerid 76561190000000000 - Выдать права администратора
						 * Пример: command+oxide.grant user 76561190000000000 skin.box - Выдать права на использования команды /skin
						 *
						 */
                    }
                };
            }
        }

        #endregion
        
        #region Variables

        private Configuration config;
        
        #region System

        private static FoundationDrop instance;
        private static Vector3 EventPosition = new Vector3((float) World.Size/2, 10, (float) World.Size/2);
        private static Event cEvent = null;
        private static string CONF_UI_MainLayer = "UI_DF_Layer";
        private static string CONF_UI_SideLayer = "UI_DF_Layer";

        #endregion

        #endregion

        #region Initialization
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config?.RewardList == null) LoadDefaultConfig();
            }
            catch
            {
                PrintWarning($"Error reading config, creating one new config!");
                LoadDefaultConfig();
            }
            
            NextTick(SaveConfig);
        }

        protected override void LoadDefaultConfig()
        {
            config = Configuration.GetConfiguration();
        } 
        
        protected override void SaveConfig() => Config.WriteObject(config);
        
        private void OnServerInitialized()
        {
            instance = this;
        }

        private void Unload()
        {
            if (cEvent != null)
            {
                StopEvent(true);
            }
            
            BasePlayer.activePlayerList.ForEach(p => p.SetPlayerFlag(BasePlayer.PlayerFlags.ChatMute, false));
            
            foreach (var check in UnityEngine.Object.FindObjectsOfType<BaseEntity>().Where(p => p.name == "S23qRT").Where(p => !p.IsDestroyed))
                check?.Kill();
            
            BasePlayer.activePlayerList.ForEach(p =>
            {
                CuiHelper.DestroyUi(p, CONF_UI_MainLayer);
                CuiHelper.DestroyUi(p, CONF_UI_SideLayer);
            });
        }

        #endregion

        #region Hooks
        
        private object OnServerCommand(ConsoleSystem.Arg arg)
        {
            if (arg.cmd.FullName.ToLower().Contains("backpack.open") && arg.Player() != null && cEvent != null &&
                cEvent.PlayerConnected.ContainsKey(arg.Player().userID))
                return false;

            return null;
        }

        private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
        {
            if (entity is BasePlayer)
            {
                BasePlayer player = entity as BasePlayer;
                
                if (cEvent != null && cEvent.PlayerConnected.ContainsKey(player.userID))
                {
                    info.damageTypes.ScaleAll(0);
                    return false;
                }
            }

            return null;
        }

        private void OnPlayerDie(BasePlayer player)
        {
            if (cEvent != null && cEvent.PlayerConnected.ContainsKey(player.userID))
            {
                cEvent.LeftEvent(player);
                return;
            }
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (cEvent != null && cEvent.PlayerConnected.ContainsKey(player.userID))
            {
                cEvent.LeftEvent(player);
                return;
            }
        }

        #endregion

        #region Commands

        [ConsoleCommand("UI_FE_Handler")]
        private void cmdConsoleHandler(ConsoleSystem.Arg args)
        {
            if (cEvent == null)
                return;
            
            if (args.HasArgs(1))
            {
                if (args.Args[0] == "join" && !cEvent.PlayerConnected.ContainsKey(args.Player().userID))
                {
                    cEvent.JoinEvent(args.Player());
                }
            }
        }
        
        [ConsoleCommand("fe.start")]
        private void cmdStartEvent(ConsoleSystem.Arg args)
        {
            if (args.Player() != null)
                return;

            StartEvent();
        }

        [ConsoleCommand("fe.stop")]
        private void cmdStopEvent(ConsoleSystem.Arg args)
        {                                             
            if (args.Player() != null)
                return;
            
            StopEvent(true);
        }

        #endregion
        
        #region Functions

        private static void SendMessage(BasePlayer player, string text)
        {
            player.ChatMessage($"<size=16>Мероприятие '<color=#538fef>падающие платформы</color>'</size>\n{text}");
        }

        private static void ClearTeleport(BasePlayer player, Vector3 position)
        {
            if (player.net?.connection != null)
            {
                player.ClientRPCPlayer(null, player, "StartLoading");
            }
            player.StartSleeping();
            player.MovePosition(position);
            
            if (player.net?.connection != null)
            {
                player.ClientRPCPlayer(null, player, "ForcePositionTo", position);
                player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            }
            
            player.UpdateNetworkGroup();
            player.SendNetworkUpdateImmediate(false);
            if (player.net?.connection == null)
            {
                return;
            }
            player.SendFullSnapshot();
        }

        private void StartEvent()
        {
            if (cEvent != null)
            {
                PrintError("Попытка начать новое мероприятие, пока не закончено предыдущее!");
                return;
            }
            else
            {
                cEvent = new Event();
                cEvent.InitializeEvent(instance.config.CONF_WaitTime);
            }
        }

        private void StopEvent(bool external = false)
        {
            if (cEvent == null)
            {
                PrintError("Попытка отключить несуществующий ивент!");
                return;
            }
            else
            {
                BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_MainLayer));
                BasePlayer.activePlayerList.ForEach(p => CuiHelper.DestroyUi(p, CONF_UI_SideLayer));
                BasePlayer.activePlayerList.ForEach(p => p.SetPlayerFlag(BasePlayer.PlayerFlags.ChatMute, false));
                cEvent.FinishEvent(external);
                cEvent = null;
            }
        }

        private IEnumerator InitializeFoundation(int startDelay)
        {
            for (int i = -instance.config.CONF_ArenaSize / 2; i < instance.config.CONF_ArenaSize / 2; i++)
            {
                for (int t = -instance.config.CONF_ArenaSize / 2; t < instance.config.CONF_ArenaSize / 2; t++)
                {
                    cEvent.BlockList.Add(new List<BaseEntity>());
                    for (int grade = 4; grade > 0; grade--)
                    {
                        var newFoundation = GameManager.server.CreateEntity("assets/prefabs/building core/foundation/foundation.prefab", EventPosition + new Vector3(i * 3, grade * 1f, t * 3));
                        newFoundation.Spawn();
						newFoundation.name = "S23qRT";
                        
                        newFoundation.GetComponent<BuildingBlock>().SetGrade((BuildingGrade.Enum) grade);
                        cEvent.BlockList.Last().Add(newFoundation);
                        yield return i;
                    }
                }
            }
            cEvent.StartEvent(startDelay);

            foreach (var check in BasePlayer.activePlayerList)
            {
                UI_DrawInvite(check);
            }
        }

        private void DropFoundation()
        {
            if (cEvent.Finished)
            {
                return;
            }
            
            if (cEvent.BlockList.Count == 0)
            {
                StopEvent();
                return;
            }
            var cStack = cEvent.BlockList.GetRandom();
            if (cStack.Count == 0)
            {
                cEvent.BlockList.Remove(cStack);
                DropFoundation();
                return;
            }

            var cBlock = cStack.First();
            if (cBlock == null || cBlock.IsDestroyed)
            {
                cStack.RemoveAt(0);
                DropFoundation();
                return;
            }
            
            cStack.RemoveAt(0);
            cBlock.Kill();

            cEvent.DestroyTimer = timer.Once(instance.config.CONF_DelayDestroy, DropFoundation);
        }

        #endregion

        #region Interface
        
        private static void UI_DrawInfo(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, CONF_UI_SideLayer);
            CuiElementContainer container = new CuiElementContainer();
            
            container.Add(new CuiElement
            {
                Parent = "Overlay",
                Name = CONF_UI_SideLayer,
                Components =
                {
                    new CuiRawImageComponent()  { FadeIn = 0.3f, Sprite = "assets/content/ui/ui.background.tiletex.psd", Material = "assets/content/ui/uibackgroundblur.mat", Color = "0 0 0 0.9" },
                    new CuiRectTransformComponent  { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"},
                }        
            });

            string text = $"<size=35><b><color=#538fefFF>ОЖИДАНИЕ НАЧАЛА ИГРЫ</color></b></size>\n" +
                          $"\n" +
                          $"<size=18>Главная задача мероприятия - выжить последним, либо уцелеть на последнем блоке\n" +
                          $"После начала игры блоки начнут разрушаться один за другим, если вы упадёте в воду - вы проиграете</size>";
            
            if (instance.config.CONF_GivePistol)
                text += "\n\n\n<size=16>После начала игры вы также получите пистолет с одним патроном, благодаря ему вы сможете разрушить одну\n" +
                        "платформу под ногами противника, советуем не тратить её в самом начале!</size>";
            
            container.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                Text = { FadeIn = 0.3f, Text = text, Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter }
            }, CONF_UI_SideLayer);
            
            CuiHelper.AddUi(player, container);
            UI_DrawLeftTime(player);
        }

        private static void UI_DrawLeftTime(BasePlayer player)
        {
            if (cEvent == null || !cEvent.PlayerConnected.ContainsKey(player.userID))
            {
                CuiHelper.DestroyUi(player, CONF_UI_SideLayer);
            }
            else
            {
                CuiHelper.DestroyUi(player, CONF_UI_SideLayer + ".LeftTime");
            }
            
            CuiElementContainer container = new CuiElementContainer();

            int leftTime = (int) (cEvent.StartTime - CurrentTime());
            
            container.Add(new CuiButton
            {
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 0.3" },
                Button = { Color = "0 0 0 0" },
                Text = { Text = leftTime.ToString(), Align = TextAnchor.MiddleCenter, FontSize = 25, Font = "robotocondensed-bold.ttf" }
            }, CONF_UI_SideLayer, CONF_UI_SideLayer + ".LeftTime");

            CuiHelper.AddUi(player, container);

            if (leftTime != 1)
            {
                instance.timer.Once(1, () => UI_DrawLeftTime(player));
            }
        }

        private void UI_DrawInvite(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, CONF_UI_MainLayer);
            CuiElementContainer container = new CuiElementContainer();

            container.Add(new CuiPanel
            {
                CursorEnabled = false,
                RectTransform = { AnchorMin = "0.9994791 0.7222223", AnchorMax = "0.9994791 0.7222223", OffsetMin = "-244.6 -82" },
                Image = { Color = "0 0 0 0" }
            }, "Overlay", CONF_UI_MainLayer);
            
            container.Add(new CuiElement
            {
                Parent = CONF_UI_MainLayer,
                Components =
                {
                    new CuiImageComponent { FadeIn = 0.3f, Color = HexToRustFormat("#605F5332") },
                    new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0" }
                }
            });

            container.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0 0.6422766", AnchorMax = "1 1", OffsetMax = "0 0" },
                Text = { FadeIn = 0.3f, Text = $"ПАДАЮЩИЕ ПЛАТФОРМЫ", Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter, FontSize = 15 }
            }, CONF_UI_MainLayer);

            container.Add(new CuiLabel
            {
                RectTransform = { AnchorMin = "0.005 0.1707318", AnchorMax = "0.995 0.8943092", OffsetMax = "0 0" },
                Text = { FadeIn = 0.3f, Text = $"Началась регистрация на мероприятие, чтобы принять участие вы должны быть голыми", Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter, FontSize = 11 }
            }, CONF_UI_MainLayer);

            container.Add(new CuiButton
            {
                RectTransform = { AnchorMin = "0.01226182 0.02845511", AnchorMax = "0.9854766 0.3414635", OffsetMax = "0 0" },
                Button = { Color = HexToRustFormat("#7C7C7C6E"), Command = "UI_FE_Handler join" },
                Text = { Text = "ЗАРЕГИСТРИРОВАТЬСЯ", Font = "robotocondensed-bold.ttf", Align = TextAnchor.MiddleCenter, FontSize = 16 }
            }, CONF_UI_MainLayer);

            CuiHelper.AddUi(player, container);
        }

        #endregion

        #region Utils

        private static string HexToRustFormat(string hex)
        {
            if (string.IsNullOrEmpty(hex))
            {
                hex = "#FFFFFFFF";
            }

            var str = hex.Trim('#');

            if (str.Length == 6)
                str += "FF";

            if (str.Length != 8)
            {
                throw new Exception(hex);
                throw new InvalidOperationException("Cannot convert a wrong format.");
            }

            var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
            var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
            var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
            var a = byte.Parse(str.Substring(6, 2), NumberStyles.HexNumber);

            Color color = new Color32(r, g, b, a);

            return string.Format("{0:F2} {1:F2} {2:F2} {3:F2}", color.r, color.g, color.b, color.a);
        }
        
        static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
        static double CurrentTime() => DateTime.UtcNow.Subtract(epoch).TotalSeconds;
        
        private void GetConfig<T>(string menu, string key, ref T varObject)
        {
            if (Config[menu, key] != null)
            {
                varObject = Config.ConvertValue<T>(Config[menu, key]);
            }
            else
            {
                Config[menu, key] = varObject;
            }
        }
		
        #endregion
        
    }
}

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