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

FREE Duelist : 1.3.5 1.3.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Game.Rust.Libraries;
using Oxide.Plugins.DuelistExtensionMethods;
using Rust;
using Rust.Workshop;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
    [Info("Duelist", "nivex", "1.3.5")]
    [Description("1v1 and team deathmatch event.")]
    public class Duelist : RustPlugin {
        [PluginReference]
        Plugin Kits, ZoneManager, Economics, ServerRewards, Clans, AimTrain, LustyMap;
        private static Duelist Instance;
        public enum Team {
            Good = 0, Evil = 1, None = 2
        }
        private const string hewwPrefab = "assets/prefabs/building/wall.external.high.wood/wall.external.high.wood.prefab";
        private const string heswPrefab = "assets/prefabs/building/wall.external.high.stone/wall.external.high.stone.prefab";
        private const bool debugMode = false;
        private List<string> readyUiList = new List<string>();
        private List<string> spectators = new List<string>();
        private List<Rematch> rematches = new List<Rematch>();
        private Dictionary<string, AttackerInfo> tdmAttackers = new Dictionary<string, AttackerInfo>();
        private Dictionary<string, string> tdmKits = new Dictionary<string, string>();
        private HashSet<GoodVersusEvilMatch> tdmMatches = new HashSet<GoodVersusEvilMatch>();
        private List<DuelingZone> duelingZones = new List<DuelingZone>();
        // where all the fun is at
        private StoredData duelsData = new StoredData();
        private Dictionary<string, string> dataDuelists = new Dictionary<string, string>();
        // active duelers
        private Dictionary<string, long> dataImmunity = new Dictionary<string, long>();
        // players immune to damage
        private Dictionary<string, Vector3> dataImmunitySpawns = new Dictionary<string, Vector3>();
        // players spawn points
        private int blockedMask = LayerMask.GetMask("Player (Server)", "Prevent Building", "Construction", "Deployed", "Trigger");
        // layers we won't be setting a zone within 50 meters of
        private int constructionMask = LayerMask.GetMask("Construction", "Deployed");
        private bool matchUpdateRequired;
        private int groundMask = LayerMask.GetMask("Terrain", "World", "Default");
        // used to find dueling zone/set custom zone and create spawn points
        private int wallMask = LayerMask.GetMask("Terrain", "World", "Default", "Construction", "Deployed");
        private int waterMask = LayerMask.GetMask("Water");
        // used to count water colliders when finding a random dueling zone on the map
        private int worldMask = LayerMask.GetMask("World");
        private Timer announceTimer;
        private SortedDictionary<string, string> boneTags = new SortedDictionary<string, string> {
            ["r_"]
            = "Right ", ["l_"] = "Left ", [".prefab"] = string.Empty, ["1"] = string.Empty, ["2"] = string.Empty, ["3"] = string.Empty, ["4"] = string.Empty, ["END"] = string.Empty, ["_"] = " ", ["."] = " "
        }
        ;
        private Dictionary<string, string> announcements = new Dictionary<string, string>();
        // users id and announcement
        private Dictionary<string, long> dataDeath = new Dictionary<string, long>();
        // users id and timestamp of when they're to be executed
        private Dictionary<string, string> dataRequests = new Dictionary<string, string>();
        // users requesting a duel and to whom
        private Dictionary<string, bool> deployables = new Dictionary<string, bool>();
        private 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 SpawnFilter filter = new SpawnFilter();
        // RandomDropPosition()
        private 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 Dictionary<string, string> prefabs = new Dictionary<string, string>();
        private bool resetDuelists;
        // if wipe is detected then assign awards and wipe VictoriesSeed / LossesSeed
        private Dictionary<string, List<ulong>> skinsCache = new Dictionary<string, List<ulong>>();
        // used to randomize custom kit skins which skin id values are 0
        private Dictionary<string, string> tdmRequests = new Dictionary<string, string>();
        // users requesting a deathmatch and to whom
        private Dictionary<string, List<ulong>> workshopskinsCache = new Dictionary<string, List<ulong>>();
        private List<string> dcsBlock = new List<string>();
        // users blocked from 1v1 for 60 seconds after suiciding or disconnecting
        private 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
        }
        private class Tracker : FacepunchBehaviour {
            public BasePlayer player;
            private Duelist _;
            private void Awake() {
                player = GetComponent<BasePlayer>();
            }
            public void Init(Duelist _) {
                this._ = _;
                InvokeRepeating(Track, 0f, 0.5f);
            }
            private void Track() {
                if (player == null || player.transform == null) {
                    Destroy(this);
                    return;
                }
                if (_.dataDuelists.ContainsKey(player.UserIDString) || _.tdmMatches.Exists(team => team.GetTeam(player) != Team.None)) {
                    if (!_.DuelTerritory(player.transform.position)) {
                        player.inventory.Strip();
                        Destroy(this);
                    }
                }
            }
            private void OnDestroy() {
                try {
                    CancelInvoke();
                }
                catch {
                }
                Destroy(this);
            }
        }
        public class Rematch {
            public Rematch(Duelist _) {
                this._ = _;
            }
            private Duelist _;
            public List<BasePlayer> Duelists = new List<BasePlayer>();
            public List<BasePlayer> Ready = new List<BasePlayer>();
            private List<BasePlayer> Evil = new List<BasePlayer>();
            private List<BasePlayer> Good = new List<BasePlayer>();
            public GoodVersusEvilMatch match;
            private Timer _notify;
            public List<BasePlayer> Players {
                get {
                    Duelists.RemoveAll(IsNotConnected);
                    Good.RemoveAll(IsNotConnected);
                    Evil.RemoveAll(IsNotConnected);
                    Ready.RemoveAll(IsNotConnected);
                    if (match == null) return Duelists;
                    var _list = new List<BasePlayer>();
                    _list.AddRange(Good);
                    _list.AddRange(Evil);
                    return _list;
                }
            }
            public bool HasPlayer(BasePlayer player) {
                return Players.Contains(player);
            }
            public bool AddRange(List<BasePlayer> players, Team team) {
                foreach (var player in players) {
                    if (IsNotConnected(player) || _.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) || !_.IsNewman(player) || _.duelsData.Bans.ContainsKey(player.UserIDString)) return false;
                return true;
            }
            public bool IsReady() {
                if (Players.Exists(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) {
                    Message(player, _.msg(key, player.UserIDString, args));
                }
            }
            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 = _.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);
                                _.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 (!_.SelectZone(player, target)) {
                        Message(player, _.msg("AllZonesFull", player.UserIDString, _.duelingZones.Count, _.playersPerZone));
                        Message(target, _.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 = "";
            public string AttackerId = "";
            public string BoneName = "";
            public string Distance = "";
            public string Weapon = "";
        }
        public class GoodVersusEvilMatch {
            public GoodVersusEvilMatch(Duelist _) {
                this._ = _;
            }
            private Duelist _;
            private HashSet<ulong> _banned = new HashSet<ulong>();
            private HashSet<BasePlayer> _evil = new HashSet<BasePlayer>();
            private HashSet<ulong> _evilKIA = new HashSet<ulong>();
            private List<BasePlayer> _evilRematch = new List<BasePlayer>();
            private HashSet<BasePlayer> _good = new HashSet<BasePlayer>();
            private HashSet<ulong> _goodKIA = new HashSet<ulong>();
            private List<BasePlayer> _goodRematch = new List<BasePlayer>();
            private string _goodHostName = "";
            private string _evilHostName = "";
            private string _goodHostId = "";
            private string _evilHostId = "";
            private string _goodCode = "";
            private string _evilCode = "";
            private int _teamSize = 2;
            private bool _started;
            private bool _ended;
            private string _kit = "";
            private DuelingZone _zone;
            private Timer _queueTimer;
            private bool _enteredQueue;
            private bool _public;
            public bool CanRematch = true;
            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(IsNotConnected);
                        _evil.RemoveWhere(IsNotConnected);
                        _good.ToList().ForEach(player => _.duelsData.Kits[player.UserIDString] = _kit);
                        _evil.ToList().ForEach(player => _.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 = _.GetRandomKit();
                _goodHostId = BasePlayer.activePlayerList.FirstOrDefault(x => x.displayName == _goodHostName)?.UserIDString ?? _goodHostId;
                _evilHostId = BasePlayer.activePlayerList.FirstOrDefault(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 = _.GetRandomKit();
                if (TeamSize > 1) {
                    Message(player, _.msg("MatchOpened", player.UserIDString, _.szMatchChatCommand, _goodCode));
                    Message(target, _.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(_good, key, args);
                _.Message(_evil, key, args);
            }
            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 _.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.ToList().Select(player => player.displayName) : _evil.ToList().Select(player => player.displayName));
            }
            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) {
                    Message(player, _.msg("MatchStartedAlready", player.UserIDString));
                    return false;
                }
                _good.RemoveWhere(IsNotConnected);
                _evil.RemoveWhere(IsNotConnected);
                if (_banned.Contains(player.userID)) return false;
                if (!_.IsNewman(player)) {
                    Message(player, _.msg("MustBeNaked", player.UserIDString));
                    return false;
                }
                switch (team) {
                    case Team.Good : if (_good.Count == _teamSize) {
                        Message(player, _.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) {
                        Message(player, _.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);
                _.Metabolize(player, false);
                _.Track(player, false);
                _.RemoveEntities(player.userID);
                Interface.Oxide.CallHook("DisableBypass", player.userID);
                if (_.DuelTerritory(player.transform.position)) {
                    if (_.sendDefeatedHome) _.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(IsNotConnected);
                if (_good.Count > 0) {
                    _goodHostId = _good.FirstOrDefault().UserIDString;
                    _.matchUpdateRequired = true;
                }
                else EndMatch(Team.Evil);
            }
            private void AssignEvilHostId() {
                _evil.RemoveWhere(IsNotConnected);
                if (_evil.Count > 0) {
                    _evilHostId = _evil.FirstOrDefault().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.Exists(IsNotConnected) || _evilRematch.Exists(IsNotConnected)) return false;
                var rematch = new Rematch(_);
                if (rematch.AddRange(_evilRematch, Team.Evil) && rematch.AddRange(_goodRematch, Team.Good)) {
                    rematch.match = this;
                    rematch.Notify();
                    _.rematches.Add(rematch);
                    return true;
                }
                return false;
            }
            private void EndMatch(Team team) {
                if (!_ended && _started) {
                    Finalize(team);
                    _.Puts(_.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, _.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;
                        Message(target, _.msg("MatchDefeat", target.UserIDString, team == Team.Evil ? _evilHostName : _goodHostName, team == Team.Evil ? _goodHostName : _evilHostName, _teamSize));
                    }
                    if (!SetupRematch()) {
                        var _list = new List<BasePlayer>();
                        _list.AddRange(_evilRematch);
                        _list.AddRange(_goodRematch);
                        foreach (var player in _list) {
                            if (IsNotConnected(player)) continue;
                            Message(player, _.msg("RematchFailed2", player.UserIDString));
                        }
                        Reuse();
                    }
                }
                End();
            }
            public void End(bool forced = false) {
                if (_zone != null) _zone.IsLocked = false;
                _queueTimer?.Destroy();
                _good.RemoveWhere(IsNull);
                _evil.RemoveWhere(IsNull);
                var _list = new List<BasePlayer>();
                _list.AddRange(_good);
                _list.AddRange(_evil);
                foreach (var player in _list) {
                    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();
                            _.SendHome(player);
                        }
                        _.Metabolize(player, false);
                        _.Track(player, false);
                    }
                }
                _good.Clear();
                _evil.Clear();
                _.tdmMatches.Remove(this);
                _.matchUpdateRequired = true;
                if (_.dataDuelists.Count == 0 && _.tdmMatches.Count == 0) _.Unsubscribe(nameof(OnPlayerHealthChange));
            }
            private void Queue() {
                DuelingZone zone = null;
                var _list = new List<BasePlayer>();
                _list.AddRange(_good);
                _list.AddRange(_evil);
                foreach (var player in _list) {
                    if (player == null) continue;
                    if (!_.IsNewman(player)) {
                        Message(player, _.msg("MustBeNaked", player.UserIDString));
                        MessageAll("MatchIsNotNaked", player.displayName);
                        _queueTimer = _.timer.Once(30f, Queue);
                        return;
                    }
                    if (zone == null) zone = _.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 = _.timer.Once(2f, Queue);
                    return;
                }
                _zone = zone ?? LastZone ?? zones.GetRandom();
                _queueTimer?.Destroy();
                Start();
            }
            public DuelingZone LastZone {
                get {
                    DuelingZone zone = null;
                    if (_good.Exists(player => _.DuelTerritory(player.transform.position))) zone = _.GetDuelZone(_good.FirstOrDefault(player => _.DuelTerritory(player.transform.position)).transform.position);
                    if (_evil.Exists(player => _.DuelTerritory(player.transform.position))) zone = _.GetDuelZone(_evil.FirstOrDefault(player => _.DuelTerritory(player.transform.position)).transform.position);
                    return zone == null || zone.TotalPlayers > 0 || zone.IsLocked ? null : zone;
                }
            }
            private void Start() {
                _.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(_good, "MatchStarted", GetNames(Team.Evil));
                _.Message(_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);
                    _.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 : FacepunchBehaviour  // Thanks @Jake_Rich for helping me get this started!
        {
            private Duelist _ => Instance;
            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 List<SphereEntity> spheres = new List<SphereEntity>();
            public bool IsLocked;
            public int Kills;
            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 || IsLocked;
                }
            }
            public Vector3 Position {
                get {
                    return _zonePos;
                }
            }
            private void OnDestroy() {
                Destroy(gameObject);
                Destroy(this);
            }
            private void OnTriggerEnter(Collider col) {
                if (col == null) return;
                var entity = col.ToBaseEntity();
                if (entity is BaseMountable) {
                    var m = entity as BaseMountable;
                    if (m.GetParentEntity() is TrainCar) {
                        return;
                    }
                    RemoveMountable(m, GetMountedPlayers(m));
                }
                else if (entity is BasePlayer) {
                    var p = entity as BasePlayer;
                    if (_.InEvent(p) || _.IsSpectator(p)) {
                        return;
                    }
                    RemovePlayer(p);
                }
            }
            public Vector3 GetEjectLocation(Vector3 a, float distance) {
                var position = ((a.XZ3D() - _zonePos.XZ3D()).normalized * (_.zoneRadius + distance)) + _zonePos;
                // credits ZoneManager
                float y = TerrainMeta.HighestPoint.y + 250f;
                RaycastHit hit;
                if (Physics.Raycast(position + new Vector3(0f, y, 0f), Vector3.down, out hit, Mathf.Infinity, targetLayer, QueryTriggerInteraction.Ignore)) {
                    position.y = hit.point.y + 0.75f;
                }
                else position.y = Mathf.Max(TerrainMeta.HeightMap.GetHeight(position), TerrainMeta.WaterMap.GetHeight(position)) + 0.75f;
                return position;
            }
            public bool RemovePlayer(BasePlayer player) {
                if (!player.IsHuman() || player.IsAdmin) {
                    return false;
                }
                var m = player.GetMounted();
                if (m.IsValid()) {
                    var players = GetMountedPlayers(m);
                    players.RemoveAll(x => x == null || !x.IsHuman());
                    if (RemoveMountable(m, players)) {
                        return true;
                    }
                }
                var position = GetEjectLocation(player.transform.position, 10f);
                if (player.IsFlying) {
                    position.y = player.transform.position.y;
                }
                player.Teleport(position);
                player.SendNetworkUpdateImmediate();
                return true;
            }
            public void DismountAllPlayers(BaseMountable m) {
                foreach (var target in GetMountedPlayers(m)) {
                    if (target == null) continue;
                    m.DismountPlayer(target, false);
                    target.EnsureDismounted();
                }
            }
            private List<BasePlayer> GetMountedPlayers(BaseMountable m) {
                BaseVehicle vehicle = m.HasParent() ? m.VehicleParent() : m as BaseVehicle;
                if (vehicle.IsValid()) {
                    return GetMountedPlayers(vehicle);
                }
                List<BasePlayer> players = new List<BasePlayer>();
                var player = m.GetMounted();
                if (player.IsValid() && player.IsHuman()) {
                    players.Add(player);
                }
                return players;
            }
            private List<BasePlayer> GetMountedPlayers(BaseVehicle vehicle) {
                List<BasePlayer> players = new List<BasePlayer>();
                if (!vehicle.HasMountPoints()) {
                    var player = vehicle.GetMounted();
                    if (player.IsValid() && player.IsHuman()) {
                        players.Add(player);
                    }
                    return players;
                }
                for (int i = 0; i < vehicle.mountPoints.Count; i++) {
                    var mountPoint = vehicle.mountPoints[i];
                    if (mountPoint.mountable == null) {
                        continue;
                    }
                    var player = mountPoint.mountable.GetMounted();
                    if (player.IsValid() && player.IsHuman()) {
                        players.Add(player);
                    }
                }
                return players;
            }
            private bool RemoveMountable(BaseMountable m, List<BasePlayer> players) {
                if (players.Count == 0) {
                    return Ej
// ... [Code preview truncated due to length. Full source in attached file] ...

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