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

FREE Spawns : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Reference: Oxide.Core.RustyCore
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConVar;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using UnityEngine;
using LogType = Oxide.Core.Logging.LogType;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using RustyCore;
using RustyCore.Utils;

namespace Oxide.Plugins
{
    [Info("Spawns", "bazuka5801","1.0.0")]
    public class Spawns : RustPlugin
    {

        #region VARIABLES
        static Spawns m_Instance;

        private RCore core = Interface.Oxide.GetLibrary<RCore>();
        List<Vector3> spawns = new List<Vector3>();
        List<GameObject> blocks = new List<GameObject>();
        float worldsize;
        #endregion

        #region CONFIGURATION

        float spawnRadius;
        int spawnsCount;
        int zoneRadius;
        int zoneOffset;
        List<string> whitelistWeapons = new List<string>(){};
        protected override void LoadDefaultConfig()
        {
            Config.GetVariable("Кол-во спаунов",out spawnsCount, 50);
            Config.GetVariable("Минимальная дистанция между спаунами", out spawnRadius, 30f);
            Config.GetVariable("Радиус зоны спауна", out zoneRadius, 700);
            Config.GetVariable("Смещение зоны от левого/правого края", out zoneOffset, 500);
            Config["Разрешённое оружие на спауне"] = whitelistWeapons = ((List<object>)Config["Разрешённое оружие на спауне"])?.Select(p=>p.ToString())?.ToList() ?? new List<string>();
            SaveConfig();
        }

        T GetConfig<T>(string name, T defaultValue) => Config[name] == null ? defaultValue : (T)Convert.ChangeType(Config[name], typeof(T));
        #endregion

        #region DATA

        private DynamicConfigFile spawnsFile = Interface.Oxide.DataFileSystem.GetFile("Spawns");

        #endregion

        #region OXIDE HOOKS

        void Init()
        {
            m_Instance = this;
            LoadDefaultConfig();
        }

        void OnServerInitialized()
        {
            lang.RegisterMessages( Messages, this );
            Messages = lang.GetMessages( "en", this );
            worldsize = TerrainMeta.Size.x;
            GenerateBlocks();
            RandomSpawns();
            CreateSpawnTriggers();
        }

        void Unloaded()
        {
            foreach (var block in blocks.Where(b => b != null))
                UnityEngine.Object.Destroy(block);
            DestroySpawnTriggers();
        }

        void OnPlayerInit(BasePlayer player)
        {
            if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot))
            {
                timer.Once(0.1f, () => OnPlayerInit(player));
                return;
            }
            if (InSpawnZone(player))
            {
                DrawUI(player);
            }
        }

        void OnEntityBuilt(Planner planner, GameObject gameobject)
        {
            if (planner == null || gameobject == null) return;
            var player = planner.GetOwnerPlayer();
            BaseEntity entity = gameobject.ToBaseEntity();
            if (entity == null) return;
            if (SpawnBlockEntity.IsBlock(entity))
            {
                player.ChatMessage("Строительство запрещено!!!\nВы находитесь в зоне возрождения, двигайтесь к центру или к полюсам карты!");
                entity.Kill();
            }
        }

        object OnPlayerRespawn(BasePlayer player)
        {
            return new BasePlayer.SpawnPoint() {pos = spawns.GetRandom(), rot = Quaternion.identity};
        }

        private List<string> Ricochets = new List<string>()
        {
            "assets/bundled/prefabs/fx/ricochet/ricochet1.prefab",
            "assets/bundled/prefabs/fx/ricochet/ricochet2.prefab",
            "assets/bundled/prefabs/fx/ricochet/ricochet3.prefab",
            "assets/bundled/prefabs/fx/ricochet/ricochet4.prefab"
        };
        private void OnEntityTakeDamage( BaseCombatEntity entity, HitInfo hitinfo )
        {
            if (entity == null || hitinfo == null || entity.IsDestroyed) return;
            var victim = entity as BasePlayer;
            if (victim == null) return;
            var info = hitinfo?.Weapon?.GetItem()?.info;
            var attacker = hitinfo.InitiatorPlayer;
            if (info == null || attacker == null) return;

            if ((InSpawnZone(entity)||InSpawnZone(attacker)) &&
                info.category == ItemCategory.Weapon && !whitelistWeapons.Contains(info.shortname)
                )
            {
                if (attacker?.IsConnected == true)
                {
                    Effect.server.Run(Ricochets.GetRandom(), hitinfo.HitPositionWorld);
                    SendReply(attacker, Messages[ "WEAPONBLOCKED" ]);
                }
                CancelDamage(hitinfo);
            }
        }
        #endregion

        #region FUNCTIONS
        
        private static void CancelDamage( HitInfo hitinfo )
        {
            hitinfo.damageTypes = new DamageTypeList();
            hitinfo.DoHitEffects = false;
            hitinfo.HitMaterial = 0;
        }

        bool IsValidSpawn(Vector3 point)
        {
            return spawns.All(spawn => !(Vector3.Distance(point, spawn) < spawnRadius)) &&
                   SpawnBlockEntity.CanPlaceSpawn(point);
        }

        void OnPlayerTeleported(BasePlayer player)
        {
            if (InSpawnZone(player))
                DrawUI(player);
            else DestroyUI(player);
        }
        void OnPlayerRespawned( BasePlayer player )
        {
            if (InSpawnZone( player ))
                DrawUI( player );
            else DestroyUI( player );
        }


        void CreateBlock(Vector3 position)
        {
            blocks.Add(SpawnBlockEntity.Create(position));
        }

        void DrawUI(BasePlayer player)
        {
            core.DrawUI(player, "Spawns", "inzone");
        }

        void DestroyUI(BasePlayer player)
        {
            core.DestroyUI( player, "Spawns", "inzone" );
        }

        #endregion

        #region API

        Dictionary<Vector3, int> GetSpawnZones()=> blocks.ToDictionary(p => p.transform.position, p => zoneRadius);

        bool InSpawnZone(BaseEntity entity) => SpawnBlockEntity.IsBlock(entity);

        #endregion

        #region COMMANDS

        void RandomSpawns()
        {
            spawns.Clear();
            int failed = 0;
            while (failed < 1000 && spawns.Count < spawnsCount)
            {
                BasePlayer.SpawnPoint spawnPoint = SpawnHandler.GetSpawnPoint();

                if (spawnPoint == null)
                {
                    failed++;
                    continue;
                }
                if (!IsValidSpawn(spawnPoint.pos))
                {
                    failed++;
                    continue;
                }
                spawns.Add(spawnPoint.pos);
            }
            if (failed >= 1000)
                Puts("FAILED > 1000");
            Puts("CREATED "+spawns.Count.ToString());
            spawnsFile.WriteObject(JsonConvert.SerializeObject(spawns, converter));
        }

        void GenerateBlocks()
        {
            CreateBlock(new Vector3(-worldsize / 2+zoneOffset, 0, 0));
            CreateBlock(new Vector3(worldsize / 2-zoneOffset, 0, 0));
        }

        #endregion

        #region CLASSES
        
        private class SpawnBlockEntity : MonoBehaviour
        {
            private static List<SpawnBlockEntity> entities = new List<SpawnBlockEntity>();
            public static bool IsBlock(BaseEntity player) => entities.Any(e=>e.IsBlockPlayer(player));

            public static bool CanPlaceSpawn(Vector3 pos)=> entities.Any(e => Vector3.Distance(e.transform.position, pos) < m_Instance.zoneRadius);


            public bool IsBlockPlayer(BaseEntity player)
                => Vector3.Distance(player.transform.position, transform.position) <= m_Instance.zoneRadius;

            void Awake()
            {
                gameObject.name = "SPAWN";

                gameObject.layer = 3;
                entities.Add(this);
            }

            void OnDestroy()
            {
                entities.Remove(this);
            }

            public static GameObject Create(Vector3 pos)
            {
                var obj = new GameObject();

                SpawnBlockEntity block = obj.AddComponent<SpawnBlockEntity>();

                block.transform.position = pos;
                return block.gameObject;
            }
            
        }
        static void DrawBox(BasePlayer player, Vector3 center, Quaternion rotation, Vector3 size)
        {
            size /= 2;
            var point1 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z + size.z), center, rotation);
            var point2 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z + size.z), center, rotation);
            var point3 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z - size.z), center, rotation);
            var point4 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z - size.z), center, rotation);
            var point5 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z + size.z), center, rotation);
            var point6 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z + size.z), center, rotation);
            var point7 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z - size.z), center, rotation);
            var point8 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z - size.z), center, rotation);

            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point2);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point3);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point5);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point2);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point3);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point8);

            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point5, point6);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point5, point7);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point6, point2);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point8, point6);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point8, point7);
            player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point7, point3);
        }

        static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation)
        {
            return rotation * (point - pivot) + pivot;
        }

        #endregion


        #region JSON CONVERTERS
        UnityVector3Converter converter = new UnityVector3Converter();

            public class UnityVector3Converter : JsonConverter
            {
                public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
                {
                    var vector = (Vector3) value;
                    writer.WriteValue($"{vector.x} {vector.y} {vector.z}");
                }

                public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                    JsonSerializer serializer)
                {
                    if (reader.TokenType == JsonToken.String)
                    {
                        var values = reader.Value.ToString().Trim().Split(' ');
                        return new Vector3(Convert.ToSingle(values[0]), Convert.ToSingle(values[1]),
                            Convert.ToSingle(values[2]));
                    }
                    var o = JObject.Load(reader);
                    return new Vector3(Convert.ToSingle(o["x"]), Convert.ToSingle(o["y"]), Convert.ToSingle(o["z"]));
                }

                public override bool CanConvert(Type objectType)
                {
                    return objectType == typeof(Vector3);
                }
            }

        #endregion

        #region Trigger

        private SpawnTrigger leftSpawnTrigger, rightSpawnTrigger;

        void CreateSpawnTriggers()
        {
            var leftGo = new GameObject();
            leftGo.transform.position = new Vector3(-worldsize / 2 + zoneOffset, 0, 0);
            leftSpawnTrigger = leftGo.AddComponent<SpawnTrigger>();
            var rightGo = new GameObject();
            rightGo.transform.position = new Vector3(worldsize / 2 - zoneOffset, 0, 0);
            rightSpawnTrigger = rightGo.AddComponent<SpawnTrigger>();
        }

        void DestroySpawnTriggers()
        {
            UnityEngine.Object.DestroyImmediate(leftSpawnTrigger.gameObject);
            UnityEngine.Object.DestroyImmediate( rightSpawnTrigger.gameObject);
        }

        public class SpawnTrigger : MonoBehaviour
        {
            private void Awake()
            {
                gameObject.layer = (int) Rust.Layer.Reserved1; //hack to get all trigger layers...otherwise child zones
                gameObject.name = "Spawn Zone";

                var rigidbody = gameObject.AddComponent<Rigidbody>();
                rigidbody.useGravity = false;
                rigidbody.isKinematic = true;
                rigidbody.detectCollisions = true;
                rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;

                var sphere = gameObject.AddComponent<SphereCollider>();
                sphere.radius = m_Instance.zoneRadius;
                sphere.isTrigger = true;
            }

            private void OnTriggerEnter( Collider col )
            {
                var player = col.gameObject.ToBaseEntity() as BasePlayer;
                if (player == null || !player.IsConnected || player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) return;
                m_Instance.DrawUI(player);
            }
            private void OnTriggerExit( Collider col )
            {
                var player = col.gameObject.ToBaseEntity() as BasePlayer;
                if (player == null || !player.IsConnected || player.HasPlayerFlag( BasePlayer.PlayerFlags.ReceivingSnapshot )) return;
                m_Instance.DestroyUI( player );
            }
        }

        #endregion


        #region Localization

        Dictionary<string, string> Messages = new Dictionary<string, string>()
        {
            { "WEAPONBLOCKED", "<color=red>Урон не проходит</color> - вы в <color=orange>SPAWN</color> зоне" },
        };

        #endregion
    }
}

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