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

FREE RandomSpawns : 0.2.0 0.2.0

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using System.Linq;

namespace Oxide.Plugins
{
    [Info("RandomSpawns", "k1lly0u", "0.2.0", ResourceId = 0)]
    class RandomSpawns : RustPlugin
    {
        #region Fields
        private bool isDisabled;
        private int spawnCount;
        private Hash<BiomeType, List<Vector3>> spawnPoints = new Hash<BiomeType, List<Vector3>>();

        private int minPlayerReq = 1;
        System.Random random = new System.Random();
        #endregion

        #region Oxide Hooks
        [ChatCommand("showspawns")]
        private void cmdShowSpawns(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin) return;           
            SendReply(player, "Total spawn count: " + spawnCount);
            foreach (var list in spawnPoints.Values)
            {
                foreach (var position in list)
                    player.SendConsoleCommand("ddraw.box", 30f, Color.magenta, position, 1f);
            }
        }

        private void OnServerInitialized()
        {           
            isDisabled = true;
            LoadVariables();
            CalculateMinimumPlayers();
            GenerateSpawnpoints();
        }
        private object OnPlayerRespawn(BasePlayer player)
        {
            if (isDisabled || BasePlayer.activePlayerList.Count < minPlayerReq)
                return null;
                        
            var targetpos = GetSpawnPoint(false);
            if (targetpos == null)
                return null;

            BasePlayer.SpawnPoint spawnPoint1 = new BasePlayer.SpawnPoint();
            spawnPoint1.pos = (Vector3)targetpos;
            spawnPoint1.rot = new Quaternion(0f, 0f, 0f, 1f);
            return spawnPoint1;
        }
        private BiomeType GetMajorityBiome(Vector3 position)
        {
            Dictionary<BiomeType, float> biomes = new Dictionary<BiomeType, float>
            {
                {BiomeType.Arctic, TerrainMeta.BiomeMap.GetBiome(position, TerrainBiome.ARCTIC) },
                {BiomeType.Arid, TerrainMeta.BiomeMap.GetBiome(position, TerrainBiome.ARID) },
                {BiomeType.Temperate, TerrainMeta.BiomeMap.GetBiome(position, TerrainBiome.TEMPERATE) },
                {BiomeType.Tundra, TerrainMeta.BiomeMap.GetBiome(position, TerrainBiome.TUNDRA) }
            };
            return biomes.OrderByDescending(x => x.Value).ToArray()[0].Key;           
        }
        #endregion

        #region Functions 
        private void CalculateMinimumPlayers()
        {
            minPlayerReq = 1000;

            foreach(var biome in configData.SpawnAreas)
            {
                if (biome.Value.Players < minPlayerReq)
                    minPlayerReq = biome.Value.Players;
            }
        }

        private object GetSpawnPoint(bool ignorePlayerRestriction = true)
        {
            BiomeType biomeType = spawnPoints.ElementAt(UnityEngine.Random.Range(0, spawnPoints.Count - 1)).Key;

            if (!ignorePlayerRestriction)            
            {
                List<BiomeType> availableTypes = new List<BiomeType>();
                int onlinePlayers = BasePlayer.activePlayerList.Count;

                foreach(var biome in configData.SpawnAreas)
                {
                    if (biome.Value.Enabled && onlinePlayers >= biome.Value.Players)                    
                        availableTypes.Add(biome.Key);                    
                }

                biomeType = availableTypes.GetRandom();                
                availableTypes.Clear();
            }

            Vector3 targetPos = spawnPoints[biomeType].GetRandom();
            if (targetPos == Vector3.zero)
                return null;

            List<BaseEntity> entities = Facepunch.Pool.GetList<BaseEntity>();
            Vis.Entities(targetPos, 15f, entities, LayerMask.GetMask("Construction", "Deployable"));
            int count = entities.Count;
            Facepunch.Pool.FreeList(ref entities);
            if (count > 0)
            {
                spawnPoints[biomeType].Remove(targetPos);
                -- spawnCount;
                if (spawnCount < 10)
                {
                    PrintWarning("All current spawnpoints have been overrun by buildings and such.Disabling random spawnpoints");
                    isDisabled = true;
                    return null;
                }
                return GetSpawnPoint(false);
            }
            return targetPos;
        }

        private void GenerateSpawnpoints()
        {
            PrintWarning("Generating spawnpoints.This may take a moment");
            for (int i = 0; i < 1500; i++)
            {
                float max = TerrainMeta.Size.x / 2;
                var success = FindNewPosition(new Vector3(0,0,0), max);
                if (success is Vector3)
                {
                    Vector3 spawnPoint = (Vector3)success;
                    float height = TerrainMeta.HeightMap.GetHeight(spawnPoint);
                    if (spawnPoint.y >= height && !(spawnPoint.y - height > 1))
                    {
                        BiomeType biome = GetMajorityBiome(spawnPoint);
                        if (configData.SpawnAreas[biome].Enabled)
                        {
                            if (!spawnPoints.ContainsKey(biome))
                                spawnPoints.Add(biome, new List<Vector3>());
                            spawnPoints[biome].Add(spawnPoint);
                        }
                    }
                }
            }            
            foreach (var biome in spawnPoints)
                spawnCount += biome.Value.Count;

            PrintWarning($"{spawnCount} spawn points generated!");
            isDisabled = false;
        }

        private Vector3 CalculatePoint(Vector3 position, float max)
        {
            var angle = Math.PI * 2.0f * random.NextDouble();
            var radius = Math.Sqrt(random.NextDouble()) * max;
            var x = position.x + radius * Math.Cos(angle);
            var y = position.y + radius * Math.Sin(angle);
            return new Vector3((float)x, 300, (float)y);
        }

        private object FindNewPosition(Vector3 position, float max, bool failed = false)
        {
            var targetPos = UnityEngine.Random.insideUnitCircle * max;
            var sourcePos = new Vector3(position.x + targetPos.x, 300, position.z + targetPos.y);
            var hitInfo = RayPosition(sourcePos);
            var success = ProcessRay(hitInfo);
            if (success == null)
            {
                if (failed) return null;
                else return FindNewPosition(position, max, true);
            }
            else if (success is Vector3)
            {
                if (failed) return null;
                else return FindNewPosition(new Vector3(sourcePos.x, ((Vector3)success).y, sourcePos.y), max, true);
            }
            else
            {
                sourcePos.y = Mathf.Max((float)success, TerrainMeta.HeightMap.GetHeight(sourcePos));
                return sourcePos;
            }
        }

        private object ProcessRay(RaycastHit hitInfo)
        {
            if (hitInfo.collider != null)
            {
                if (hitInfo.collider?.gameObject.layer == LayerMask.NameToLayer("Water"))
                    return null;
                if (hitInfo.collider?.gameObject.layer == LayerMask.NameToLayer("Prevent Building"))
                    return null;
                if (hitInfo.GetEntity() != null)
                {
                    return hitInfo.point.y;
                }
                if (hitInfo.collider?.name == "areaTrigger")
                    return null;
                if (hitInfo.collider?.GetComponentInParent<SphereCollider>() || hitInfo.collider?.GetComponentInParent<BoxCollider>())
                {
                    return hitInfo.collider.transform.position + new Vector3(0, -1, 0);
                }               
            }
            return hitInfo.point.y;
        }

        private RaycastHit RayPosition(Vector3 sourcePos)
        {
            RaycastHit hitInfo;
            Physics.Raycast(sourcePos, Vector3.down, out hitInfo);//, LayerMask.GetMask("Terrain", "World", "Construction"));

            return hitInfo;
        }
        #endregion

        #region Config    
        enum BiomeType { Arid, Arctic, Temperate, Tundra }
        private ConfigData configData;
        class ConfigData
        {
            [JsonProperty(PropertyName = "Biome Options")]
            public Dictionary<BiomeType, BiomeOptions> SpawnAreas { get; set; }

            public class BiomeOptions
            {
                [JsonProperty(PropertyName = "Enable spawn points to be generated in this biome")]
                public bool Enabled { get; set; }
                [JsonProperty(PropertyName = "Minimum required online players before spawns from this biome will be selected")]
                public int Players { get; set; }
            }
        }
        private void LoadVariables()
        {
            LoadConfigVariables();
            SaveConfig();
        }
        protected override void LoadDefaultConfig()
        {
            var config = new ConfigData
            {
                SpawnAreas = new Dictionary<BiomeType, ConfigData.BiomeOptions>
                {
                    [BiomeType.Temperate] = new ConfigData.BiomeOptions { Enabled = true, Players = 1 },
                    [BiomeType.Arid] = new ConfigData.BiomeOptions { Enabled = true, Players = 10 },
                    [BiomeType.Tundra] = new ConfigData.BiomeOptions { Enabled = true, Players = 20 },
                    [BiomeType.Arctic] = new ConfigData.BiomeOptions { Enabled = true, Players = 30 }
                }
            };
            SaveConfig(config);
        }
        private void LoadConfigVariables() => configData = Config.ReadObject<ConfigData>();
        void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
        #endregion
    }
}

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

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

Сверху