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

FREE ArenaEvents : 0.1.65 0.1.65

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
 //Requires: ArenaStatistics
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Globalization;
using System.Reflection;
using Oxide.Core;
using Oxide.Core.Configuration;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.AI;
namespace Oxide.Plugins {
    [Info("Arena Events", "k1lly0u", "0.1.65")]
    [Description("Logic controllers from Arena events")]
    class ArenaEvents : RustPlugin {
#region Fields
        StoredData storedData;
        private DynamicConfigFile data;
        public static Arena Arena;
        public static ArenaStatistics Statistics;
        public static ArenaEvents ins;
        private static NavMeshHit navHit;
        private static FieldInfo _brain = typeof(global : : HumanNPC).GetField("_brain", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        private static FieldInfo _memory = typeof(HumanNPC).GetField("myMemory", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
        private static FrameBudgeter frameBudgeter;
        private const string FLAG_PREFAB = "assets/prefabs/deployable/signs/sign.post.double.prefab";
        private const string SCIENTIST_PREFAB = "assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc.prefab";
        static bool isUnloading;
#endregion
#region Oxide Hooks
        private void Loaded() {
            data = Interface.Oxide.DataFileSystem.GetFile("Arena/event_specific_data");
            ToggleHookSubscription(false);
            isUnloading = false;
        }
        private void OnServerInitialized() {
            ins = this;
            LoadData();
            frameBudgeter = new GameObject("ArenaEvents.NPCFrameBudgeter").AddComponent<FrameBudgeter>();
        }
        private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (entity != null && info != null) {
                CTF.CTFFlag ctfFlag = entity.GetComponent<CTF.CTFFlag>() ?? entity.GetComponentInParent<CTF.CTFFlag>();
                if (ctfFlag != null) Arena.NullifyDamage(info);
            }
        }
        private void OnEntityDeath(ScientistNPC entity, HitInfo info) {
            if (entity == null) return;
            NPCSurvival.NPCController npcController = entity.GetComponent<NPCSurvival.NPCController>();
            if (npcController != null) npcController.eventGame.OnNpcDeath(entity, info);
        }
        private void OnEntitySpawned(BaseNetworkable entity) {
            if (Arena == null || entity == null) return;
            if (entity.GetComponent<LootableCorpse>()) {
                foreach (KeyValuePair<string, Arena.EventManager> eventGame in Arena.events) {
                    if (eventGame.Value is NPCSurvival && eventGame.Value.IsEventNPC((entity as LootableCorpse).playerSteamID)) {
                        eventGame.Value.OnNpcCorpseSpawned(entity as LootableCorpse);
                        break;
                    }
                }
            }
        }
        private object OnPlayerDropActiveItem(BasePlayer player, Item item) {
            NPCPlayer npcPlayer = player?.GetComponent<NPCPlayer>();
            if (npcPlayer != null) {
                foreach (KeyValuePair<string, Arena.EventManager> eventGame in Arena.events) {
                    if (eventGame.Value is NPCSurvival) {
                        if (eventGame.Value.IsEventNPC(player.userID)) return false;
                    }
                }
            }
            return null;
        }
        private object OnNpcTarget(global : : HumanNPC npcPlayer, BaseEntity target) {
            NPCSurvival.NPCController monitor = npcPlayer?.GetComponent<NPCSurvival.NPCController>();
            if (monitor != null) {
                return monitor.CanTargetEntity(target);
            }
            return null;
        }
        // Used for Slasher game mode to make it night time, disabled until spectate has been fixed
        //private object CanNetworkTo(BaseNetworkable entity, BasePlayer player)
        //{
        //    if (!(entity is EnvSync))
        //        return null;
        //    Arena.EventPlayer eventPlayer = Arena.GetUser(player);
        //    if (eventPlayer == null)
        //        return null;
        //    Slasher manager = Arena.GetEvent(eventPlayer.currentEvent) as Slasher;
        //    if (manager == null)
        //        return null;
        //    if (manager.matchStatus == Slasher.MatchStatus.Pending)
        //        return null;
        //    EnvSync env = entity as EnvSync;
        //    if (Net.sv.write.Start())
        //    {
        //        Connection connection = player.net.connection;
        //        connection.validate.entityUpdates = connection.validate.entityUpdates + 1;
        //        BaseNetworkable.SaveInfo saveInfo = new BaseNetworkable.SaveInfo
        //        {
        //            forConnection = player.net.connection,
        //            forDisk = false
        //        };
        //        Net.sv.write.PacketID(Message.Type.Entities);
        //        Net.sv.write.UInt32(player.net.connection.validate.entityUpdates);
        //        using (saveInfo.msg = Pool.Get<Entity>())
        //        {
        //            env.Save(saveInfo);
        //            saveInfo.msg.environment.dateTime = manager.timeSync;
        //            saveInfo.msg.ToProto(Net.sv.write);
        //            env.PostSave(saveInfo);
        //            Net.sv.write.Send(new SendInfo(player.net.connection));
        //        }
        //    }
        //    return false;
        //}
        private void Unload() {
            if (Arena != null) Arena.isUnloading = true;
            UnityEngine.Object.Destroy(frameBudgeter.gameObject);
            isUnloading = true;
            ins = null;
            Statistics = null;
            Arena = null;
        }
#endregion
#region NPC Logic Limiter
        private class FrameBudgeter : MonoBehaviour {
            private double maxMilliseconds = 1f;
            private Stopwatch sw = Stopwatch.StartNew();
            private int lastIndex = 0;
            private void Update() {
                sw.Reset();
                sw.Start();
                int count = NPCSurvival.NPCController.allNpcs?.Count ?? 0;
                if (lastIndex >= count) lastIndex = 0;
                for (int i = lastIndex; i < count; i++) {
                    if (sw.Elapsed.TotalMilliseconds > maxMilliseconds) {
                        lastIndex = i;
                        return;
                    }
                    NPCSurvival.NPCController.allNpcs[i]?.DoUpdate();
                }
                lastIndex = 0;
            }
        }
#endregion
#region Functions
        private void ToggleHookSubscription(bool enabled) {
            if (enabled) {
                Subscribe(nameof(OnEntityTakeDamage));
                Subscribe(nameof(OnEntityDeath));
                Subscribe(nameof(OnEntitySpawned));
                Subscribe(nameof(OnPlayerDropActiveItem));
            }
            else {
                Unsubscribe(nameof(OnEntityTakeDamage));
                Unsubscribe(nameof(OnEntityDeath));
                Unsubscribe(nameof(OnEntitySpawned));
                Unsubscribe(nameof(OnPlayerDropActiveItem));
            }
        }
        public void RegisterEvents(Arena arena) {
            Arena = arena;
            Statistics = Arena.Statistics;
            ToggleHookSubscription(true);
            Arena.eventTypes.Add("Free For All");
            Arena.eventTypes.Add("Team Deathmatch");
            Arena.eventTypes.Add("Survival");
            Arena.eventTypes.Add("Team Survival");
            Arena.eventTypes.Add("GunGame");
            Arena.eventTypes.Add("One in the Chamber");
            Arena.eventTypes.Add("Capture the Flag");
            Arena.eventTypes.Add("NPC Survival");
            //Arena.eventTypes.Add("Slasher"); Disabled until spectate is fixed...//Arena.eventTypes.Add("Infected");
            Arena.additionalParameters.Add("GunGame", new List<Arena.AdditionalParamData> {
                new Arena.AdditionalParamData {
                    field = "Weapon Set", isRequired = true, type = "string", useSelector = true, selectorHook = "GetWeaponSets", selectorDesc = "Select a weapon set", useInput = false
                }
                , new Arena.AdditionalParamData {
                    field = "Use Downgrade Weapon", isRequired = true, type = "bool", useToggle = true
                }
                , new Arena.AdditionalParamData {
                    field = "Player Gear", isRequired = true, type = "string", useSelector = true, selectorDesc = "Select a kit for the players gear (No Weapons)", selectorHook = "GetAllKits"
                }
            }
            );
            Arena.additionalParameters.Add("One in the Chamber", new List<Arena.AdditionalParamData> {
                new Arena.AdditionalParamData {
                    field = "Player Lives", isRequired = true, requireValue = true, type = "int", useInput = true
                }
                , new Arena.AdditionalParamData {
                    field = "Player Gear", isRequired = true, type = "string", useSelector = true, selectorDesc = "Select a kit for the players gear (No Weapons)", selectorHook = "GetAllKits"
                }
                , new Arena.AdditionalParamData {
                    field = "Primary Weapon", isRequired = true, type = "string", useSelector = true, selectorHook = "GetAllWeapons", selectorDesc = "Select a primary weapon.This will be the weapon that receives bullets for kills",
                }
                , new Arena.AdditionalParamData {
                    field = "Secondary Weapon", isRequired = true, type = "string", useSelector = true, selectorHook = "GetAllWeapons", selectorDesc = "Select a secondary weapon.This will be the weapon that you use when you run out of bullets",
                }
                ,
            }
            );
            Arena.additionalParameters.Add("NPC Survival", new List<Arena.AdditionalParamData> {
                new Arena.AdditionalParamData {
                    field = "Player Lives", isRequired = true, requireValue = true, type = "int", useInput = true
                }
                , new Arena.AdditionalParamData {
                    field = "Rounds to Play", isRequired = true, requireValue = true, type = "int", useInput = true
                }
                , new Arena.AdditionalParamData {
                    field = "NPCs to Spawn", isRequired = true, requireValue = true, type = "int", useInput = true
                }
                , new Arena.AdditionalParamData {
                    field = "Additional NPCs (per round)", isRequired = true, type = "int", useInput = true
                }
                , new Arena.AdditionalParamData {
                    field = "NPC Spawnfile", isRequired = true, type = "string", useSelector = true, selectorHook = "GetSpawnfileNames", selectorDesc = "Select a spawnfile for NPCs",
                }
                , new Arena.AdditionalParamData {
                    field = "Use Scientists", isRequired = true, type = "bool", useToggle = true
                }
                , new Arena.AdditionalParamData {
                    field = "Use Murderers", isRequired = true, type = "bool", useToggle = true
                }
            }
            );
            Arena.additionalParameters.Add("Infected", new List<Arena.AdditionalParamData>() {
                new Arena.AdditionalParamData {
                    field = "Infected Kit", isRequired = true, type = "string", useSelector = true, selectorDesc = "Select a kit for the infected", selectorHook = "GetAllKits"
                }
                , new Arena.AdditionalParamData {
                    field = "Infected Spawnfile", isRequired = true, type = "string", useSelector = true, selectorHook = "GetSpawnfileNames", selectorDesc = "Select a spawnfile for the infected",
                }
                , new Arena.AdditionalParamData {
                    field = "Survivors start with random weapon", isRequired = true, type = "bool", useToggle = true
                }
                , new Arena.AdditionalParamData {
                    field = "Round Timer", isRequired = true, requireValue = true, type = "int", useInput = true
                }
                ,
            }
            );
            //Arena.additionalParameters.Add("Slasher", new List<Arena.AdditionalParamData>
            //    {
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Rounds to Play",
            //            isRequired = true,
            //            requireValue = true,
            //            type = "int",
            //            useInput = true
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Slasher Kill Timer (seconds)",
            //            isRequired = true,
            //            requireValue = true,
            //            type = "int",
            //            useInput = true
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Player Kill Timer (seconds)",
            //            isRequired = true,
            //            requireValue = true,
            //            type = "int",
            //            useInput = true
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Slasher Weapon",
            //            isRequired = true,
            //            type = "string",
            //            useSelector = true,
            //            selectorHook = "GetAllWeapons",
            //            selectorDesc = "Select the weapon the slasher will use.This weapon will be automatically equipped with a flashlight",
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Slasher Kit",
            //            isRequired = true,
            //            type = "string",
            //            useSelector = true,
            //            selectorDesc = "Select a kit for the slasher (no weapons)",
            //            selectorHook = "GetAllKits"
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Slasher Spawnfile",
            //            isRequired = true,
            //            type = "string",
            //            useSelector = true,
            //            selectorHook = "GetSpawnfileNames",
            //            selectorDesc = "Select a spawnfile for the slasher",
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Player Kit",
            //            isRequired = true,
            //            type = "string",
            //            useSelector = true,
            //            selectorDesc = "Select a kit for the hunted (no weapons)",
            //            selectorHook = "GetAllKits"
            //        },
            //        new Arena.AdditionalParamData
            //        {
            //            field = "Player Damage Modifier",
            //            isRequired = true,
            //            requireValue = true,
            //            type = "float",
            //            useInput = true
            //        },
            //    });
        }
        public object SetEventMode(string eventName, GameObject eventManager) {
            switch (eventName) {
                case "Free For All" : eventManager.gameObject.AddComponent<FreeForAll>();
                return true;
                case "Team Deathmatch" : eventManager.gameObject.AddComponent<TDM>();
                return true;
                case "Survival" : eventManager.gameObject.AddComponent<Survival>();
                return true;
                case "Team Survival" : eventManager.gameObject.AddComponent<TeamSurvival>();
                return true;
                case "One in the Chamber" : eventManager.gameObject.AddComponent<OITC>();
                return true;
                case "GunGame" : eventManager.gameObject.AddComponent<GunGame>();
                return true;
                case "Capture the Flag" : eventManager.gameObject.AddComponent<CTF>();
                return true;
                case "NPC Survival" : eventManager.gameObject.AddComponent<NPCSurvival>();
                return true;
                //case "Slasher":
                //    eventManager.gameObject.AddComponent<Slasher>();
                //    return true;
                case "Infected" : eventManager.gameObject.AddComponent<Infected>();
                return true;
                default : break;
            }
            return null;
        }
        private string[] GetWeaponSets() => storedData.gungameSets.Keys.ToArray();
        private string[] GetAllWeapons() => ItemManager.itemList.Where(x => x.category == ItemCategory.Weapon).Select(x => x.shortname).ToArray();
#endregion
#region Event Require Checks
        public bool IsTeamEvent(string eventType) {
            if (eventType == "Team Deathmatch" || eventType == "Team Survival" || eventType == "Capture the Flag") return true;
            return false;
        }
        public bool IsSurvivalEvent(string eventType) {
            if (eventType == "Survival" || eventType == "Team Survival" || eventType == "One in the Chamber" || eventType == "NPC Survival") return true;
            return false;
        }
        public bool IgnoreKillLimit(string eventType) {
            if (eventType == "Survival" || eventType == "Team Survival" || eventType == "One in the Chamber" || eventType == "GunGame" || eventType == "NPC Survival" || eventType == "Slasher" || eventType == "Infected") return true;
            return false;
        }
        public bool IgnoreTimeLimit(string eventType) {
            if (eventType == "Slasher" || eventType == "Infected") return true;
            return false;
        }
        public bool IgnoreKitSelection(string eventType) {
            if (eventType == "One in the Chamber" || eventType == "GunGame" || eventType == "Slasher") return true;
            return false;
        }
        public bool IgnoreClassSelector(string eventType) {
            if (eventType == "One in the Chamber" || eventType == "GunGame" || eventType == "NPC Survival" || eventType == "Slasher" || eventType == "Infected") return true;
            return false;
        }
        public bool RequiresTimeOrKillLimit(string eventType) {
            if (eventType == "Team Deathmatch" || eventType == "Free For All" || eventType == "Capture the Flag") return true;
            return false;
        }
#endregion
#region Game Modes
#region Free For All
        private class FreeForAll : Arena.EventManager {
            private Arena.EventPlayer winner = null;
            public override void Prestart() {
                winner = null;
                base.Prestart();
            }
            public override void JoinEvent(Arena.EventPlayer eventPlayer, Arena.Team team = Arena.Team.None) {
                if (eventPlayers.Contains(eventPlayer)) return;
                eventPlayer.ResetStats();
                eventPlayer.team = team;
                eventPlayers.Add(eventPlayer);
                BroadcastToPlayers("joinevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.JoinEvent(eventPlayer, team);
                switch (status) {
                    case Arena.EventStatus.Pending : if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                    else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    return;
                    case Arena.EventStatus.Finished : if (eventPlayers.Count >= config.minimumPlayers && status == Arena.EventStatus.Finished) {
                        BroadcastToPlayers("playersreached", new string[] {
                            Arena.configData.GameTimers.MatchPrestart[config.eventType].ToString()
                        }
                        , true);
                        Prestart();
                    }
                    else {
                        if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                        else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    }
                    return;
                    case Arena.EventStatus.Started : SpawnPlayer(eventPlayer, true, true);
                    return;
                }
            }
            public override void LeaveEvent(Arena.EventPlayer eventPlayer) {
                if (status != Arena.EventStatus.Finished) BroadcastToPlayers("leftevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.LeaveEvent(eventPlayer);
            }
            public override void OnPlayerDeath(Arena.EventPlayer victim, BasePlayer attacker = null, HitInfo info = null) {
                if (victim == null) return;
                victim.AddDeath();
                if (attacker != null) {
                    Arena.EventPlayer attackerPlayer = Arena.GetUser(attacker);
                    if (attackerPlayer != null && victim != attackerPlayer) {
                        attackerPlayer.AddKill();
                        if (config.killLimit > 0 && attackerPlayer.kills >= config.killLimit) {
                            winner = attackerPlayer;
                            EndMatch();
                            return;
                        }
                    }
                }
                UpdateScoreboard();
                base.OnPlayerDeath(victim, attacker);
            }
            public override void EndMatch() {
                if (isUnloading || (Arena != null && Arena.isUnloading)) return;
                if (winner == null) {
                    if (eventPlayers.Count > 0) {
                        int kills = 0;
                        int deaths = 0;
                        foreach (Arena.EventPlayer eventPlayer in eventPlayers) {
                            if (eventPlayer.kills > kills) {
                                winner = eventPlayer;
                                kills = eventPlayer.kills;
                                deaths = eventPlayer.deaths;
                            }
                            else if (eventPlayer.kills == kills) {
                                if (eventPlayer.deaths < deaths) {
                                    winner = eventPlayer;
                                    kills = eventPlayer.kills;
                                    deaths = eventPlayer.deaths;
                                }
                            }
                        }
                    }
                }
                List<ulong> losers = eventPlayers.Select(x => x.player.userID).ToList();
                if (winner != null) {
                    Statistics.OnEventWin(new List<ulong> {
                        winner.player.userID
                    }
                    , config);
                    BroadcastWinners("globalwin", new string[] {
                        winner.player.displayName, config.eventName
                    }
                    );
                    losers.Remove(winner.player.userID);
                }
                Statistics.OnEventLose(losers, config);
                foreach (Arena.EventPlayer eventPlayer in eventPlayers) Statistics.OnGamePlayed(eventPlayer.player.userID, config);
                base.EndMatch();
            }
        }
#endregion
#region Team Deathmatch
        private class TDM : Arena.EventManager {
            public int teamAKills;
            public int teamBKills;
            public override void Prestart() {
                teamAKills = 0;
                teamBKills = 0;
                base.Prestart();
            }
            public override void StartMatch() {
                BalanceTeams();
                base.StartMatch();
            }
            public override void JoinEvent(Arena.EventPlayer eventPlayer, Arena.Team team = Arena.Team.None) {
                if (eventPlayers.Contains(eventPlayer)) return;
                eventPlayer.ResetStats();
                Arena.LockInventory(eventPlayer.player);
                eventPlayer.team = team;
                eventPlayers.Add(eventPlayer);
                BroadcastToPlayers("joinevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.JoinEvent(eventPlayer, team);
                switch (status) {
                    case Arena.EventStatus.Pending : if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                    else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    return;
                    case Arena.EventStatus.Finished : if (eventPlayers.Count >= config.minimumPlayers && status == Arena.EventStatus.Finished) {
                        BroadcastToPlayers("playersreached", new string[] {
                            Arena.configData.GameTimers.MatchPrestart[config.eventType].ToString()
                        }
                        , true);
                        Prestart();
                    }
                    else {
                        if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                        else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    }
                    return;
                    case Arena.EventStatus.Started : SpawnPlayer(eventPlayer, true, true);
                    return;
                }
            }
            public override void LeaveEvent(Arena.EventPlayer eventPlayer) {
                Arena.UnlockInventory(eventPlayer.player);
                if (status != Arena.EventStatus.Finished) BroadcastToPlayers("leftevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.LeaveEvent(eventPlayer);
                if (ins.configData.BalanceOnLeave) BalanceTeams();
            }
            public override void OnPlayerTakeDamage(Arena.EventPlayer eventPlayer, HitInfo info) {
                BasePlayer attacker = info.InitiatorPlayer;
                if (attacker != null) {
                    Arena.EventPlayer eventAttacker = Arena.GetUser(attacker);
                    if (eventAttacker != null) {
                        if (eventAttacker.team == eventPlayer.team) {
                            BroadcastToPlayer(eventAttacker, Arena.msg("friendlyFire", attacker.userID));
                            if (!config.ffEnabled) {
                                Arena.NullifyDamage(info);
                                return;
                            }
                        }
                    }
                }
                base.OnPlayerTakeDamage(eventPlayer, info);
            }
            public override void OnPlayerDeath(Arena.EventPlayer victim, BasePlayer attacker = null, HitInfo info = null) {
                if (victim == null) return;
                victim.AddDeath();
                if (attacker != null) {
                    Arena.EventPlayer attackerPlayer = Arena.GetUser(attacker);
                    if (attackerPlayer != null && victim != attackerPlayer) {
                        attackerPlayer.AddKill();
                        if (attackerPlayer.team == Arena.Team.A) teamAKills++;
                        if (attackerPlayer.team == Arena.Team.B) teamBKills++;
                        if (config.killLimit > 0 && (teamAKills >= config.killLimit || teamBKills >= config.killLimit)) {
                            EndMatch();
                            return;
                        }
                    }
                }
                UpdateScoreboard();
                base.OnPlayerDeath(victim, attacker);
            }
            public override void GiveTeamGear(Arena.EventPlayer eventPlayer) {
                string kitName = eventPlayer.team == Arena.Team.A ? config.teamA.kit : config.teamB.kit;
                Arena.GiveKit(eventPlayer.player, kitName);
            }
            public override void EndMatch() {
                if (isUnloading || (Arena != null && Arena.isUnloading)) return;
                Arena.Team team = teamAKills > teamBKills ? Arena.Team.A : teamBKills > teamAKills ? Arena.Team.B : Arena.Team.None;
                List<ulong> losers = eventPlayers.Where(x => x.team != team).Select(y => y.player.userID).ToList();
                Statistics.OnEventLose(losers, config);
                if (team != Arena.Team.None) {
                    List<ulong> winners = eventPlayers.Where(x => x.team == team).Select(y => y.player.userID).ToList();
                    Statistics.OnEventWin(winners, config);
                    BroadcastWinners("globalteamwin", new string[] {
                        team == Arena.Team.A ? (string.IsNullOrEmpty(config.teamA.name) ? Arena.msg("Team A") : config.teamA.name) : (string.IsNullOrEmpty(config.teamB.name) ? Arena.msg("Team B") : config.teamB.name), eventPlayers.Where(x => x.team == team).Select(y => y.player.displayName).ToSentence(), config.eventName
                    }
                    );
                }
                foreach (Arena.EventPlayer eventPlayer in eventPlayers) Statistics.OnGamePlayed(eventPlayer.player.userID, config);
                base.EndMatch();
            }
        }
#endregion
#region Survival
        private class Survival : Arena.EventManager {
            private List<Arena.DeadPlayer> deadPlayers = new List<Arena.DeadPlayer>();
            private Arena.EventPlayer winner;
            public override void Prestart() {
                winner = null;
                deadPlayers.Clear();
                base.Prestart();
            }
            public override bool CanJoinEvent() {
                if (status == Arena.EventStatus.Started) return false;
                return base.CanJoinEvent();
            }
            public override void JoinEvent(Arena.EventPlayer eventPlayer, Arena.Team team = Arena.Team.None) {
                if (eventPlayers.Contains(eventPlayer)) return;
                eventPlayer.ResetStats();
                eventPlayer.team = team;
                eventPlayers.Add(eventPlayer);
                BroadcastToPlayers("joinevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.JoinEvent(eventPlayer, team);
                switch (status) {
                    case Arena.EventStatus.Pending : if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                    else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    break;
                    case Arena.EventStatus.Finished : if (eventPlayers.Count >= config.minimumPlayers && status == Arena.EventStatus.Finished) {
                        BroadcastToPlayers("playersreached", new string[] {
                            Arena.configData.GameTimers.MatchPrestart[config.eventType].ToString()
                        }
                        , true);
                        Prestart();
                    }
                    else {
                        if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                        else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    }
                    break;
                    case Arena.EventStatus.Started : return;
                }
            }
            public override void LeaveEvent(Arena.EventPlayer eventPlayer) {
                deadPlayers.Add(new Arena.DeadPlayer(eventPlayer, eventPlayer.kills, eventPlayer.deaths));
                if (status != Arena.EventStatus.Finished) BroadcastToPlayers("survleftevent", new string[] {
                    eventPlayer.player.displayName, (eventPlayers.Count - 1).ToString()
                }
                );
                base.LeaveEvent(eventPlayer);
            }
            public override void OnPlayerDeath(Arena.EventPlayer victim, BasePlayer attacker = null, HitInfo info = null) {
                if (victim == null) return;
                victim.isDead = true;
                victim.isEliminated = true;
                victim.AddDeath();
                if (attacker != null) {
                    Arena.EventPlayer attackerPlayer = Arena.GetUser(attacker);
                    if (attackerPlayer != null && victim != attackerPlayer) attackerPlayer.AddKill();
                }
                base.OnPlayerDeath(victim, attacker, info);
                if (!deathKick) {
                    deadPlayers.Add(new Arena.DeadPlayer(victim, victim.kills, victim.deaths));
                    foreach (Arena.EventPlayer spectator in eventPlayers.Where(x => x.player.IsSpectating())) spectator.UpdateSpectateTarget();
                    BroadcastToPlayer(victim, Arena.msg("youareout", victim.player.userID));
                    victim.BeginSpectating();
                }
                else LeaveEvent(victim);
                UpdateScoreboard();
                bool allDead = true;
                foreach (Arena.EventPlayer eventPlayer in eventPlayers) {
                    if (!eventPlayer.isEliminated) {
                        allDead = false;
                        break;
                    }
                }
                if (allDead || eventPlayers.Count <= 1) EndMatch();
                if (CountAlive() == 1) {
                    Arena.EventPlayer[] winners = eventPlayers.Where(x => !x.isDead && !x.player.IsSpectating()).ToArray();
                    if (winners.Length == 1) winner = winners[0];
                    EndMatch();
                }
            }
            public override void EndMatch() {
                if (isUnloading || (Arena != null && Arena.isUnloading)) return;
                if (winner == null) {
                    if (eventPlayers.Count > 0) {
                        int kills = 0;
                        int deaths = 0;
                        foreach (Arena.EventPlayer eventPlayer in eventPlayers.Where(x => !x.isDead)) {
                            if (eventPlayer.kills > kills) {
                                winner = eventPlayer;
                                kills = eventPlayer.kills;
                                deaths = eventPlayer.deaths;
                            }
                            else if (eventPlayer.kills == kills) {
                                if (eventPlayer.deaths < deaths) {
                                    winner = eventPlayer;
                                    kills = eventPlayer.kills;
                                    deaths = eventPlayer.deaths;
                                }
                            }
                        }
                    }
                }
                if (winner != null) {
                    Statistics.OnGamePlayed(winner.player.userID, config);
                    Statistics.OnEventWin(new List<ulong> {
                        winner.player.userID
                    }
                    , config);
                    BroadcastToPlayer(winner, Arena.msg("youarewinner", winner.player.userID));
                    BroadcastWinners("globalwin", new string[] {
                        winner.player.displayName, config.eventName
                    }
                    );
                }
                List<ulong> losers = deadPlayers.Select(x => x.playerId).ToList();
                losers.AddRange(eventPlayers.Where(x => x.isDead).Select(x => x.player.userID));
                foreach (ulong loser in losers) Statistics.OnGamePlayed(loser, config);
                Statistics.OnEventLose(losers, config);
                base.EndMatch();
            }
            public override List<Arena.ScoreEntry> GetGameScores(Arena.Team team = Arena.Team.A) {
                List<Arena.ScoreEntry> gameScores = new List<Arena.ScoreEntry>();
                ulong[] deadPlayerIds = deadPlayers.Select(x => x.playerId).ToArray();
                int i = 1;
                foreach (Arena.EventPlayer eventPlayer in eventPlayers.OrderByDescending(x => x.kills)) {
                    if (deadPlayerIds.Contains(eventPlayer.player.userID)) continue;
                    gameScores.Add(new Arena.ScoreEntry(eventPlayer, i, eventPlayer.kills, eventPlayer.deaths));
                    i++;
                }
                List<Arena.DeadPlayer> reversedDead = new List<Arena.DeadPlayer>(deadPlayers);
                reversedDead.Reverse();
                foreach (Arena.DeadPlayer deadPlayer in reversedDead) {
                    if (gameScores.Find(x => x.displayName == deadPlayer.playerName) != null) continue;
                    gameScores.Add(new Arena.ScoreEntry() {
                        position = i, value2 = deadPlayer.value2, displayName = $"{Arena.msg("deadplayer")} {deadPlayer.playerName}", value1 = deadPlayer.value1
                    }
                    );
                    i++;
                }
                return gameScores;
            }
            public override string GetScoreString() => Arena.msg("Survivors");
        }
#endregion
#region Team Survival
        private class TeamSurvival : Arena.EventManager {
            private List<Arena.DeadPlayer> deadPlayers = new List<Arena.DeadPlayer>();
            private Arena.Team winners;
            public override void Prestart() {
                winners = Arena.Team.None;
                deadPlayers.Clear();
                base.Prestart();
            }
            public override void StartMatch() {
                BalanceTeams();
                base.StartMatch();
            }
            public override bool CanJoinEvent() {
                if (status == Arena.EventStatus.Started) return false;
                return base.CanJoinEvent();
            }
            public override void JoinEvent(Arena.EventPlayer eventPlayer, Arena.Team team = Arena.Team.None) {
                if (eventPlayers.Contains(eventPlayer)) return;
                eventPlayer.ResetStats();
                Arena.LockInventory(eventPlayer.player);
                eventPlayer.team = team;
                eventPlayers.Add(eventPlayer);
                BroadcastToPlayers("joinevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.JoinEvent(eventPlayer, team);
                switch (status) {
                    case Arena.EventStatus.Pending : if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                    else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    return;
                    case Arena.EventStatus.Finished : if (eventPlayers.Count >= config.minimumPlayers && status == Arena.EventStatus.Finished) {
                        BroadcastToPlayers("playersreached", new string[] {
                            Arena.configData.GameTimers.MatchPrestart[config.eventType].ToString()
                        }
                        , true);
                        Prestart();
                    }
                    else {
                        if (Arena.configData.EventSettings.SendToArenaOnJoin) SpawnPlayer(eventPlayer, false, true);
                        else BroadcastToPlayer(eventPlayer, Arena.msg("waitingForPlayers", eventPlayer.player.userID));
                    }
                    return;
                    case Arena.EventStatus.Started : SpawnPlayer(eventPlayer, true, true);
                    return;
                }
            }
            public override void LeaveEvent(Arena.EventPlayer eventPlayer) {
                deadPlayers.Add(new Arena.DeadPlayer(eventPlayer, eventPlayer.kills, eventPlayer.deaths));
                Arena.UnlockInventory(eventPlayer.player);
                if (status != Arena.EventStatus.Finished) BroadcastToPlayers("leftevent", new string[] {
                    eventPlayer.player.displayName
                }
                );
                base.LeaveEvent(eventPlayer);
                if (ins.configData.BalanceOnLeave) BalanceTeams();
            }
            public override void OnPlayerTakeDamage(Arena.EventPlayer eventPlayer, HitInfo info) {
                BasePlayer attacker = info.InitiatorPlayer;
                if (attacker != null) {
                    Arena.EventPlayer eventAttacker = Arena.GetUser(attacker);
                    if (eventAttacker != null) {
                        if (eventAttacker.team == eventPlayer.team) {
                            BroadcastToPlayer(eventAttacker, Arena.msg("friendlyFire", attacker.userID));
                            if (!config.ffEnabled) {
                                Arena.NullifyDamage(info);
                                return;
                            }
                        }
                    }
                }
                base.OnPlayerTakeDamage(eventPlayer, info);
            }
            public override void OnPlayerDeath(Arena.EventPlayer victim, BasePlayer attacker = null, HitInfo info = null) {
                if (victim == null) return;
                victim.isDead = true;
                victim.isEliminated = true;
                victim.AddDeath();
                if (attacker != null) {
                    Arena.EventPlayer attackerPlayer = Arena.GetUser(attacker);
                    if (attackerPlayer != null && victim != attackerPlayer) attackerPlayer.AddKill();
                }
                base.OnPlayerDeath(victim, attacker);
                if (!deathKick) {
                    deadPlayers.Add(new Arena.DeadPlayer(victim, victim.kills, victim.deaths));
                    foreach (Arena.EventPlayer spectator in eventPlayers.Where(x => x.player.IsSpectating())) spectator.UpdateSpectateTarget();
                    BroadcastToPlayer(victim, Arena.msg("youareout", victim.player.userID));
                    victim.BeginSpectating();
                }
                else LeaveEvent(victim);
                UpdateScoreboard();
                int teamACount = GetTeamAlive(Arena.Team.A);
                int teamBCount = GetTeamAlive(Arena.Team.B);
                if (teamACount == 0) winners = Arena.Team.A;
                if (teamBCount == 0) winners = Arena.Team.B;
                if (winners != Arena.Team.None) {
                    BroadcastWinners("globalteamwin", new string[] {
                        winners == Arena.Team.A ? (string.IsNullOrEmpty(config.teamA.name) ? Arena.msg("Team A") : config.teamA.name) : (string.IsNullOrEmpty(config.teamB.name) ? Arena.msg("Team B") : config.teamB.name), eventPlayers.Where(x => x.team == winners).Select(y => y.player.displayName).ToSentence(), config.eventName
                    }
                    );
                    BroadcastToPlayers("teamwin", new string[] {
                        winners == Arena.Team.A ? (string.IsNullOrEmpty(config.teamA.name) ? Arena.msg("Team A") : config.teamA.name) : (string.IsNullOrEmpty(config.teamB.name) ? Arena.msg("Team B") : config.teamB.name)
                    }
                    );
                    InvokeHandler.Invoke(this, EndMatch, 2f);
                    return;
                }
                bool allDead = true;
                foreach (Arena.EventPlayer eventPlayer in eventPlayers) {
                    if (!eventPlayer.isEliminated) {
                        allDead = false;
                        break;
                    }
                }
                if (allDead || eventPlayers.Count <= 1) EndMatch();
            }
            public override void GiveTeamGear(Arena.EventPlayer eventPlayer) {
                string kitName = eventPlayer.team == Arena.Team.A ? config.teamA.kit : config.teamB.kit;
                Arena.GiveKit(eventPlayer.player, kitName);
            }
            public override void EndMatch() {
                if (isUnloading || (Arena != null && Arena.isUnloading)) return;
                int teamACount = GetTeamCount(Arena.Team.A);
                int teamBCount = GetTeamCount(Arena.Team.B);
                winners = teamACount > teamBCount ? Arena.Team.A : teamBCount > teamACount ? Arena.Team.B : Arena.Team.None;
                List<ulong> winnerPlayers = eventPlayers.Where(x => x.team == winners).Select(y => y.player.userID).ToList();
                Statistics.OnEventWin(winnerPlayers, config);
                List<ulong> loserPlayers = eventPlayers.Where(x => x.team != winners).Select(y => y.player.userID).ToList();
                loserPlayers.AddRange(deadPlayers.Where(x => x.team != winners).Select(x => x.playerId));
                Statistics.OnEventLose(loserPlayers, config);
                foreach (ulong winner in winnerPlayers) Statistics.OnGamePlayed(winner, config);
                foreach (ulong loser in loserPlayers) Statistics.OnGamePlayed(loser, config);
                base.EndMatch();
            }
            public override List<Arena.ScoreEntry> GetGameScores(Arena.Team team = Arena.Team.A) {
                List<Arena.ScoreEntry> gameScores = new List<Arena.ScoreEntry>();
                ulong[] deadPlayerIds = deadPlayers.Select(x => x.playerId).ToArray();
                int i = 1;
                foreach (Arena.EventPlayer eventPlayer in eventPlayers.Where(x => x.team == team).OrderByDescending(x => x.kills)) {
                    if (deadPlayerIds.Contains(eventPlayer.player.userID)) continue;
                    gameScores.Add(new Arena.ScoreEntry(eventPlayer, i, eventPlayer.kills, eventPlayer.deaths));
                    i++;
                }
                List<Arena.DeadPlayer> reversedDead = new List<Arena.DeadPlayer>(deadPlayers.Where(x => x.team == team));
                reversedDead.Reverse();
                foreach (Arena.DeadPlayer deadPlayer in reversedDead) {
                    if (gameScores.Find(x => x.displayName == deadPlayer.playerName) != null) continue;
                    gameScores.Add(new Arena.ScoreEntry() {
                        position = i, value2 = deadPlayer.value2, displayNam
// ... [Code preview truncated due to length. Full source in attached file] ...

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