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

FREE EventManager : 2.0.24 2.0.24

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;

namespace Oxide.Plugins
{
    [Info("Event Manager", "Reneb / k1lly0u", "2.0.24", ResourceId = 740)]
    class EventManager : RustPlugin
    {
        #region Fields
        [PluginReference]
        Plugin Spawns;

        [PluginReference]
        Plugin Kits;

        [PluginReference]
        Plugin ZoneManager;

        [PluginReference]
        Plugin ServerRewards;

        [PluginReference]
        Plugin Economics;

        private string EventSpawnFile;
        private string EventGameName;
        private string ZoneName;
        private string TokenType;

        private bool EventOpen;
        private bool EventStarted;
        private bool EventEnded;
        private bool EventPending;
        private int EventMaxPlayers = 0;
        private int EventMinPlayers = 0;
        private int EventAutoNum = -1;

        public int PlayTimer;

        public float LastAnnounce;
        public bool AutoEventLaunched = false;
        public bool UseClassSelection;
        public GameMode EventMode;

        private List<string> EventGames;
        private List<EventPlayer> EventPlayers;
        public List<ulong> Godmode;
        public List<Timer> AutoArenaTimers;

        private Dictionary<ulong, Timer> KillTimers;

        private ConfigData configData;

        ClassData classData;
        private DynamicConfigFile Class_Data;

        static bool Debug = false;
        #endregion

        #region Classes        
        class EventPlayer : MonoBehaviour
        {
            public BasePlayer player;

            public float health;
            public float calories;
            public float hydration;

            public bool inEvent;
            public bool savedInventory;
            public bool savedHome;
            public bool OOB;

            public string currentClass;

            public List<EventInvItem> InvItems = new List<EventInvItem>();
            public Vector3 Home;

            void Awake()
            {                
                inEvent = true;
                savedInventory = false;
                savedHome = false;
                player = GetComponent<BasePlayer>();
                ELog($"{player.displayName} component init");
            }
            public void SaveHealth()
            {
                ELog($"{player.displayName} saving health");
                health = player.health;
                calories = player.metabolism.calories.value;
                hydration = player.metabolism.hydration.value;
            }
            public void SaveHome()
            {
                ELog($"{player.displayName} saving home");
                if (!savedHome)
                    Home = player.transform.position;
                savedHome = true;
            }
            public void TeleportHome()
            {
                ELog($"{player.displayName} TP home");
                if (!savedHome)
                    return;
                TPPlayer(player, Home);
                savedHome = false;
            }
            public void SaveInventory()
            {
                ELog($"{player.displayName} saving inv");
                if (savedInventory)
                    return;
                InvItems.Clear();
                InvItems.AddRange(GetItems(player.inventory.containerWear, "wear"));
                InvItems.AddRange(GetItems(player.inventory.containerMain, "main"));
                InvItems.AddRange(GetItems(player.inventory.containerBelt, "belt"));
                ELog($"{player.displayName} inventory count: {InvItems.Count}");
                savedInventory = true;
            }
            private IEnumerable<EventInvItem> GetItems(ItemContainer container, string containerName)
            {
                return container.itemList.Select(item => new EventInvItem
                {
                    itemid = item.info.itemid,
                    container = containerName,
                    amount = item.amount,
                    ammo = (item.GetHeldEntity() as BaseProjectile)?.primaryMagazine.contents ?? 0,
                    skin = item.skin,
                    condition = item.condition,
                    contents = item.contents?.itemList.Select(item1 => new EventInvItem
                    {
                        itemid = item1.info.itemid,
                        amount = item1.amount,
                        condition = item1.condition
                    }).ToArray()
                });
            }
            public void RestoreInventory()
            {
                ELog($"{player.displayName} restoring inventory, saved count: {InvItems.Count}");
                player.inventory.Strip();
                foreach (var kitem in InvItems)
                {
                    var item = ItemManager.CreateByItemID(kitem.itemid, kitem.amount, kitem.skin);
                    item.condition = kitem.condition;
                    var weapon = item.GetHeldEntity() as BaseProjectile;
                    if (weapon != null) weapon.primaryMagazine.contents = kitem.ammo;
                    player.inventory.GiveItem(item, kitem.container == "belt" ? player.inventory.containerBelt : kitem.container == "wear" ? player.inventory.containerWear : player.inventory.containerMain);
                    if (kitem.contents == null) continue;
                    foreach (var ckitem in kitem.contents)
                    {
                        var item1 = ItemManager.CreateByItemID(ckitem.itemid, ckitem.amount);
                        if (item1 == null) continue;
                        item1.condition = ckitem.condition;
                        item1.MoveToContainer(item.contents);
                    }
                }
                ELog($"{player.displayName} restored count: {player.inventory.containerBelt.itemList.Count + player.inventory.containerMain.itemList.Count + player.inventory.containerWear.itemList.Count}");
                savedInventory = false;
            }
        }
        class EventInvItem
        {
            public int itemid;
            public bool bp;
            public int skin;
            public string container;
            public int amount;
            public float condition;
            public int ammo;
            public EventInvItem[] contents;
        }
        class ConfigData
        {
            public string Default_Gamemode { get; set; }
            public string Default_Spawnfile { get; set; }
            public int Battlefield_Timer { get; set; }
            public bool KillDeserters { get; set; }
            public int Required_AuthLevel { get; set; }
            public string Messaging_MainColor { get; set; }
            public string Messaging_MsgColor { get; set; }
            public bool Announce_Event { get; set; }
            public bool AnnounceDuring_Event { get; set; }
            public int AnnounceEvent_Interval { get; set; }
            public bool UseEconomicsAsTokens { get; set; }
            public bool UseClassSelector_Default { get; set; }
            public AutoEvents z_AutoEvents { get; set; }
        }
        class AutoEvents
        {
            public int GameInterval { get; set; }
            public bool AutoCancel { get; set; }
            public int AutoCancel_Timer { get; set; }
            public List<AutoEventSetup> z_AutoEventSetup { get; set; }
        }
        class AutoEventSetup
        {
            public bool UseClassSelector { get; set; }
            public string GameType { get; set; }
            public GameMode EventMode { get; set; }
            public string Spawnfile { get; set; }
            public string Kit { get; set; }
            public bool CloseOnStart { get; set; }
            public int TimeToJoin { get; set; }
            public int MinimumPlayers { get; set; }
            public int MaximumPlayers { get; set; }
            public int TimeLimit { get; set; }
            public string ZoneID { get; set; }

        }
        class ClassData
        {
            public Dictionary<string, string> ClassKits = new Dictionary<string, string>();
        }
        public class UI
        {
            static public CuiElementContainer CreateElementContainer(string panelName, string color, string aMin, string aMax, bool useCursor)
            {
                var NewElement = new CuiElementContainer()
                {
                    {
                        new CuiPanel
                        {
                            Image = {Color = color},
                            RectTransform = {AnchorMin = aMin, AnchorMax = aMax},
                            CursorEnabled = useCursor
                        },
                        new CuiElement().Parent = "Overlay",
                        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 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 = 1.0f },
                    RectTransform = { AnchorMin = aMin, AnchorMax = aMax },
                    Text = { Text = text, FontSize = size, Align = align }
                },
                panel);
            }
        }
        public enum GameMode
        {
            Normal,
            Battlefield
        }
        #endregion

        #region Oxide Hooks
        void Loaded()
        {
            EventGames = new List<string>();
            EventMode = GameMode.Normal;
            EventPlayers = new List<EventPlayer>();
            AutoArenaTimers = new List<Timer>();
            KillTimers = new Dictionary<ulong, Timer>();
            Class_Data = Interface.Oxide.DataFileSystem.GetFile("EventManager_Classes");

        }
        void OnServerInitialized()
        {
            lang.RegisterMessages(Messages, this);
            LoadVariables();
            LoadData();
            EventOpen = false;
            EventStarted = false;
            EventEnded = true;
            EventPending = false;
            UseClassSelection = configData.UseClassSelector_Default;
            EventGameName = configData.Default_Gamemode;
            timer.Once(0.2f, InitializeGames);
        }
        void InitializeGames()
        {
            //Interface.Oxide.CallHook("RegisterGame");
            SelectSpawnfile(configData.Default_Spawnfile);
        }
        void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList) DestroyUI(player);
            EndEvent();
            DestroyGame();
        }
        void OnPlayerRespawned(BasePlayer player)
        {
            if (!EventStarted) return;
            if (!player.GetComponent<EventPlayer>()) return;
            if (player.GetComponent<EventPlayer>().inEvent)
            {
                if (!EventStarted) return;
                TeleportPlayerToEvent(player);
            }
            else
            {
                RedeemInventory(player);
                TeleportPlayerHome(player);
                TryErasePlayer(player);
            }
        }
        void OnPlayerAttack(BasePlayer player, HitInfo hitinfo)
        {
            if (!EventStarted) return;
            if (player.GetComponent<EventPlayer>() == null || !(player.GetComponent<EventPlayer>().inEvent))
                return;
            if (hitinfo.HitEntity != null)
                Interface.Oxide.CallHook("OnEventPlayerAttack", player, hitinfo);
            return;
        }
        void OnEntityDeath(BaseEntity entity, HitInfo hitinfo)
        {
            if (!EventStarted) return;
            if ((entity as BasePlayer)?.GetComponent<EventPlayer>() == null) return;
            Interface.Oxide.CallHook("OnEventPlayerDeath", ((BasePlayer)entity), hitinfo);
            return;
        }
        void OnPlayerDisconnected(BasePlayer player)
        {
            if (!EventStarted) return;
            if (player.GetComponent<EventPlayer>() != null)
                LeaveEvent(player);
        }
        void OnEntityTakeDamage(BaseEntity entity, HitInfo info)
        {
            if (!EventStarted) return;
            var player = entity as BasePlayer;
            if (Godmode == null || player == null) return;
            if (Godmode.Contains(player.userID))
            {
                info.damageTypes = new DamageTypeList();
                info.HitMaterial = 0;
                info.PointStart = Vector3.zero;
            }
        }
        #endregion

        #region Checks
        bool hasEventStarted()
        {
            return EventStarted;
        }
        bool isPlaying(BasePlayer player)
        {
            EventPlayer eplayer = player.GetComponent<EventPlayer>();
            return eplayer != null && eplayer.inEvent;
        }
        object canRedeemKit(BasePlayer player)
        {
            if (!EventStarted) return null;
            TryErasePlayer(player);
            EventPlayer eplayer = player.GetComponent<EventPlayer>();
            if (eplayer == null) return null;
            return false;
        }
        object canShop(BasePlayer player)
        {
            if (!EventStarted) return null;
            EventPlayer eplayer = player.GetComponent<EventPlayer>();
            if (eplayer == null) return null;
            return GetMessage("CanShop");
        }

        object CanTeleport(BasePlayer player)
        {
            if (!EventStarted) return null;
            EventPlayer eplayer = player.GetComponent<EventPlayer>();
            if (eplayer == null) return null;
            return GetMessage("CanTP");
        }
        #endregion

        #region Config
        private void LoadVariables()
        {
            LoadConfigVariables();
            SaveConfig();
        }
        private void LoadConfigVariables()
        {
            configData = Config.ReadObject<ConfigData>();
        }
        protected override void LoadDefaultConfig()
        {
            Puts("Creating a new config file");
            var config = new ConfigData
            {
                AnnounceDuring_Event = true,
                AnnounceEvent_Interval = 120,
                Announce_Event = true,
                Battlefield_Timer = 1200,
                Default_Gamemode = "Deathmatch",
                Default_Spawnfile = "deathmatchspawns",
                KillDeserters = true,
                Required_AuthLevel = 1,
                Messaging_MainColor = "#FF8C00",
                Messaging_MsgColor = "#939393",
                UseEconomicsAsTokens = false,
                UseClassSelector_Default = true,
                z_AutoEvents = new AutoEvents
                {
                    AutoCancel = true,
                    AutoCancel_Timer = 300,
                    GameInterval = 1200,
                    z_AutoEventSetup = CreateDefaultAutoConfig()
                }
            };
            SaveConfig(config);
        }
        void SaveConfig(ConfigData config)
        {
            Config.WriteObject(config, true);
        }
        static List<AutoEventSetup> CreateDefaultAutoConfig()
        {
            var newautoconfiglist = new List<AutoEventSetup>
            {
                new AutoEventSetup
                {
                    GameType = "Deathmatch",
                    EventMode = GameMode.Battlefield,
                    Spawnfile = "deathmatchspawns",
                    Kit = "",
                    CloseOnStart = true,
                    TimeToJoin = 60,
                    TimeLimit = 1800,
                    MinimumPlayers = 2,
                    MaximumPlayers = 20,
                    UseClassSelector = false,
                    ZoneID = null
                },
                new AutoEventSetup
                {
                    GameType = "TeamDeathmatch",
                    EventMode = GameMode.Normal,
                    Spawnfile = "tdm_spawns_a",
                    Kit = "tdmkit",
                    CloseOnStart = false,
                    TimeToJoin = 60,
                    TimeLimit = 0,
                    MinimumPlayers = 2,
                    MaximumPlayers = 20,
                    UseClassSelector = false,
                    ZoneID = null
                },
                new AutoEventSetup
                {
                    GameType = "GunGame",
                    EventMode = GameMode.Battlefield,
                    Spawnfile = "ggspawns",
                    Kit = "ggkit",
                    CloseOnStart = false,
                    TimeToJoin = 60,
                    TimeLimit = 0,
                    MinimumPlayers = 2,
                    MaximumPlayers = 20,
                    UseClassSelector = false,
                    ZoneID = null
                },
                new AutoEventSetup
                {
                    GameType = "ChopperSurvival",
                    EventMode = GameMode.Normal,
                    Spawnfile = "csspawns",
                    Kit = "cskit",
                    CloseOnStart = true,
                    TimeToJoin = 60,
                    TimeLimit = 0,
                    MinimumPlayers = 1,
                    MaximumPlayers = 20,
                    UseClassSelector = false,
                    ZoneID = null
                }
            };
            return newautoconfiglist;
        }
        #endregion

        #region Messaging
        private void MSG(BasePlayer player, string langkey, bool title = true)
        {
            string message = $"<color={configData.Messaging_MsgColor}>{GetMessage(langkey)}</color>";
            if (title) message = $"<color={configData.Messaging_MainColor}>{GetMessage("Title")}</color>" + message;
            SendReply(player, message);
        }
        void BroadcastToChat(string msg)
        {
            ELog(msg);
            PrintToChat($"<color={configData.Messaging_MainColor}>{GetMessage("Title")}</color><color={configData.Messaging_MsgColor}>{GetMessage(msg)}</color>");
        }
        private string GetMessage(string key) => lang.GetMessage(key, this);

        [HookMethod("BroadcastEvent")]
        public void BroadcastEvent(string msg)
        {
            foreach (EventPlayer eventplayer in EventPlayers)
                SendReply(eventplayer.player, $"<color={configData.Messaging_MainColor}>" + msg + "</color>");
        }

        Dictionary<string, string> Messages = new Dictionary<string, string>
        {
            { "multipleNames", "Multiple players found"},
            { "noPlayerFound", "No players found"},
            { "MessagesEventMinPlayers", "The Event {0} has reached min players and will start in {1} seconds"},
            { "MessagesEventMaxPlayers", "The Event {0} has reached max players.You may not join for the moment"},
            { "MessagesEventStatusClosedStarted", "The Event {0} has already started, it's too late to join."},
            { "Title", "Event Manager: "},
            { "MessagesEventStatusClosedEnd", "There is currently no event"},
            { "MessagesEventStatusOpenStarted", "The Event {0} has started, but is still opened: /event join"},
            { "MessagesEventStatusOpen", "The Event {0} is currently opened for entries: /event, join"},
            { "MessagesEventCloseAndEnd", "The Event needs to be closed and ended before using this command."},
            { "MessagesEventNotAnEvent", "This Game {0} isn't registered, did you reload the game after loading Event - Core?"},
            { "MessagesEventNotInEvent", "You are not currently in the Event."},
            { "MessagesEventBegin", "Event: {0} is about to begin!"},
            { "MessagesEventLeft", "{0} has left the Event! (Total Players: {1})"},
            { "MessagesEventJoined", "{0} has joined the Event!  (Total Players: {1})"},
            { "MessagesEventAlreadyJoined", "You are already in the Event."},
            { "MessagesEventPEnd", "Event: {0} is now over, restoring players and sending them home!"},
            { "MessagesEventEnd", "All players respawned, {0} has ended!"},
            { "MessagesEventNoGamePlaying", "An Event game is not underway."},
            { "MessagesEventCancel", "The Event was cancelled!"},
            { "MessagesEventClose", "The Event entrance is now closed!"},
            { "MessagesEventOpen", "The Event is now open for : {0} !  Type /event join to join!"},
            { "MessagesPermissionsNotAllowed", "You are not allowed to use this command"},
            { "MessagesEventNotSet", "An Event game must first be chosen."},
            { "MessagesErrorSpawnfileIsNull", "The spawnfile can't be set to null"},
            { "MessagesEventNoSpawnFile", "A spawn file must first be loaded."},
            { "MessagesEventAlreadyOpened", "The Event is already open."},
            { "MessagesEventAlreadyClosed", "The Event is already closed."},
            { "MessagesEventAlreadyStarted", "An Event game has already started."},
            { "ClassSelect", "Choose your class!" },
            { "ClassNotice", "You can reopen this menu at any time by typing /event class" },
            { "CanShop", "You are not allowed to shop while in an Event" },
            { "CanTP", "You are not allowed to teleport while in an Event" },
            { "NoPlayers", "Not enough players" },
            { "NoAuto", "No Automatic Events Configured" },
            { "NoAutoInit", "No Events were successfully initialized, check that your events are correctly configured" },
            { "TimeLimit", "Time limit reached" },
            { "EventCancelled", "Event {0} was cancelled because: {1}" },
            { "EventOpen", "Event {0} in now opened, you can join it by typing /event join" },
            { "StillOpen", "Event {0} is still open, you can join it by typing /event join" },
            { "EventClosed", "The Event is currently closed." },
            { "NotInEvent", "You are not currently in the Event." },
            { "NullKitname", "You can't have a null kitname" },
            { "NoKits", "Unable to find the Kits plugin" },
            { "KitNotExist", "The kit {0} doesn't exist" },
            { "CancelAuto", "Auto events have been cancelled" }
        };
        #endregion

        #region Class Selection
        private void SelectClass(BasePlayer player)
        {
            string panelName = "ClassSelector";
            CuiHelper.DestroyUi(player, panelName);
            if (player.IsSleeping() || player.IsReceivingSnapshot() || player.IsDead())
            {                
                timer.Once(3, () => SelectClass(player));
                return;
            }            

            var Class_Element = UI.CreateElementContainer(panelName, "0.1 0.1 0.1 0.98", "0.05 0.05", "0.95 0.95", true);

            UI.CreatePanel(ref Class_Element, panelName, "0.9 0.9 0.9 0.1", "0.04 0.05", "0.96 0.94");
            UI.CreateLabel(ref Class_Element, panelName, "0.9 0.9 0.9 1.0", $"<color={configData.Messaging_MainColor}>{EventGameName}</color>", 24, "0.05 0.85", "0.95 0.92");
            UI.CreateLabel(ref Class_Element, panelName, "0.9 0.9 0.9 1.0", $"<color={configData.Messaging_MainColor}>{GetMessage("ClassSelect")}</color>", 24, "0.05 0.75", "0.95 0.83");
            UI.CreateLabel(ref Class_Element, panelName, "0.9 0.9 0.9 1.0", $"<color={configData.Messaging_MainColor}>{GetMessage("ClassNotice")}</color>", 18, "0.05 0.05", "0.95 0.12");

            int i = 0;
            foreach (var entry in classData.ClassKits)
            {
                CreateClassButton(ref Class_Element, panelName, entry.Key, entry.Value, i);
                i++;
            }

            CuiHelper.AddUi(player, Class_Element);
        }
        private void CreateClassButton(ref CuiElementContainer container, string panelName, string name, string kit, int number)
        {
            Vector2 dimensions = new Vector2(0.25f, 0.07f);
            Vector2 origin = new Vector2(0.095f, 0.6f);
            float offsetY = 0;
            float offsetX = 0;
            switch (number)
            {
                case 0:
                case 1:
                case 2:
                    offsetX = (0.03f + dimensions.x) * number;
                    break;
                case 3:
                case 4:
                case 5:
                    {
                        offsetX = (0.03f + dimensions.x) * (number - 3);
                        offsetY = (0.07f + dimensions.y) * 1;
                    }
                    break;
                case 6:
                case 7:
                case 8:
                    {
                        offsetX = (0.03f + dimensions.x) * (number - 6);
                        offsetY = (0.07f + dimensions.y) * 2;
                    }
                    break;
            }
            Vector2 offset = new Vector2(offsetX, -offsetY);

            Vector2 posMin = origin + offset;
            Vector2 posMax = posMin + dimensions;

            UI.CreateButton(ref container, panelName, "0.2 0.2 0.2 0.7", name, 18, posMin.x + " " + posMin.y, posMax.x + " " + posMax.y, $"Choose_Class {kit}");
        }

        [ConsoleCommand("Choose_Class")]
        void cmdChoose_Class(ConsoleSystem.Arg arg)
        {
            var player = arg.connection.player as BasePlayer;
            if (player == null)
                return;
            CuiHelper.DestroyUi(player, "ClassSelector");
            var className = arg.GetString(0).Replace("'", "");
            bool noGear = false;
            if (string.IsNullOrEmpty(player.GetComponent<EventPlayer>().currentClass)) noGear = true;
            player.GetComponent<EventPlayer>().currentClass = className;
            if (noGear) GivePlayerKit(player, null);
        }
        #endregion

        #region Game Timer UI
        private void StartTimer(int time)
        {
            AutoArenaTimers.Add(timer.Once(time, () => CancelEvent(GetMessage("TimeLimit"))));
            PlayTimer = time;
            foreach (var player in EventPlayers)
                TimerCountdown(player.player);
        }
        private void TimerCountdown(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "PlayTimer");
            if (EventStarted)
            {
                var timerElement = UI.CreateElementContainer("PlayTimer", "0.3 0.3 0.3 0.6", "0.45 0.91", "0.55 0.948", false);
                TimeSpan dateDifference = TimeSpan.FromSeconds(PlayTimer);
                string clock = string.Format("{0:D2}:{1:D2}", dateDifference.Minutes, dateDifference.Seconds);
                UI.CreateLabel(ref timerElement, "PlayTimer", "", clock, 20, "0 0", "1 1");
                CuiHelper.AddUi(player, timerElement);
                PlayTimer--;
                AutoArenaTimers.Add(timer.In(1, () => TimerCountdown(player)));
            }
        }
        private void DestroyUI(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, "ClassSelector");
            CuiHelper.DestroyUi(player, "PlayTimer");
        }
        #endregion

        #region Global Functions
        bool hasAccess(ConsoleSystem.Arg arg)
        {
            if (arg.connection?.authLevel < 1)
            {
                SendReply(arg, GetMessage("MessagesPermissionsNotAllowed"));
                return false;
            }
            return true;
        }
        static void TPPlayer(BasePlayer player, Vector3 destination)
        {        
            if (player.net?.connection != null)
                player.ClientRPCPlayer(null, player, "StartLoading", null, null, null, null, null);
            ELog($"Teleporting {player.displayName} to {destination}");
            StartSleeping(player);
            player.MovePosition(destination);
            if (player.net?.connection != null)
                player.ClientRPCPlayer(null, player, "ForcePositionTo", destination);
            player.TransformChanged();
            if (player.net?.connection != null)
                player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
            player.UpdateNetworkGroup();
            player.SendNetworkUpdateImmediate(false);
            if (player.net?.connection == null) return;
            try { player.ClearEntityQueue(null); } catch { }
            player.SendFullSnapshot();
        }
        static void StartSleeping(BasePlayer player)
        {
            if (player.IsSleeping())
                return;
            ELog($"Put {player.displayName} to sleep");
            player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
            if (!BasePlayer.sleepingPlayerList.Contains(player))
                BasePlayer.sleepingPlayerList.Add(player);
            player.CancelInvoke("InventoryUpdate");
        }
        #endregion

        #region Player Management
        [HookMethod("TeleportAllPlayersToEvent")]
        public void TeleportAllPlayersToEvent()
        {
            ELog("TeleportAllPlayersToEvent");
            foreach (EventPlayer eventplayer in EventPlayers.ToArray())
                TeleportPlayerToEvent(eventplayer.player);
        }

        void TeleportPlayerToEvent(BasePlayer player)
        {
            var eventPlayer = player.GetComponent<EventPlayer>();
            if (eventPlayer == null || player.net?.connection == null) return;
            ELog($"Tp2Event {player.displayName}");
            var targetpos = Spawns.Call("GetRandomSpawn", EventSpawnFile);
            if (targetpos is string)
                return;
            var newpos = Interface.Oxide.CallHook("EventChooseSpawn", player, targetpos);
            if (newpos is Vector3)
                targetpos = newpos;
            if (newpos is bool)
                if ((bool)newpos == false)
                {
                    ELog($"Tp2Event {player.displayName} newpos is false");
                    timer.Once(3, () => TeleportPlayerToEvent(player));
                        return;
                }
            if (!configData.KillDeserters)
                ZoneManager?.Call("AddPlayerToZoneKeepinlist", ZoneName, player);

           
            TPPlayer(player, (Vector3)targetpos);

            Interface.Oxide.CallHook("OnEventPlayerSpawn", player);
        }
        void SaveAllInventories()
        {
            ELog($"SaveAllInventories");
            foreach (EventPlayer player in EventPlayers)
                player?.SaveInventory();
        }
        void SaveAllPlayerStats()
        {
            ELog($"SaveAllStats");
            foreach (EventPlayer player in EventPlayers)
                player?.SaveHealth();
        }
        void SaveAllHomeLocations()
        {
            ELog($"SaveAllHomes");
            foreach (EventPlayer player in EventPlayers)
                player?.SaveHome();
        }
        void SetAllEventPlayers()
        {
            ELog($"SetAllPlayers");
            foreach (EventPlayer player in EventPlayers)
                SetEventPlayer(player);
        }      
        void RedeemInventory(BasePlayer player)
        {            
            EventPlayer eventplayer = player.GetComponent<EventPlayer>();
            if (eventplayer == null) return;
            ELog($"Redeem Inventory {player.displayName}");
            if (player.IsDead() || player.health < 1)
            {
                ELog($"RI {player.displayName} is dead");
                timer.Once(5, () => RedeemInventory(player));
                return;
            }
            eventplayer.player.inventory.Strip();
            if (eventplayer.savedInventory)
                eventplayer.RestoreInventory();
        }
        void TeleportPlayerHome(BasePlayer player)
        {            
            EventPlayer eventplayer = player.GetComponent<EventPlayer>();
            if (eventplayer == null) return;
            ELog($"TPPlayerHome {player.displayName}");
            if (player.IsDead() || player.health < 1)
            {
                ELog($"TPPH {player.displayName} is dead");
                return;
            }
            if (eventplayer.savedHome)
                eventplayer.TeleportHome();
        }
        void TryErasePlayer(BasePlayer player)
        {            
            var eventplayer = player.GetComponent<EventPlayer>();
            if (eventplayer == null) return;
            ELog($"TryErase {player.displayName}");
            if (!(eventplayer.inEvent) && !(eventplayer.savedHome) && !(eventplayer.savedInventory))
            {
                ELog($"{player.displayName} !inevent/savedhome/savedinventory");
                eventplayer.enabled = false;
                EventPlayers.Remove(eventplayer);
                UnityEngine.Object.Destroy(eventplayer);
            }
        }
        [HookMethod("GivePlayerKit")]
        public void GivePlayerKit(BasePlayer player, string GiveKit)
        {
            ELog($"give {player.displayName} kit");
            player.inventory.Strip();
            if (!AutoEventLaunched)
            {                
                if (!UseClassSelection)
                    Kits.Call("GiveKit", player, GiveKit);
                else
                {
                    if (string.IsNullOrEmpty(player.GetComponent<EventPlayer>().currentClass))
                        SelectClass(player);
                    else GiveClassKit(player);
                }
            }
            else
            {
                if (!configData.z_AutoEvents.z_AutoEventSetup[EventAutoNum].UseClassSelector)
                    Kits.Call("GiveKit", player, configData.z_AutoEvents.z_AutoEventSetup[EventAutoNum].Kit);
                else
                {
                    if (string.IsNullOrEmpty(player.GetComponent<EventPlayer>().currentClass))
                        SelectClass(player);
                    else GiveClassKit(player);
                }
            }
        }
        private void GiveClassKit(BasePlayer player)
        {
            ELog($"Give class kit {player.displayName}");
            Kits.Call("GiveKit", player, player.GetComponent<EventPlayer>().currentClass);
            Interface.Oxide.CallHook("OnPlayerSelectClass", player);
        }
        void EjectPlayer(BasePlayer player)
        {
            ELog($"Ejecting {player.displayName}");
            if (player.IsAlive())
            {
                ELog($"Eject Alive {player.displayName}");
                player.SetPlayerFlag(BasePlayer.PlayerFlags.Wounded, false);
                player.CancelInvoke("WoundingEnd");
                player.metabolism.bleeding.value = 0f;
            }
            if (!configData.KillDeserters)
                if (!string.IsNullOrEmpty(ZoneName))
                    ZoneManager?.Call("RemovePlayerFromZoneKeepinlist", ZoneName, player);

            player.GetComponent<EventPlayer>().inEvent = false;
            Interface.Oxide.CallHook("DisableBypass", player.userID);
        }    
        void RestorePlayerHealth(BasePlayer player)
        {
            ELog($"Restoring health {player.displayName}");
            EventPlayer eventplayer = player.GetComponent<EventPlayer>();
            if (eventplayer)
            {
                ELog($"RH {player.displayName} is event player");
                player.health = eventplayer.health;
                player.metabolism.calories.value = eventplayer.calories;
                player.metabolism.hydration.value = eventplayer.hydration;
                player.metabolism.bleeding.value = 0;
                player.metabolism.SendChangesToClient();
            }
        }
        #endregion

        #region Event Management
        [HookMethod("OpenEvent")]
        public object OpenEvent()
        {
            if (EventOpen)
                return $"{EventGameName} is already open";
            ELog($"Opening Event {EventGameName}");

            var success = Interface.Oxide.CallHook("CanEventOpen");
            if (success is string)
                return (string)success;
            
            EventOpen = true;
            EventPlayers = new List<EventPlayer>();

            var name = EventGameName;
            if (EventMode == GameMode.Battlefield)
                name = "Battlefield - ";
            BroadcastToChat(string.Format(GetMessage("MessagesEventOpen"), name));
            Interface.Oxide.CallHook("OnEventOpenPost");
                     
            ELog($"Game type: {EventMode}");
            ELog($"AutoEvent: {AutoEventLaunched}");
            ELog($"{EventGameName} Successfully opened");

            return true;
        }
        void OnEventOpenPost() => OnEventOpenPostAutoEvent();
        void OnEventOpenPostAutoEvent()
        {
            if (!AutoEventLaunched) return;
            ELog($"Start auto event timers");
            DestroyTimers();
            var autocfg = configData.z_AutoEvents;
            if (autocfg.AutoCancel_Timer != 0)
                AutoArenaTimers.Add(timer.Once(autocfg.AutoCancel_Timer, () => CancelEvent(GetMessage("NoPlayers"))));
            AutoArenaTimers.Add(timer.Repeat(configData.AnnounceEvent_Interval, 0, AnnounceEvent));
        }
        object CanEventOpen()
        {
            if (EventGameName == null) return GetMessage("MessagesEventNotSet");
            else if (EventSpawnFile == null) return GetMessage("MessagesEventNoSpawnFile");
            else if (EventOpen) return GetMessage("MessagesEventAlreadyOpened");

            object success = Spawns.Call("GetSpawnsCount", EventSpawnFile);
            if (success is string)
                return (string)success;
            return null;
        }

        [HookMethod("CloseEvent")]
        public object CloseEvent()
        {
            if (!EventOpen) return GetMessage("MessagesEventAlreadyClosed");
            EventOpen = false;
            Interface.Oxide.CallHook("OnEventClosePost");
            if (EventStarted)
                BroadcastToChat(GetMessage("MessagesEventClose"));
            else
                BroadcastToChat(GetMessage("MessagesEventCancel"));
            return true;
        }
        object AutoEventNext()
        {
            ELog($"Next auto event");
            if (configData.z_AutoEvents.z_AutoEventSetup.Count == 0)
            {
                ELog($"No events setup");
                AutoEventLaunched = false;
                return GetMessage("NoAuto");
            }
            bool successful = false;
            for (int i = 0; i < configData.z_AutoEvents.z_AutoEventSetup.Count; i++)
            {
                EventAutoNum++;
                if (EventAutoNum >= configData.z_AutoEvents.z_AutoEventSetup.Count) EventAutoNum = 0;

                var autocfg = configData.z_AutoEvents.z_AutoEventSetup[EventAutoNum];

                object success = SelectEvent(autocfg.GameType);
                if (success is string) { continue; }

                success = SelectSpawnfile(autocfg.Spawnfile);
                if (success is string) { continue; }

                success = SelectMinplayers(autocfg.MinimumPlayers);
                if (success is string) { continue; }

                success = SelectMaxplayers(autocfg.MaximumPlayers);
                if (success is string) { continue; }

                success = Interface.Oxide.CallHook("CanEventOpen");
                if (success is string) { continue; }

                if (!string.IsNullOrEmpty(autocfg.ZoneID))
                    ZoneName = autocfg.ZoneID;

                successful = true;
                break;
            }
            if (!successful)
            {
                ELog($"No events init");
                return GetMessage("NoAutoInit");
            }
            ELog($"Auto init success");
            AutoArenaTimers.Add(timer.Once(configData.z_AutoEvents.GameInterval, () => OpenEvent()));
            return null;
        }
        void OnEventStartPost()
        {
            ELog($"Event starting");
            DestroyTimers();
            if (AutoEventLaunched)
                OnEventStartPostAutoEvent();
            else if (EventMode == GameMode.Battlefield)
                StartTimer(configData.Battlefield_Timer);
            if (configData.AnnounceDuring_Event)
                AutoArenaTimers.Add(timer.Repeat(configData.AnnounceEvent_Interval, 0, () => AnnounceDuringEvent()));
        }
        void OnEventStartPostAutoEvent()
        {           
            if (configData.z_AutoEvents.z_AutoEventSetup[EventAutoNum].TimeLimit != 0)
                StartTimer(configData.z_AutoEvents.z_AutoEventSetup[EventAutoNum].TimeLimit);
        }
        void DestroyTimers()
        {
            ELog($"Destroying timers");
            foreach (Timer eventtimer in AutoArenaTimers)
                eventtimer.Destroy();
            AutoArenaTimers.Clear();
        }
        void CancelEvent(string reason)
        {
            ELog($"Cancelling event");
            var message = GetMessage("EventCancelled");
            object success = Interface.Oxide.CallHook("OnEventCancel");
            if (success != null)
            {
                if (success is string)
                    message = (string)success;
                else
                    return;
            }
            BroadcastToChat(string.Format(message, EventGameName, reason));
            DestroyTimers();
            if (EventStarted)
                EndEvent();
            else if (AutoEventLaunched)
                AutoEventNext();
        }
        void AnnounceEvent()
        {
            var message = GetMessage("EventOpen");
            object success = Interface.Oxide.CallHook("OnEventAnnounce");
            if (success is string)
            {
                message = (string)success;
            }
            BroadcastToChat(string.Format(message, EventGameName));
        }
        void AnnounceDuringEvent()
        {
            if (configData.AnnounceDuring_Event)
            {
                if (EventOpen && EventStarted)
                {
                    var message = GetMessage("StillOpen");
                    foreach (BasePlayer player in BasePlayer.activePlayerList)
                    {
                        if (!player.GetComponent<EventPlayer>())
                            SendReply(player, string.Format(message, EventGameName));
                    }
                }
            }
        }
        object LaunchEvent()
        {
            ELog($"Launching auto events");
            AutoEventLaunched = true;
            if (!EventStarted)
            {
                if (!EventOpen)
                {
                    object success = AutoEventNext();
                    if (success is string)                    
                        return (string)success;
                    
                    success = OpenEvent();
                    if (success is string)                    
                        return (string)success;                    
                }
                else OnEventOpenPostAutoEvent();
            }
            else OnEventStartPostAutoEvent();
            ELog($"Launch successful");
            return null;
        }

        [HookMethod("EndEvent")]
        public object EndEvent()
        {
            if (EventEnded) return GetMessage("MessagesEventNoGamePlaying");
            ELog($"Ending event");
            foreach (var player in EventPlayers)
                Interface.Oxide.CallHook("DestroyUI", player.player);

            BroadcastToChat(string.Format(GetMessage("MessagesEventPEnd"), EventGameName));
            EventOpen = false;
            EventStarted = false;
            EventPending = false;
            EventEnded = true;
            EnableGod();
            BroadcastToChat(string.Format(GetMessage("MessagesEventEnd"), EventGameName));
            Interface.Oxide.CallHook("OnEventEndPre");
            ProcessPlayers();
            return true;
        }       
        void ProcessPlayers()
        {
            ELog($"Processing players");
            for (int i = 0; i < EventPlayers.Count; i++)
                RestorePlayer(EventPlayers[i]);

            timer.Once(5, () =>
            {
                if (EventPlayers.Count > 0)
                {
                    ELog($"EventPlayers.Count > 0, count is {EventPlayers.Count}");
                    ProcessPlayers();
                    return;
                }
                ELog($"EventPlayers.Count is 0");
                DestroyGame();
                Interface.Oxide.CallHook("OnEventEndPost");
            });

            
        }
        void RestorePlayer(EventPlayer p)
        {            
            if (p == null) return;
            ELog($"Restoring {p.player.displayName}");
            if (p.player.IsDead() || !p.player.IsAlive())
            {
                ELog($"RP {p.player.displayName} is dead");
                var pos = Spawns.Call("GetRandomSpawn", EventSpawnFile);
                if (pos is Vector3) p.player.RespawnAt((Vector3)pos, new Quaternion());
                else p.player.Respawn();
                return;
            }
            if (p.player.IsWounded() || p.player.health < 2)
            {
                ELog($"RP {p.player.displayName} is wounded");
                p.player.SetPlayerFlag(BasePlayer.PlayerFlags.Wounded, false);
                RestorePlayerHealth(p.player);
                return;
            }
            if (p.player.IsSleeping())
            {
                ELog($"RP {p.player.displayName} is sleeping");
                p.player.EndSleeping();
                return;
            }
            ELog($"Starting restoration of {p.player.displayName}");
            p.RestoreInventory();
            p.TeleportHome();
            RestorePlayerHealth(p.player);
            Godmode.Remove(p.player.userID);
            if (!p.savedHome && !p.savedInventory)
            {
                ELog($"{p.player.displayName} has no saved home or inv, try erase");
                EjectPlayer(p.player);
                TryErasePlayer(p.player);
            }            
        }
        
        void EnableGod()
        {
            Godmode = new List<ulong>();
            foreach (EventPlayer player in EventPlayers)
            {
                ELog($"Godmode added {player.player.displayName}");
                Godmode.Add(player.player.userID);
                player.player.metabolism.bleeding.value = 0;
                player.player.metabolism.SendChangesToClient();
            }
        }
        void DisableGod()
        {      
            Godmode.Clear();
        }
        void DestroyGame()
        {
            ELog($"Destroying game");
            DestroyTimers();
            EventPlayers.Clear();
   
// ... [Code preview truncated due to length. Full source in attached file] ...

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