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

FREE VehicleSpawner : 1.0.5 1.0.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("VehicleSpawner", "RIPJAWBONES", "1.0.5")]
    [Description("Allows players to spawn vehicle prefabs with chat commands and limits the number of vehicles a player can have with various restrictions and options.")]
    class VehicleSpawner : RustPlugin {
#region Plugin References
        [PluginReference]
        private Plugin NoEscape = null;
#endregion
#region Data Fields
        private const string DespawnButtonColor = "0.835 0.254 0.156 0.5";
        private const string ButtonTextColor = "2.11 2.26 2.37 0.7";
        private const string SpawnButtonColor = "0.556 0.741 0.247 0.5";
        private const string BackgroundMaterial = "assets/content/ui/uibackgroundblur-ingamemenu.mat";
        private Dictionary<ulong, string> openMenus = new Dictionary<ulong, string>();
        private Dictionary<ulong, bool> lastUiState = new Dictionary<ulong, bool>();
        private Dictionary<ulong, DateTime> lastSpawnTimes = new Dictionary<ulong, DateTime>();
        private Dictionary<ulong, Dictionary<string, DateTime>> lastPrefabSpawnTimes = new Dictionary<ulong, Dictionary<string, DateTime>>();
        private Dictionary<ulong, List<BaseEntity>> playerEntities = new Dictionary<ulong, List<BaseEntity>>();
        private Dictionary<ulong, Timer> activeCountdownTimers = new Dictionary<ulong, Timer>();
        private Dictionary<ulong, string> activeTimerCommands = new Dictionary<ulong, string>();
#endregion
#region Configuration
        private Configuration config;
        class Configuration {
            public Dictionary<string, PrefabData> Prefabs {
                get;
                set;
            }
            public MessageSettings MsgSettings {
                get;
                set;
            }
            = new MessageSettings();
            public Settings Settings {
                get;
                set;
            }
            = new Settings();
            public string UsePermission {
                get;
                set;
            }
            = "vehiclespawner.use";
            public string UiPermission {
                get;
                set;
            }
            = "vehiclespawner.ui";
        }
        public class MessageSettings {
            [JsonProperty(PropertyName = "Message Icon SteamID")]
            public ulong MessageIconSteamId {
                get;
                set;
            }
            = 76561197960839785;
            [JsonProperty(PropertyName = "Message Prefix")]
            public string MessagePrefix {
                get;
                set;
            }
            = "[Vehicle Manager]";
            [JsonProperty(PropertyName = "Message Prefix Color")]
            public string MessagePrefixColor {
                get;
                set;
            }
            = "#5af";
        }
        class Settings {
            [JsonProperty("AmountOfPrefabsAllowedAtOnce")]
            public int AmountOfPrefabsAllowedAtOnce {
                get;
                set;
            }
            = 2;
            [JsonProperty("DestroyOnDisconnect")]
            public bool DestroyOnDisconnect {
                get;
                set;
            }
            = true;
            [JsonProperty("DestroyOnDeath")]
            public bool DestroyOnDeath {
                get;
                set;
            }
            = true;
            [JsonProperty("GlobalSpawnCooldownTimer")]
            public float GlobalSpawnCooldownTimer {
                get;
                set;
            }
            = 10.0f;
            [JsonProperty("BlockNearPlayer")]
            public BlockNearPlayerSettings BlockNearPlayer {
                get;
                set;
            }
            = new BlockNearPlayerSettings();
            [JsonProperty("UseRaidBlocked")]
            public bool UseRaidBlocked {
                get;
                set;
            }
            = true;
            [JsonProperty("UseCombatBlocked")]
            public bool UseCombatBlocked {
                get;
                set;
            }
            = true;
        }
        public class BlockNearPlayerSettings {
            [JsonProperty("UsePlayerDistance")]
            public bool UsePlayerDistance {
                get;
                set;
            }
            = true;
            [JsonProperty("PlayerDistance")]
            public float PlayerDistance {
                get;
                set;
            }
            = 5.0f;
            [JsonProperty("IgnoreTeam")]
            public bool IgnoreTeam {
                get;
                set;
            }
            = true;
        }
        class PrefabData {
            public int SpawnOption {
                get;
                set;
            }
            = 1;
            // Default to current method
            public float SpawnHeight {
                get;
                set;
            }
            = 3.0f;
            // Default height
            public string PrefabPath {
                get;
                set;
            }
            public int FuelAmount {
                get;
                set;
            }
            = 0;
            public float SpawnDistance {
                get;
                set;
            }
            public List<string> ChatCommands {
                get;
                set;
            }
            public Vector3 Rotation {
                get;
                set;
            }
            = Vector3.zero;
            public float CooldownTimer {
                get;
                set;
            }
            = 60.0f;
            public float SpawnDelay {
                get;
                set;
            }
            = 5.0f;
            public bool BlockOnLand {
                get;
                set;
            }
            = false;
            public bool BlockButAllowInSafeZone {
                get;
                set;
            }
            = false;
            public bool BlockInBuildingBlocked {
                get;
                set;
            }
            = true;
            public bool BlockButAllowInBuildingAuthorized {
                get;
                set;
            }
            = false;
            public string Permission {
                get;
                set;
            }
            = "";
            public bool LockFuel {
                get;
                set;
            }
            = false;
            public bool AutoMount {
                get;
                set;
            }
            = false;
            public bool SkySpawn {
                get;
                set;
            }
            = false;
            public float SkySpawnHeight {
                get;
                set;
            }
            = 50.0f;
            public bool BlockInSafeZone {
                get;
                set;
            }
            = true;
            public bool BlockInAuthorizedArea {
                get;
                set;
            }
            = true;
            public bool UseTracks {
                get;
                set;
            }
            = false;
            public bool DisableUIButton {
                get;
                set;
            }
            = false;
        }
#endregion
#region Configuration Methods
        protected override void LoadDefaultConfig() {
            config = new Configuration {
                UsePermission = "vehiclespawner.use", Prefabs = new Dictionary<string, PrefabData> {
                    {
                        "Minicopter", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/minicopter/minicopter.entity.prefab", FuelAmount = 0, SpawnDistance = 5.0f, ChatCommands = new List<string> {
                                "mini", "mymini", "minicopter", "myminicopter"
                            }
                            , Rotation = new Vector3(0, 90, 0), CooldownTimer = 0.0f, SpawnDelay = 0.0f, BlockOnLand = false, Permission = "vehiclespawner.minicopter", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Scrap Transport Helicopter", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab", FuelAmount = 0, SpawnDistance = 8.0f, ChatCommands = new List<string> {
                                "scrap", "myscrap", "heli", "myheli", "helicopter", "myhelicopter", "scrappy", "myscrappy", "scraptransport"
                            }
                            , Rotation = new Vector3(0, 180, 0), CooldownTimer = 10.0f, SpawnDelay = 5.0f, BlockOnLand = false, Permission = "vehiclespawner.scraptransporthelicopter", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Attack Helicopter", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/attackhelicopter/attackhelicopter.entity.prefab", FuelAmount = 0, SpawnDistance = 8.0f, ChatCommands = new List<string> {
                                "attack", "myattack", "attackheli", "myattackheli", "attackhelicopter", "myattackhelicopter", "atkheli", "atk", "myatk", "myatkheli"
                            }
                            , Rotation = new Vector3(0, 90, 0), CooldownTimer = 180.0f, SpawnDelay = 10.0f, BlockOnLand = false, Permission = "vehiclespawner.attackhelicopter", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Chinook", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/prefabs/npc/ch47/ch47.entity.prefab", FuelAmount = 0, SpawnDistance = 10.0f, ChatCommands = new List<string> {
                                "chinook", "mychinook", "ch47", "mych47"
                            }
                            , Rotation = new Vector3(0, 240, 0), CooldownTimer = 180.0f, SpawnDelay = 10.0f, BlockOnLand = false, Permission = "vehiclespawner.chinook", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Balloon", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/prefabs/deployable/hot air balloon/hotairballoon.prefab", FuelAmount = 0, SpawnDistance = 12.0f, ChatCommands = new List<string> {
                                "balloon", "myballoon", "hotairballoon", "myhotairballoon", "myhab", "hab"
                            }
                            , Rotation = new Vector3(0, 90, 0), CooldownTimer = 120.0f, SpawnDelay = 10.0f, BlockOnLand = false, Permission = "vehiclespawner.balloon", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Horse", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/rust.ai/nextai/testridablehorse.prefab", FuelAmount = 0, SpawnDistance = 5.0f, ChatCommands = new List<string> {
                                "horse", "myhorse"
                            }
                            , Rotation = new Vector3(0, 0, 0), CooldownTimer = 180.0f, SpawnDelay = 10.0f, BlockOnLand = false, Permission = "vehiclespawner.horse", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Car", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/sedan_a/sedantest.entity.prefab", FuelAmount = 0, SpawnDistance = 6.0f, ChatCommands = new List<string> {
                                "sedan", "mysedan", "car", "mycar"
                            }
                            , Rotation = new Vector3(0, 0, 0), CooldownTimer = 180.0f, SpawnDelay = 10.0f, BlockOnLand = false, Permission = "vehiclespawner.car", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "Row Boat", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/boats/rowboat/rowboat.prefab", FuelAmount = 0, SpawnDistance = 9.0f, ChatCommands = new List<string> {
                                "rowboat", "row", "myrow", "myrowboat", "boat", "myboat"
                            }
                            , Rotation = new Vector3(0, 0, 0), CooldownTimer = 10.0f, SpawnDelay = 3.0f, BlockOnLand = true, Permission = "vehiclespawner.rowboat", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                    , {
                        "RHIB", new PrefabData {
                            DisableUIButton = false, PrefabPath = "assets/content/vehicles/boats/rhib/rhib.prefab", FuelAmount = 0, SpawnDistance = 10.0f, ChatCommands = new List<string> {
                                "rhib", "myrhib", "mybigboat", "bigboat"
                            }
                            , Rotation = new Vector3(0, 0, 0), CooldownTimer = 10.0f, SpawnDelay = 5.0f, BlockOnLand = true, Permission = "vehiclespawner.rhib", SpawnOption = 1, SpawnHeight = 3.0f
                        }
                    }
                }
                , Settings = new Settings {
                    AmountOfPrefabsAllowedAtOnce = 2, DestroyOnDisconnect = true, DestroyOnDeath = true, GlobalSpawnCooldownTimer = 10.0f, BlockNearPlayer = new BlockNearPlayerSettings {
                        UsePlayerDistance = true, PlayerDistance = 5.0f, IgnoreTeam = true
                    }
                    , UseRaidBlocked = true, UseCombatBlocked = true
                }
                , MsgSettings = new MessageSettings {
                    MessageIconSteamId = 76561197960839785, MessagePrefix = "[VehicleSpawner]", MessagePrefixColor = "#5af"
                }
                , UiPermission = "vehiclespawner.ui"
            }
            ;
            SaveConfig();
        }
        private void LoadConfig() {
            config = Config.ReadObject<Configuration>();
            if (config == null) {
                PrintError("Config is null, using default values.");
                LoadDefaultConfig();
            }
        }
        private void SaveConfig() => Config.WriteObject(config, true);
#endregion
#region Initialization
        private void OnServerInitialized() {
            LoadConfig();
        }
        private void Init() {
            LoadConfig();
            permission.RegisterPermission(config.UsePermission, this);
            permission.RegisterPermission(config.UiPermission, this);
            RegisterChatCommands();
            foreach (var prefabEntry in config.Prefabs) {
                var prefabData = prefabEntry.Value;
                if (!string.IsNullOrEmpty(prefabData.Permission)) {
                    permission.RegisterPermission(prefabData.Permission, this);
                }
            }
        }
        private void RegisterChatCommands() {
            AddCovalenceCommand("destroyall", nameof(HandleDestroyAllCommand));
            foreach (var prefabEntry in config.Prefabs) {
                foreach (var chatCommand in prefabEntry.Value.ChatCommands) {
                    AddCovalenceCommand($"no{chatCommand}", nameof(NoVehicleCommand));
                    AddCovalenceCommand(chatCommand, nameof(VehicleSpawnCommand));
                }
            }
        }
#endregion
#region Utility Methods
        private void LockVehicleFuelContainer(BaseVehicle vehicle, bool lockFuel) {
            if (!lockFuel || vehicle == null) return;
            var fuelSystem = vehicle.GetFuelSystem() as EntityFuelSystem;
            if (fuelSystem == null) return;
            var fuelContainer = fuelSystem.GetFuelContainer();
            if (fuelContainer != null) {
                fuelContainer.inventory.SetLocked(true);
            }
        }
        private void AddFuelToVehicle(BaseVehicle vehicle, int fuelAmount) {
            if (vehicle == null) return;
            var fuelSystem = vehicle.GetFuelSystem() as EntityFuelSystem;
            if (fuelSystem == null) return;
            var fuelContainer = fuelSystem.GetFuelContainer();
            if (fuelContainer == null) return;
            var fuelItem = ItemManager.CreateByItemID(-946369541, fuelAmount);
            if (fuelItem != null) {
                fuelItem.MoveToContainer(fuelContainer.inventory);
            }
        }
        private void RemoveOldestEntity(ulong playerId) {
            if (!playerEntities.ContainsKey(playerId) || playerEntities[playerId].Count == 0) {
                return;
            }
            // Get the oldest entity
            BaseEntity oldestEntity = playerEntities[playerId].FirstOrDefault();
            // Kill the oldest entity
            oldestEntity?.Kill();
            // Remove the oldest entity from the list
            playerEntities[playerId].Remove(oldestEntity);
            // Notify the player
            var basePlayer = BasePlayer.FindByID(playerId);
            if (basePlayer != null) {
                SendMessage(basePlayer, "One of your vehicles has been removed to make space for a new one.");
            }
            // Check if the removal has cleared the list and clean up if necessary
            if (playerEntities[playerId].Count == 0) {
                playerEntities.Remove(playerId);
            }
        }
        private bool IsCombatBlocked(BasePlayer player) {
            return NoEscape?.Call<bool>("IsCombatBlocked", player) ?? false;
        }
        private bool IsRaidBlocked(BasePlayer player) {
            return NoEscape?.Call<bool>("IsRaidBlocked", player) ?? false;
        }
        private void SendMessage(object player, string message) {
            if (player == null) return;
            BasePlayer basePlayer = null;
            if (player is IPlayer) {
                var iplayer = (IPlayer)player;
                basePlayer = iplayer.Object as BasePlayer;
            }
            else if (player is BasePlayer) {
                basePlayer = (BasePlayer)player;
            }
            if (basePlayer != null) {
                var coloredMessagePrefix = $"<color={config.MsgSettings.MessagePrefixColor}>{config.MsgSettings.MessagePrefix}</color>";
                var fullMessage = $"{coloredMessagePrefix} {message}";
                basePlayer.SendConsoleCommand("chat.add", 2, config.MsgSettings.MessageIconSteamId.ToString(), fullMessage);
            }
        }
        private void AutoMount(BasePlayer player, BaseEntity entity) {
            var vehicle = entity as BaseVehicle;
            if (vehicle != null && vehicle.mountPoints != null && vehicle.mountPoints.Count > 0) {
                var mountable = vehicle.mountPoints[0].mountable;
                if (mountable != null) {
                    mountable.MountPlayer(player);
                }
                else {
                    SendMessage(player, "Failed to mount.No mountable found at the first mount point.");
                }
            }
            else {
                SendMessage(player, $"The entity {entity.ShortPrefabName} does not support auto-mounting.");
            }
        }
        private void RemoveFuelFromPrefab(BaseEntity entity) {
            var vehicle = entity as BaseVehicle;
            if (vehicle != null) {
                var fuelSystem = vehicle.GetFuelSystem() as EntityFuelSystem;
                if (fuelSystem != null) {
                    var fuelContainer = fuelSystem.fuelStorageInstance.Get(true);
                    if (fuelContainer != null) {
                        var fuelItem = fuelContainer.inventory.FindItemByItemID(-946369541);
                        fuelItem?.RemoveFromContainer();
                        fuelItem?.Remove();
                    }
                }
            }
        }
        private bool FindNearbyTrack(Vector3 position) {
            TrainTrackSpline nearestTrackSpline;
            float nearestSplineDistance;
            return TrainTrackSpline.TryFindTrackNear(position, 15.0f, out nearestTrackSpline, out nearestSplineDistance);
        }
        private bool MoveToTrack(TrainCar train, Vector3 position) {
            TrainTrackSpline trainTrackSpline;
            float frontWheelSplineDist;
            if (!TrainTrackSpline.TryFindTrackNear(train.GetFrontWheelPos(), 15.0f, out trainTrackSpline, out frontWheelSplineDist)) {
                return false;
            }
            train.FrontWheelSplineDist = frontWheelSplineDist;
            Vector3 targetFrontWheelTangent;
            Vector3 positionAndTangent = trainTrackSpline.GetPositionAndTangent(train.FrontWheelSplineDist, train.transform.forward, out targetFrontWheelTangent);
            train.SetTheRestFromFrontWheelData(ref trainTrackSpline, positionAndTangent, targetFrontWheelTangent, train.localTrackSelection, null, true);
            train.FrontTrackSection = trainTrackSpline;
            return true;
        }
        private static Vector3 GetPositionInFrontOfPlayer(BasePlayer player, float distance) {
            return player.transform.position + (player.eyes.BodyForward() * distance);
        }
        private static Vector3 GetGroundBuilding(Vector3 position) {
            RaycastHit hitInfo;
            if (Physics.Raycast(position + Vector3.up * 100, Vector3.down, out hitInfo, Mathf.Infinity, LayerMask.GetMask("Terrain", "World", "Construction", "Deployable", "Vehicle"))) {
                position.y = hitInfo.point.y;
            }
            return position;
        }
#endregion
#region Helper
        private string SetFlags(BasePlayer player, string prefabKey) {
            var prefabData = config.Prefabs[prefabKey];
            if (prefabData.BlockButAllowInBuildingAuthorized && prefabData.BlockButAllowInSafeZone) {
                if (!player.IsBuildingAuthed() && !player.InSafeZone()) {
                    return $"You can only spawn <color=#00ff00>{prefabKey}s</color> in building authorized areas or safe zones.";
                }
            }
            else {
                if (prefabData.BlockButAllowInBuildingAuthorized && !player.IsBuildingAuthed()) {
                    return "You can only spawn in building authorized areas.";
                }
                if (prefabData.BlockButAllowInSafeZone && !player.InSafeZone()) {
                    return "You can only spawn in safe zones.";
                }
            }
            if (prefabData.BlockButAllowInBuildingAuthorized && prefabData.BlockButAllowInSafeZone) {
                if (!player.InSafeZone() && !player.IsBuildingAuthed()) {
                    return "You can only spawn in building authorized areas or safe zones.";
                }
            }
            if (prefabData.BlockInBuildingBlocked && player.IsBuildingBlocked()) {
                return "You cannot spawn while building blocked.";
            }
            if (prefabData.BlockInSafeZone && player.InSafeZone()) {
                return $"You can not spawn a <color=#00ff00>{prefabKey}</color> in safe zones.";
            }
            if (prefabData.BlockInAuthorizedArea && player.IsBuildingAuthed()) {
                return $"You cannot spawn a <color=#55aaff>{prefabKey}</color> in an authorized area.";
            }
            if (!IsPlayerOutside(player)) {
                return "test2 Bad location detected, try spawning elsewhere.";
            }
            if (config.Settings.BlockNearPlayer.UsePlayerDistance) {
                int nearbyPlayerCount = 0;
                foreach (BasePlayer nearPlayer in BasePlayer.activePlayerList) {
                    if (!nearPlayer.IsConnected || !nearPlayer.IsAlive()) continue;
                    if (nearPlayer == player) continue;
                    if (Vector3.Distance(player.transform.position, nearPlayer.transform.position) <= config.Settings.BlockNearPlayer.PlayerDistance) {
                        if (!config.Settings.BlockNearPlayer.IgnoreTeam || nearPlayer.Team == null || !nearPlayer.Team.members.Contains(player.userID)) {
                            nearbyPlayerCount++;
                        }
                    }
                }
                if (nearbyPlayerCount > 0) {
                    return $"Spawn blocked.Players are nearby.";
                }
            }
            if (config.Settings.UseRaidBlocked && IsRaidBlocked(player)) {
                return "You cannot spawn while raid blocked.";
            }
            if (config.Settings.UseCombatBlocked && IsCombatBlocked(player)) {
                return $"You cannot spawn a <color=#00ff00>{prefabKey}</color> while combat blocked.";
            }
            return "OK";
        }
#endregion
#region Validation Methods
        private bool IsGroundDetected(BasePlayer player) {
            Vector3 rayStart = player.transform.position + new Vector3(0, 0.5f, 0);
            return Physics.Raycast(rayStart, Vector3.down, out _, Mathf.Infinity, LayerMask.GetMask("Terrain", "World"));
        }
        private bool IsPlayerBelowGround(BasePlayer player) {
            float terrainHeight = TerrainMeta.HeightMap.GetHeight(player.transform.position);
            return player.transform.position.y < (terrainHeight - 5.0f);
        }
        private bool IsPlayerOutside(BasePlayer player) {
            bool isObstructionAbove = Physics.Raycast(new Ray(player.transform.position + new Vector3(0, 1.0f, 0), Vector3.up), 50f);
            return !isObstructionAbove;
        }
#endregion Validation Methods
#region Validation
        private string ValidateSpawnLocation(BasePlayer player) {
            if (!IsGroundDetected(player)) {
                return "Spawn failed: No ground detected below.";
            }
            if (IsPlayerBelowGround(player)) {
                return "Spawn failed: You are below ground level.";
            }
            if (!IsPlayerOutside(player)) {
                return "Spawn failed: You must be outside to spawn.";
            }
            return "OK";
        }
#endregion Validation
#region Command Handlers
        private void HandleDestroyAllCommand(IPlayer iPlayer, string command, string[] args) {
            var basePlayer = iPlayer.Object as BasePlayer;
            if (basePlayer == null || !basePlayer.IsConnected) {
                SendMessage(iPlayer, "An error occurred.You might not be connected properly.");
                return;
            }
            if (!permission.UserHasPermission(basePlayer.UserIDString, config.UsePermission)) {
                SendMessage(basePlayer, "You do not have permission to use this command.");
                return;
            }
            if (playerEntities.TryGetValue(basePlayer.userID, out List<BaseEntity> entities)) {
                if (entities.Count > 0) {
                    foreach (var entity in entities.ToList()) {
                        RemoveFuelFromPrefab(entity);
                        entity.Kill();
                    }
                    entities.Clear();
                    SendMessage(basePlayer, "All your vehicles have been destroyed.");
                }
                else {
                    SendMessage(basePlayer, "You do not have any vehicles spawned.");
                }
            }
            else {
                SendMessage(basePlayer, "You do not have any vehicles spawned.");
            }
        }
        private void NoVehicleCommand(IPlayer iPlayer, string command, string[] args) {
            var basePlayer = iPlayer.Object as BasePlayer;
            if (basePlayer == null) {
                SendMessage(basePlayer, "An error occurred.Unable to process the command.");
                return;
            }
            if (!permission.UserHasPermission(basePlayer.UserIDString, config.UsePermission)) {
                SendMessage(basePlayer, "You do not have permission to use this command.");
                return;
            }
            string prefabCommand = command.Substring(2).ToLower();
            if (!playerEntities.ContainsKey(basePlayer.userID) || playerEntities[basePlayer.userID].Count == 0) {
                SendMessage(basePlayer, "You do not have any vehicles spawned.");
                return;
            }
            string prefabKey = config.Prefabs.FirstOrDefault(prefabEntry => prefabEntry.Value.ChatCommands.Contains(prefabCommand, StringComparer.OrdinalIgnoreCase)).Key;
            if (string.IsNullOrEmpty(prefabKey)) {
                SendMessage(basePlayer, $"Vehicle command <color=#55aaff>{prefabCommand}</color> not found.");
                return;
            }
            if (!string.IsNullOrEmpty(config.Prefabs[prefabKey].Permission) && !permission.UserHasPermission(basePlayer.UserIDString, config.Prefabs[prefabKey].Permission)) {
                SendMessage(basePlayer, $"You do not have permission to destroy your <color=#55aaff>{prefabKey}</color>.");
                return;
            }
            bool prefabFound = false;
            List<BaseEntity> entitiesToRemove = new List<BaseEntity>();
            foreach (var entity in playerEntities[basePlayer.userID]) {
                if (entity.PrefabName.Equals(config.Prefabs[prefabKey].PrefabPath, StringComparison.OrdinalIgnoreCase)) {
                    entitiesToRemove.Add(entity);
                    prefabFound = true;
                }
            }
            foreach (var entity in entitiesToRemove) {
                playerEntities[basePlayer.userID].Remove(entity);
                entity.Kill();
            }
            if (prefabFound) {
                SendMessage(basePlayer, $"<color=#55aaff>{prefabKey}</color> has been destroyed.");
            }
            else {
                SendMessage(basePlayer, $"Vehicle spawned with command <color=#55aaff>{prefabCommand}</color> not found.");
            }
        }
        private void VehicleSpawnCommand(IPlayer player, string command, string[] args) {
            string cleanCommand = command.TrimStart('/');
            string prefabKey = config.Prefabs.FirstOrDefault(p => p.Value.ChatCommands.Contains(cleanCommand, StringComparer.OrdinalIgnoreCase)).Key;
            BasePlayer basePlayer = player.Object as BasePlayer;
            if (basePlayer == null) return;
            if (!permission.UserHasPermission(basePlayer.UserIDString, config.UsePermission)) {
                SendMessage(player, $"You do not have permission to spawn a <color=#55aaff>{prefabKey}</color>.");
                return;
            }
            if ((player.Object as BasePlayer)?.GetMountedVehicle() != null) {
                SendMessage(player, $"You cannot spawn a <color=#55aaff>{prefabKey}</color> while mounted.");
                return;
            }
            if (activeTimerCommands.TryGetValue(basePlayer.userID, out string previousCommand)) {
                string previousPrefabKey = config.Prefabs.FirstOrDefault(p => p.Value.ChatCommands.Contains(previousCommand, StringComparer.OrdinalIgnoreCase)).Key;
                if (previousCommand == command) {
                    if (activeCountdownTimers.TryGetValue(basePlayer.userID, out Timer existingTimer)) {
                        existingTimer.Destroy();
                        activeCountdownTimers.Remove(basePlayer.userID);
                        activeTimerCommands.Remove(basePlayer.userID);
                        lastSpawnTimes[basePlayer.userID] = DateTime.UtcNow;
                        SendMessage(player, $"<color=#55aaff>{previousPrefabKey}</color> countdown cancelled.");
                    }
                    return;
                }
                else {
                    if (activeCountdownTimers.TryGetValue(basePlayer.userID, out Timer existingTimer)) {
                        existingTimer.Destroy();
                        activeCountdownTimers.Remove(basePlayer.userID);
                        activeTimerCommands.Remove(basePlayer.userID);
                        SendMessage(player, $"<color=#55aaff>{previousPrefabKey}</color> countdown cancelled.");
                    }
                }
            }
            foreach (var prefabEntry in config.Prefabs) {
                var prefabData = prefabEntry.Value;
                if (prefabData.ChatCommands.Contains(command, StringComparer.OrdinalIgnoreCase)) {
                    if (!string.IsNullOrEmpty(prefabData.Permission) && !permission.UserHasPermission(player.Id, prefabData.Permission)) {
                        SendMessage(player, $"You do not have permission to spawn a <color=#55aaff>{prefabKey}</color>.");
                        return;
                    }
                    if (prefabData.UseTracks) {
                        Vector3 playerPosition = basePlayer.transform.position + (basePlayer.eyes.BodyForward() * prefabData.SpawnDistance);
                        if (!FindNearbyTrack(playerPosition)) {
                            SendMessage(player, "You must be near train tracks to spawn a <color=#55aaff>{prefabKey}</color>.");
                            return;
                        }
                    }
                    if (lastSpawnTimes.TryGetValue(basePlayer.userID, out DateTime lastGlobalSpawnTime)) {
                        TimeSpan timeSinceLastGlobalSpawn = DateTime.UtcNow - lastGlobalSpawnTime;
                        if (timeSinceLastGlobalSpawn.TotalSeconds < config.Settings.GlobalSpawnCooldownTimer) {
                            SendMessage(player, $"Vehicle cooldown active.Please wait <color=#FF7276>{(config.Settings.GlobalSpawnCooldownTimer - timeSinceLastGlobalSpawn.TotalSeconds):N0}</color> more seconds before spawning any <color=#55aaff>vehicles</color>.");
                            return;
                        }
                    }
                    if (lastPrefabSpawnTimes.TryGetValue(basePlayer.userID, out Dictionary<string, DateTime> prefabCooldowns) && prefabCooldowns.TryGetValue(prefabData.PrefabPath, out DateTime lastPrefabSpawnTime)) {
                        TimeSpan timeSinceLastPrefabSpawn = DateTime.UtcNow - lastPrefabSpawnTime;
                        if (timeSinceLastPrefabSpawn.TotalSeconds < prefabData.CooldownTimer) {
                            SendMessage(player, $"Cooldown for <color=#55aaff>{prefabKey}s</color> active.Please wait <color=#FF7276>{(prefabData.CooldownTimer - timeSinceLastPrefabSpawn.TotalSeconds):N0}</color> more seconds to spawn this vehicle again.");
                            return;
                        }
                    }
                    string locationValidationResult = ValidateSpawnLocation(basePlayer);
                    if (locationValidationResult != "OK") {
                        SendMessage(player, locationValidationResult);
                        return;
                    }
                    string flagResult = SetFlags(basePlayer, prefabKey);
                    if (flagResult != "OK") {
                        SendMessage(player, flagResult);
                        return;
                    }
                    Vector3 spawnPosition = GetPositionInFrontOfPlayer(basePlayer, prefabData.SpawnDistance);
                    spawnPosition = GetGroundBuilding(spawnPosition);
                    if (prefabData.BlockOnLand) {
                        int topologyLayer = TerrainMeta.TopologyMap.GetTopology(spawnPosition);
                        bool isOnMainLand = (topologyLayer & (int)TerrainTopology.Enum.Mainland) != 0;
                        bool isInRiver = (topologyLayer & (int)TerrainTopology.Enum.River) != 0;
                        bool isInLake = (topologyLayer & (int)TerrainTopology.Enum.Lake) != 0;
                        if (isOnMainLand && !isInRiver && !isInLake) {
                            SendMessage(player, $"You cannot spawn a <color=#55aaff>{prefabKey}</color> on land!");
                            return;
                        }
                    }
                    if (prefabData.SpawnDelay <= 0) {
                        SpawnVehicle(player, prefabEntry.Key, prefabData.PrefabPath, prefabData.SpawnDistance, prefabData.Rotation, prefabData.BlockOnLand);
                        if (!lastPrefabSpawnTimes.ContainsKey(basePlayer.userID)) {
                            lastPrefabSpawnTimes[basePlayer.userID] = new Dictionary<string, DateTime>();
                        }
                        lastPrefabSpawnTimes[basePlayer.userID][prefabData.PrefabPath] = DateTime.UtcNow;
                        return;
                    }
                    SendMessage(player, $"Spawning a <color=#55aaff>{prefabKey}</color> in <color=#FF7276>{prefabData.SpawnDelay}</color> seconds.");
                    Timer newTimer = timer.Once(prefabData.SpawnDelay, () => {
                        if (!player.IsConnected || player.Object == null) return;
                        SpawnVehicle(player, prefabEntry.Key, prefabData.PrefabPath, prefabData.SpawnDistance, prefabData.Rotation, prefabData.BlockOnLand);
                        if (playerEntities.TryGetValue(basePlayer.userID, out List<BaseEntity> spawnedEntities) && spawnedEntities.Any(e => e.PrefabName == prefabData.PrefabPath)) {
                            if (!lastPrefabSpawnTimes.ContainsKey(basePlayer.userID)) {
                                lastPrefabSpawnTimes[basePlayer.userID] = new Dictionary<string, DateTime>();
                            }
                            lastPrefabSpawnTimes[basePlayer.userID][prefabData.PrefabPath] = DateTime.UtcNow;
                        }
                        lastSpawnTimes[basePlayer.userID] = DateTime.UtcNow;
                        activeCountdownTimers.Remove(basePlayer.userID);
                        activeTimerCommands.Remove(basePlayer.userID);
                    }
                    );
                    activeCountdownTimers[basePlayer.userID] = newTimer;
                    activeTimerCommands[basePlayer.userID] = command;
                    return;
                }
            }
            SendMessage(player, $"Vehicle not found.");
        }
#endregion
#region Spawning Logic
        private void SpawnVehicle(IPlayer iPlayer, string prefabKey, string prefabPath, float spawnDistance, Vector3 configRotation, bool blockOnLand) {
            var basePlayer = iPlayer?.Object as BasePlayer;
            if (basePlayer == null) return;
            ulong playerId = basePlayer.userID;
            if (lastSpawnTimes.TryGetValue(playerId, out DateTime lastGlobalSpawnTime)) {
                TimeSpan timeSinceLastGlobalSpawn = DateTime.UtcNow - lastGlobalSpawnTime;
                if (timeSinceLastGlobalSpawn.TotalSeconds < config.Settings.GlobalSpawnCooldownTimer) {
                    SendMessage(basePlayer, $"Vehicle cooldown active.Please wait {(config.Settings.GlobalSpawnCooldownTimer - timeSinceLastGlobalSpawn.TotalSeconds):N0} more seconds before spawning any <color=#55aaff>vehicles</color>.");
                    return;
                }
            }
            if (!playerEntities.ContainsKey(playerId)) {
                playerEntities[playerId] = new List<BaseEntity>();
            }
            else if (playerEntities[playerId].Count >= config.Settings.AmountOfPrefabsAllowedAtOnce) {
                RemoveOldestEntity(playerId);
            }
            var prefabData = config.Prefabs[prefabKey];
            Vector3 spawnPosition = CalculateSpawnPosition(basePlayer, spawnDistance, prefabData.SpawnOption, prefabData.SpawnHeight, prefabData.BlockOnLand);
            Quaternion spawnRotation = Quaternion.LookRotation(basePlayer.eyes.BodyForward()) * Quaternion.Euler(configRotation);
            string flagResult = SetFlags(basePlayer, prefabKey);
            if (flagResult != "OK") {
                SendMessage(basePlayer, flagResult);
                return;
            }
            BaseEntity entity = GameManager.server.CreateEntity(prefabPath, spawnPosition, spawnRotation);
            if (entity == null) {
                PrintError("Failed to create prefab entity.");
                return;
            }
            entity.Spawn();
            PostSpawnActions(basePlayer, entity, prefabKey, prefabPath);
            playerEntities[playerId].Add(entity);
            SendMessage(basePlayer, $"Your <color=#55aaff>{prefabKey}</color> has spawned.");
            lastSpawnTimes[basePlayer.userID] = DateTime.UtcNow;
        }
        private Vector3 CalculateSpawnPosition(BasePlayer player, float distance, int spawnOption, float spawnHeight, bool blockOnLand) {
            Vector3 position;
            if (blockOnLand) {
                float heightOffset = 3.0f;
                Vector3 playerPosition = player.transform.position;
                Vector3 playerEyesDirection = player.eyes.BodyForward();
                position = playerPosition + playerEyesDirection * distance + Vector3.up * heightOffset;
            }
            else {
                switch (spawnOption) {
                    case 1 : position = GetPositionInFrontOfPlayer(player, distance);
                    position = GetGroundBuilding(position);
                    break;
                    case 2 : Vector3 playerPosition = player.transform.position;
                    Vector3 playerEyesDirection = player.eyes.BodyForward();
                    position = playerPosition + playerEyesDirection * distance + Vector3.up * spawnHeight;
                    break;
                    default : position = Vector3.zero;
                    // Fallback in case of configuration errors
                    PrintWarning($"Invalid spawn option: {spawnOption}.Please check your configuration.");
                    break;
                }
            }
            return position;
        }
        private void PostSpawnActions(BasePlayer player, BaseEntity entity, string prefabKey, string prefabPath) {
            var prefabData = config.Prefabs[prefabKey];
            if (prefabData == null) return;
            if (prefabData.UseTracks && entity is TrainCar train && !MoveToTrack(train, entity.transform.position)) {
                entity.Kill();
                SendMessage(player, "Failed to spawn.No nearby tracks found.");
                return;
            }
            if (prefabData.SkySpawn) {
                SkySpawn(player, entity, prefabData.SkySpawnHeight);
            }
            if (prefabData.AutoMount) {
                AutoMount(player, entity);
            }
            if (prefabData.FuelAmount > 0 && entity is BaseVehicle vehicle) {
                AddFuelToVehicle(vehicle, prefabData.FuelAmount);
                if (prefabData.LockFuel) {
                    LockVehicleFuelContainer(vehicle, true);
                }
            }
        }
        private void SkySpawn(BasePlayer player, BaseEntity entity, float skySpawnHeight) {
            if (entity == null) return;
            var vehicle = entity as BaseVehicle;
            if (vehicle != null && vehicle.mountPoints != null && vehicle.mountPoints.Count > 0) {
                var mountable = vehicle.mountPoints[0].mountable;
                if (mountable != null) {
                    mountable.MountPlayer(player);
                    entity.SetFlag(BaseEntity.Flags.On, true);
                }
                else {
                    player.ChatMessage("Failed to mount.No mountable found at the first mount point.");
                }
            }
            if (player != null) {
            }
            Vector3 skySpawnPosition = entity.transform.position + new Vector3(0, skySpawnHeight, 0);
            entity.transform.position = skySpawnPosition;
            entity.SendNetworkUpdateImmediate();
        }
#endregion
#region Event Handlers
        void OnEntityKill(BaseNetworkable entity) {
            if (entity == null) return;
            BaseEntity baseEntity = entity as BaseEntity;
            if (baseEntity == null) return;
            foreach (var playerEntry in playerEntities.ToList()) {
                ulong playerId = playerEntry.Key;
                List<BaseEntity> entitiesList = playerEntry.Value;
                if (entitiesList.Contains(baseEntity)) {
                    entitiesList.Remove(baseEntity);
                    // Check if the player has more vehicles than allowed
                    if (entitiesList.Count > config.Settings.AmountOfPrefabsAllowedAtOnce) {
                        // Remove the oldest vehicle
                        RemoveOldestEntity(playerId);
                    }
                    if (entitiesList.Count == 0) {
                        playerEntities.Remove(playerId);
                    }
                    break;
                }
            }
        }
        void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
            if (entity is BasePlayer player) {
                if (!permission.UserHasPermission(player.UserIDString, config.UsePermission)) {
                    return;
                }
                bool hasBulletDamage = info.damageTypes.Has(Rust.DamageType.Bullet);
                bool hasExplosionDamage = info.damageTypes.Has(Rust.DamageType.Explosion);
                bool hasBluntDamage = info.damageTypes.Has(Rust.DamageType.Blunt);
                bool hasAnimalDamage = info.damageTypes.Has(Rust.DamageType.Bite);
                if (activeTimerCommands.TryGetValue(player.userID, out string prefabCommand) && !string.IsNullOrEmpty(prefabCommand)) {
                    string prefabKey = config.Prefabs.FirstOrDefault(p => p.Value.ChatCommands.Contains(prefabCommand, StringComparer.OrdinalIgnoreCase)).Key;
                    if (hasBulletDamage || hasExplosionDamage || hasAnimalDamage) {
                        if (activeCountdownTimers.TryGetValue(player.userID, out Timer timer)) {
                            timer.Destroy();
                            activeCountdownTimers.Remove(player.userID);
                            activeTimerCommands.Remove(player.userID);
                            SendMessage(player, $"Your {prefabKey} spawn countdown has been cancelled due to taking damage.");
                        }
                    }
                }
            }
        }
        void OnPlayerDeath(BasePlayer player, HitInfo info) {
            if (config.Settings.DestroyOnDeath) {
                if (playerEntities.TryGetValue(player.userID, out List<BaseEntity> vehicles)) {
                    foreach (var vehicle in vehicles.ToList()) {
                        if (vehicle != null && !vehicle.IsDestroyed) {
                            RemoveFuelFromPrefab(vehicle);
                     
// ... [Code preview truncated due to length. Full source in attached file] ...

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