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

FREE Duelist : 1.1.9 1.1.9

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Facepunch;
using Network;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using Rust.Workshop;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
    [Info("Duelist", "nivex", "1.1.9")]
    [Description("1v1 and team deathmatch event.")]
    public class Duelist : RustPlugin {
        public enum Team {
            Good = 0, Evil = 1, None = 2
        }
        private static readonly string hewwPrefab = "assets/prefabs/building/wall.external.high.wood/wall.external.high.wood.prefab";
        private static readonly string heswPrefab = "assets/prefabs/building/wall.external.high.stone/wall.external.high.stone.prefab";
        private static Duelist ins;
        private static bool init;
        // are we initialized properly? if not disable certain functionality
        private readonly bool debugMode = false;
        private static readonly List<string> readyUiList = new List<string>();
        private static readonly List<string> spectators = new List<string>();
        private static readonly List<Rematch> rematches = new List<Rematch>();
        private static readonly Dictionary<string, AttackerInfo> tdmAttackers = new Dictionary<string, AttackerInfo>();
        private static readonly Dictionary<string, string> tdmKits = new Dictionary<string, string>();
        private static readonly HashSet<GoodVersusEvilMatch> tdmMatches = new HashSet<GoodVersusEvilMatch>();
        private static readonly List<DuelingZone> duelingZones = new List<DuelingZone>();
        // where all the fun is at
        private static StoredData duelsData = new StoredData();
        private static readonly Dictionary<string, string> dataDuelists = new Dictionary<string, string>();
        // active duelers
        private static readonly Dictionary<string, long> dataImmunity = new Dictionary<string, long>();
        // players immune to damage
        private static readonly Dictionary<string, Vector3> dataImmunitySpawns = new Dictionary<string, Vector3>();
        // players spawn points
        private readonly int blockedMask = LayerMask.GetMask("Player (Server)", "Prevent Building", "Construction", "Deployed", "Trigger");
        // layers we won't be setting a zone within 50 meters of
        private readonly int constructionMask = LayerMask.GetMask("Construction", "Deployed");
        private static bool matchUpdateRequired;
        private readonly int groundMask = LayerMask.GetMask("Terrain", "World", "Default");
        // used to find dueling zone/set custom zone and create spawn points
        private readonly int wallMask = LayerMask.GetMask("Terrain", "World", "Default", "Construction", "Deployed");
        private readonly int waterMask = LayerMask.GetMask("Water");
        // used to count water colliders when finding a random dueling zone on the map
        private readonly int worldMask = LayerMask.GetMask("World");
        private Timer announceTimer;
        private readonly SortedDictionary<string, string> boneTags = new SortedDictionary<string, string> {
            ["r_"]
            = "Right ", ["l_"] = "Left ", [".prefab"] = "", ["1"] = "", ["2"] = "", ["3"] = "", ["4"] = "", ["END"] = "", ["_"] = " ", ["."] = " "
        }
        ;
        private static readonly Dictionary<string, string> announcements = new Dictionary<string, string>();
        // users id and announcement
        private readonly Dictionary<string, long> dataDeath = new Dictionary<string, long>();
        // users id and timestamp of when they're to be executed
        private readonly Dictionary<string, string> dataRequests = new Dictionary<string, string>();
        // users requesting a duel and to whom
        private readonly Dictionary<string, bool> deployables = new Dictionary<string, bool>();
        private readonly Dictionary<ulong, List<BaseEntity>> duelEntities = new Dictionary<ulong, List<BaseEntity>>();
        private DynamicConfigFile duelsFile;
        private Timer eventTimer;
        // timer to check for immunity and auto death time of duelers
        private Timer matchTimer;
        // timer to check for updates to the match ui
        private readonly SpawnFilter filter = new SpawnFilter();
        // RandomDropPosition()
        [PluginReference]
        private Plugin Kits, ZoneManager, Economics, ServerRewards, LustyMap, Backpacks, PermaMap;
        private readonly Dictionary<Vector3, float> managedZones = new Dictionary<Vector3, float>();
        // blocked zones from zonemanager plugin
        private List<Vector3> monuments = new List<Vector3>();
        // positions of monuments on the server
        private readonly Dictionary<string, string> prefabs = new Dictionary<string, string>();
        private bool resetDuelists;
        // if wipe is detected then assign awards and wipe VictoriesSeed / LossesSeed
        private readonly Dictionary<string, List<ulong>> skinsCache = new Dictionary<string, List<ulong>>();
        // used to randomize custom kit skins which skin id values are 0
        private readonly Dictionary<string, string> tdmRequests = new Dictionary<string, string>();
        // users requesting a deathmatch and to whom
        private readonly Dictionary<string, List<ulong>> workshopskinsCache = new Dictionary<string, List<ulong>>();
        private readonly List<string> dcsBlock = new List<string>();
        // users blocked from 1v1 for 60 seconds after suiciding or disconnecting
        private readonly Dictionary<string, string> playerZones = new Dictionary<string, string>();
        // id, set zone name
        public class StoredData {
            public List<string> Allowed = new List<string>();
            // list of users that allow duel requests
            public Dictionary<string, List<string>> AutoGeneratedSpawns = new Dictionary<string, List<string>>();
            public Dictionary<string, string> Bans = new Dictionary<string, string>();
            // users banned from dueling
            public Dictionary<string, BetInfo> Bets = new Dictionary<string, BetInfo>();
            // active bets users have placed
            public Dictionary<string, List<string>> BlockedUsers = new Dictionary<string, List<string>>();
            // users and the list of players they blocked from requesting duels with
            public List<string> Chat = new List<string>();
            // user ids of those who opted out of seeing duel death messages
            public List<string> ChatEx = new List<string>();
            // user ids of those who opted to see duel death messages when the config blocks them for all players
            public Dictionary<string, List<BetInfo>> ClaimBets = new Dictionary<string, List<BetInfo>>();
            // active bets users need to claim after winning a bet
            public Dictionary<string, string> CustomKits = new Dictionary<string, string>();
            // userid and custom kit
            public bool DuelsEnabled;
            // enable/disable dueling for all players (not admins)
            public Dictionary<string, string> Homes = new Dictionary<string, string>();
            // user id and location of where they teleported from
            public Dictionary<string, string> Kits = new Dictionary<string, string>();
            // userid and kit.give kit when they wake up inside of the dueling zone
            public Dictionary<string, int> Losses = new Dictionary<string, int>();
            // user id / losses for lifetime
            public Dictionary<string, int> LossesSeed = new Dictionary<string, int>();
            // user id / losses for seed
            public SortedDictionary<long, string> Queued = new SortedDictionary<long, string>();
            // queued duelers sorted by timestamp and user id.first come first serve
            public List<string> Restricted = new List<string>();
            // list of users blocked from requesting a duel for 60 seconds
            public List<string> Spawns = new List<string>();
            // custom spawn points
            public List<string> AutoReady = new List<string>();
            public Dictionary<string, int> MatchVictories = new Dictionary<string, int>();
            // player name & total wins
            public Dictionary<string, int> MatchVictoriesSeed = new Dictionary<string, int>();
            // player name & wins for current seed
            public Dictionary<string, int> MatchLosses = new Dictionary<string, int>();
            // player name & total losses
            public Dictionary<string, int> MatchLossesSeed = new Dictionary<string, int>();
            // player name & losses for current seed
            public Dictionary<string, int> MatchDeaths = new Dictionary<string, int>();
            // player name & total deaths
            public Dictionary<string, int> MatchDeathsSeed = new Dictionary<string, int>();
            // player name & deaths for the seed
            public Dictionary<string, int> MatchKills = new Dictionary<string, int>();
            // player name & total kills
            public Dictionary<string, int> MatchKillsSeed = new Dictionary<string, int>();
            // player name & kills for current seed
            public Dictionary<string, Dictionary<string, int>> MatchSizesVictories = new Dictionary<string, Dictionary<string, int>>();
            // size, id, wins
            public Dictionary<string, Dictionary<string, int>> MatchSizesVictoriesSeed = new Dictionary<string, Dictionary<string, int>>();
            // size, id, wins seed
            public Dictionary<string, Dictionary<string, int>> MatchSizesLosses = new Dictionary<string, Dictionary<string, int>>();
            // size, id, losses
            public Dictionary<string, Dictionary<string, int>> MatchSizesLossesSeed = new Dictionary<string, Dictionary<string, int>>();
            // size, id, losses seed
            public int TotalDuels;
            // the total amount of duels ever played on the server
            public Dictionary<string, int> Victories = new Dictionary<string, int>();
            // user id / wins for lifetime
            public Dictionary<string, int> VictoriesSeed = new Dictionary<string, int>();
            // user id / wins for seed
            public List<string> ZoneIds = new List<string>();
            // the locations of each dueling zone
            public Dictionary<string, string> DuelZones = new Dictionary<string, string>();
            // location, name
        }
        class Tracker : MonoBehaviour {
            public BasePlayer player;
            void Awake() {
                player = GetComponent<BasePlayer>();
                InvokeHandler.InvokeRepeating(this, Track, 0f, 0.5f);
            }
            void Track() {
                if (player == null || player.transform == null) {
                    GameObject.Destroy(this);
                    return;
                }
                if (dataDuelists.ContainsKey(player.UserIDString) || tdmMatches.Any(team => team.GetTeam(player) != Team.None)) {
                    if (!DuelTerritory(player.transform.position)) {
                        player.inventory.Strip();
                        GameObject.Destroy(this);
                    }
                }
            }
            void OnDestroy() {
                InvokeHandler.CancelInvoke(this, Track);
                GameObject.Destroy(this);
            }
        }
        public class PlayerComparer : IEqualityComparer<BasePlayer> {
            public bool Equals(BasePlayer player, BasePlayer target) {
                return player != null && target != null && player.UserIDString == target.UserIDString;
            }
            public int GetHashCode(BasePlayer player) {
                return player?.UserIDString.GetHashCode() ?? 0;
            }
        }
        public class Rematch {
            public List<BasePlayer> Duelists {
                get;
            }
            = new List<BasePlayer>();
            public List<BasePlayer> Ready {
                get;
            }
            = new List<BasePlayer>();
            private List<BasePlayer> Evil {
                get;
            }
            = new List<BasePlayer>();
            private List<BasePlayer> Good {
                get;
            }
            = new List<BasePlayer>();
            public GoodVersusEvilMatch match {
                get;
                set;
            }
            private Timer _notify {
                get;
                set;
            }
            public List<BasePlayer> Players {
                get {
                    Duelists.RemoveAll(player => !player || !player.IsConnected);
                    Good.RemoveAll(player => !player || !player.IsConnected);
                    Evil.RemoveAll(player => !player || !player.IsConnected);
                    Ready.RemoveAll(player => !player || !player.IsConnected);
                    return match == null ? Duelists : Good.Union(Evil, new PlayerComparer()).ToList();
                }
            }
            public bool HasPlayer(BasePlayer player) {
                return Players.Contains(player);
            }
            public bool AddRange(List<BasePlayer> players, Team team) {
                foreach (var player in players) {
                    if (!player || !player.IsConnected || InEvent(player) || Good.Contains(player) || Evil.Contains(player)) break;
                    if (team == Team.Evil) Evil.Add(player);
                    else Good.Add(player);
                }
                return (team == Team.Evil ? Evil.Count : Good.Count) == players.Count;
            }
            public bool IsReady(BasePlayer player) {
                if (InEvent(player) || !ins.IsNewman(player) || duelsData.Bans.ContainsKey(player.UserIDString)) return false;
                return true;
            }
            public bool IsReady() {
                if (Players.Any(player => !IsReady(player))) {
                    Reset("RematchFailed2");
                    return false;
                }
                return Ready.Count == (match == null ? 2 : match.TeamSize * 2);
            }
            private void Reset(string key) {
                tdmMatches.Remove(match);
                MessageAll(key);
                Duelists.Clear();
                Good.Clear();
                Evil.Clear();
                Ready.Clear();
                _notify?.Destroy();
                rematches.Remove(this);
                matchUpdateRequired = true;
            }
            public void MessageAll(string key, params object[] args) {
                foreach (var player in Players) {
                    player.ChatMessage(ins.msg(key, player.UserIDString, args ?? new string[0]));
                }
            }
            public void Notify() {
                MessageAll("RematchNotify", 60f, match == null ? szDuelChatCommand : szMatchChatCommand);
                foreach (var player in Players) if (duelsData.AutoReady.Contains(player.UserIDString)) Ready.Add(player);
                if (IsReady()) {
                    Start();
                    rematches.Remove(this);
                }
                else if (match == null || !match.IsPublic) _notify = ins.timer.Once(60f, () => Cancel());
            }
            private void Cancel() {
                if (match != null && match.IsPublic) return;
                if (rematches.Contains(this)) {
                    if (sendHomeSpectatorWhenRematchTimesOut) {
                        foreach (var player in Players) {
                            if (IsSpectator(player)) {
                                EndSpectate(player);
                                ins.SendHome(player);
                            }
                        }
                    }
                    if (match != null) {
                        match.Reuse();
                    }
                    tdmMatches.Remove(match);
                    Reset("RematchTimedOut");
                }
            }
            public void Start() {
                if (match == null) {
                    var player = Ready[0];
                    var target = Ready[1];
                    if (!ins.SelectZone(player, target)) {
                        player.ChatMessage(ins.msg("AllZonesFull", player.UserIDString, duelingZones.Count, playersPerZone));
                        target.ChatMessage(ins.msg("AllZonesFull", target.UserIDString, duelingZones.Count, playersPerZone));
                    }
                }
                else {
                    match.Reuse();
                    tdmMatches.Add(match);
                    if (!AddMatchPlayers(Good, Team.Good) || !AddMatchPlayers(Evil, Team.Evil)) {
                        Reset("RematchFailed");
                        match.Reuse();
                    }
                }
                _notify?.Destroy();
                rematches.Remove(this);
            }
            private bool AddMatchPlayers(List<BasePlayer> players, Team team) {
                foreach (var player in players) if (!match.AddMatchPlayer(player, team)) return false;
                return true;
            }
        }
        public class AttackerInfo {
            public string AttackerName {
                get;
                set;
            }
            = "";
            public string AttackerId {
                get;
                set;
            }
            = "";
            public string BoneName {
                get;
                set;
            }
            = "";
            public string Distance {
                get;
                set;
            }
            = "";
            public string Weapon {
                get;
                set;
            }
            = "";
        }
        public class GoodVersusEvilMatch {
            private readonly HashSet<ulong> _banned = new HashSet<ulong>();
            private readonly HashSet<BasePlayer> _evil = new HashSet<BasePlayer>();
            private readonly HashSet<ulong> _evilKIA = new HashSet<ulong>();
            private readonly List<BasePlayer> _evilRematch = new List<BasePlayer>();
            private readonly HashSet<BasePlayer> _good = new HashSet<BasePlayer>();
            private readonly HashSet<ulong> _goodKIA = new HashSet<ulong>();
            private readonly List<BasePlayer> _goodRematch = new List<BasePlayer>();
            private string _goodHostName {
                get;
                set;
            }
            = "";
            private string _evilHostName {
                get;
                set;
            }
            = "";
            private string _goodHostId {
                get;
                set;
            }
            = "";
            private string _evilHostId {
                get;
                set;
            }
            = "";
            private string _goodCode {
                get;
                set;
            }
            = "";
            private string _evilCode {
                get;
                set;
            }
            = "";
            private int _teamSize {
                get;
                set;
            }
            = 2;
            private bool _started {
                get;
                set;
            }
            private bool _ended {
                get;
                set;
            }
            private string _kit {
                get;
                set;
            }
            = "";
            private DuelingZone _zone {
                get;
                set;
            }
            private Timer _queueTimer {
                get;
                set;
            }
            private bool _enteredQueue {
                get;
                set;
            }
            private bool _public {
                get;
                set;
            }
            private bool _canRematch {
                get;
                set;
            }
            = true;
            public bool CanRematch {
                get {
                    return _canRematch;
                }
                set {
                    _canRematch = value;
                }
            }
            public string Id {
                get {
                    return _goodHostId + _evilHostId;
                }
            }
            public string Versus {
                get {
                    return string.Format("{0} / {1} {2}v{2}", _goodHostName, _evilHostName, _teamSize);
                }
            }
            public bool IsPublic {
                get {
                    return _public;
                }
                set {
                    _public = value;
                    matchUpdateRequired = true;
                    MessageAll(_public ? "MatchPublic" : "MatchPrivate");
                }
            }
            public int TeamSize {
                get {
                    return _teamSize;
                }
                set {
                    if (IsStarted) return;
                    _teamSize = value;
                    matchUpdateRequired = true;
                    MessageAll("MatchSizeChanged", _teamSize);
                }
            }
            public DuelingZone Zone {
                get {
                    return _zone;
                }
            }
            public bool EitherEmpty {
                get {
                    return _good.Count == 0 || _evil.Count == 0;
                }
            }
            public bool IsStarted {
                get {
                    return _started;
                }
                set {
                    _started = value;
                    matchUpdateRequired = true;
                }
            }
            public bool IsOver {
                get {
                    return _ended;
                }
                set {
                    _ended = value;
                    matchUpdateRequired = true;
                }
            }
            public string Kit {
                get {
                    return _kit;
                }
                set {
                    _kit = value;
                    if (!EitherEmpty) {
                        _good.RemoveWhere(target => !target || !target.IsConnected);
                        _evil.RemoveWhere(target => !target || !target.IsConnected);
                        foreach (var player in _good.Union(_evil, new PlayerComparer())) duelsData.Kits[player.UserIDString] = _kit;
                        MessageAll("MatchKitSet", _kit);
                    }
                }
            }
            public void Reuse() {
                if (_zone != null) _zone.IsLocked = false;
                _evilRematch.Clear();
                _goodRematch.Clear();
                _good.Clear();
                _evil.Clear();
                _goodKIA.Clear();
                _evilKIA.Clear();
                _started = false;
                _ended = false;
                _enteredQueue = false;
                _kit = ins.GetRandomKit();
                _goodHostId = BasePlayer.activePlayerList.Find(x => x.displayName == _goodHostName)?.UserIDString ?? _goodHostId;
                _evilHostId = BasePlayer.activePlayerList.Find(x => x.displayName == _evilHostName)?.UserIDString ?? _evilHostId;
                matchUpdateRequired = true;
            }
            public void Setup(BasePlayer player, BasePlayer target) {
                tdmMatches.Add(this);
                _goodHostName = player.displayName;
                _goodHostId = player.UserIDString;
                _evilHostName = target.displayName;
                _evilHostId = target.UserIDString;
                _goodCode = Random.Range(10000, 99999).ToString();
                _evilCode = Random.Range(10000, 99999).ToString();
                if (_teamSize < minDeathmatchSize) _teamSize = minDeathmatchSize;
                AddMatchPlayer(player, Team.Good);
                AddMatchPlayer(target, Team.Evil);
                if (tdmKits.ContainsKey(player.UserIDString)) {
                    Kit = tdmKits[player.UserIDString];
                    tdmKits.Remove(player.UserIDString);
                }
                else if (tdmKits.ContainsKey(target.UserIDString)) {
                    Kit = tdmKits[target.UserIDString];
                    tdmKits.Remove(target.UserIDString);
                }
                else Kit = ins.GetRandomKit();
                if (TeamSize > 1) {
                    player.ChatMessage(ins.msg("MatchOpened", player.UserIDString, szMatchChatCommand, _goodCode));
                    target.ChatMessage(ins.msg("MatchOpened", target.UserIDString, szMatchChatCommand, _evilCode));
                }
                matchUpdateRequired = true;
            }
            public bool IsFull() {
                return _good.Count == _teamSize && _evil.Count == _teamSize;
            }
            public bool IsFull(Team team) {
                return team == Team.Good ? _good.Count == _teamSize : _evil.Count == _teamSize;
            }
            public void MessageAll(string key, params object[] args) {
                Message(Team.Good, key, args);
                Message(Team.Evil, key, args);
            }
            public void Message(Team team, string key, params object[] args) {
                foreach (var player in team == Team.Evil ? _evil : _good) {
                    if (!player || !player.IsConnected) continue;
                    player.ChatMessage(ins.msg(key, player.UserIDString, args ?? new string[0]));
                }
            }
            public Team GetTeam(BasePlayer player) {
                return _good.Contains(player) ? Team.Good : _evil.Contains(player) ? Team.Evil : Team.None;
            }
            public bool IsHost(BasePlayer player) {
                return player.UserIDString == _goodHostId || player.UserIDString == _evilHostId;
            }
            public void SetCode(BasePlayer player, string code) {
                if (GetTeam(player) == Team.Evil) _evilCode = code;
                else if (GetTeam(player) == Team.Good) _goodCode = code;
            }
            public string Code(Team team) {
                return team == Team.Good ? _goodCode : _evilCode;
            }
            public bool AlliedTo(BasePlayer player, Team team) {
                return ins.IsAllied(player.UserIDString, team == Team.Good ? _goodHostId : _evilHostId);
            }
            public bool IsBanned(ulong targetId) {
                return _banned.Contains(targetId);
            }
            public bool Ban(BasePlayer target) {
                if (target.UserIDString == _goodHostId || target.UserIDString == _evilHostId || IsBanned(target.userID)) return false;
                _banned.Add(target.userID);
                RemoveMatchPlayer(target);
                return true;
            }
            public bool Equals(GoodVersusEvilMatch match) {
                return match._good.Equals(_good) && match._evil.Equals(_evil);
            }
            public string GetNames(Team team) {
                return string.Join(", ", team == Team.Good ? _good.Select(player => player.displayName).ToArray() : _evil.Select(player => player.displayName).ToArray());
            }
            public void GiveShirt(BasePlayer player) {
                Item item = ItemManager.CreateByName(teamShirt, 1, GetTeam(player) == Team.Evil ? teamEvilShirt : teamGoodShirt);
                if (item == null) return;
                if (item.info.category != ItemCategory.Attire) {
                    item.Remove(0.01f);
                    return;
                }
                foreach (Item wear in player.inventory.containerWear.itemList) {
                    if (wear.info.shortname.Contains("shirt")) {
                        wear.RemoveFromContainer();
                        wear.Remove(0.01f);
                        break;
                    }
                }
                item.MoveToContainer(player.inventory.containerWear, -1, false);
                if (!player.inventory.containerWear.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerWear.SetFlag(ItemContainer.Flag.IsLocked, true);
            }
            public bool AddMatchPlayer(BasePlayer player, Team team) {
                if (_started) {
                    player.ChatMessage(ins.msg("MatchStartedAlready", player.UserIDString));
                    return false;
                }
                _good.RemoveWhere(target => !target || !target.IsConnected);
                _evil.RemoveWhere(target => !target || !target.IsConnected);
                if (_banned.Contains(player.userID)) return false;
                if (!ins.IsNewman(player)) {
                    player.ChatMessage(ins.msg("MustBeNaked", player.UserIDString));
                    return false;
                }
                switch (team) {
                    case Team.Good : if (_good.Count == _teamSize) {
                        player.ChatMessage(ins.msg("MatchTeamFull", player.UserIDString, _teamSize));
                        return false;
                    }
                    _good.Add(player);
                    MessageAll("MatchJoinedTeam", player.displayName, _goodHostName, _good.Count, _teamSize, _evilHostName, _evil.Count);
                    break;
                    case Team.Evil : if (_evil.Count == _teamSize) {
                        player.ChatMessage(ins.msg("MatchTeamFull", player.UserIDString, _teamSize));
                        return false;
                    }
                    _evil.Add(player);
                    MessageAll("MatchJoinedTeam", player.displayName, _evilHostName, _evil.Count, _teamSize, _goodHostName, _good.Count);
                    break;
                }
                if (_good.Count == _teamSize && _evil.Count == _teamSize) Queue();
                return true;
            }
            public bool RemoveMatchPlayer(BasePlayer player) {
                if (player == null) return false;
                if (player.inventory.containerWear.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerWear.SetFlag(ItemContainer.Flag.IsLocked, false);
                ins.Metabolize(player, false);
                ins.Track(player, false);
                ins.RemoveEntities(player.userID);
                Interface.Oxide.CallHook("DisableBypass", player.userID);
                if (DuelTerritory(player.transform.position)) {
                    if (sendDefeatedHome) ins.SendHome(player);
                    else StartSpectate(player);
                }
                if (IsOver) {
                    _good.Remove(player);
                    _evil.Remove(player);
                    return true;
                }
                if (_good.Remove(player)) {
                    if (_good.Count == 0) {
                        if (_started) {
                            _goodKIA.Add(player.userID);
                            _goodRematch.Add(player);
                        }
                        else MessageAll("MatchNoPlayersLeft");
                        EndMatch(Team.Evil);
                        return true;
                    }
                    if (_started) {
                        _goodKIA.Add(player.userID);
                        _goodRematch.Add(player);
                    }
                    if (player.UserIDString == _goodHostId) AssignGoodHostId();
                    return true;
                }
                if (_evil.Remove(player)) {
                    if (_evil.Count == 0) {
                        if (_started) {
                            _evilKIA.Add(player.userID);
                            _evilRematch.Add(player);
                        }
                        else MessageAll("MatchNoPlayersLeft");
                        EndMatch(Team.Good);
                        return true;
                    }
                    if (_started) {
                        _evilKIA.Add(player.userID);
                        _evilRematch.Add(player);
                    }
                    if (player.UserIDString == _evilHostId) AssignEvilHostId();
                    return true;
                }
                return false;
            }
            private void AssignGoodHostId() {
                _good.RemoveWhere(player => !player || !player.IsConnected);
                if (_good.Count > 0) {
                    _goodHostId = _good.First().UserIDString;
                    matchUpdateRequired = true;
                }
                else EndMatch(Team.Evil);
            }
            private void AssignEvilHostId() {
                _evil.RemoveWhere(player => !player || !player.IsConnected);
                if (_evil.Count > 0) {
                    _evilHostId = _evil.First().UserIDString;
                    matchUpdateRequired = true;
                }
                else EndMatch(Team.Good);
            }
            private void Finalize(Team team) {
                Interface.CallHook("OnDuelistFinalized", team == Team.Good ? _goodKIA : _evilKIA);
                switch (team) {
                    case Team.Evil : {
                        foreach (ulong playerId in _goodKIA) {
                            UpdateMatchStats(playerId.ToString(), false, true, false, false);
                            UpdateMatchSizeStats(playerId.ToString(), true, false, _teamSize);
                        }
                        foreach (ulong playerId in _evilKIA) {
                            AwardPlayer(playerId, teamEconomicsMoney, teamServerRewardsPoints);
                            UpdateMatchStats(playerId.ToString(), true, false, false, false);
                            UpdateMatchSizeStats(playerId.ToString(), false, true, _teamSize);
                        }
                        break;
                    }
                    case Team.Good : {
                        foreach (ulong playerId in _evilKIA) {
                            UpdateMatchStats(playerId.ToString(), false, true, false, false);
                            UpdateMatchSizeStats(playerId.ToString(), true, false, _teamSize);
                        }
                        foreach (ulong playerId in _goodKIA) {
                            AwardPlayer(playerId, teamEconomicsMoney, teamServerRewardsPoints);
                            UpdateMatchStats(playerId.ToString(), true, false, false, false);
                            UpdateMatchSizeStats(playerId.ToString(), false, true, _teamSize);
                        }
                        break;
                    }
                }
                _goodKIA.Clear();
                _evilKIA.Clear();
            }
            private bool SetupRematch() {
                if (!CanRematch || _goodRematch.Any(player => !player || !player.IsConnected) || _evilRematch.Any(player => !player || !player.IsConnected)) return false;
                var rematch = new Rematch();
                if (rematch.AddRange(_evilRematch, Team.Evil)) {
                    if (rematch.AddRange(_goodRematch, Team.Good)) {
                        rematch.match = this;
                        rematches.Add(rematch);
                        rematch.Notify();
                        return true;
                    }
                }
                return false;
            }
            private void EndMatch(Team team) {
                if (!_ended && _started) {
                    Finalize(team);
                    ins.Puts(ins.msg("MatchDefeat", null, team == Team.Evil ? _evilHostName : _goodHostName, team == Team.Evil ? _goodHostName : _evilHostName, _teamSize));
                    IsOver = true;
                    IsStarted = false;
                    foreach (var player in _evil.ToList()) {
                        RemoveMatchPlayer(player);
                        if (player != null && player.IsConnected && !_evilRematch.Contains(player)) _evilRematch.Add(player);
                    }
                    foreach (var player in _good.ToList()) {
                        RemoveMatchPlayer(player);
                        if (player != null && player.IsConnected && !_goodRematch.Contains(player)) _goodRematch.Add(player);
                    }
                    foreach (var target in BasePlayer.activePlayerList.Where(p => p?.displayName != null)) {
                        if (guiAnnounceUITime > 0f && (_goodKIA.Contains(target.userID) || _evilKIA.Contains(target.userID))) CreateAnnouncementUI(target, ins.msg("MatchDefeat", target.UserIDString, team == Team.Evil ? _evilHostName : _goodHostName, team == Team.Evil ? _goodHostName : _evilHostName, _teamSize));
                        if (duelsData.Chat.Contains(target.UserIDString) && !_goodKIA.Contains(target.userID) && !_evilKIA.Contains(target.userID)) continue;
                        target.ChatMessage(ins.msg("MatchDefeat", target.UserIDString, team == Team.Evil ? _evilHostName : _goodHostName, team == Team.Evil ? _goodHostName : _evilHostName, _teamSize));
                    }
                    if (!SetupRematch()) {
                        foreach (var player in _evilRematch.Union(_goodRematch, new PlayerComparer())) {
                            if (!player || !player.IsConnected) continue;
                            player.ChatMessage(ins.msg("RematchFailed2", player.UserIDString));
                        }
                        Reuse();
                    }
                }
                End();
            }
            public void End() {
                if (_zone != null) _zone.IsLocked = false;
                _queueTimer?.Destroy();
                _good.RemoveWhere(player => !player);
                _evil.RemoveWhere(player => !player);
                foreach (var player in _good.Union(_evil, new PlayerComparer())) {
                    if (player.inventory.containerWear.HasFlag(ItemContainer.Flag.IsLocked)) player.inventory.containerWear.SetFlag(ItemContainer.Flag.IsLocked, false);
                    if (IsStarted || IsOver) {
                        if (DuelTerritory(player.transform.position)) {
                            player.inventory.Strip();
                            ins.SendHome(player);
                        }
                        ins.Metabolize(player, false);
                        ins.Track(player, false);
                    }
                }
                _good.Clear();
                _evil.Clear();
                tdmMatches.Remove(this);
                matchUpdateRequired = true;
                if (dataDuelists.Count == 0 && tdmMatches.Count == 0) ins.Unsubscribe(nameof(OnPlayerHealthChange));
            }
            private void Queue() {
                DuelingZone zone = null;
                foreach (var player in _good.Union(_evil, new PlayerComparer())) {
                    if (!ins.IsNewman(player)) {
                        player.ChatMessage(ins.msg("MustBeNaked", player.UserIDString));
                        MessageAll("MatchIsNotNaked", player.displayName);
                        _queueTimer = ins.timer.Once(30f, () => Queue());
                        return;
                    }
                    if (zone == null) zone = ins.GetPlayerZone(player, TeamSize);
                }
                var zones = duelingZones.Where(x => x.TotalPlayers == 0 && !x.IsLocked && x.Spawns.Count >= (requireTeamSize ? TeamSize * 2 : 2)).ToList();
                if (zones == null || zones.Count == 0) {
                    if (!_enteredQueue) {
                        MessageAll("MatchQueued");
                        _enteredQueue = true;
                    }
                    _queueTimer = ins.timer.Once(2f, () => Queue());
                    return;
                }
                _zone = zone ?? LastZone ?? zones.GetRandom();
                _queueTimer?.Destroy();
                Start();
            }
            public DuelingZone LastZone {
                get {
                    DuelingZone zone = null;
                    if (_good.Any(player => DuelTerritory(player.transform.position))) zone = GetDuelZone(_good.First(player => DuelTerritory(player.transform.position)).transform.position);
                    if (_evil.Any(player => DuelTerritory(player.transform.position))) zone = GetDuelZone(_evil.First(player => DuelTerritory(player.transform.position)).transform.position);
                    return zone == null || zone.TotalPlayers > 0 || zone.IsLocked ? null : zone;
                }
            }
            private void Start() {
                ins.SubscribeHooks(true);
                var goodSpawn = _zone.Spawns.GetRandom();
                var evilSpawn = goodSpawn;
                float dist = -100f;
                foreach (var spawn in _zone.Spawns)  // get the furthest spawn point away from the good team and assign it to the evil team
                {
                    float distance = Vector3.Distance(spawn, goodSpawn);
                    if (distance > dist) {
                        dist = distance;
                        evilSpawn = spawn;
                    }
                }
                Message(Team.Good, "MatchStarted", GetNames(Team.Evil));
                Message(Team.Evil, "MatchStarted", GetNames(Team.Good));
                _zone.IsLocked = true;
                IsStarted = true;
                Spawn(_good, goodSpawn);
                Spawn(_evil, evilSpawn);
            }
            private void Spawn(HashSet<BasePlayer> players, Vector3 spawn) {
                foreach (var player in players) {
                    duelsData.Kits[player.UserIDString] = _kit;
                    if (!DuelTerritory(player.transform.position) || !duelsData.Homes.ContainsKey(player.UserIDString)) {
                        var ppos = player.transform.position;
                        if (IsOnConstruction(ppos)) ppos.y += 1;
                        // prevent player from becoming stuck or dying when teleported home
                        duelsData.Homes[player.UserIDString] = ppos.ToString();
                    }
                    RemoveFromQueue(player.UserIDString);
                    ins.Teleport(player, spawn);
                    if (immunityTime >= 1) {
                        dataImmunity[player.UserIDString] = TimeStamp() + immunityTime;
                        dataImmunitySpawns[player.UserIDString] = spawn;
                    }
                }
            }
        }
        public class DuelKitItem {
            public string ammo;
            public int amount;
            public string container;
            public List<string> mods;
            public string shortname;
            public ulong skin;
            public int slot;
        }
        public class BetInfo {
            public string trigger;
            // the trigger used to request this as a bet
            public int amount;
            // amount the player bet
            public int itemid;
            // the unique identifier of the item
            public int max;
            // the maximum amount allowed to bet on this item
            public bool Equals(BetInfo bet) {
                return bet.amount == amount && bet.itemid == itemid;
            }
        }
        public class DuelingZone  // Thanks @Jake_Rich for helping me get this started!
        {
            private HashSet<BasePlayer> _players = new HashSet<BasePlayer>();
            private HashSet<BasePlayer> _waiting = new HashSet<BasePlayer>();
            private Vector3 _zonePos;
            private List<Vector3> _duelSpawns = new List<Vector3>();
            // spawn points generated on the fly
            private int _kills;
            // create a new zone randomly on the map when the counter hits the configured amount once all duels are finished
            private bool _locked;
            public bool IsLocked {
                get {
                    return _locked;
                }
                set {
                    _locked = value;
                }
            }
            public int Kills {
                get {
                    return _kills;
                }
                set {
                    _kills = value;
                }
            }
            public int TotalPlayers {
                get {
                    return _players.Count;
                }
            }
            public List<BasePlayer> Players {
                get {
                    return _players.ToList();
                }
            }
            public List<Vector3> Spawns {
                get {
                    var spawns = GetSpawnPoints(this);
                    // get custom spawn points if any exist
                    return spawns == null || spawns.Count < 2 ? _duelSpawns : spawns;
                }
            }
            public bool IsFull {
                get {
                    return TotalPlayers + _waiting.Count + 2 > playersPerZone || _locked;
                }
            }
            public Vector3 Position {
                get {
                    return _zonePos;
                }
            }
            public void Setup(Vector3 position) {
                _zonePos = position;
                _duelSpawns = GetAutoSpawns(this);
            }
            public float Distance(Vector3 position) {
                position.y = 0f;
                return Vector3.Distance(new Vector3(_zonePos.x, 0f, _zonePos.z), position);
            }
            public bool? AddWaiting(BasePlayer player, BasePlayer target) {
                if (IsFull) return false;
                if (requiredDuelMoney > 0.0 && ins.Economics != null) {
                    double playerMoney = Convert.ToDouble(ins.Economics.Call("GetPlayerMoney", player.userID));
                    double targetMoney = Convert.ToDouble(ins.Economics.Call("GetPlayerMoney", target.userID));
                    if (playerMoney < requiredDuelMoney || targetMoney < requiredDuelMoney) {
                        RemoveFromQueue(player.UserIDString);
                        RemoveFromQueue(target.UserIDString);
                        player.ChatMessage(ins.msg("MoneyRequired", player.UserIDString, requiredDuelMoney));
                        target.ChatMessage(ins.msg("MoneyRequired", target.UserIDString, requiredDuelMoney));
                        return null;
                    }
                    bool playerWithdrawn = Convert.ToBoolean(ins.Economics.Call("Withdraw", player.userID, requiredDuelMoney));
                    bool targetWithdrawn = Convert.ToBoolean(ins.Economics.Call("Withdraw", target.userID, requiredDuelMoney));
                    if (!playerWithdrawn || !targetWithdrawn) {
                        RemoveFromQueue(player.UserIDString);
 
// ... [Code preview truncated due to length. Full source in attached file] ...

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