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

FREE ArenaSlasher : 2.0.2 2.0.2

Нет прав для скачивания
C#:
// Requires: Arena
using Network;
using Newtonsoft.Json;
using Oxide.Plugins.ArenaEx;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

///Скачано с дискорд сервера Rust Edit [PRO+]
///discord.gg/9vyTXsJyKR

namespace Oxide.Plugins
{
    [Info("Arena Slasher", "discord.gg/9vyTXsJyKR", "2.0.2"), Description("Slasher event mode for Arena")]
    class ArenaSlasher : RustPlugin, IEventPlugin
    {
        private string[] _torchItems = new string[] { "torch", "flashlight.held" };
        private string[] _validWeapons;

        private long _midnightTime;
        private long _middayTime;

        private const string WEAPON_FLASHLIGHT_ITEM = "weapon.mod.flashlight";

        private static EnvSync EnvSync;

        private static ArenaSlasher Instance;

        private static Hash<BasePlayer, SlasherEvent> EventPlayers = new Hash<BasePlayer, SlasherEvent>();

        #region Oxide Hooks
        private void Loaded()
        {
            Instance = this;

            _middayTime = new DateTime().AddHours(12).ToBinary();
            _midnightTime = new DateTime().ToBinary();

            Unsubscribe(nameof(CanNetworkTo));
        }

        private void OnServerInitialized()
        {
            Arena.RegisterEvent(EventName, this);

            GetMessage = Message;

            EnvSync = GameObject.FindObjectOfType<EnvSync>();

            FindValidWeapons();
        }

        protected override void LoadDefaultMessages() => lang.RegisterMessages(Messages, this);

        private object CanNetworkTo(EnvSync env, BasePlayer player)
        {
            SlasherEvent slasherEvent;

            if (env == null || player == null || !EventPlayers.TryGetValue(player, out slasherEvent) || slasherEvent == null)
                return null;

            if (Net.sv.write.Start())
            {
                Connection connection = player.net.connection;
                connection.validate.entityUpdates = connection.validate.entityUpdates + 1;
                BaseNetworkable.SaveInfo saveInfo = new BaseNetworkable.SaveInfo
                {
                    forConnection = player.net.connection,
                    forDisk = false
                };

                Net.sv.write.PacketID(Network.Message.Type.Entities);
                Net.sv.write.UInt32(player.net.connection.validate.entityUpdates);

                using (saveInfo.msg = Facepunch.Pool.Get<ProtoBuf.Entity>())
                {
                    env.Save(saveInfo);

                    saveInfo.msg.environment.dateTime = slasherEvent.IsPlayingRound ? _midnightTime : _middayTime;

                    saveInfo.msg.ToProto(Net.sv.write);
                    Net.sv.write.Send(new SendInfo(player.net.connection));
                }
            }

            return false;
        }

        private void Unload()
        {
            EventPlayers.Clear();

            if (!Arena.IsUnloading)
                Arena.UnregisterEvent(EventName);

            Configuration = null;
            Instance = null;
        }
        #endregion

        #region Functions
        private void FindValidWeapons()
        {
            List<string> list = Facepunch.Pool.GetList<string>();

            foreach (ItemDefinition itemDefinition in ItemManager.itemList)
            {
                if (itemDefinition.category == ItemCategory.Weapon || itemDefinition.category == ItemCategory.Tool)
                {
                    if (!itemDefinition.isHoldable)
                        continue;

                    AttackEntity attackEntity = itemDefinition.GetComponent<ItemModEntity>()?.entityPrefab?.Get()?.GetComponent<AttackEntity>();
                    if (attackEntity != null && (attackEntity is BaseMelee || attackEntity is BaseProjectile))
                        list.Add(itemDefinition.shortname);
                }
            }

            list.Sort();

            _validWeapons = list.ToArray();

            Facepunch.Pool.FreeList(ref list);
        }

        private string[] GetSlasherWeapons() => _validWeapons;

        private string[] GetSlasherTorches() => _torchItems;
        #endregion

        #region Event Checks
        public string EventName => "Slasher";

        public string EventIcon => Configuration.EventIcon;

        public bool InitializeEvent(Arena.EventConfig config) => Arena.InitializeEvent<SlasherEvent>(this, config);

        public bool CanUseClassSelector => false;

        public bool RequireTimeLimit => false;

        public bool RequireScoreLimit => false;

        public bool UseScoreLimit => false;

        public bool UseTimeLimit => false;

        public bool IsTeamEvent => false;

        public bool CanSelectTeam => false;

        public bool CanUseRustTeams => false;

        public bool IsRoundBased => true;

        public bool ProcessWinnersBetweenRounds => false;
        
        public bool CanUseBots => false;

        public string TeamAName => "Team A";

        public string TeamBName => "Team B";

        public void FormatScoreEntry(Arena.ScoreEntry scoreEntry, ulong langUserId, out string score1, out string score2)
        {
            score1 = string.Format(Message("Score.Kills", langUserId), scoreEntry.value1);
            score2 = string.Format(Message("Score.Deaths", langUserId), scoreEntry.value2);
        }

        public List<Arena.EventParameter> AdditionalParameters { get; } = new List<Arena.EventParameter>
        {
            new Arena.EventParameter
            {
                DataType = "string",
                Field = "torchItem",
                Input = Arena.EventParameter.InputType.Selector,
                SelectMultiple = false,
                SelectorHook = "GetSlasherTorches",
                IsRequired = true,
                DefaultValue = "flashlight.held",
                Name = "Torch Item"
            },
            new Arena.EventParameter
            {
                DataType = "string",
                Field = "slasherWeapon",
                Input = Arena.EventParameter.InputType.Selector,
                SelectMultiple = false,
                SelectorHook = "GetSlasherWeapons",
                IsRequired = false,
                Name = "Slasher Weapon",
                DefaultValue = "shotgun.pump"
            },
            new Arena.EventParameter
            {
                DataType = "string",
                Field = "slasherClothing",
                Input = Arena.EventParameter.InputType.Selector,
                SelectMultiple = false,
                SelectorHook = "GetAllKits",
                IsRequired = false,
                Name = "Slasher Clothing"
            },
            new Arena.EventParameter
            {
                DataType = "int",
                Field = "slasherTime",
                Input = Arena.EventParameter.InputType.InputField,
                IsRequired = true,
                DefaultValue = 180,
                Name = "Slasher Timer (seconds)"
            },
            new Arena.EventParameter
            {
                DataType = "int",
                Field = "playerTime",
                Input = Arena.EventParameter.InputType.InputField,
                IsRequired = true,
                DefaultValue = 120,
                Name = "Player Timer (seconds)"
            },
        };

        public string ParameterIsValid(string fieldName, object value)
        {
            switch (fieldName)
            {
                case "slasherWeapon":
                    {
                        if (ItemManager.FindItemDefinition((string)value) == null)
                            return "Unable to find a weapon with the specified shortname";

                        return null;
                    }
                case "slasherClothing":
                    {
                        object success = Arena.Instance.ValidateKit((string)value);
                        if (success != null)
                            return (string)success;

                        return null;
                    }
                default:
                    return null;
            }
        }
        #endregion

        #region Event Classes
        public class SlasherEvent : Arena.BaseEventGame
        {
            private ItemDefinition torchItem;
            private ItemDefinition slasherWeapon;
            private string slasherKit;

            private int slasherTime;
            private int playerTime;

            private Arena.BaseEventPlayer slasherPlayer;

            private List<Arena.BaseEventPlayer> remainingSlashers;

            internal bool IsPlayingRound { get; private set; }

            internal override void InitializeEvent(IEventPlugin plugin, Arena.EventConfig config)
            {
                torchItem = ItemManager.FindItemDefinition(config.GetParameter<string>("torchItem"));
                slasherWeapon = ItemManager.FindItemDefinition(config.GetParameter<string>("slasherWeapon"));

                slasherKit = config.GetParameter<string>("slasherClothing");

                slasherTime = config.GetParameter<int>("slasherTime");
                playerTime = config.GetParameter<int>("playerTime");

                remainingSlashers = Facepunch.Pool.GetList<Arena.BaseEventPlayer>();

                base.InitializeEvent(plugin, config);
            }

            protected override void OnDestroy()
            {
                Facepunch.Pool.FreeList(ref remainingSlashers);

                EventPlayers.Clear();

                base.OnDestroy();
            }

            protected override void StartEvent()
            {
                Config.RoundsToPlay = eventPlayers.Count;

                remainingSlashers.Clear();

                remainingSlashers.AddRange(eventPlayers);

                eventPlayers.ForEach((Arena.BaseEventPlayer slasherPlayer) => EventPlayers.Add(slasherPlayer.Player, this));

                base.StartEvent();

                CloseEvent();
            }

            protected override bool CanEnterBetweenRounds() => false;

            protected override Arena.BaseEventPlayer AddPlayerComponent(BasePlayer player) => player.gameObject.AddComponent<SlasherPlayer>();

            protected override void CreateEventPlayer(BasePlayer player, Arena.Team team = Arena.Team.None)
            {
                base.CreateEventPlayer(player, team);

                Arena.LockClothingSlots(player);
            }

            internal override void LeaveEvent(BasePlayer player)
            {
                bool isSlasher = slasherPlayer != null && player.GetComponent<SlasherPlayer>() == slasherPlayer;

                EventPlayers.Remove(player);
                base.LeaveEvent(player);

                if (isSlasher && Status != Arena.EventStatus.Finished)
                    EndRound();
            }

            #region Event Items
            protected override void OnKitGiven(Arena.BaseEventPlayer eventPlayer)
            {
                List<Item> list = Facepunch.Pool.GetList<Item>();
                eventPlayer.Player.inventory.AllItemsNoAlloc(ref list);

                bool isSlasher = eventPlayer == slasherPlayer;

                for (int i = 0; i < list.Count; i++)
                {
                    Item item = list[i];

                    if (!isSlasher && item.info.category == ItemCategory.Attire)
                        continue;

                    item.RemoveFromContainer();
                    item.Remove();
                }

                if (isSlasher)
                {
                    Arena.GiveKit(eventPlayer.Player, slasherKit);
                    GiveSlasherWeapon(eventPlayer);
                }
                else GiveTorch(eventPlayer);

                eventPlayer.Player.inventory.SendUpdatedInventory(PlayerInventory.Type.Belt, eventPlayer.Player.inventory.containerBelt);
            }

            private void GiveSlasherWeapon(Arena.BaseEventPlayer eventPlayer)
            {
                Item item = ItemManager.Create(slasherWeapon);

                if (item.contents != null && item.contents.availableSlots.Count > 0)
                {
                    Item attachment = ItemManager.CreateByName(WEAPON_FLASHLIGHT_ITEM);
                    if (!attachment.MoveToContainer(item.contents))
                        attachment.Remove();
                    else item.GetHeldEntity()?.SendMessage("SetLightsOn", true, SendMessageOptions.DontRequireReceiver);
                }

                item.MoveToContainer(eventPlayer.Player.inventory.containerBelt);

                BaseProjectile baseProjectile = item.GetHeldEntity() as BaseProjectile;
                if (baseProjectile != null)
                {
                    Item ammo = ItemManager.Create(baseProjectile.primaryMagazine.ammoType, baseProjectile.primaryMagazine.capacity * 5);
                    ammo.MoveToContainer(eventPlayer.Player.inventory.containerMain);
                }
            }

            private void GiveTorch(Arena.BaseEventPlayer eventPlayer)
            {
                Item item = ItemManager.Create(torchItem);
                item.MoveToContainer(eventPlayer.Player.inventory.containerBelt);
                item.GetHeldEntity()?.SendMessage("SetLightsOn", true, SendMessageOptions.DontRequireReceiver);
            }

            protected override bool CanDropAmmo() => false;

            protected override bool CanDropBackpack() => false;

            protected override bool CanDropCorpse() => false;

            protected override bool CanDropWeapon() => false;
            #endregion

            internal override void OnEventPlayerDeath(Arena.BaseEventPlayer victim, Arena.BaseEventPlayer attacker = null, HitInfo info = null)
            {
                if (victim == null)
                    return;

                attacker?.OnKilledPlayer(info);

                if (victim == slasherPlayer || GetAlivePlayerCount() <= 1)
                {
                    victim.AddPlayerDeath();

                    if (victim == slasherPlayer)
                        BroadcastToPlayers(GetMessage, "Notification.HuntedWin");
                    else BroadcastToPlayers(GetMessage, "Notification.SlasherWin");

                    InvokeHandler.Invoke(this, EndRound, 0.1f);
                    return;
                }

                victim.OnPlayerDeath(attacker, 0f);

                UpdateScoreboard();

                base.OnEventPlayerDeath(victim, attacker);
            }

            internal override void RebuildSpectateTargets()
            {
                spectateTargets.Clear();

                for (int i = 0; i < eventPlayers.Count; i++)
                {
                    Arena.BaseEventPlayer eventPlayer = eventPlayers[i];

                    if (eventPlayer == null || eventPlayer == slasherPlayer || eventPlayer.IsDead || eventPlayer.Player.IsSpectating())
                        continue;

                    spectateTargets.Add(eventPlayer);
                }
            }

            #region Rounds
            protected override void StartNextRound()
            {
                base.StartNextRound();

                IsPlayingRound = true;

                EnvSync.SendNetworkUpdateImmediate();

                _roundNumber += 1;

                slasherPlayer = GetRandomSlasher();

                StartCoroutine(ResetPlayers());

                Timer.StartTimer(slasherTime, GetMessage("Timer.Slasher", 0UL), OnSlasherTimerExpired);

                BroadcastToPlayers(GetMessage, "Notification.RoundStarted", slasherPlayer.Player.displayName);

                UpdateScoreboard();
            }

            protected override void EndRound()
            {
                slasherPlayer = null;

                Timer.StopTimer();

                IsPlayingRound = false;

                GodmodeEnabled = true;

                EnvSync.SendNetworkUpdateImmediate();

                StartCoroutine(ResetPlayers());

                base.EndRound();                
            }

            private void OnSlasherTimerExpired()
            {
                Timer.StartTimer(playerTime, GetMessage("Timer.Hunted", 0UL), EndRound);

                StartCoroutine(GiveSlasherWeapons());

                BroadcastToPlayers(GetMessage, "Notification.HuntersTurn");
            }

            private Arena.BaseEventPlayer GetRandomSlasher()
            {
                Arena.BaseEventPlayer nextSlasher = remainingSlashers.GetRandom();

                remainingSlashers.Remove(nextSlasher);

                if (remainingSlashers.Count == 0)
                    remainingSlashers.AddRange(eventPlayers);

                if (nextSlasher == null)
                    return GetRandomSlasher();
                return nextSlasher;
            }

            private IEnumerator ResetPlayers()
            {
                List<Arena.BaseEventPlayer> currentPlayers = Facepunch.Pool.GetList<Arena.BaseEventPlayer>();
                currentPlayers.AddRange(eventPlayers);

                for (int i = 0; i < currentPlayers.Count; i++)
                {
                    Arena.BaseEventPlayer eventPlayer = currentPlayers[i];
                    if (eventPlayer != null)
                    {
                        if (eventPlayer.IsDead)
                        {
                            Arena.ResetPlayer(eventPlayer.Player);
                            OnPlayerRespawn(eventPlayer);
                        }
                        else
                        {
                            Arena.StripInventory(eventPlayer.Player);
                            Arena.ResetMetabolism(eventPlayer.Player);

                            yield return CoroutineEx.waitForEndOfFrame;
                            yield return CoroutineEx.waitForEndOfFrame;

                            Arena.GiveKit(eventPlayer.Player, eventPlayer.Kit);

                            yield return CoroutineEx.waitForEndOfFrame;

                            OnKitGiven(eventPlayer);
                        }
                    }

                    yield return CoroutineEx.waitForEndOfFrame;
                    yield return CoroutineEx.waitForEndOfFrame;
                }

                Facepunch.Pool.FreeList(ref currentPlayers);
            }

            private IEnumerator GiveSlasherWeapons()
            {
                for (int i = eventPlayers.Count - 1; i >= 0; i--)
                {
                    Arena.BaseEventPlayer eventPlayer = eventPlayers[i];

                    if (eventPlayer.IsDead || eventPlayer == slasherPlayer)
                        continue;

                    GiveSlasherWeapon(eventPlayer);

                    yield return CoroutineEx.waitForEndOfFrame;
                    yield return CoroutineEx.waitForEndOfFrame;
                }
            }
            #endregion

            protected override void GetWinningPlayers(ref List<Arena.BaseEventPlayer> winners)
            {
                Arena.BaseEventPlayer winner = null;

                if (eventPlayers.Count > 0)
                {
                    int kills = 0;
                    int deaths = 0;

                    for (int i = 0; i < eventPlayers.Count; i++)
                    {
                        Arena.BaseEventPlayer eventPlayer = eventPlayers[i];
                        if (eventPlayer == null)
                            continue;

                        if (eventPlayer.Kills > kills)
                        {
                            winner = eventPlayer;
                            kills = eventPlayer.Kills;
                            deaths = eventPlayer.Deaths;
                        }
                        else if (eventPlayer.Kills == kills)
                        {
                            if (eventPlayer.Deaths < deaths)
                            {
                                winner = eventPlayer;
                                kills = eventPlayer.Kills;
                                deaths = eventPlayer.Deaths;
                            }
                        }
                    }
                }

                if (winner != null)
                    winners.Add(winner);
            }

            #region Scoreboards
            protected override void BuildScoreboard()
            {
                scoreContainer = ArenaUI.CreateScoreboardBase(this);

                int index = -1;
                ArenaUI.CreatePanelEntry(scoreContainer, string.Format(GetMessage("Score.RoundNumber", 0UL), RoundNumber, Config.RoundsToPlay), index += 1);

                ArenaUI.CreateScoreEntry(scoreContainer, string.Empty, "K", "D", index += 1);

                for (int i = 0; i < Mathf.Min(scoreData.Count, 15); i++)
                {
                    Arena.ScoreEntry score = scoreData[i];
                    ArenaUI.CreateScoreEntry(scoreContainer, score.displayName, ((int)score.value1).ToString(), ((int)score.value2).ToString(), i + index + 1);
                }
            }

            protected override float GetFirstScoreValue(Arena.BaseEventPlayer eventPlayer) => eventPlayer.Kills;

            protected override float GetSecondScoreValue(Arena.BaseEventPlayer eventPlayer) => eventPlayer.Deaths;

            protected override void SortScores(ref List<Arena.ScoreEntry> list)
            {
                list.Sort(delegate (Arena.ScoreEntry a, Arena.ScoreEntry b)
                {
                    int primaryScore = a.value1.CompareTo(b.value1) * -1;

                    if (primaryScore == 0)
                        return a.value2.CompareTo(b.value2);

                    return primaryScore;
                });
            }
            #endregion
        }

        private class SlasherPlayer : Arena.BaseEventPlayer
        {
            internal override void OnPlayerDeath(Arena.BaseEventPlayer attacker = null, float respawnTime = 5, HitInfo hitInfo = null)
            {
                AddPlayerDeath(attacker);

                DestroyUI();

                BeginSpectating();
            }
        }
        #endregion

        #region Config        
        private static ConfigData Configuration;

        private class ConfigData
        {
            [JsonProperty(PropertyName = "Amount of time between rounds (seconds)")]
            public int TimeBetweenRounds { get; set; }

            public string EventIcon { get; set; }

            public Oxide.Core.VersionNumber Version { get; set; }
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            Configuration = Config.ReadObject<ConfigData>();

            if (Configuration.Version < Version)
                UpdateConfigValues();

            Config.WriteObject(Configuration, true);
        }

        protected override void LoadDefaultConfig() => Configuration = GetBaseConfig();

        private ConfigData GetBaseConfig()
        {
            return new ConfigData
            {
                EventIcon = "https://www.rustedit.io/images/arena/arena_slasher.png",
                TimeBetweenRounds = 10,
                Version = Version
            };
        }

        protected override void SaveConfig() => Config.WriteObject(Configuration, true);

        private void UpdateConfigValues()
        {
            PrintWarning("Config update detected! Updating config values...");

            Configuration.Version = Version;
            PrintWarning("Config update completed!");
        }

        #endregion

        #region Localization
        public string Message(string key, ulong playerId = 0U) => lang.GetMessage(key, this, playerId != 0U ? playerId.ToString() : null);

        private static Func<string, ulong, string> GetMessage;

        private readonly Dictionary<string, string> Messages = new Dictionary<string, string>
        {
            ["Score.Kills"] = "Kills: {0}",
            ["Score.Deaths"] = "Deaths: {0}",
            ["Score.Name"] = "Kills",
            ["Score.Limit"] = "Score Limit : {0}",
            ["Score.RoundNumber"] = "Round {0} / {1}",
            ["Timer.Slasher"] = "Slasher Time",
            ["Timer.Hunted"] = "Hunted Time",
            ["Notification.RoundStartsIn"] = "The next round starts in <color=#007acc>{0}</color> seconds",
            ["Notification.RoundStarted"] = "<color=#007acc>{0}</color> is the slasher.Hide from them!",
            ["Notification.HuntersTurn"] = "The hunted have become the hunters!",
            ["Notification.HuntedWin"] = "The hunted have won this round!",
            ["Notification.SlasherWin"] = "The slasher has won this round!"
        };
        #endregion
    }
}

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

Другие ресурсы пользователя 15FPS

Сверху