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

FREE Skirmish : 1.0.5 1.0.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
 //Requires: EventHelper
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
/* 1.0.1
 * Added API Calls: 
- void Skimish_StartRegistration(string activeArena, bool isFFA);
- void Skimish_EndGame();
- void Skimish_StartGame(string activeArena, bool isFFA);
 * Changed the message order in OnEntityTakeDamage.* Added a new UI to start and end the game.Type /sk
 */
namespace Oxide.Plugins {
    [Info("Skirmish", "imthenewguy", "1.0.5")]
    [Description("This plugin was fixed by Инкуб to order [Rust Plugin Sliv]: https://discord.gg/pFgKw6Dyyq")]
    class Skirmish : RustPlugin {
#region Config
        private Configuration config;
        public class Configuration {
            [JsonProperty("Maximum hits a player can take before they are out")]
            public int max_hits = 7;
            [JsonProperty("Maximum ammo capacity of a snowball launcher in the event")]
            public int max_ammo = 10;
            [JsonProperty("Minimum players required to start a game")]
            public int minimum_players = 2;
            [JsonProperty("How many seconds do the players have to register to player before we start")]
            public float seconds_before_game_starts = 300;
            [JsonProperty("Chance for a game to be FFA instead of TDM [%]")]
            public int ffa_chance = 40;
            [JsonProperty("Maximum time that the game can run for (seconds)")]
            public float max_time = 1800f;
            [JsonProperty("Sound effect")]
            public string damage_sound = "assets/prefabs/deployable/barricades/effects/damage.prefab";
            [JsonProperty("Reward dead players on the winning team")]
            public bool reward_dead = true;
            [JsonProperty("Free for all suit [shortname]")]
            public string ffa_suit = "hazmatsuit.nomadsuit";
            [JsonProperty("Team death match - team 1 suit [shortname]")]
            public string tdm1_suit = "hazmatsuit_scientist_peacekeeper";
            [JsonProperty("Team death match - team 2 suit [shortname]")]
            public string tdm2_suit = "hazmatsuit_scientist";
            [JsonProperty("Clear all data on map wipe")]
            public bool clear_data = true;
            [JsonProperty("Run the game automatically with EventHelper?")]
            public bool use_event_helper = true;
            [JsonProperty("How often should we start a game (if not being managed through EventHelper)")]
            public float auto_start_time = 7200;
            [JsonProperty("Clear NPCs from around the arena when the game starts?")]
            public bool delete_npcs = false;
            [JsonProperty("Max distance from anchor entities that NPCs will be deleted from on game start.")]
            public float delete_max_distance = 100f;
            [JsonProperty("Commands to prevent when a player are at the event")]
            public string[] prevent_commands = {
                "kit"
            }
            ;
            [JsonProperty("Automatically give players their items back after leaving [if running auto kit set to false]")]
            public bool kit_back_on_death = true;
            [JsonProperty("Announce when players join the event")]
            public bool announce_on_join = true;
            [JsonProperty("Maximum number of participants allowed per round (0 == no limit)")]
            public int max_players = 32;
            [JsonProperty("Prize table")]
            public List<PrizeInfo> prizes = new List<PrizeInfo>();
            [JsonProperty("Arena setups - Make sure your entity combinations and arena names are unique")]
            public Dictionary<string, ArenaInfo> arenas = new Dictionary<string, ArenaInfo>();
            public string ToJson() => JsonConvert.SerializeObject(this);
            public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());
        }
        protected override void LoadDefaultConfig() {
            config = new Configuration();
            config.arenas = default_Arenas;
            config.prizes = defaultPrizes;
        }
        public List<PrizeInfo> defaultPrizes {
            get {
                return new List<PrizeInfo>() {
                    new PrizeInfo("scrap", 50, 200), new PrizeInfo("wood", 1500, 5000), new PrizeInfo("stones", 1500, 5000), new PrizeInfo("sulfur", 1000, 2000), new PrizeInfo("potato", 5, 20, 0, "tasty potatoes")
                }
                ;
            }
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) {
                    throw new JsonException();
                }
                if (!config.ToDictionary().Keys.SequenceEqual(Config.ToDictionary(x => x.Key, x => x.Value).Keys)) {
                    PrintToConsole("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch {
                PrintToConsole($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() {
            PrintToConsole($"Configuration changes saved to {Name}.json");
            Config.WriteObject(config, true);
        }
        public class ArenaInfo {
            public bool enabled = true;
            public string Anchor_Entity_Main;
            public string Anchor_Entity_Secondary;
            public ulong Anchor_id;
            public List<Vector3> FFA_Spawns = new List<Vector3>();
            public List<Vector3> TDM_Spawns_1 = new List<Vector3>();
            public List<Vector3> TDM_Spawns_2 = new List<Vector3>();
        }
        public class PrizeInfo {
            public string shortname;
            public ulong skin;
            public string displayname;
            public int min_amount;
            public int max_amount;
            public PrizeInfo(string shortname, int min_amount, int max_amount, ulong skin = 0, string displayname = null) {
                this.shortname = shortname;
                this.skin = skin;
                this.min_amount = min_amount;
                this.max_amount = max_amount;
                this.displayname = displayname;
            }
        }
#endregion
#region Data
        PlayerEntity pcdData;
        private DynamicConfigFile PCDDATA;
        void Init() {
            PCDDATA = Interface.Oxide.DataFileSystem.GetFile(this.Name);
            LoadData();
            permission.RegisterPermission("skirmish.admin", this);
            UnsubHooks();
        }
        void Unload() {
            foreach (var player in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(player, "paintball_splats");
                CuiHelper.DestroyUi(player, "SkirmishStartPanel");
            }
            EndGame();
            EventHelper.Call("EMRemoveEvent", this.Name);
            SaveData();
        }
        void SaveData() {
            PCDDATA.WriteObject(pcdData);
        }
        void LoadData() {
            try {
                pcdData = Interface.Oxide.DataFileSystem.ReadObject<PlayerEntity>(this.Name);
            }
            catch {
                Puts(lang.GetMessage("PlayerDataLoading", this));
                pcdData = new PlayerEntity();
            }
        }
        class PlayerEntity {
            public Dictionary<ulong, PlayerInfo> pEntity = new Dictionary<ulong, PlayerInfo>();
            public Vector3 lobby_point;
            public Dictionary<string, ArenaInfo> arenas = new Dictionary<string, ArenaInfo>();
        }
        class TeleportInfo {
            public List<Vector3> ffa_destinations = new List<Vector3>();
            public Dictionary<int, List<Vector3>> tdm_destinations = new Dictionary<int, List<Vector3>>();
        }
        class PlayerInfo {
            public int prizes;
        }
#endregion;
#region Localization
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["EliminatedYou"]
                = "You have been eliminated by <color=#DFF008>{0}</color>.", ["EliminatedOther"] = "You eliminated <color=#DFF008>{0}</color>.", ["UnclaimedPrizes"] = "You have unclaimed prizes from winning round(s) of skirmish.Type <color=#13ff00>/skprize</color> to redeem them.", ["MissingLobby"] = "Attempted to start skirmish up but we are missing lobby destination.", ["GameStarting"] = "A game of skirmish at the <color=#ffae00>{0}</color> will start in <color=#ffae00>{1}</color> seconds.Type <color=#13ff00>/skjoin</color> to join.\nGame Type: <color=#ffae00>{2}</color>", ["SkirmishStart60"] = "Skirmish starts in <color=#ffae00>60 seconds</color>.Type <color=#13ff00>/skjoin</color> to join.", ["SkirmishStarted"] = "Skirmish registration has closed.", ["SkirmishCancelledNoPlayers"] = "Cancelling game due to low player count.", ["SkirmishCancelledNoArenas"] = "Could not find arena data for {0}.", ["GameStarted"] = "Skirmish has started!", ["EndNoWinners"] = "There were no winners of the skirmish match as everyone died.", ["EndWinnerSolo"] = "<color=#13ff00>{0}</color> has won the round!", ["EndWinnerTeam"] = "<color=#13ff00>Team {0}</color> are the winners:\n- {1}", ["MsgWinner"] = "You received a prize for winning (Available: <color=#13ff00>{0}</color>).Type <color=#13ff00>/skprize</color> to redeem it.", ["MsgWinnerTeam"] = "You received a prize for winning (Available: {0}).Type /skprize to redeem it.", ["ClearedData"] = "Cleared data", ["CannotRedeem"] = "You cannot redeem these while in a match.", ["NoPrizes"] = "You do not have any prizes outstanding.", ["NullPrize"] = "Error - prize was null", ["PrizeReceived"] = "You received <color=#13ff00>{0}x {1}</color>.", ["NoGamesRunning"] = "No games running.", ["NotJoiningAllowed"] = "You are not allowed to join this game.", ["AlreadyRegistered"] = "You have already registed for this event.", ["ErrorJoining"] = "Could not join event.Check print out from EventHelper for more info.", ["GameAlreadyRunning"] = "Game already running", ["EndedMatch"] = "Ended match", ["UnloadingSkirmish"] = "Unloading Skirmish...", ["NoLobbyFoundConsole"] = "No lobby point found.Type /sksetlobby while in game to set one.", ["ConsoleFoundStoredAnchors"] = "Found and stored {0} arenas into memory.", ["AutoStartingConsole"] = "Auto starting Skirmish", ["AddingPrizesConsole"] = "Adding prizes", ["ClearingAI"] = "Clearing AI from arenas.", ["SetLobbyManually"] = "Set the lobby postion to {0}", ["AnchorPairFound"] = "Found the {0} anchor from saved data.", ["SearchingAnchors"] = "Existing anchor data for {0} is invalid.Searching for anchor entity.", ["AnchorFailed"] = "Could not acquire anchors for {0}", ["NewAnchorFound"] = "Found new arena: {0}.Adding to data.", ["NoArenaData"] = "No arena data could be found.", ["PlayerDataLoading"] = "Couldn't load player data, creating new Playerfile", ["UITitle"] = "Skirmish Event", ["UIisRunning"] = "Game Running", ["UIArena"] = "Arena", ["UIMode"] = "Mode", ["UIDelayTitle"] = "Delay before start", ["UIStart"] = "START", ["UIStop"] = "STOP", ["EventFull"] = "This event is full.", ["JoinedMessage"] = "<color=#fbff00>{0}</color> joined the <color=#ffa200>Skirmish</color> lobby <color=#fbff00>[</color>{1}<color=#fbff00>]</color>"
            }
            , this);
        }
#endregion
#region Globals
        class PaintballInfo {
            public int hits_taken;
            public int team;
        }
        Dictionary<BasePlayer, PaintballInfo> Participants = new Dictionary<BasePlayer, PaintballInfo>();
        List<BasePlayer> corpseWatch = new List<BasePlayer>();
        private List<PlayerCorpse> Corpses = new List<PlayerCorpse>();
        const string perm_admin = "skirmish.admin";
        bool isRunning;
        bool AllowJoin;
        bool isFFA;
        bool GameStarted;
        Timer GameDelayTimer;
        List<BasePlayer> team_1 = new List<BasePlayer>();
        List<BasePlayer> team_2 = new List<BasePlayer>();
        string active_arena;
        Dictionary<string, BaseNetworkable> anchor_entities = new Dictionary<string, BaseNetworkable>();
        [PluginReference]
        private Plugin EventHelper, NightVision, ImageLibrary;
#endregion
#region Hooks
        void OnPlayerDisconnected(BasePlayer player, string reason) {
            LeaveEvent(player);
        }
        object CanMountEntity(BasePlayer player, BaseMountable entity) {
            if (Participants.ContainsKey(player)) return false;
            return null;
        }
        void OnEntitySpawned(BaseNetworkable entity) {
            if (active_arena == null) return;
            if (entity != null && Vector3.Distance(entity.transform.position, anchor_entities[active_arena].transform.position) < 80) {
                if (entity is ScientistNPC || entity is BaseAnimalNPC) entity.KillMessage();
            }
        }
        void OnServerInitialized(bool initial) {
            if (config.arenas == null || config.arenas.Count == 0) {
                config.arenas = default_Arenas;
                SaveConfig();
            }
            if (!FoundAnchors()) {
                Puts(lang.GetMessage("UnloadingSkirmish", this));
                Interface.Oxide.UnloadPlugin(Name);
                return;
            }
            if (pcdData.lobby_point == Vector3.zero) Puts(lang.GetMessage("NoLobbyFoundConsole", this));
            EventHelper.Call("EMCreateEvent", this.Name, config.use_event_helper, true, true, true, config.kit_back_on_death, true, pcdData.lobby_point);
            EventHelper.Call("EMExternalPluginSettings", this.Name);
            EventHelper.Call("EMBlackListCommands", this.Name, config.prevent_commands);
            Puts(string.Format(lang.GetMessage("ConsoleFoundStoredAnchors", this), anchor_entities.Count));
            splats = new List<string>() {
                "splat1", "splat2", "splat3", "splat4", "splat5", "splat6"
            }
            ;
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lmvNN.png", "splat1");
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lmXHw.png", "splat2");
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lmgwh.png", "splat3");
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lm3Ga.png", "splat4");
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lmW8x.png", "splat5");
            ImageLibrary?.Call("AddImage", "https://gspics.org/images/2024/01/21/0lm6oQ.png", "splat6");
            if (!config.use_event_helper) {
                if (config.auto_start_time > 0) GameDelayTimer = timer.Every(config.auto_start_time, () => {
                    Puts(lang.GetMessage("AutoStartingConsole", this));
                    StartRegistration();
                }
                );
            }
            if (config.prizes == null || config.prizes.Count == 0) {
                Puts(lang.GetMessage("AddingPrizesConsole", this));
                config.prizes = defaultPrizes;
                SaveConfig();
            }
            Puts(lang.GetMessage("ClearingAI", this));
            foreach (var arena in anchor_entities) {
                ClearAI(arena.Value.transform.position);
            }
        }
        void ClearAI(Vector3 pos) {
            if (!config.delete_npcs) return;
            var ai = BaseNetworkable.serverEntities.Where(x => (x is BaseAnimalNPC || x is ScientistNPC) && Vector3.Distance(x.transform.position, pos) < config.delete_max_distance).ToList();
            if (ai == null || ai.Count == 0) return;
            foreach (var entity in ai.ToList()) {
                entity.KillMessage();
            }
        }
        object CanDropActiveItem(BasePlayer player) {
            if (Participants.ContainsKey(player)) return false;
            return null;
        }
        object OnItemAction(Item item, string action, BasePlayer player) {
            if (Participants.ContainsKey(player)) return false;
            return null;
        }
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (!Participants.ContainsKey(player)) return;
            if (NightVision != null) {
                NightVision.Call("UnlockPlayerTime", player);
                permission.RevokeUserPermission(player.UserIDString, "nightvision.allowed");
            }
            corpseWatch.Add(player);
            Participants.Remove(player);
            CheckWin();
        }
        void OnNewSave(string filename) {
            pcdData.arenas.Clear();
            pcdData.lobby_point = Vector3.zero;
            if (config.clear_data) {
                ClearData();
            }
        }
        object OnEntityTakeDamage(BasePlayer player, HitInfo info) {
            PaintballInfo pi;
            if (player == null || info == null || !Participants.TryGetValue(player, out pi)) return null;
            var attacker = info.InitiatorPlayer;
            if (attacker == null || !Participants.ContainsKey(attacker)) return null;
            PaintballInfo api;
            if (!Participants.TryGetValue(attacker, out api) || (api.team == pi.team && !isFFA)) return null;
            var weapon = attacker.GetActiveItem();
            if (weapon == null) return null;
            if (weapon.info.shortname == "snowball" || weapon.info.shortname == "snowballgun") {
                pi.hits_taken++;
                if (pi.hits_taken >= config.max_hits) {
                    PrintToChat(player, string.Format(lang.GetMessage("EliminatedYou", this, player.UserIDString), attacker.displayName));
                    PrintToChat(attacker, string.Format(lang.GetMessage("EliminatedOther", this, player.UserIDString), player.displayName));
                    LeaveEvent(player);
                    CheckWin();
                }
                else {
                    SendSplats(player, pi.hits_taken);
                    EffectNetwork.Send(new Effect(config.damage_sound, player.transform.position, player.transform.position), player.net.connection);
                }
                return false;
            }
            return null;
        }
        void OnPlayerCorpseSpawned(BasePlayer player, PlayerCorpse corpse) {
            if (!isRunning) return;
            if (corpseWatch.Contains(player)) {
                Corpses.Add(corpse);
                corpseWatch.Remove(player);
            }
        }
        void OnPlayerRespawned(BasePlayer player) {
            if (permission.UserHasPermission(player.UserIDString, "nightvision.allowed")) permission.RevokeUserPermission(player.UserIDString, "nightvision.allowed");
            if (pcdData.pEntity.ContainsKey(player.userID) && pcdData.pEntity[player.userID].prizes > 0) PrintToChat(player, lang.GetMessage("UnclaimedPrizes", this, player.UserIDString));
            if (Convert.ToBoolean(EventHelper.Call("EMIsParticipating", player, this.Name))) {
                EventHelper.Call("EMPlayerLeaveEvent", player, this.Name);
            }
        }
        object CanLootEntity(BasePlayer player, StorageContainer container) {
            if (Participants.ContainsKey(player)) return false;
            return null;
        }
        object CanLootEntity(BasePlayer player, LootableCorpse container) {
            if (Corpses.Contains(container) && !Participants.ContainsKey(player)) return false;
            return null;
        }
#endregion
#region Helpers
        void UnsubHooks() {
            Unsubscribe("OnEntityTakeDamage");
            Unsubscribe("CanDropActiveItem");
            Unsubscribe("OnItemAction");
            Unsubscribe("OnPlayerDeath");
            Unsubscribe("OnPlayerCorpseSpawned");
            Unsubscribe("CanEntityTakeDamage");
            Unsubscribe("CanMountEntity");
            Unsubscribe("CanLootEntity");
            Unsubscribe("OnExitZone");
            Unsubscribe("OnEnterZone");
            Unsubscribe("OnEntitySpawned");
            Unsubscribe("OnPlayerDisconnected");
        }
        void DeleteTimers() {
            foreach (var t in _timers) {
                if (!t.Destroyed) t.Destroy();
            }
            _timers.Clear();
        }
        void EndGame() {
            // Do end game stuff
            Interface.Call("Skimish_EndGame");
            DeleteTimers();
            if (Participants != null && Participants.Count > 0) {
                foreach (var player in Participants.Keys.ToList()) {
                    if (NightVision != null) {
                        NightVision.Call("UnlockPlayerTime", player);
                        permission.RevokeUserPermission(player.UserIDString, "nightvision.allowed");
                    }
                    if (player.IsAlive() && player.IsConnected) {
                        EventHelper.Call("EMPlayerLeaveEvent", player, this.Name);
                    }
                    Participants.Remove(player);
                }
            }
            if (Corpses.Count > 0) {
                foreach (var corpse in Corpses.ToList()) {
                    if (corpse != null) corpse.Kill();
                }
            }
            Corpses.Clear();
            corpseWatch.Clear();
            if (BasePlayer.activePlayerList != null && BasePlayer.activePlayerList.Count > 0) {
                foreach (var player in BasePlayer.activePlayerList) {
                    CuiHelper.DestroyUi(player, "paintball_splats");
                }
            }
            team_1.Clear();
            team_2.Clear();
            if (!config.use_event_helper) {
                if (GameDelayTimer != null && !GameDelayTimer.Destroyed) GameDelayTimer.Destroy();
                if (config.auto_start_time > 0) GameDelayTimer = timer.Every(config.auto_start_time, () => {
                    Puts(lang.GetMessage("AutoStartingConsole", this));
                    StartRegistration();
                }
                );
            }
            UnsubHooks();
            active_arena = null;
            if (isRunning) {
                EventHelper.Call("EMEndEvent", this.Name);
                PrintToChat(lang.GetMessage("EndedMatch", this));
                isRunning = false;
            }
            AllowJoin = false;
            GameStarted = false;
        }
        List<Timer> _timers = new List<Timer>();
        private void StartRegistration(float time_override = 0, string arena = null, string mode = null) {
            if (isRunning) return;
            if (GameDelayTimer != null && GameDelayTimer.Destroyed) GameDelayTimer.Destroy();
            var randomArena = pcdData.arenas.ToList().GetRandom();
            if (!string.IsNullOrEmpty(arena)) {
                randomArena = new KeyValuePair<string, ArenaInfo>(arena, config.arenas[arena]);
            }
            if (pcdData.lobby_point == Vector3.zero || (randomArena.Value.FFA_Spawns == null && config.ffa_chance > 0) || ((randomArena.Value.TDM_Spawns_1.Count == 0 || randomArena.Value.TDM_Spawns_2.Count == 0) && config.ffa_chance < 100)) {
                PrintToChat(lang.GetMessage("MissingLobby", this));
                return;
            }
            // Set the active arena key to active_arena var.active_arena = randomArena.Key;
            Subscribe("OnPlayerDeath");
            Subscribe("OnPlayerCorpseSpawned");
            Subscribe("CanMountEntity");
            Subscribe("CanLootEntity");
            Subscribe("OnPlayerDisconnected");
            EventHelper.Call("EMStartEvent", this.Name);
            isRunning = true;
            AllowJoin = true;
            if (string.IsNullOrEmpty(mode)) {
                if (config.ffa_chance == 100) isFFA = true;
                else if (config.ffa_chance == 0) isFFA = false;
                else if (UnityEngine.Random.Range(0, 100) < config.ffa_chance + 1) isFFA = true;
                else isFFA = false;
            }
            else {
                if (mode == "ffa") isFFA = true;
                else isFFA = false;
            }
            var str = isFFA ? "Free-For-All" : "Team Death Match";
            var time_to_start = time_override > 0 ? time_override : config.seconds_before_game_starts;
            PrintToChat(string.Format(lang.GetMessage("GameStarting", this), randomArena.Key, time_to_start, str));
            Interface.Call("Skimish_StartRegistration", active_arena, isFFA);
            if (time_to_start > 60) {
                _timers.Add(timer.Once(time_to_start - 60, () => {
                    PrintToChat(lang.GetMessage("SkirmishStart60", this));
                    return;
                }
                ));
            }
            _timers.Add(timer.Once(time_to_start, () => {
                PrintToChat(lang.GetMessage("SkirmishStarted", this));
                StartGame();
            }
            ));
        }
        void StartGame() {
            AllowJoin = false;
            Subscribe("OnEntityTakeDamage");
            Subscribe("CanDropActiveItem");
            Subscribe("OnItemAction");
            Subscribe("CanEntityTakeDamage");
            Subscribe("OnEntitySpawned");
            if (Participants.Count < config.minimum_players) {
                PrintToChat(lang.GetMessage("SkirmishCancelledNoPlayers", this));
                EndGame();
                return;
            }
            ArenaInfo arenaData;
            if (!pcdData.arenas.TryGetValue(active_arena, out arenaData)) {
                Puts(string.Format(lang.GetMessage("SkirmishCancelledNoArenas", this), active_arena));
                EndGame();
                return;
            }
            Interface.Call("Skimish_StartGame", active_arena, isFFA);
            PrintToChat(lang.GetMessage("GameStarted", this));
            GameStarted = true;
            Puts(lang.GetMessage("ClearingAI", this));
            ClearAI(anchor_entities[active_arena].transform.position);
            if (isFFA) {
                List<Vector3> used = new List<Vector3>();
                foreach (var player in Participants.Keys) {
                    if (used.Count == arenaData.FFA_Spawns.Count) used.Clear();
                    Vector3 RandomPos = arenaData.FFA_Spawns.Where(x => !used.Contains(x)).ToList().GetRandom();
                    player.flyhackPauseTime = 10f;
                    Player.Teleport(player, RandomPos);
                    player.StartSleeping();
                    player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
                    player.ClientRPCPlayer(null, player, "StartLoading");
                    player.SendEntityUpdate();
                    player.UpdateNetworkGroup();
                    player.SendNetworkUpdateImmediate(false);
                    GiveSnowballLauncher(player);
                }
            }
            else {
                System.Random rand = new System.Random();
                var lastGiven = 0;
                foreach (var player in Participants.OrderBy(x => rand.Next()).ToDictionary(item => item.Key, item => item.Value)) {
                    if (lastGiven == 0) {
                        player.Value.team = 1;
                        lastGiven++;
                    }
                    else if (lastGiven == 1) {
                        player.Value.team = 2;
                        lastGiven++;
                    }
                    else {
                        player.Value.team = 1;
                        lastGiven = 1;
                    }
                    player.Key.flyhackPauseTime = 10f;
                    if (player.Value.team == 1) Player.Teleport(player.Key, arenaData.TDM_Spawns_1.GetRandom());
                    else Player.Teleport(player.Key, arenaData.TDM_Spawns_2.GetRandom());
                    player.Key.StartSleeping();
                    player.Key.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
                    player.Key.ClientRPCPlayer(null, player.Key, "StartLoading");
                    player.Key.SendEntityUpdate();
                    player.Key.UpdateNetworkGroup();
                    player.Key.SendNetworkUpdateImmediate(false);
                    GiveSnowballLauncher(player.Key, player.Value.team);
                    if (player.Value.team == 1) team_1.Add(player.Key);
                    else team_2.Add(player.Key);
                }
            }
            _timers.Add(timer.Once(config.max_time, () => {
                EndGame();
            }
            ));
        }
        void ClearData() {
            pcdData.pEntity.Clear();
            SaveData();
        }
        private void LeaveEvent(BasePlayer player, bool manually_left = false, bool died = false) {
            if (Participants.ContainsKey(player)) Participants.Remove(player);
            if (NightVision != null) {
                NightVision.Call("UnlockPlayerTime", player);
                permission.RevokeUserPermission(player.UserIDString, "nightvision.allowed");
            }
            if (!died) {
                EventHelper.Call("EMPlayerLeaveEvent", player, this.Name, manually_left);
            }
            CuiHelper.DestroyUi(player, "paintball_splats");
            CheckWin();
        }
        void GiveSnowballLauncher(BasePlayer player, int team = 0) {
            var item = ItemManager.CreateByName("snowballgun", 1, 0);
            (item.GetHeldEntity() as BaseProjectile).primaryMagazine.capacity = config.max_ammo;
            player.GiveItem(item);
            for (int i = 0; i < 24 - player.inventory.containerMain.itemList.Count; i++) {
                player.GiveItem(ItemManager.CreateByName("snowball", 10));
            }
            if (team == 0) {
                ItemManager.CreateByName(config.ffa_suit, 1).MoveToContainer(player.inventory.containerWear);
            }
            else if (team == 1) ItemManager.CreateByName(config.tdm1_suit, 1).MoveToContainer(player.inventory.containerWear);
            else ItemManager.CreateByName(config.tdm2_suit, 1).MoveToContainer(player.inventory.containerWear);
        }
        void CheckWin() {
            if (!isRunning || !GameStarted) return;
            if (Participants.Count == 0) {
                PrintToChat(lang.GetMessage("EndNoWinners", this));
                EndGame();
                return;
            }
            if (isFFA) {
                if (Participants.Count == 1) {
                    var winner = Participants.Keys.First();
                    PrintToChat(string.Format(lang.GetMessage("EndWinnerSolo", this), winner.displayName));
                    PlayerInfo pi;
                    if (!pcdData.pEntity.TryGetValue(winner.userID, out pi)) pcdData.pEntity.Add(winner.userID, pi = new PlayerInfo());
                    PrintToChat(winner, string.Format(lang.GetMessage("MsgWinner", this, winner.UserIDString), pi.prizes));
                    pi.prizes++;
                    Interface.CallHook("SKWinner", winner);
                    EndGame();
                }
            }
            else {
                var team_1_count = 0;
                var team_2_count = 0;
                foreach (var player in Participants) {
                    if (player.Value.team == 1) team_1_count++;
                    else if (player.Value.team == 2) team_2_count++;
                }
                if (team_2_count <= 0 || team_1_count <= 0) {
                    var str = team_1_count <= 0 ? "2" : "1";
                    List<BasePlayer> winners;
                    if (config.reward_dead) {
                        if (str == "1") winners = team_1;
                        else winners = team_2;
                    }
                    else winners = Participants.Keys.ToList();
                    PrintToChat(string.Format(lang.GetMessage("EndWinnerTeam", this), str, string.Join("\n- ", Participants.Keys.Select(x => x.displayName).ToList())));
                    foreach (var player in winners) {
                        if (player == null) continue;
                        PlayerInfo pi;
                        if (!pcdData.pEntity.TryGetValue(player.userID, out pi)) pcdData.pEntity.Add(player.userID, pi = new PlayerInfo());
                        pi.prizes++;
                        PrintToChat(player, string.Format(lang.GetMessage("MsgWinner", this, player.UserIDString), pi.prizes));
                    }
                    Interface.CallHook("SKWinners", winners);
                    EndGame();
                }
            }
        }
#endregion
#region Chat Commands
        [ChatCommand("skcleardata")]
        void ClearSkirmishData(BasePlayer player) {
            ClearData();
            PrintToChat(player, lang.GetMessage("ClearedData", this, player.UserIDString));
        }
        [ChatCommand("sksetlobby")]
        void SetLobby(BasePlayer player) {
            if (!permission.UserHasPermission(player.UserIDString, perm_admin)) return;
            pcdData.lobby_point = player.transform.position;
            EventHelper.Call("EMUpdateLobby", this.Name, pcdData.lobby_point);
            PrintToChat(player, string.Format(lang.GetMessage("SetLobbyManually", this, player.UserIDString), player.transform.position));
        }
        [ChatCommand("skprize")]
        void RedeemReward(BasePlayer player) {
            if (Participants.ContainsKey(player)) {
                PrintToChat(player, lang.GetMessage("CannotRedeem", this, player.UserIDString));
                return;
            }
            PlayerInfo pi;
            if (!pcdData.pEntity.TryGetValue(player.userID, out pi) || pi.prizes <= 0) {
                PrintToChat(player, lang.GetMessage("NoPrizes", this, player.UserIDString));
                return;
            }
            var prize = config.prizes.GetRandom();
            if (prize == null) {
                PrintToChat(player, lang.GetMessage("NullPrize", this, player.UserIDString));
                return;
            }
            var item = ItemManager.CreateByName(prize.shortname, UnityEngine.Random.Range(prize.min_amount, prize.max_amount + 1), prize.skin);
            if (item == null) return;
            if (prize.displayname != null) item.name = prize.displayname;
            player.GiveItem(item);
            PrintToChat(player, string.Format(lang.GetMessage("PrizeReceived", this, player.UserIDString), item.amount, item.name ?? item.info.displayName.english));
            pi.prizes--;
            if (pi.prizes == 0) pcdData.pEntity.Remove(player.userID);
        }
        [ChatCommand("skjoin")]
        void RegisterPlayer(BasePlayer player) {
            if (!isRunning) {
                PrintToChat(player, lang.GetMessage("NoGamesRunning", this, player.UserIDString));
                return;
            }
            if (!AllowJoin) {
                PrintToChat(player, lang.GetMessage("NotJoiningAllowed", this, player.UserIDString));
                return;
            }
            if (Participants.ContainsKey(player)) {
                PrintToChat(player, lang.GetMessage("AlreadyRegistered", this, player.UserIDString));
                return;
            }
            if (config.max_players > 0 && Participants.Count >= config.max_players) {
                PrintToChat(player, lang.GetMessage("EventFull", this, player.UserIDString));
                return;
            }
            if (!Convert.ToBoolean(EventHelper.Call("EMEnrollPlayer", player, this.Name))) {
                PrintToChat(player, lang.GetMessage("ErrorJoining", this, player.UserIDString));
                return;
            }
            if (NightVision != null) {
                permission.GrantUserPermission(player.UserIDString, "nightvision.allowed", NightVision);
                NightVision.Call("LockPlayerTime", player, 10f);
            }
            Participants.Add(player, new PaintballInfo());
            if (config.announce_on_join) {
                var str = config.max_players > 0 ? $"{Participants.Count}/{config.max_players}" : Participants.Count.ToString();
                PrintToChat(string.Format(lang.GetMessage("JoinedMessage", this), player.displayName, str));
            }
        }
        [ChatCommand("skleave")]
        void LeaveSkirmish(BasePlayer player) {
            if (Participants.ContainsKey(player)) {
                LeaveEvent(player, true);
            }
        }
        [ChatCommand("skstart")]
        void StartSkirmishCMD(BasePlayer player, string command, string[] args) {
            if (!permission.UserHasPermission(player.UserIDString, perm_admin)) return;
            if (isRunning) {
                PrintToChat(player, lang.GetMessage("GameAlreadyRunning", this, player.UserIDString));
                return;
            }
            var time_override = 0f;
            if (args.Length == 1 && args[0].IsNumeric()) time_override = Convert.ToSingle(args[0]);
            if (config.use_event_helper) {
                EventHelper.Call("EMManuallyStarted", this.Name);
            }
            StartRegistration(time_override);
        }
        [ChatCommand("skend")]
        void EndSkirmishCMD(BasePlayer player) {
            if (!permission.UserHasPermission(player.UserIDString, perm_admin)) return;
            EndGame();
        }
#endregion
#region API
        object CanEntityTakeDamage(BasePlayer player, HitInfo info) {
            if (player == null || info == null) return null;
            if (!player.IsNpc && player.userID.IsSteamId()) {
                PaintballInfo pi;
                if (!Participants.TryGetValue(player, out pi)) return null;
                var attacker = info.InitiatorPlayer;
                if (attacker == null || attacker.IsNpc || !attacker.userID.IsSteamId()) return null;
                if (!Participants.ContainsKey(attacker)) return false;
                PaintballInfo api;
                if (!Participants.TryGetValue(attacker, out api)) return null;
                if (pi.team == api.team && !isFFA) return false;
                return false;
            }
            return null;
        }
        void EMEndGame(string eventName) {
            if (eventName == this.Name) {
                EndGame();
            }
        }
        void EMStartNextEvent(string eventName) {
            if (eventName == this.Name) {
                StartRegistration();
            }
        }
#endregion
#region Splats
        List<string> splats;
        void SendSplats(BasePlayer player, int quantity) {
            var container = new CuiElementContainer();
            container.Add(new CuiPanel {
                CursorEnabled = false, Image = {
                    Color = "0.1254902 0.1254902 0.1254902 0"
                }
                , RectTransform = {
                    AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-16.003 -16", OffsetMax = "15.997 16"
                }
            }
            , "Overlay", "paintball_splats");
            if (quantity >= 1) {
                container.Add(new CuiElement {
                    Name = "splat_1", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "0 1", AnchorMax = "0 1", OffsetMin = "-501.997 13.337", OffsetMax = "-245.997 269.337"
                        }
                    }
                }
                );
            }
            if (quantity >= 2) {
                container.Add(new CuiElement {
                    Name = "splat_2", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "1 1", AnchorMax = "1 1", OffsetMin = "246.004 13.677", OffsetMax = "502.004 269.677"
                        }
                    }
                }
                );
            }
            if (quantity >= 3) {
                container.Add(new CuiElement {
                    Name = "splat_3", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "0 0", AnchorMax = "0 0", OffsetMin = "-501.997 -269.997", OffsetMax = "-245.997 -13.997"
                        }
                    }
                }
                );
            }
            if (quantity >= 4) {
                container.Add(new CuiElement {
                    Name = "splat_4", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "1 0", AnchorMax = "1 0", OffsetMin = "246.004 -269.657", OffsetMax = "502.004 -13.657"
                        }
                    }
                }
                );
            }
            if (quantity >= 5) {
                container.Add(new CuiElement {
                    Name = "splat_5", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-261.997 -127.997", OffsetMax = "-5.997 128.003"
                        }
                    }
                }
                );
            }
            if (quantity >= 6) {
                container.Add(new CuiElement {
                    Name = "splat_6", Parent = "paintball_splats", Components = {
                        new CuiRawImageComponent {
                            Color = "1 1 1 0.8", Png = (string)ImageLibrary?.Call("GetImage", splats.GetRandom())
                        }
                        , new CuiRectTransformComponent {
                            AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "6.003 -127.997", OffsetMax = "262.003 128.003"
                        }
                    }
                }
                );
            }
            CuiHelper.DestroyUi(player, "paintball_splats");
            CuiHelper.AddUi(player, container);
        }
#endregion
#region Find Anchors
        bool FoundAnchors() {
            foreach (var anchor_pair in config.arenas) {
                if (!anchor_pair.Value.enabled) continue;
                ArenaInfo arenaData;
                if (pcdData.arenas.TryGetValue(anchor_pair.Key, out arenaData)) {
                    NetworkableId anchorId = new NetworkableId(arenaData.Anchor_id);
                    var anchor = BaseNetworkable.serverEntities.Find(anchorId);
                    if (anchor != null) {
                        Puts(string.Format(lang.GetMessage("AnchorPairFound", this), anchor_pair.Key));
                        if (!anchor_entities.ContainsKey(anchor_pair.Key)) anchor_entities.Add(anchor_pair.Key, anchor);
                        if (arenaData.FFA_Spawns.Count == 0) arenaData.FFA_Spawns = ConvertLocalsToWorld(anchor, anchor_pair.Value.FFA_Spawns);
                        if (arenaData.TDM_Spawns_1.Count == 0) arenaData.TDM_Spawns_1 = ConvertLocalsToWorld(anchor, anchor_pair.Value.TDM_Spawns_1);
                        if (arenaData.TDM_Spawns_2.Count == 0) arenaData.TDM_Spawns_2 = ConvertLocalsToWorld(anchor, anchor_pair.Value.TDM_Spawns_2);
                        continue;
                    }
                    else {
                        Puts(string.Format(lang.GetMessage("SearchingAnchors", this), anchor_pair.Key));
                        arenaData.FFA_Spawns.Clear();
                        arenaData.TDM_Spawns_1.Clear();
                        arenaData.TDM_Spawns_2.Clear();
                        arenaData.Anchor_id = 0;
                    }
                }
                List<BaseNetworkable> anchor_main = new List<BaseNetworkable>();
                List<BaseNetworkable> anchor_second = new List<BaseNetworkable>();
                foreach (var entity in BaseNetworkable.serverEntities) {
                    if (entity.PrefabName == anchor_pair.Value.Anchor_Entity_Main) anchor_main.Add(entity);
                    else if (entity.PrefabName == anchor_pair.Value.Anchor_Entity_Secondary) anchor_second.Add(entity);
                }
                if (anchor_main.Count == 0 || anchor_second.Count == 0) {
                    Puts(string.Format(lang.GetMessage("AnchorFailed", this), anchor_pair.Key));
                    continue;
                }
                var found_anchor = false;
                foreach (var main in anchor_main) {
                    foreach (var second in anchor_second) {
                        if (Vector3.Distance(second.transform.position, main.transform.position) < 1) {
                            // Saves the anchor information to a dictionary for use in running the games.anchor_entities.Add(anchor_pair.Key, main);
                            // Saves the info from the config to the data file with the ID of the anchor entity.ArenaInfo ai;
                            if (!pcdData.arenas.TryGetValue(anchor_pair.Key, out ai)) pcdData.arenas.Add(anchor_pair.Key, ai = new ArenaInfo());
                            ai.Anchor_id = main.net.ID.Value;
                            ai.FFA_Spawns = ConvertLocalsToWorld(main, anchor_pair.Value.FFA_Spawns);
                            ai.TDM_Spawns_1 = ConvertLocalsToWorld(main, anchor_pair.Value.TDM_Spawns_1);
                            ai.TDM_Spawns_2 = ConvertLocalsToWorld(main, anchor_pair.Value.TDM_Spawns_2);
                            ai.Anchor_Entity_Main = main.PrefabName;
                            ai.Anchor_Entity_Secondary = second.PrefabName;
                            found_anchor = true;
                            Puts(string.Format(lang.GetMessage("NewAnchorFound", this), anchor_pair.Key));
                            break;
                        }
                    }
                    if (found_anchor) break;
                }
            }
            if (anchor_entities.Count > 0) {
                if (pcdData.lobby_point == Vector3.zero && ancho
// ... [Code preview truncated due to length. Full source in attached file] ...

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