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

FREE EventManager : 3.0.4 3.0.4

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Requires: EMInterface

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json.Linq;
using Rust;
using Network;

namespace Oxide.Plugins
{
    [Info("Event Manager", "Reneb / k1lly0u", "3.0.4", ResourceId = 740)]
    class EventManager : RustPlugin
    {
        #region Fields
        [PluginReference] EMInterface EMInterface;
        [PluginReference] Plugin Economics;
        [PluginReference] Plugin FriendlyFire;
        [PluginReference] Plugin Kits;
        [PluginReference] Plugin ServerRewards;
        [PluginReference] Plugin Spawns;
        [PluginReference] Plugin ZoneManager;

        MethodInfo killLifestory;

        static EventManager ins;
        static List<MessageData> popupQueue;

        private Dictionary<ulong, Timer> KillTimers;
        private RestorationManager Restoration;

        private GameTimer _GameTimer;
        private WaveTimer _WaveTimer;
        private DynamicConfigFile P_Stats;
        private DynamicConfigFile RestoreData;

        private bool _GodEnabled;

        private bool ResetNoCorpse;

        private static string ScoreUI = "EMUI_Scoreboard";
        private static string ClockUI = "EMUI_Timer";
        private static string DeathUI = "EMUI_Death";
        private static string TimerUI = "EMUI_DeathTimer";

        private FieldInfo spectateFilter = typeof(BasePlayer).GetField("spectateFilter", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));

        public Dictionary<ulong, PlayerStatistics> StatsCache;
        public List<EMInterface.AEConfig> ValidAutoEvents;
        public Dictionary<string, Events> ValidEvents;
        public Events _Event;

        public string _EventName;
        public string _CurrentEventConfig;
        public string _NextEventConfig;
        public int _NextAutoConfig;

        public bool _Open;
        public bool _Started;
        public bool _Ended;
        public bool _Pending;
        public bool _Destoyed;
        public bool _Launched;
        public bool _RandomizeAuto;
        public bool _TimerStarted;

        public int _EventNum = 0;

        public List<Timer> EventTimers;
        public Dictionary<ulong, Timer> RespawnTimers;
        public Dictionary<string, EventSetting> EventGames;
        public ScoreData GameScores;
        public SpawnManager SpawnCount;
        public List<EventPlayer> EventPlayers;
        public List<BasePlayer> Joiners;

        public Statistics GameStatistics;
        public GameMode EventMode;
        #endregion

        #region UI
        #region Popup Messages
        private static string Popup = "EMUI_Popupmsg";
        private List<string> PopupPanels = new List<string>();
        private int popUpCount = 0;

        public void PopupMessage(string message)
        {
            popupQueue.Add(new MessageData(message, 6, ""));
            UpdateMessages();
        }
        private CuiElementContainer CreateMessageEntry(int number, string panelName, MessageData data)
        {
            PopupPanels.Add(panelName);
            var pos = GetFeedPosition(number);
            var Main = UI.CreateElementContainer(panelName, "0 0 0 0", $"{pos[0]} {pos[1]}", $"{pos[2]} {pos[3]}", false, "Hud");
            UI.CreateOutLineLabel(ref Main, panelName, "0 0 0 1", data.message, 17, "1 1", "0 0", "1 1");
            return Main;
        }
        private float[] GetFeedPosition(int number)
        {
            Vector2 initialPos = new Vector2(0.25f, 0.89f);
            Vector2 dimensions = new Vector2(0.5f, 0.04f);
            var yPos = initialPos.y - ((dimensions.y + 0.005f) * number);
            return new float[] { initialPos.x, yPos, initialPos.x + dimensions.x, yPos + dimensions.y };
        }
        private void UpdateMessages(bool destroyed = false)
        {
            if (destroyed)
            {
                if (popupQueue.Count > 0)
                {
                    for (int i = 0; i < popupQueue.Count; i++)
                    {
                        if (i >= 3)
                            return;

                        var feed = popupQueue[i];
                        var panelName = feed.elementID;
                        if (!feed.started)
                        {
                            panelName = Popup + popUpCount;
                            popUpCount++;
                            feed.Begin(panelName);
                        }
                        AddUI(CreateMessageEntry(i, panelName, popupQueue[i]));
                    }
                }
            }
            else
            {
                if (popupQueue.Count > 0 && popupQueue.Count < 3)
                {
                    var feed = popupQueue[popupQueue.Count - 1];
                    var panelName = Popup + popUpCount;
                    popUpCount++;
                    AddUI(CreateMessageEntry(popupQueue.Count - 1, panelName, feed));
                    feed.Begin(panelName);
                }
            }
        }
        private void AddUI(CuiElementContainer element)
        {
            foreach (var player in EventPlayers)
            {
                if (player.inEvent && player.enabled)
                    CuiHelper.AddUi(player.GetPlayer(), element);
            }
        }
        private void DestroyUpdate()
        {
            for (int i = 0; i < popupQueue.Count; i++)
            {
                foreach (var player in BasePlayer.activePlayerList)
                {
                    CuiHelper.DestroyUi(player, popupQueue[i].elementID);
                }
            }
            UpdateMessages(true);
        }
        private void DestroyPopupUI(BasePlayer player)
        {
            for (int i = 0; i < popupQueue.Count; i++)
            {
                CuiHelper.DestroyUi(player, popupQueue[i].elementID);
            }
        }
        private void DestroyPopupUI(MessageData element)
        {
            if (!string.IsNullOrEmpty(element.elementID))
            {
                foreach (var player in BasePlayer.activePlayerList)
                {
                    CuiHelper.DestroyUi(player, element.elementID);
                }
            }
            popupQueue.Remove(element);
            DestroyUpdate();
        }
        private void DestroyAllPopups()
        {
            foreach (var player in BasePlayer.activePlayerList)
                foreach (var message in PopupPanels)
                    CuiHelper.DestroyUi(player, message);
            PopupPanels.Clear();
        }


        #endregion

        #region Scoreboards
        public class ScoreData
        {
            public Dictionary<ulong, Scoreboard> Scores = new Dictionary<ulong, Scoreboard>();
            public string ScoreType;
            public string Additional;
        }
        public class Scoreboard
        {
            public string Name;
            public int Position;
            public int Score;
        }

        public void CreateScoreboard(BasePlayer player)
        {
            if (GameScores == null) return;
            var scores = GameScores.Scores;
            var type = GameScores.ScoreType;
            var additional = GameScores.Additional;

            var Main = UI.CreateElementContainer(ScoreUI, "0.1 0.1 0.1 0.7", "0.82 0.55", "0.99 0.98", false, "Hud.Under");

            int count = 0;
            if (!string.IsNullOrEmpty(additional))
            {
                UI.CreateLabel(ref Main, ScoreUI, "", additional, 12, $"0.05 {GetHeight(count)}", $"0.95 {GetHeight(count) + 0.06f}");
                count++;
            }
            if (scores != null)
            {
                var topScores = scores.Take(11);
                UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MainColor}>Name</color>", 12, $"0.25 {GetHeight(count)}", $"0.7 {GetHeight(count) + 0.06f}");
                if (type != null) UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MainColor}>{type}</color>", 12, $"0.7 {GetHeight(count)}", $"0.95 {GetHeight(count) + 0.06f}");
                count++;

                if (scores.ContainsKey(player.userID) && scores[player.userID].Position > 10)
                {
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MainColor}>{scores[player.userID].Position + 1}</color>", 12, $"0.05 {GetHeight(count)}", $"0.25 {GetHeight(count) + 0.06f}");
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MsgColor}>{scores[player.userID].Name}</color>", 12, $"0.25 {GetHeight(count)}", $"0.7 {GetHeight(count) + 0.06f}");
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MsgColor}>{scores[player.userID].Score}</color>", 12, $"0.7 {GetHeight(count)}", $"0.95 {GetHeight(count) + 0.06f}");
                    count++;
                }
                foreach (var score in topScores)
                {
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MainColor}>{score.Value.Position + 1}</color>", 12, $"0.05 {GetHeight(count)}", $"0.25 {GetHeight(count) + 0.06f}");
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MsgColor}>{score.Value.Name}</color>", 12, $"0.25 {GetHeight(count)}", $"0.7 {GetHeight(count) + 0.06f}");
                    UI.CreateLabel(ref Main, ScoreUI, "", $"<color={configData.Messaging.MsgColor}>{score.Value.Score}</color>", 12, $"0.7 {GetHeight(count)}", $"0.95 {GetHeight(count) + 0.06f}");
                    count++;
                }
            }
            DestroyScoreboard(player);
            CuiHelper.AddUi(player, Main);
        }
        public void UpdateScoreboard(ScoreData data)
        {
            GameScores = data;
            foreach (var eventPlayer in EventPlayers)
            {
                CreateScoreboard(eventPlayer.GetPlayer());
            }
        }
        float GetHeight(int num) => 0.89f - (0.06f * num);
        void DestroyScoreboard(BasePlayer player) => CuiHelper.DestroyUi(player, ScoreUI);

        #endregion
        #endregion

        #region Oxide Hooks
        void Loaded()
        {
            Unsubscribe(nameof(OnEntityTakeDamage));
            Unsubscribe(nameof(OnPlayerAttack));
            Unsubscribe(nameof(OnItemPickup));
            Unsubscribe(nameof(OnRunPlayerMetabolism));
            Unsubscribe(nameof(CanNetworkTo));
            Unsubscribe(nameof(CanLootPlayer));

            P_Stats = Interface.Oxide.DataFileSystem.GetFile("EventManager/Statistics");
            RestoreData = Interface.Oxide.DataFileSystem.GetFile("EventManager/Restoration_data");
            Restoration = new RestorationManager();

            killLifestory = typeof(BasePlayer).GetMethod("LifeStoryEnd", (BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic));
        }
        void OnServerInitialized()
        {
            lang.RegisterMessages(Messages, this);
            if (!Spawns)
            {
                PrintError("Unable to load EventManager - Spawns database not found.Please download Spawns database to continue");
                rust.RunServerCommand("oxide.unload", new object[] { "EventManager" });
                return;
            }
            if (!ZoneManager)
            {
                PrintError("Unable to load EventManager - ZoneManager not found.Please download ZoneManager to continue");
                rust.RunServerCommand("oxide.unload", new object[] { "EventManager" });
                return;
            }
            if (!Kits)
                PrintError("Kits is not installed! Unable to issue any weapon kits");
            SetVars();
            LoadVariables();
            LoadData();
            ins = this;

            foreach(var player in BasePlayer.activePlayerList)
                CheckForRestore(player);

            timer.In(5, ()=>
            {
                Interface.CallHook("RegisterGame");
                ValidateAllEvents();
            });
        }
        void Unload()
        {
            SaveStatistics();
            SaveRestoreInfo();
            if (_Open) CloseEvent();
            if (_Started)
            {
                foreach(var eventPlayer in EventPlayers)
                {
                    eventPlayer?.GetPlayer().DieInstantly();
                    UnityEngine.Object.DestroyImmediate(eventPlayer);
                }
            }
            else DestroyGame();
        }

        void OnPlayerInit(BasePlayer player)
        {
            CheckForRestore(player);
        }
        void OnPlayerDisconnected(BasePlayer player)
        {
            if (Joiners.Contains(player))
                Joiners.Remove(player);
            if (GetUser(player))
                LeaveEvent(player);
        }
        void OnPlayerRespawned(BasePlayer player)
        {
            if (!_Started && !_Open)
                CheckForRestore(player);
            else
            {
                var eventPlayer = GetUser(player);
                if (eventPlayer == null) return;
                if (!EventPlayers.Contains(eventPlayer))
                {
                    UnityEngine.Object.DestroyImmediate(eventPlayer);
                    return;
                }
                if (eventPlayer.inEvent && !eventPlayer.isLeaving)
                    TeleportPlayerToEvent(player);
                else if (!eventPlayer.isLeaving)
                    Restoration.RestorePlayer(player);
            }
        }

        void OnPlayerAttack(BasePlayer player, HitInfo hitinfo)
        {
            var eventPlayer = GetUser(player);
            if (eventPlayer == null || !eventPlayer.inEvent)
                return;

            if (hitinfo.HitEntity != null)
                Interface.Oxide.CallHook("OnEventPlayerAttack", player, hitinfo);

            if (hitinfo.IsProjectile())
                AddStats(player, StatType.Shots);
            return;
        }
        void OnEntityTakeDamage(BaseEntity entity, HitInfo info)
        {
            if (entity.GetComponent<EventCorpse>())
            {
                NullifyDamage(info);
                return;
            }
            var player = entity.ToPlayer();
            var attacker = info.InitiatorPlayer;

            if (player != null)
            {
                var eventPlayer = GetUser(player);
                if (eventPlayer != null)
                {
                    if (eventPlayer.isDead)
                    {
                        NullifyDamage(info);
                        return;
                    }
                    if (_GodEnabled)
                    {
                        NullifyDamage(info);
                        return;
                    }

                    float damageAmount = info.damageTypes.Total();
                    if (attacker != null)
                    {
                        if (!GetUser(attacker))
                        {
                            NullifyDamage(info);
                            return;
                        }
                        else
                        {
                            object multiply = Interface.CallHook("HasDamageMultiplier", player, attacker);
                            if (multiply is float)
                            {
                                damageAmount *= (float)multiply;
                            }
                        }
                    }

                    if (info.isHeadshot)
                        damageAmount *= 2;

                    if (player.health - damageAmount < 1)
                    {
                        NullifyDamage(info);
                        OnPlayerDie(player, info);
                        return;
                    }
                }
                else if (attacker != null)
                {
                    if (GetUser(attacker))
                    {
                        NullifyDamage(info);
                        return;
                    }
                }
            }
        }

        private void OnRunPlayerMetabolism(PlayerMetabolism metabolism, BaseCombatEntity entity, float delta)
        {
            var eventPlayer = GetUser(entity?.ToPlayer());
            if (eventPlayer == null) return;
            if (eventPlayer.isDead)
            {
                metabolism.bleeding.value = 0;
                metabolism.poison.value = 0;
                metabolism.radiation_level.value = 0;
                metabolism.radiation_poison.value = 0;
                metabolism.wetness.value = 0;
            }
            else
                metabolism.bleeding.value = 0f;
        }
        void OnItemPickup(Item item, BasePlayer player)
        {
            if (_Started && GetUser(player) != null && _Event.DisableItemPickup)
            {
                item.Remove(0.01f);
                SendMsg(player, "ItemPickup");
            }
        }
        object CanLootPlayer(BasePlayer target, BasePlayer looter)
        {
            if (_Started && GetUser(looter) != null && _Event.DisableItemPickup)
            {
                SendMsg(looter, "NoLooting");
                return true;
            }
            return null;
        }

        void SetVars()
        {
            EventGames = new Dictionary<string, EventSetting>();
            EventPlayers = new List<EventPlayer>();
            Joiners = new List<BasePlayer>();
            EventTimers = new List<Timer>();
            RespawnTimers = new Dictionary<ulong, Timer>();
            ValidAutoEvents = new List<EMInterface.AEConfig>();
            ValidEvents = new Dictionary<string, Events>();
            KillTimers = new Dictionary<ulong, Timer>();
            StatsCache = new Dictionary<ulong, PlayerStatistics>();
            GameScores = new ScoreData();
            SpawnCount = new SpawnManager();
            Restoration = new RestorationManager();
            popupQueue = new List<MessageData>();

            _Open = false;
            _Started = false;
            _Ended = true;
            _Pending = false;
            _Destoyed = true;
            _Launched = false;
            _GodEnabled = false;
            _RandomizeAuto = false;
            _EventName = null;
            _NextEventConfig = null;
            _CurrentEventConfig = null;
            _NextAutoConfig = 0;
            _Event = DefaultConfig;
            EventMode = GameMode.Normal;

            _TimerStarted = false;
            _GameTimer = null;
        }
        void CheckForRestore(BasePlayer player)
        {
            if (player.IsSleeping() || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))
            {
                timer.Once(3, () => CheckForRestore(player));
                return;
            }
            var eventPlayer = GetUser(player);
            if (eventPlayer != null && eventPlayer.inEvent && _Started) return;

            if (Restoration.HasPendingRestore(player.userID))
            {
                if (Restoration.ReadyToRestore(player))
                {
                    if (!Restoration.RestorePlayer(player))
                    {
                        SendMsg(player, "failedRestore");
                    }
                }
            }
        }
        #endregion

        #region Config
        private ConfigData configData;
        class ConfigData
        {
            public EM_Messaging Messaging { get; set; }
            public EM_Options Options { get; set; }
        }
        class EM_Options
        {
            public bool AllowClassSelectionOnDeath { get; set; }
            public bool LaunchAutoEventsOnStartup { get; set; }
            public int Battlefield_Timer { get; set; }
            public int Required_AuthLevel { get; set; }
            public bool DropCorpseOnDeath { get; set; }
            public bool UseSpectateMode { get; set; }
            public bool UseEconomicsAsTokens { get; set; }
            public bool UseEventPrestart { get; set; }
            public int EventPrestartTimer { get; set; }
        }
        class EM_Messaging
        {
            public bool AnnounceEvent { get; set; }
            public bool AnnounceEvent_During { get; set; }
            public int AnnounceEvent_Interval { get; set; }
            public string MainColor { get; set; }
            public string MsgColor { get; set; }
        }
        private void LoadVariables()
        {
            LoadConfigVariables();
            SaveConfig();
        }
        private void LoadConfigVariables()
        {
            try
            {
                configData = Config.ReadObject<ConfigData>();
            }
            catch (Exception)
            {
                Puts("Invalid config file, restoring default");
                LoadDefaultConfig();
            }
        }
        protected override void LoadDefaultConfig()
        {
            var config = new ConfigData
            {
                Messaging = new EM_Messaging
                {
                    AnnounceEvent_During = true,
                    AnnounceEvent_Interval = 120,
                    AnnounceEvent = true,
                    MainColor = "#FF8C00",
                    MsgColor = "#939393"
                },
                Options = new EM_Options
                {
                    AllowClassSelectionOnDeath = true,
                    Battlefield_Timer = 1200,
                    DropCorpseOnDeath = true,
                    EventPrestartTimer = 30,
                    LaunchAutoEventsOnStartup = false,
                    Required_AuthLevel = 1,
                    UseEconomicsAsTokens = false,
                    UseSpectateMode = true,
                    UseEventPrestart = true
                }
            };
            SaveConfig(config);
        }
        void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
        #endregion

        #region Messaging
        public void BroadcastEvent(string msg)
        {
            foreach (EventPlayer eventplayer in EventPlayers)
                SendReply(eventplayer.GetPlayer(), $"<color={configData.Messaging.MainColor}>" + msg + "</color>");
        }
        public void BroadcastToChat(string message) => PrintToChat($"<color={configData.Messaging.MainColor}>{msg("Title")}</color><color={configData.Messaging.MsgColor}>{msg(message)}</color>");
        static string msg(string key, BasePlayer player = null) => ins.lang.GetMessage(key, ins, player?.UserIDString);
        private void SendMsg(BasePlayer player, string langkey, bool title = true)
        {
            string message = $"<color={configData.Messaging.MsgColor}>{msg(langkey)}</color>";
            if (title) message = $"<color={configData.Messaging.MainColor}>{msg("Title")}</color>" + message;
            SendReply(player, message);
        }
        void AnnounceEvent()
        {
            object success = Interface.Oxide.CallHook("OnEventAnnounce");
            if (success is string)
                BroadcastToChat((string)success);
            else BroadcastToChat(string.Format(msg("eventOpen"), _Event.EventType));
        }
        void AnnounceDuringEvent()
        {
            if (configData.Messaging.AnnounceEvent_During)
            {
                if (_Open && _Started)
                {
                    foreach (BasePlayer player in BasePlayer.activePlayerList)
                    {
                        if (!GetUser(player))
                            SendMsg(player, string.Format(msg("stillOpen"), _Event.EventType));
                    }
                }
            }
        }

        #endregion

        #region Information Classes
        public class Events
        {
            public bool CloseOnStart;
            public bool DisableItemPickup;
            public bool UseClassSelector;
            public int MinimumPlayers;
            public int MaximumPlayers;
            public int ScoreLimit;
            public int RespawnTimer;
            public int GameRounds;
            public int EnemiesToSpawn;
            public string EventType;
            public string Kit;
            public string WeaponSet;
            public string Spawnfile;
            public string Spawnfile2;
            public string ZoneID;
            public GameMode GameMode;
            public RespawnType RespawnType;
            public SpawnType SpawnType;
        }
        public class EventSetting
        {
            public bool LockClothing;
            public bool RequiresKit;
            public bool RequiresSpawns;
            public bool RequiresMultipleSpawns;
            public bool CanUseClassSelector;
            public bool CanPlayBattlefield;
            public bool CanChooseRespawn;
            public bool ForceCloseOnStart;
            public bool IsRoundBased;
            public bool SpawnsEnemies;
            public string ScoreType;
        }
        public class EventInvItem
        {
            public int itemid;
            public ulong skin;
            public int amount;
            public float condition;
            public int ammo;
            public string ammotype;
            public ProtoBuf.Item.InstanceData instanceData;
            public EventInvItem[] contents;
        }
        public class RestoreInfo
        {
            public Dictionary<InventoryType, List<EventInvItem>> inventory = new Dictionary<InventoryType, List<EventInvItem>>();
            public float health, hydration, calories, x, y, z;
        }

        public class UI
        {
            static public CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool useCursor = false, string parent = "Overlay")
            {
                var NewElement = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = {Color = color},
                            RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
                            CursorEnabled = useCursor
                        },
                        new CuiElement().Parent = parent,
                        panelName
                    }
                };
                return NewElement;
            }
            static public void CreatePanel(ref CuiElementContainer container, string panel, string color, string aMin, string aMax, bool cursor = false)
            {
                container.Add(new CuiPanel
                {
                    Image = { Color = color },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    CursorEnabled = cursor
                },
                panel);
            }
            static public void CreateLabel(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiLabel
                {
                    Text = { Color = color, FontSize = size, Align = align, Text = text },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax }
                },
                panel);

            }
            static public void CreateOutLineLabel(ref CuiElementContainer container, string panel, string color, string text, int size, string distance, string aMin, string aMax, TextAnchor align = TextAnchor.MiddleCenter, string parent = "Overlay")
            {
                CuiElement textElement = new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    FadeOut = 0.2f,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = text,
                            FontSize = size,
                            Align = TextAnchor.MiddleCenter,
                            FadeIn = 0.2f
                        },
                        new CuiOutlineComponent
                        {
                            Distance = distance,
                            Color = color
                        },
                        new CuiRectTransformComponent
                        {
                            AnchorMin = aMin,
                            AnchorMax = aMax
                        }
                    }
                };
                container.Add(textElement);
            }
            static public void CreateButton(ref CuiElementContainer container, string panel, string color, string text, int size, string aMin, string aMax, string command, TextAnchor align = TextAnchor.MiddleCenter)
            {
                container.Add(new CuiButton
                {
                    Button = { Color = color, Command = command, FadeIn = 0f },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    Text = { Text = text, FontSize = size, Align = align }
                },
                panel);
            }
            static public void ImageFromStorage(ref CuiElementContainer container, string panel, string png, string aMin, string aMax)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiRawImageComponent {Png = png },
                        new CuiRectTransformComponent {AnchorMin = aMin, AnchorMax = aMax }
                    }
                });
            }
            static public void ImageFromURL(ref CuiElementContainer container, string panel, string url, string aMin, string aMax)
            {
                container.Add(new CuiElement
                {
                    Name = CuiHelper.GetGuid(),
                    Parent = panel,
                    Components =
                    {
                        new CuiRawImageComponent {Url = url },
                        new CuiRectTransformComponent {AnchorMin = aMin, AnchorMax = aMax }
                    }
                });
            }
        }

        public enum InventoryType { Main, Wear, Belt };
        public enum GameMode
        {
            Normal,
            Battlefield
        }
        public enum SpawnType
        {
            Random,
            Consecutive
        }
        public enum RespawnType
        {
            None,
            Timer,
            Waves
        }
        #endregion

        #region Components
        public class EventPlayer : MonoBehaviour
        {
            private BasePlayer player;
            private EventCorpse corpse;

            public bool inEvent, isDead, isRespawning, isSpectating, OOB, isLeaving;
            public string currentClass;
            public int restoreAttempts;

            void Awake()
            {
                inEvent = true;
                isDead = false;
                isRespawning = false;
                OOB = false;
                player = GetComponent<BasePlayer>();
            }
            public BasePlayer GetPlayer() => player;
            public void SetCorpse(EventCorpse corpse) => this.corpse = corpse ?? null;
            public EventCorpse GetCorpse() => corpse ?? null;
        }
        public class EventCorpse : MonoBehaviour
        {
            public LootableCorpse entity;
            void Awake()
            {
                entity = GetComponent<LootableCorpse>();
            }
            void OnDestroy()
            {
                if (entity == null) return;
                if (entity?.containers == null) return;
                foreach (var container in entity.containers)
                {
                    Item[] array = container.itemList.ToArray();
                    for (int i = 0; i < array.Length; i++)
                        array[i].Remove(0f);
                }
                ItemManager.DoRemoves();
                entity.DieInstantly();
            }
        }

        private class GameTimer : MonoBehaviour
        {
            int timeRemaining;
            void Awake() => timeRemaining = 0;
            public void StartTimer(int time)
            {
                timeRemaining = time;
                InvokeRepeating("TimerTick", 1f, 1f);
                ins._TimerStarted = true;
            }
            void OnDestroy()
            {
                CancelInvoke("TimerTick");
                ins._TimerStarted = false;
                Destroy(this);
            }
            internal void TimerTick()
            {
                timeRemaining--;
                if (timeRemaining == 0)
                {
                    DestroyUI();
                    ins.CancelEvent(msg("TimeLimit"));
                    CancelInvoke("TimerTick");
                }
                else UpdateUITimer();
            }
            internal void UpdateUITimer()
            {
                string clockTime = "";
                TimeSpan dateDifference = TimeSpan.FromSeconds(timeRemaining);
                var hours = dateDifference.Hours;
                var mins = dateDifference.Minutes;
                var secs = dateDifference.Seconds;
                if (hours > 0)
                    clockTime = string.Format("{0:00}:{1:00}:{2:00}", hours, mins, secs);
                else clockTime = string.Format("{0:00}:{1:00}", mins, secs);

                var CUI = UI.CreateElementContainer(ClockUI, "0.1 0.1 0.1 0.7", "0.45 0.95", "0.55 0.99", false, "Hud.Under");
                UI.CreateLabel(ref CUI, ClockUI, "", clockTime, 16, "0 0", "1 1");
                foreach (var ePlayer in ins.EventPlayers)
                {
                    CuiHelper.DestroyUi(ePlayer.GetPlayer(), ClockUI);
                    CuiHelper.AddUi(ePlayer.GetPlayer(), CUI);
                }
            }
            internal void DestroyUI()
            {
                foreach (var player in BasePlayer.activePlayerList)
                    CuiHelper.DestroyUi(player, ClockUI);
            }
        }
        private class WaveTimer : MonoBehaviour
        {
            private int waveTimer;
            void Awake()
            {
                waveTimer = ins._Event.RespawnTimer;
                InvokeRepeating("RespawnTick", 1f, 1f);
            }
            void OnDestroy() => CancelInvoke("RespawnTick");
            private void RespawnTick()
            {
                waveTimer--;
                if (waveTimer <= 0)
                    waveTimer = ins._Event.RespawnTimer;
            }
            public int GetTime() => waveTimer;
        }
        public class SpawnManager
        {
            public int spawnsCountA = 0;
            public int spawnsCountB = 0;
            private int lastSpawnA = 0;
            private int lastSpawnB = 0;

            public object GetSpawnPoint(string file, bool team = true, int min = -1, int max = -1)
            {
                if (ins._Event.SpawnType == SpawnType.Consecutive)
                {
                    if (min > 0)
                    {
                        if (team)
                        {
                            if (lastSpawnA < min || (max > 0 && lastSpawnA > max))
                            {
                                lastSpawnA = min - 1;
                                return GetNextSpawn(file, team);
                            }
                        }
                        else
                        {
                            if (lastSpawnB < min || (max > 0 && lastSpawnB > max))
                            {
                                lastSpawnB = min - 1;
                                return GetNextSpawn(file, team);
                            }
                        }
                    }
                    return GetNextSpawn(file, team);
                }
                else
                {
                    if (min > 0)
                    {
                        if (max > 0)
                            return GetRandomRange(file, min, max);
                        else return GetRandomRange(file, min, 9999);
                    }
                    return GetRandomSpawn(file);
                }
            }
            private object GetRandomSpawn(string file) => ins.Spawns.Call("GetRandomSpawn", file);
            private object GetRandomRange(string file, int min, int max) => ins.Spawns.Call("GetRandomSpawnRange", file, min, max);
            private object GetNextSpawn(string file, bool team)
            {
                int number;
                if (team)
                {
                    ++lastSpawnA;
                    if (lastSpawnA >= spawnsCountA)
                        lastSpawnA = 0;
                    number = lastSpawnA;
                }
                else
                {
                    ++lastSpawnB;
                    if (lastSpawnB >= spawnsCountB)
                        lastSpawnB = 0;
                    number = lastSpawnB;
                }
                return ins.Spawns.Call("GetSpawn", file, number);
            }
            public void SetSpawnCount(bool team, int number)
            {
                if (team)
                    spawnsCountA = number;
                else spawnsCountB = number;
            }
        }
        private class MessageData
        {
            public int timecount;
            public string elementID;
            public string message;
            public bool started;

            public MessageData(string message, int timecount, string elementID)
            {
                this.timecount = timecount;
                this.elementID = elementID;
                this.message = message;
                started = false;
            }
            public void Begin(string elementID)
            {
                this.elementID = elementID;
                started = true;
                StartDestroy();
            }
            void StartDestroy()
            {
                if (timecount > 0)
                {
                    timecount--;
                    ins.timer.Once(1, () => StartDestroy());
                }
                else if (timecount == 0)
                {
                    ins.DestroyPopupUI(this);
                }
            }
        }

        private EventPlayer GetUser(BasePlayer player)
        {
            if (player == null) return null;
            var eventPlayer = player.GetComponent<EventPlayer>();
            if (eventPlayer == null) return null;
            return eventPlayer;
        }
        #endregion

        #region Event Management
        public object SelectEvent(string name)
        {
            if (!(EventGames.ContainsKey(name))) return string.Format(msg("noEvent"), name);
            if (_Started || _Open) return msg("isAlreadyStarted");
            Interface.CallHook("OnSelectEventGamePost", new object[] { name });
            return true;
        }
        object SetEventDetails()
        {
            var success = SelectEvent(_Event.EventType);
            if (success is string) return (string)success;
            if (EventGames.ContainsKey(_Event.EventType))
            {
                EventMode = _Event.GameMode;
                if (EventGames[_Event.EventType].RequiresSpawns && !string.IsNullOrEmpty(_Event.Spawnfile))
                {
                    Interface.CallHook("SetSpawnfile", true, _Event.Spawnfile);
                    object count = Spawns.Call("GetSpawnsCount", _Event.Spawnfile);
                    if (count is int)
                        SpawnCount.SetSpawnCount(true, (int)count);
                }
                if (EventGames[_Event.EventType].RequiresMultipleSpawns && !string.IsNullOrEmpty(_Event.Spawnfile2))
                {
                    Interface.CallHook("SetSpawnfile", false, _Event.Spawnfile2);
                    object count = Spawns.Call("GetSpawnsCount", _Event.Spawnfile2);
                    if (count is int)
                        SpawnCount.SetSpawnCount(false, (int)count);
                }
                if (_Event.GameRounds > 0)
                    Interface.CallHook("SetGameRounds", _Event.GameRounds);
                if (_Event.EnemiesToSpawn > 0)
                    Interface.CallHook("SetEnemyCount", _Event.EnemiesToSpawn);
                if (!string.IsNullOrEmpty(EventGames[_Event.EventType].ScoreType))
                    Interface.CallHook("SetScoreLimit", _Event.ScoreLimit);
                if (!string.IsNullOrEmpty(_Event.WeaponSet))
                    Interface.CallHook("ChangeWeaponSet", _Event.WeaponSet);
                if (!string.IsNullOrEmpty(_Event.Kit))
                    Interface.CallHook("OnSelectKit", _Event.Kit);
                if (!string.IsNullOrEmpty(_Event.ZoneID))
                {
                    Interface.CallHook("SetEventZone", _Event.ZoneID);
                    if (configData.Options.DropCorpseOnDeath)
                    {
                        var hasFlag = ZoneManager?.Call("HasFlag", _Event.ZoneID, "NoCorpse");
                        if (hasFlag is bool && (bool)hasFlag)
                        {
                            ZoneManager?.Call("RemoveFlag", _Event.ZoneID, "NoCorpse");
                            ResetNoCorpse = true;
                        }
                    }
                }
                if (EventGames[_Event.EventType].ForceCloseOnStart)
                    _Event.CloseOnStart = true;
                if (!EventGames[_Event.EventType].CanChooseRespawn)
                {
                    var type = Interface.CallHook("GetRespawnType");
                    if (type != null)
                        _Event.RespawnType = (RespawnType)type;
                    var time = Interface.CallHook("GetRespawnTime");
                    if (time != null)
                        _Event.RespawnTimer = (int)time;
                }
                return null;
            }
            return "Error setting event details.Please check your settings";
        }

        public object OpenEvent()
        {
            if (_Event == null) return msg("noneSelected");
            if (string.IsNullOrEmpty(_Event.EventType)) return msg("noTypeSelected");
            if (_Open) return string.Format(msg("isAlreadyOpen"), _Event.EventType);
            if (_Started && !_Open)
            {
                if (!EventGames[_Event.EventType].ForceCloseOnStart)
                {
                    _Open = true;
                    return null;
                }
                else return msg("cantOpen");
            }
            var success = ValidateEvent(_Event);
            if (success is string)
                return (string)success;
            success = SetEventDetails();
            if (success is string)
                return (string)success;
            success = Interface.Oxide.CallHook("CanEventOpen");
            if (success is string)
                return (string)success;
            EMInterface.EventVoting.OpenEventVoting(false);

            _Open = true;
            GameScores = new ScoreData();
            EventPlayers = new List<EventPlayer>();
            Joiners = new List<BasePlayer>();

            _EventName = _Event.EventType;
            if (_Event.GameMode == GameMode.Battlefield)
                _EventName = $"{msg("Battlefield")} - {_EventName}";

            if (!string.IsNullOrEmpty(_CurrentEventConfig))
                _EventName = $"{_CurrentEventConfig} ({_Event.EventType})";

            BroadcastToChat(string.Format(msg("eventOpen"), _EventName));
            Interface.Oxide.CallHook("OnEventOpenPost");

            return true;
        }
        public object CloseEvent()
        {
            if (!_Open) return msg("eventAlreadyClosed");
            _Open = false;
            Interface.Oxide.CallHook("OnEventClosePost");

            if (_Started)
                BroadcastToChat(msg("eventClose"));
            else
            {
                DestroyTimers();
                BroadcastToChat(msg("eventCancel"));
                EMInterface.EventVoting.OpenEventVoting(true);
            }
            return true;
        }

        public object StartEvent()
        {
            object success = Interface.Oxide.CallHook("CanEventStart");
            if (success is string)
                return (string)success;

            Subscribe(nameof(OnEntityTakeDamage));
            Subscribe(nameof(OnPlayerAttack));
            Subscribe(nameof(OnRunPlayerMetabolism));
            Subscribe(nameof(OnItemPickup));
            Subscribe(nameof(CanNetworkTo));
            Subscribe(nameof(CanLootPlayer));

            Interface.Oxide.CallHook("OnEventStartPre");
            BroadcastToChat(string.Format(msg("eventBegin"), _EventName));
            _Started = true;
            _Ended = false;
            _Destoyed = false;

            if (!GameStatistics.GamesPlayed.ContainsKey(_Event.EventType))
                GameStatistics.GamesPlayed.Add(_Event.EventType, 1);
            else GameStatistics.GamesPlayed[_Event.EventType]++;

            DestroyTimers();
            PreStartEvent();
            return true;
        }
        public void PreStartEvent()
        {
            if (_Event.CloseOnStart)
                CloseEvent();
            EnableGod();
            CreateEventPlayers();
        }

        public object EndEvent()
        {
            DestroyAllPopups();

            if (_Ended) return msg("noGamePlaying");

            EnableGod();
            RespawnAllPlayers();

            _Open = false;
            _Started = false;
            _Pending = false;

            if (_GameTimer != null)
                UnityEngine.Object.Destroy(_GameTimer);
            if (_WaveTimer != null)
                UnityEngine.Object.Destroy(_WaveTimer);

            Interface.CallHook("OnEventEndPre");
            for (int i = 0; i < EventPlayers.Count; i++)
            {
                DestroyScoreboard(EventPlayers[i].GetPlayer());
                CuiHelper.DestroyUi(EventPlayers[i].GetPlayer(), ClockUI);
            }

            BroadcastToChat(string.Format(msg("restoringPlayers"), _Event.EventType));

            _Ended = true;

            Restoration.StartRestoration();
            return true;
        }
        void FinalizeGameEnd()
        {
            CalculateRanks();
            DestroyGame();
            Interface.Oxide.CallHook("OnEventEndPost");
            SaveRestoreInfo();

            if (ResetNoCorpse)
            {
                ZoneManager?.Call("AddFlag", _Event.ZoneID, "NoCorpse");
                ResetNoCorpse = false;
            }
        }

        public void CancelEvent(string reason)
        {
            DestroyTimers();
            if (_Started)
                EndEvent();

            object success = Interface.Oxide.CallHook("OnEventCancel");
            if (success is string)
                BroadcastToChat((string)success);
            else BroadcastToChat(string.Format(msg("EventCancelled"), _EventName, reason));

            DestroyGame();

            if (_Launched)
                AutoEventNext();
        }
        public void CancelAutoEvent(string reason)
        {
            if (_Started || _Open)
            {
                if (_Started)
                {
                    EndEvent();
                    object success = Interface.Oxide.CallHook("OnEventCancel");
                    if (success is string)
                        BroadcastToChat((string)success);
                    else BroadcastToChat(string.Format(msg("Event
// ... [Code preview truncated due to length. Full source in attached file] ...

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