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

FREE RandomRespawner : 1.2.2 1.2.2

Нет прав для скачивания
C#:
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Rust;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("Random Respawner", "Egor Blagov/Arainrr", "1.2.2")]
    [Description("Plugin respawns player in random place")]
    internal class RandomRespawner : RustPlugin {
        private const int MaxTrials = 200;
        private const string PERMISSION_USE = "randomrespawner.use";
        private const int MASK_BIOME = (int)(TerrainBiome.Enum.Arid | TerrainBiome.Enum.Temperate | TerrainBiome.Enum.Tundra | TerrainBiome.Enum.Arctic);
        private const int MASK_SPLAT = (int)(TerrainSplat.Enum.Dirt | TerrainSplat.Enum.Snow | TerrainSplat.Enum.Sand | TerrainSplat.Enum.Rock | TerrainSplat.Enum.Grass | TerrainSplat.Enum.Forest | TerrainSplat.Enum.Stones | TerrainSplat.Enum.Gravel);
        private Coroutine findSpawnPosCoroutine;
        private readonly List<Vector3> spawnPositionCache = new List<Vector3>();
        private List<Collider> colliders;
        private List<BaseEntity> entities;
        private List<BasePlayer> players;
#region Oxide Hooks
        private void Init() {
            colliders = Facepunch.Pool.GetList<Collider>();
            entities = Facepunch.Pool.GetList<BaseEntity>();
            players = Facepunch.Pool.GetList<BasePlayer>();
            permission.RegisterPermission(PERMISSION_USE, this);
        }
        private void OnServerInitialized() {
            findSpawnPosCoroutine = ServerMgr.Instance.StartCoroutine(FindSpawnPositions());
        }
        private void Unload() {
            Facepunch.Pool.Free(ref entities);
            Facepunch.Pool.Free(ref colliders);
            Facepunch.Pool.Free(ref players);
            if (findSpawnPosCoroutine != null) ServerMgr.Instance.StopCoroutine(findSpawnPosCoroutine);
        }
        private IEnumerator FindSpawnPositions() {
            float mapSizeX = TerrainMeta.Size.x / 2;
            float mapSizeZ = TerrainMeta.Size.z / 2;
            Vector3 randomPos = Vector3.zero;
            for (int i = 0; i < 3000; i++) {
                randomPos.x = UnityEngine.Random.Range(-mapSizeX, mapSizeX);
                randomPos.z = UnityEngine.Random.Range(-mapSizeZ, mapSizeZ);
                if (TestPos(ref randomPos)) {
                    spawnPositionCache.Add(randomPos);
                }
                if (i % 20 == 0) yield return CoroutineEx.waitForEndOfFrame;
            }
            PrintWarning($"Successfully found {spawnPositionCache.Count} spawn positions.");
            findSpawnPosCoroutine = null;
        }
        private object OnPlayerRespawn(BasePlayer player) {
            if (!permission.UserHasPermission(player.UserIDString, PERMISSION_USE)) {
                return null;
            }
            var spawnPos = GetRandomSpawnPos();
            if (!spawnPos.HasValue) {
                PrintWarning("Unable to generate random respawn position, try limit exceed, spawn as default");
                return null;
            }
            if (Interface.CallHook("OnRandomRespawn", player, spawnPos.Value) != null) {
                return null;
            }
            return new BasePlayer.SpawnPoint {
                pos = spawnPos.Value,
            }
            ;
        }
#endregion Oxide Hooks
        private Vector3? GetRandomSpawnPos() {
            Vector3 spawnPos;
            for (int i = 0; i < MaxTrials; i++) {
                spawnPos = spawnPositionCache.GetRandom();
                if (TestPosAgain(spawnPos)) {
                    return spawnPos;
                }
            }
            return null;
        }
        private bool TestPos(ref Vector3 randomPos) {
            RaycastHit hitInfo;
            if (!Physics.Raycast(randomPos + Vector3.up * 300f, Vector3.down, out hitInfo, 400f, Layers.Solid) || hitInfo.GetEntity() != null) {
                return false;
            }
            randomPos.y = hitInfo.point.y;
            if (ConVar.AntiHack.terrain_kill && AntiHack.TestInsideTerrain(randomPos)) {
                return false;
            }
            var slope = GetPosSlope(randomPos);
            if (slope < configData.minSlope || slope > configData.maxSlope) {
                return false;
            }
            bool flag;
            var biome = GetPosBiome(randomPos);
            if (configData.biomes.TryGetValue(biome, out flag) && !flag) {
                return false;
            }
            var splat = GetPosSplat(randomPos);
            if (configData.splats.TryGetValue(splat, out flag) && !flag) {
                return false;
            }
            return TestPosAgain(randomPos);
        }
        private bool TestPosAgain(Vector3 spawnPos) {
            if (WaterLevel.Test(spawnPos)) {
                return false;
            }
            if (!ValidBounds.Test(spawnPos)) {
                return false;
            }
            colliders.Clear();
            Vis.Colliders(spawnPos, 3f, colliders);
            foreach (var collider in colliders) {
                switch (collider.gameObject.layer) {
                    case (int)Layer.Prevent_Building : if (configData.preventSpawnAtMonument) {
                        return false;
                    }
                    break;
                    case (int)Layer.Vehicle_Large :  //cargoshiptest
                    case (int)Layer.Vehicle_World : case (int)Layer.Vehicle_Detailed : return false;
                }
                if (configData.preventSpawnAtZone && collider.name.Contains("zonemanager", CompareOptions.IgnoreCase)) {
                    return false;
                }
                if (configData.preventSpawnAtRadZone && collider.name.Contains("radiation", CompareOptions.IgnoreCase)) {
                    return false;
                }
                if (collider.name.Contains("fireball", CompareOptions.IgnoreCase) || collider.name.Contains("iceberg", CompareOptions.IgnoreCase) || collider.name.Contains("ice_sheet", CompareOptions.IgnoreCase)) {
                    return false;
                }
            }
            if (configData.radiusFromPlayers > 0) {
                players.Clear();
                Vis.Entities(spawnPos, configData.radiusFromPlayers, players, Layers.Mask.Player_Server);
                foreach (var player in players) {
                    if (!player.IsSleeping()) {
                        return false;
                    }
                }
            }
            if (configData.radiusFromBuilding > 0) {
                entities.Clear();
                Vis.Entities(spawnPos, configData.radiusFromBuilding, entities, Layers.PlayerBuildings);
                if (entities.Any()) return false;
            }
            return true;
        }
#region Helpers
        private static TerrainBiome.Enum GetPosBiome(Vector3 position) => (TerrainBiome.Enum)TerrainMeta.BiomeMap.GetBiomeMaxType(position, MASK_BIOME);
        private static TerrainSplat.Enum GetPosSplat(Vector3 position) => (TerrainSplat.Enum)TerrainMeta.SplatMap.GetSplatMaxType(position, MASK_SPLAT);
        private static float GetPosSlope(Vector3 position) => TerrainMeta.HeightMap.GetSlope(position);
#endregion Helpers
#region ConfigurationFile
        private ConfigData configData;
        private class ConfigData {
            [JsonProperty(PropertyName = "Minimum Distance From Other Players (Including NPC Players)")]
            public float radiusFromPlayers = 20.0f;
            [JsonProperty(PropertyName = "Minimum Distance From Building")]
            public float radiusFromBuilding = 20.0f;
            [JsonProperty(PropertyName = "Prevent Players To Be Respawn At Monuments")]
            public bool preventSpawnAtMonument = true;
            [JsonProperty(PropertyName = "Prevent Players To Be Respawn At ZoneManager")]
            public bool preventSpawnAtZone = true;
            [JsonProperty(PropertyName = "Prevent Players To Be Respawn At RadiationZone")]
            public bool preventSpawnAtRadZone = true;
            [JsonProperty(PropertyName = "Minimum Slope")]
            public float minSlope = 0f;
            [JsonProperty(PropertyName = "Maximum Slope")]
            public float maxSlope = 60f;
            [JsonProperty(PropertyName = "Biome Settings")]
            public Dictionary<TerrainBiome.Enum, bool> biomes = new Dictionary<TerrainBiome.Enum, bool> {
                [TerrainBiome.Enum.Arid]
                = true, [TerrainBiome.Enum.Temperate] = true, [TerrainBiome.Enum.Tundra] = true, [TerrainBiome.Enum.Arctic] = true,
            }
            ;
            [JsonProperty(PropertyName = "Splat Settings")]
            public Dictionary<TerrainSplat.Enum, bool> splats = new Dictionary<TerrainSplat.Enum, bool> {
                [TerrainSplat.Enum.Dirt]
                = true, [TerrainSplat.Enum.Snow] = true, [TerrainSplat.Enum.Sand] = true, [TerrainSplat.Enum.Rock] = true, [TerrainSplat.Enum.Grass] = true, [TerrainSplat.Enum.Forest] = true, [TerrainSplat.Enum.Stones] = true, [TerrainSplat.Enum.Gravel] = true,
            }
            ;
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                configData = Config.ReadObject<ConfigData>();
                if (configData == null) LoadDefaultConfig();
            }
            catch {
                PrintError("The configuration file is corrupted");
                LoadDefaultConfig();
            }
            SaveConfig();
        }
        protected override void LoadDefaultConfig() {
            PrintWarning("Creating a new configuration file");
            configData = new ConfigData();
        }
        protected override void SaveConfig() => Config.WriteObject(configData);
#endregion ConfigurationFile
    }
}

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