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

FREE VehicleBuy : 1.1.7 1.1.7

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core;
using UnityEngine;
using System.Linq;
using ConVar;
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust.Modular;
using Debug = UnityEngine.Debug;
using Physics = UnityEngine.Physics;
using Time = UnityEngine.Time;
namespace Oxide.Plugins {
    [Info("Purchase Vehicles from the Shop", "M&B-Studios", "1.1.7")]
    class VehicleBuy : RustPlugin {
        private class LockedVehicleTracker {
            public Dictionary<VehicleInfo, HashSet<BaseEntity>> VehiclesWithLocksByType {
                get;
            }
            = new Dictionary<VehicleInfo, HashSet<BaseEntity>>();
            private readonly VehicleInfoManager _vehicleInfoManager;
            public LockedVehicleTracker(VehicleInfoManager vehicleInfoManager) {
                _vehicleInfoManager = vehicleInfoManager;
            }
            public void OnServerInitialized() {
                foreach (var entity in BaseNetworkable.serverEntities) {
                    var baseEntity = entity as BaseEntity;
                    if (baseEntity == null) continue;
                    var vehicleInfo = _vehicleInfoManager.GetVehicleInfo(baseEntity);
                    if (vehicleInfo == null || GetVehicleLock(baseEntity) == null) continue;
                    OnLockAdded(baseEntity);
                }
            }
            public void OnLockAdded(BaseEntity vehicle) {
                GetEntityListForVehicle(vehicle)?.Add(vehicle);
            }
            public void OnLockRemoved(BaseEntity vehicle) {
                GetEntityListForVehicle(vehicle)?.Remove(vehicle);
            }
            private HashSet<BaseEntity> EnsureEntityList(VehicleInfo vehicleInfo) {
                HashSet<BaseEntity> vehicleList;
                if (!VehiclesWithLocksByType.TryGetValue(vehicleInfo, out vehicleList)) {
                    vehicleList = new HashSet<BaseEntity>();
                    VehiclesWithLocksByType[vehicleInfo] = vehicleList;
                }
                return vehicleList;
            }
            private HashSet<BaseEntity> GetEntityListForVehicle(BaseEntity entity) {
                var vehicleInfo = _vehicleInfoManager.GetVehicleInfo(entity);
                if (vehicleInfo == null) return null;
                return EnsureEntityList(vehicleInfo);
            }
        }
        private const float MaxDeployDistance = 3;
        private class VehicleInfo {
            public string VehicleType;
            public string[] PrefabPaths;
            public Vector3 LockPosition;
            public Quaternion LockRotation;
            public string ParentBone;
            public string CodeLockPermission {
                get;
                private set;
            }
            public string KeyLockPermission {
                get;
                private set;
            }
            public uint[] PrefabIds {
                get;
                private set;
            }
            public Func<BaseEntity, BaseEntity> DetermineLockParent = (entity) => entity;
            public Func<BaseEntity, float> TimeSinceLastUsed = (entity) => 0;
            public void OnServerInitialized(VehicleBuy pluginInstance) {
                if (!pluginInstance.permission.PermissionExists(CodeLockPermission, pluginInstance)) pluginInstance.permission.RegisterPermission(CodeLockPermission, pluginInstance);
                if (!pluginInstance.permission.PermissionExists(KeyLockPermission, pluginInstance)) pluginInstance.permission.RegisterPermission(KeyLockPermission, pluginInstance);
                // Custom vehicles aren't currently allowed to specify prefabs since they reuse existing prefabs.if (PrefabPaths != null)
                {
                    var prefabIds = new List<uint>();
                    foreach (var prefabName in PrefabPaths) {
                        var prefabId = StringPool.Get(prefabName);
                        if (prefabId != 0) {
                            prefabIds.Add(prefabId);
                        }
                        else {
                        }
                    }
                    PrefabIds = prefabIds.ToArray();
                }
            }
            // In the future, custom vehicles may be able to pass in a method to override this.public bool IsMounted(BaseEntity entity)
            {
                var vehicle = entity as BaseVehicle;
                if (vehicle != null) return vehicle.AnyMounted();
                var mountable = entity as BaseMountable;
                if (mountable != null) return mountable.AnyMounted();
                return false;
            }
        }
        private class VehicleInfoManager {
            private readonly VehicleBuy _plugin;
            private readonly Dictionary<uint, VehicleInfo> _prefabIdToVehicleInfo = new Dictionary<uint, VehicleInfo>();
            private readonly Dictionary<string, VehicleInfo> _customVehicleTypes = new Dictionary<string, VehicleInfo>();
            public VehicleInfoManager(VehicleBuy plugin) {
                _plugin = plugin;
            }
            public void OnServerInitialized() {
                var allVehicles = new[] {
                    new VehicleInfo {
                        VehicleType = "attackhelicopter", PrefabPaths = new[] {
                            "assets/content/vehicles/attackhelicopter/attackhelicopter.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.6f, 1.08f, 1.01f), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as AttackHelicopter)?.lastEngineOnTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "chinook", PrefabPaths = new[] {
                            "assets/prefabs/npc/ch47/ch47.entity.prefab"
                        }
                        , LockPosition = new Vector3(-1.175f, 2, 6.5f), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as CH47Helicopter)?.lastPlayerInputTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "duosub", PrefabPaths = new[] {
                            "assets/content/vehicles/submarine/submarineduo.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.455f, 1.29f, 0.75f), LockRotation = Quaternion.Euler(0, 180, 10), TimeSinceLastUsed = (vehicle) => (vehicle as SubmarineDuo)?.timeSinceLastUsed ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "hotairballoon", PrefabPaths = new[] {
                            "assets/prefabs/deployable/hot air balloon/hotairballoon.prefab"
                        }
                        , LockPosition = new Vector3(1.45f, 0.9f, 0), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as HotAirBalloon)?.sinceLastBlast ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "kayak", PrefabPaths = new[] {
                            "assets/content/vehicles/boats/kayak/kayak.prefab"
                        }
                        , LockPosition = new Vector3(-0.43f, 0.2f, 0.2f), LockRotation = Quaternion.Euler(0, 90, 90), TimeSinceLastUsed = (vehicle) => (vehicle as Kayak)?.timeSinceLastUsed ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "locomotive", PrefabPaths = new[] {
                            "assets/content/vehicles/trains/locomotive/locomotive.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.11f, 2.89f, 4.95f), TimeSinceLastUsed = (vehicle) => (vehicle as TrainEngine)?.decayingFor ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "magnetcrane", PrefabPaths = new[] {
                            "assets/content/vehicles/crane_magnet/magnetcrane.entity.prefab"
                        }
                        , LockPosition = new Vector3(-1.735f, -1.445f, 0.79f), LockRotation = Quaternion.Euler(0, 0, 90), ParentBone = "Top", TimeSinceLastUsed = (vehicle) => Time.realtimeSinceStartup - (vehicle as MagnetCrane)?.lastDrivenTime ?? Time.realtimeSinceStartup,
                    }
                    , new VehicleInfo {
                        VehicleType = "minicopter", PrefabPaths = new[] {
                            "assets/content/vehicles/minicopter/minicopter.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.15f, 0.7f, -0.1f), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as Minicopter)?.lastEngineOnTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "modularcar",  // There are at least 37 valid Modular Car prefabs.PrefabPaths = FindPrefabsOfType<ModularCar>(),
                        LockPosition = new Vector3(-0.9f, 0.35f, -0.5f), DetermineLockParent = (vehicle) => FindFirstDriverModule((ModularCar)vehicle), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as ModularCar)?.lastEngineOnTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "rhib", PrefabPaths = new[] {
                            "assets/content/vehicles/boats/rhib/rhib.prefab"
                        }
                        , LockPosition = new Vector3(-0.68f, 2.00f, 0.7f), TimeSinceLastUsed = (vehicle) => (vehicle as RHIB)?.timeSinceLastUsedFuel ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "ridablehorse", PrefabPaths = new[] {
                            "assets/rust.ai/nextai/testridablehorse.prefab"
                        }
                        , LockPosition = new Vector3(-0.6f, 0.25f, -0.1f), LockRotation = Quaternion.Euler(0, 95, 90), ParentBone = "Horse_RootBone", TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as RidableHorse)?.lastInputTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "rowboat", PrefabPaths = new[] {
                            "assets/content/vehicles/boats/rowboat/rowboat.prefab"
                        }
                        , LockPosition = new Vector3(-0.83f, 0.51f, -0.57f), TimeSinceLastUsed = (vehicle) => (vehicle as MotorRowboat)?.timeSinceLastUsedFuel ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "scraptransport", PrefabPaths = new[] {
                            "assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab"
                        }
                        , LockPosition = new Vector3(-1.25f, 1.22f, 1.99f), TimeSinceLastUsed = (vehicle) => Time.time - (vehicle as ScrapTransportHelicopter)?.lastEngineOnTime ?? Time.time,
                    }
                    , new VehicleInfo {
                        VehicleType = "sedan", PrefabPaths = new[] {
                            "assets/content/vehicles/sedan_a/sedantest.entity.prefab"
                        }
                        , LockPosition = new Vector3(-1.09f, 0.79f, 0.5f),
                    }
                    , new VehicleInfo {
                        VehicleType = "sedanrail", PrefabPaths = new[] {
                            "assets/content/vehicles/sedan_a/sedanrail.entity.prefab"
                        }
                        , LockPosition = new Vector3(-1.09f, 1.025f, -0.26f), TimeSinceLastUsed = (vehicle) => (vehicle as TrainEngine)?.decayingFor ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "snowmobile", PrefabPaths = new[] {
                            "assets/content/vehicles/snowmobiles/snowmobile.prefab"
                        }
                        , LockPosition = new Vector3(-0.205f, 0.59f, 0.4f), TimeSinceLastUsed = (vehicle) => (vehicle as Snowmobile)?.timeSinceLastUsed ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "solosub", PrefabPaths = new[] {
                            "assets/content/vehicles/submarine/submarinesolo.entity.prefab"
                        }
                        , LockPosition = new Vector3(0f, 1.85f, 0f), LockRotation = Quaternion.Euler(0, 90, 90), TimeSinceLastUsed = (vehicle) => (vehicle as BaseSubmarine)?.timeSinceLastUsed ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "tomaha", PrefabPaths = new[] {
                            "assets/content/vehicles/snowmobiles/tomahasnowmobile.prefab"
                        }
                        , LockPosition = new Vector3(-0.37f, 0.4f, 0.125f), TimeSinceLastUsed = (vehicle) => (vehicle as Snowmobile)?.timeSinceLastUsed ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "tugboat", PrefabPaths = new[] {
                            "assets/content/vehicles/boats/tugboat/tugboat.prefab"
                        }
                        , LockPosition = new Vector3(0.065f, 6.8f, 4.12f), LockRotation = Quaternion.Euler(0, 90, 60), TimeSinceLastUsed = (vehicle) => (vehicle as Tugboat)?.timeSinceLastUsedFuel ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "workcart", PrefabPaths = new[] {
                            "assets/content/vehicles/trains/workcart/workcart.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.2f, 2.35f, 2.7f), TimeSinceLastUsed = (vehicle) => (vehicle as TrainEngine)?.decayingFor ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "workcartaboveground", PrefabPaths = new[] {
                            "assets/content/vehicles/trains/workcart/workcart_aboveground.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.2f, 2.35f, 2.7f), TimeSinceLastUsed = (vehicle) => (vehicle as TrainEngine)?.decayingFor ?? 0,
                    }
                    , new VehicleInfo {
                        VehicleType = "workcartcovered", PrefabPaths = new[] {
                            "assets/content/vehicles/trains/workcart/workcart_aboveground2.entity.prefab"
                        }
                        , LockPosition = new Vector3(-0.2f, 2.35f, 2.7f), TimeSinceLastUsed = (vehicle) => (vehicle as TrainEngine)?.decayingFor ?? 0,
                    }
                    ,
                }
                ;
                foreach (var vehicleInfo in allVehicles) {
                    vehicleInfo.OnServerInitialized(_plugin);
                    foreach (var prefabId in vehicleInfo.PrefabIds) {
                        _prefabIdToVehicleInfo[prefabId] = vehicleInfo;
                    }
                }
            }
            public void RegisterCustomVehicleType(VehicleBuy pluginInstance, VehicleInfo vehicleInfo) {
                vehicleInfo.OnServerInitialized(pluginInstance);
                _customVehicleTypes[vehicleInfo.VehicleType] = vehicleInfo;
            }
            public VehicleInfo GetVehicleInfo(BaseEntity entity) {
                VehicleInfo vehicleInfo;
                if (_prefabIdToVehicleInfo.TryGetValue(entity.prefabID, out vehicleInfo)) return vehicleInfo;
                foreach (var customVehicleInfo in _customVehicleTypes.Values) {
                    if (customVehicleInfo.DetermineLockParent(entity) != null) return customVehicleInfo;
                }
                return null;
            }
            public BaseEntity GetCustomVehicleParent(BaseEntity entity) {
                foreach (var vehicleInfo in _customVehicleTypes.Values) {
                    var lockParent = vehicleInfo.DetermineLockParent(entity);
                    if (lockParent != null) return lockParent;
                }
                return null;
            }
        }
        public class PlaceMonuments : FacepunchBehaviour {
            private BasePlayer Player {
                get;
                set;
            }
            private float NextTime {
                get;
                set;
            }
            private bool d = false;
            private void Awake() {
                Player = GetComponent<BasePlayer>();
            }
            private void Update() {
                if (!Player) {
                    return;
                }
                if (Player.serverInput.WasJustPressed(BUTTON.FIRE_PRIMARY)) {
                    if (NextTime > Time.time) {
                        return;
                    }
                    NextTime = Time.time + 1f;
                    Item activeItem = Player.GetActiveItem();
                    if (activeItem == null) return;
                    if (!Instance.cfg.Vehicles.Any(x => x.Value.Skin == activeItem.skin)) return;
                    var vehicle = Instance.cfg.Vehicles.FirstOrDefault(x => x.Value.Skin == activeItem.skin);
                    var depl = activeItem?.GetHeldEntity().GetComponent<Planner>();
                    if (depl == null) return;
                    var deployable = depl.GetModDeployable();
                    if (deployable == null) return;
                    var ent = GameManager.server.CreateEntity(deployable.entityPrefab.resourcePath);
                    if (!ent) return;
                    ent.Spawn();
                    ent.OwnerID = Player.userID;
                    ent.skinID = activeItem.skin;
                    ent.SendNetworkUpdateImmediate();
                    Interface.CallHook("OnEntityBuilt", Player.GetHeldEntity(), ent.transform.gameObject);
                    activeItem.UseItem(1);
                }
            }
            public void DoDestroy() {
                DestroyImmediate(this);
            }
        }
        private Dictionary<ulong, ulong> PRM = new();
        public static VehicleBuy Instance;
        internal class PlayerData {
            public Dictionary<string, int> Cooldowns = new();
        }
        internal struct VendingMachinePosition {
            public Vector3 Offset;
            public Transform transform;
            public Vector3 Rotation;
            public VendingMachinePosition(Transform position, Vector3 rotation, Vector3 offset) {
                this.transform = position;
                this.Rotation = rotation;
                this.Offset = offset;
            }
        }
        private Dictionary<ulong, PlayerData> _players = new();
        [PluginReference]
        private Plugin ImageLibrary, Economics, ServerRewards;
        private const string Prefab_CodeLock_DeployedEffect = "assets/prefabs/locks/keypad/effects/lock-code-deploy.prefab";
        private const string Prefab_CodeLock_DeniedEffect = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
        private const string Prefab_CodeLock_UnlockEffect = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab";
        private const string PERM_USE = "vehiclebuy.use";
        private const string PERM_PICKUP = "vehiclebuy.pickup";
        private const string PERM_RECALL = "vehiclebuy.recall";
        private const string PURCHASE_EFFECT = "assets/prefabs/deployable/vendingmachine/effects/vending-machine-purchase-human.prefab";
        private static readonly DateTime Epoch = new(1970, 1, 1, 0, 0, 0);
        private static int CurrentTime() => (int)DateTime.UtcNow.Subtract(Epoch).TotalSeconds;
        private readonly VehicleInfoManager _vehicleInfoManager;
        private readonly LockedVehicleTracker _lockedVehicleTracker;
        private List<BaseEntity> VendingMachines = new List<BaseEntity>();
        private VendingMachinePosition BANDITCAMP_POSITION;
        private VendingMachinePosition OUTPOST_POSITION;
        private VendingMachinePosition fvA_POSITION;
        private VendingMachinePosition fvB_POSITION;
        private VendingMachinePosition fvC_POSITION;
        private MonumentInfo Outpost;
        private MonumentInfo BanditCamp;
        private List<MonumentInfo> FishingVillagesA = new();
        private List<MonumentInfo> FishingVillagesB = new();
        private List<MonumentInfo> FishingVillagesC = new();
        private const string VENDINGMACHINE_PREFAB = @"assets/prefabs/deployable/vendingmachine/vendingmachine.deployed.prefab";
#region Base Hooks
        private bool CanPlayerBypassLock(BasePlayer player, BaseLock baseLock, bool provideFeedback) {
            var hookResult = Interface.CallHook("CanUseLockedEntity", player, baseLock);
            if (hookResult is bool) return (bool)hookResult;
            var canAccessLock = IsPlayerAuthorizedToLock(player, baseLock);
            if (canAccessLock) {
                if (provideFeedback && !(baseLock is KeyLock)) {
                    Effect.server.Run(Prefab_CodeLock_UnlockEffect, baseLock, 0, Vector3.zero, Vector3.forward);
                }
                return true;
            }
            if (provideFeedback) {
                Effect.server.Run(Prefab_CodeLock_DeniedEffect, baseLock, 0, Vector3.zero, Vector3.forward);
            }
            return false;
        }
        private static VehicleModuleSeating FindFirstDriverModule(ModularCar car) {
            for (int socketIndex = 0; socketIndex < car.TotalSockets; socketIndex++) {
                BaseVehicleModule module;
                if (car.TryGetModuleAt(socketIndex, out module)) {
                    var seatingModule = module as VehicleModuleSeating;
                    if (seatingModule != null && seatingModule.HasADriverSeat()) return seatingModule;
                }
            }
            return null;
        }
        public VehicleBuy() {
            _vehicleInfoManager = new VehicleInfoManager(this);
            _lockedVehicleTracker = new LockedVehicleTracker(_vehicleInfoManager);
        }
        private void OnServerInitialized() {
            Outpost = TerrainMeta.Path.Monuments.FirstOrDefault(p => p.name.ToLower().Contains("monument/medium/compound"));
            BanditCamp = TerrainMeta.Path.Monuments.FirstOrDefault(p => p.name.ToLower().Contains("monument/medium/bandit_town"));
            BANDITCAMP_POSITION = new VendingMachinePosition {
                Offset = new Vector3(-53.28f, 2f, 28.72f), transform = BanditCamp?.transform ?? null, Rotation = new Vector3(0, 51.4f, 0)
            }
            ;
            OUTPOST_POSITION = new VendingMachinePosition {
                Offset = new Vector3(32f, 1.51f, -15.34f), transform = Outpost?.transform ?? null, Rotation = new Vector3(0, 270f, 0)
            }
            ;
            fvA_POSITION = new() {
                Offset = new Vector3(1.2f, 2f, 4.48f), Rotation = new Vector3(0, 180f, 0)
            }
            ;
            fvB_POSITION = new() {
                Offset = new Vector3(-10.04f, 2f, 20.58f), Rotation = new Vector3(0, 270f, 0)
            }
            ;
            fvC_POSITION = new() {
                Offset = new Vector3(-8.72f, 2f, 12.23f), Rotation = new Vector3(0, 90f, 0)
            }
            ;
            var fvA = TerrainMeta.Path.Monuments.Where(p => p.name.ToLower().Contains("monument/fishing_village/fishing_village_a"));
            var fvB = TerrainMeta.Path.Monuments.Where(p => p.name.ToLower().Contains("monument/fishing_village/fishing_village_b"));
            var fvC = TerrainMeta.Path.Monuments.Where(p => p.name.ToLower().Contains("monument/fishing_village/fishing_village_c"));
            if (fvA.Any()) FishingVillagesA.AddRange(fvA);
            else {
                PrintError("Fishing villages A not found at map");
            }
            if (fvB.Any()) FishingVillagesB.AddRange(fvB);
            else {
                PrintError("Fishing villages B not found at map");
            }
            if (fvC.Any()) FishingVillagesC.AddRange(fvC);
            else {
                PrintError("Fishing villages C not found at map");
            }
            if (Outpost == null) {
                PrintError("Outpost not found at the map!");
            }
            if (BanditCamp == null) {
                PrintError("Bandit Camp not found at the map!");
            }
            permission.RegisterPermission(PERM_USE, this);
            permission.RegisterPermission(PERM_PICKUP, this);
            permission.RegisterPermission(PERM_RECALL, this);
            foreach (var x in cfg.Commands) cmd.AddChatCommand(x, this, cmdVehicleBuy);
            RegisterCommands();
            foreach (var x in cfg.Vehicles) {
                ImageLibrary.Call("AddImage", x.Value.Image, x.Key + ".image");
            }
            foreach (var x in cfg.Vehicles.Where(x => !string.IsNullOrEmpty(x.Value.Permission)).Select(x => x.Value.Permission)) {
                permission.RegisterPermission(x, this);
            }
            foreach (var x in BasePlayer.activePlayerList) x.gameObject.AddComponent<PlaceMonuments>();
            Instance = this;
            _vehicleInfoManager.OnServerInitialized();
            _lockedVehicleTracker.OnServerInitialized();
            foreach (var networkable in BaseNetworkable.serverEntities) {
                var entity = networkable as BaseEntity;
                if ((object)entity == null) continue;
                var vehicleInfo = _vehicleInfoManager.GetVehicleInfo(entity);
                if (vehicleInfo == null) continue;
                var lockEntity = GetVehicleLock(entity);
                if (lockEntity == null) continue;
                var transform = lockEntity.transform;
                transform.localPosition = vehicleInfo.LockPosition;
                transform.localRotation = vehicleInfo.LockRotation;
                lockEntity.SendNetworkUpdate_Position();
            }
            Subscribe(nameof(OnEntityKill));
            // timer.Once(10f, () =>
            // {
            SpawnVendingMachines();
            // });
        }
        private void Unload() {
            DestroyVendingMachines();
            foreach (var x in BasePlayer.activePlayerList) x.gameObject.GetComponent<PlaceMonuments>()?.DoDestroy();
            foreach (var basePlayer in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(basePlayer, Layer);
            }
            Instance = null;
        }
#endregion
#region Functions
        [ChatCommand("getposfva")]
        private void cmdGetPosfva(BasePlayer player) {
            if (!player.IsAdmin) return;
            var pos = player.GetNetworkPosition();
            var fva = FishingVillagesA.FirstOrDefault();
            // player.Teleport(fva.transform.position);
            player.ChatMessage($"Monument pos = {fva.transform.position}");
            player.ChatMessage($"Local to mon = {fva.transform.InverseTransformPoint(player.GetNetworkPosition())}");
            player.ChatMessage($"Global = X - {pos.x}, Y - {pos.y}, Z - {pos.z}");
            player.ChatMessage($"qu - {player.GetNetworkRotation()}");
        }
        [ChatCommand("getposfvb")]
        private void cmdGetPosfvb(BasePlayer player) {
            if (!player.IsAdmin) return;
            var pos = player.GetNetworkPosition();
            var fva = FishingVillagesB.FirstOrDefault();
            // player.Teleport(fva.transform.position);
            player.ChatMessage($"Monument pos = {fva.transform.position}");
            player.ChatMessage($"Local to mon = {fva.transform.InverseTransformPoint(player.GetNetworkPosition())}");
            player.ChatMessage($"Global = X - {pos.x}, Y - {pos.y}, Z - {pos.z}");
            player.ChatMessage($"qu - {player.GetNetworkRotation()}");
        }
        [ChatCommand("getposfvc")]
        private void cmdGetPosfvc(BasePlayer player) {
            if (!player.IsAdmin) return;
            var pos = player.GetNetworkPosition();
            var fva = FishingVillagesC.FirstOrDefault();
            // player.Teleport(fva.transform.position);
            player.ChatMessage($"Monument pos = {fva.transform.position}");
            player.ChatMessage($"Local to mon = {fva.transform.InverseTransformPoint(player.GetNetworkPosition())}");
            player.ChatMessage($"Global = X - {pos.x}, Y - {pos.y}, Z - {pos.z}");
            player.ChatMessage($"qu - {player.GetNetworkRotation()}");
        }
        [ChatCommand("getposoutpost")]
        private void cmdGetPosOP(BasePlayer player) {
            if (!player.IsAdmin) return;
            var pos = player.GetNetworkPosition();
            player.ChatMessage($"Monument pos = {Outpost.transform.position}");
            player.ChatMessage($"Local to mon = {Outpost.transform.InverseTransformPoint(player.GetNetworkPosition())}");
            player.ChatMessage($"Global = X - {pos.x}, Y - {pos.y}, Z - {pos.z}");
            player.ChatMessage($"qu - {player.GetNetworkRotation()}");
        }
        [ChatCommand("getposbandit")]
        private void cmdGetPosBC(BasePlayer player) {
            if (!player.IsAdmin) return;
            var pos = player.GetNetworkPosition();
            player.ChatMessage($"Monument pos = {BanditCamp.transform.position}");
            player.ChatMessage($"Local to mon = {BanditCamp.transform.InverseTransformPoint(player.GetNetworkPosition())}");
            player.ChatMessage($"Global = X - {pos.x}, Y - {pos.y}, Z - {pos.z}");
            player.ChatMessage($"qu - {player.GetNetworkRotation()}");
        }
        object OnGiveSoldItem(VendingMachine vending, Item soldItem, BasePlayer buyer) {
            if (!VMProducts.ContainsKey(vending.net.ID)) return null;
            var vmopt = VMProducts[vending.net.ID];
            if (!vmopt.Any(x => x.RandomShortname == soldItem.info.shortname)) return null;
            var item = vmopt.FirstOrDefault(x => x.RandomShortname == soldItem.info.shortname);
            var itemToGive = ItemManager.CreateByItemID(item.Get().DeployableItemId, soldItem.amount, item.Get().Skin);
            if (!string.IsNullOrEmpty(item.Get().Name)) itemToGive.name = item.Get().Name;
            buyer.GiveItem(itemToGive, BaseEntity.GiveItemReason.Generic);
            return false;
        }
        object CanAdministerVending(BasePlayer player, VendingMachine machine) {
            if (VMProducts.ContainsKey(machine.net.ID)) return false;
            return null;
        }
        private void SpawnVendingMachines() {
            if (cfg.VendingMachines.BanditCampSpawnMachine && BanditCamp) {
                var machine = SpawnVendingMachine(BANDITCAMP_POSITION);
                if (!machine.TryGetComponent<VendingMachine>(out var comp)) {
                    GameObject.Destroy(machine.gameObject);
                    return;
                }
                SetupVendingMachine(machine, comp, cfg.VendingMachines.BanditCampOrders);
            }
            if (cfg.VendingMachines.OutpostSpawnMachine && Outpost) {
                var machine = SpawnVendingMachine(OUTPOST_POSITION);
                // BasePlayer.activePlayerList.First().Teleport(machine.transform.position);
                if (!machine.TryGetComponent<VendingMachine>(out var comp)) {
                    GameObject.Destroy(machine.gameObject);
                    return;
                }
                SetupVendingMachine(machine, comp, cfg.VendingMachines.OutpostOrders);
            }
            if (cfg.VendingMachines.FishingVillageASpawnMachine && FishingVillagesA.Any()) {
                foreach (var x in FishingVillagesA) {
                    var machine = SpawnVendingMachine(fvA_POSITION, x.transform);
                    if (!machine.TryGetComponent<VendingMachine>(out var comp)) {
                        GameObject.Destroy(machine.gameObject);
                        return;
                    }
                    SetupVendingMachine(machine, comp, cfg.VendingMachines.FishingVillageAOrders);
                }
            }
            if (cfg.VendingMachines.FishingVillageBSpawnMachine && FishingVillagesB.Any()) {
                foreach (var x in FishingVillagesB) {
                    var machine = SpawnVendingMachine(fvB_POSITION, x.transform);
                    if (!machine.TryGetComponent<VendingMachine>(out var comp)) {
                        GameObject.Destroy(machine.gameObject);
                        return;
                    }
                    SetupVendingMachine(machine, comp, cfg.VendingMachines.FishingVillageBOrders);
                }
            }
            if (cfg.VendingMachines.FishingVillageBSpawnMachine && FishingVillagesB.Any()) {
                foreach (var x in FishingVillagesC) {
                    var machine = SpawnVendingMachine(fvC_POSITION, x.transform);
                    if (!machine.TryGetComponent<VendingMachine>(out var comp)) {
                        GameObject.Destroy(machine.gameObject);
                        return;
                    }
                    SetupVendingMachine(machine, comp, cfg.VendingMachines.FishingVillageCOrders);
                }
            }
        }
        private Effect reusableSoundEffectInstance = new Effect();
        private void SendEffect(BasePlayer player, string effect) {
            reusableSoundEffectInstance.Init(Effect.Type.Generic, player, 0, Vector3.zero, Vector3.forward, player.limitNetworking ? player.Connection : null);
            reusableSoundEffectInstance.pooledString = effect;
            if (string.IsNullOrEmpty(reusableSoundEffectInstance.pooledString)) {
                return;
            }
            if (player.limitNetworking) {
                EffectNetwork.Send(reusableSoundEffectInstance, player.Connection);
            }
            else EffectNetwork.Send(reusableSoundEffectInstance);
        }
        private void SetupVendingMachine(BaseEntity machine, VendingMachine comp, List<VMOrder> items) {
            comp.shopName = "VEHICLE SHOP";
            Dictionary<string, string> usedShortnames = new Dictionary<string, string>();
            foreach (var item in items) {
                if (!cfg.Vehicles.ContainsKey(item.VehicleKey)) continue;
                var vehicledef = ItemManager.FindItemDefinition(cfg.Vehicles[item.VehicleKey].Shortname);
                var pricedef = ItemManager.FindItemDefinition(item.Shortname);
                var randDef = ItemManager.itemList.FirstOrDefault(x => !usedShortnames.ContainsKey(x.shortname));
                usedShortnames.Add(randDef.shortname, item.VehicleKey);
                comp.sellOrders.sellOrders.Add(new ProtoBuf.VendingMachine.SellOrder {
                    itemToSellID = randDef.itemid, itemToSellAmount = 1, currencyID = pricedef.itemid, currencyAmountPerItem = item.Price, inStock = 10000, currencyIsBP = false, itemToSellIsBP = false, itemCondition = 100, itemConditionMax = 100
                }
                );
            }
            foreach (var x in usedShortnames) {
                var item = ItemManager.CreateByName(x.Key, 10000, cfg.Vehicles[x.Value].Skin);
                item.MoveToContainer(comp.inventory);
            }
            VMProducts.Add(machine.net.ID, usedShortnames.Select(x => new VendingMachineCache {
                RandomShortname = x.Key, VehicleKey = x.Value
            }
            ));
            VendingMachines.Add(machine);
        }
        internal class VendingMachineCache {
            public string RandomShortname;
            public string VehicleKey;
            public VehicleInfoConfig Get() => Instance.cfg.Vehicles[VehicleKey];
        }
        private Dictionary<NetworkableId, IEnumerable<VendingMachineCache>> VMProducts = new();
        private void DestroyVendingMachines() {
            VendingMachines.ForEach(x => x.Kill());
        }
        private BaseEntity SpawnVendingMachine(VendingMachinePosition position) => SpawnVendingMachine(position, position.transform);
        private BaseEntity SpawnVendingMachine(VendingMachinePosition position, Transform transform) {
            BaseEntity entity = (BaseEntity)GameManager.server.CreateEntity(VENDINGMACHINE_PREFAB, transform.TransformPoint(position.Offset));
            if (entity.TryGetComponent<StabilityEntity>(out var comp)) comp.grounded = true;
            entity.OwnerID = 92929294944;
            entity.Spawn();
            entity.transform.rotation = transform.rotation * Quaternion.Euler(position.Rotation);
            return entity;
        }
        private static string[] FindPrefabsOfType<T>() where T : BaseEntity {
            var prefabList = new List<string>();
            foreach (var assetPath in GameManifest.Current.entities) {
                var entity = GameManager.server.FindPrefab(assetPath)?.GetComponent<T>();
                if (entity == null) continue;
                prefabList.Add(entity.PrefabName);
            }
            return prefabList.ToArray();
        }
        private void SetCooldown(BasePlayer player, string key, int cooldownTime) {
            _players.TryAdd(player.userID, new PlayerData());
            _players[player.userID].Cooldowns.TryAdd(key, 0);
            _players[player.userID].Cooldowns[key] = CurrentTime() + cooldownTime;
        }
        private int GetCooldown(BasePlayer player, string key) {
            _players.TryAdd(player.userID, new PlayerData());
            if (_players[player.userID].Cooldowns.TryGetValue(key, out var cooldown)) return cooldown - CurrentTime();
            return -1;
        }
        private bool IsCooldown(BasePlayer player, string key) => GetCooldown(player, key) > 0;
        private int ItemsCount(BasePlayer player, string shortname) {
            return player.inventory.GetAmount(ItemManager.FindItemDefinition(shortname).itemid);
        }
        private bool CanBuy(BasePlayer player, VehicleInfoConfig product) {
            if (!player.IPlayer.HasPermission(PERM_USE)) return false;
            return product.SellCurrency switch {
                0 => ItemsCount(player, product.Shortname) >= product.Price, 1 => GetBalance(player, product) >= product.Price, 2 => GetBalance(player, product) >= product.Price, _ => false
            }
            ;
        }
        private bool Collect(BasePlayer player, VehicleInfoConfig product) {
            if (!CanBuy(player, product)) return false;
            switch (product.SellCurrency) {
                case 0 : player.inventory.Take(null, ItemManager.FindItemDefinition(product.Shortname).itemid, product.Price);
                return true;
                case 1 : Withdraw(player, product.Price, 1, product.Shortname);
                return true;
                case 2 : Withdraw(player, product.Price, product.SellCurrency, product.Shortname);
                return true;
                default : return false;
            }
        }
        private string GetRemainingCost(BasePlayer player, VehicleInfoConfig product) {
            return product.SellCurrency switch {
                0 => product.Price - ItemsCount(player, product.Shortname) + " " + ItemManager.FindItemDefinition(product.Shortname).displayName.english.ToUpper(), 1 => product.Price - GetBalance(player, product) + " " + cfg.CurrencyName, 2 => product.Price - GetBalance(player, product) + " " + cfg.CurrencyNameSR, _ => ""
            }
            ;
        }
        private int GetBalance(BasePlayer player, VehicleInfoConfig product) {
            if (product.SellCurrency == 1 && !Economics) {
                PrintError("Economics plugin is not available!");
                return -1;
            }
            if (product.SellCurrency == 2 && !ServerRewards) {
                PrintError("ServerRewards plugin is not available!");
                return -1;
            }
            return product.SellCurrency switch {
                0 => ItemsCount(player, product.Shortname), 1 => Convert.ToInt32(Economics?.Call<double>("Balance", player.userID.Get())), 2 => (int)ServerRewards?.Call("CheckPoints", player.userID.Get()), _ => throw new ArgumentOutOfRangeException()
            }
            ;
        }
        private void Withdraw(BasePlayer player, int price, int type, string shortname) {
            switch (type) {
                case 0 : if (string.IsNullOrEmpty(shortname)) {
                    PrintError("Shortname in 'Withdraw' is null!");
                    return;
                }
                player.inventory.Take(null, ItemManager.FindItemDefinition(shortname).itemid, price);
                break;
                case 1 : Economics?.Call("Withdraw", player.userID.Get(), (double)price);
                break;
                case 2 : ServerRewards?.Call("TakePoints", player.userID.Get(), price);
                break;
            }
        }
        private string GetCost(string key) {
            if (!cfg.Vehicles.ContainsKey(key)) return "";
            var product = cfg.Vehicles.FirstOrDefault(x => x.Key == key);
            switch (product.Value.SellCurrency) {
                case 0 : {
                    var itemDef = ItemManager.FindItemDefinition(product.Value.Shortname);
                    return itemDef == null ? "UNKNOWN ITEM" : $"{product.Value.Price} {itemDef.displayName.english.ToUpper()}";
                }
                case 1 : return $"{product.Value.Price} {cfg.CurrencyName}";
                case 2 : return $"{product.Value.Price} {cfg.CurrencyNameSR}";
                default : return "ERROR CHECK CFG";
            }
        }
        public void RegisterCommands() {
            foreach (var vehicle in cfg.Vehicles) {
                AddCovalenceCommand(vehicle.Value.Command, nameof(CmdAddVehicle));
            }
        }
        bool GiveVehicle(ItemContainer container, VehicleInfoConfig vehicleSettings, bool needFuel = true) {
            var item = ItemManager.CreateByItemID(vehicleSettings.DeployableItemId, 1, vehicleSettings.Skin);
            item.name = vehicleSettings.Name;
            return item.MoveToContainer(container, -1, false);
        }
        private void GetOutParts(ModularCar car) {
            foreach (var child in car.children) {
                var engineModule = child as VehicleModuleEngine;
                if (engineModule == null) continue;
                var engineStorage = engineModule.GetContainer() as EngineStorage;
                if (engineStorage == null) continue;
                engineStorage.inventory.Clear();
                engineStorage.SendNetworkUpdate();
            }
        }
        private void AddEngineParts(ModularCar car, List<string> shortnames) {
            foreach (var child in car.children) {
                var engineModule = child as VehicleModuleEngine;
                if (engineModule == null) continue;
                var engineStorage = engineModule.GetContainer() as EngineStorage;
                if (engineStorage == null || !engineStorage.inventory.IsEmpty()) continue;
                foreach (var x in shortnames) {
                    AddPartsToEngineStorage(engineStorage, x);
                }
                engineModule.RefreshPerformanceStats(engineStorage);
            }
        }
        private void AddPartsToEngineStorage(EngineStorage engineStorage, string shortname) {
            if (engineStorage.inventory == null) return;
            var inventory = engineStorage.inventory;
            for (var i = 0; i < inventory.capacity; i++) {
                var item = inventory.GetSlot(i);
                if (item != null) continue;
                // if (tier > 0)
                // {
                TryAddEngineItem(engineStorage, -1, shortname);
                // }
            }
        }
        private bool TryAddEngineItem(EngineStorage engineStorage, int slot, string shortname) {
            var component = ItemManager.FindItemDefinition(shortname);
            var item = ItemManager.Create(component);
            if (item == null) return false;
            item.MoveToContainer(engineStorage.inventory, slot, allowStack : false);
            return true;
        }
        bool GiveVehicle(BasePlayer player, VehicleInfoConfig vehicleSettings, bool needfuel = true) {
            var item = ItemManager.CreateByItemID(vehicleSettings.DeployableItemId, 1, vehicleSettings.Skin);
            item.name = vehicleSettings.Name + (needfuel ? "" : "   ");
            if (!player.inventory.GiveItem(item)) {
                item.Drop(player.inventory.containerMain.dropPosition, player.inventory.containerMain.dropVelocity, new Quaternion());
                return false;
            }
            return true;
        }
        private BaseEntity GetMinDistance(Vector3 position, IEnumerable<BaseEntity> entities) {
            BaseEntity result = null;
            float min = float.PositiveInfinity;
            BaseEntity[] ents = entities.ToArray();
            foreach (var t in ents) {
                var dist = Vector3.Distance(position, t.transform.position);
                if (dist < min) {
                    result = t;
                    min = dist;
                }
            }
            return result;
        }
        private bool HasInConfig(BaseEntity entity, string key) {
            return cfg.Vehicles.Any(x => x.Key == key && x.Value.Skin == entity.skinID && x.Value.Prefab == entity.PrefabName && x.Value.CanCallback);
        }
#endregion
#region UI
        private const string Layer = "ui.VehicleBuy.bg";
        private void UI_DrawMain(BasePlayer player) {
            var container = new CuiElementContainer();
            container.Add(new CuiPanel {
                CursorEnabled = true, Image = {
                    Color = "0.18 0.19 0.29 1.00", Material = "assets/icons/greyout.mat"
                }
                , RectTransform = {
                    AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-421.59 -233.87", OffsetMax = "421.59 233.43"
                }
            }
            , "Overlay", Layer);
            container.Add(new CuiButton {
                Button = {
                    Color = "0.50 0.50 1.00 1.00", Sprite = "assets/icons/close.png", Close = Layer
                }
                , Text = {
                    Text = ""
                }
                , RectTransform = {
                    AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "389.186 202.986", OffsetMax = "414 227.8"
                }
            }
            , Layer, Layer + ".close");
            CuiHelper.DestroyUi(player, Layer);
            CuiHelper.AddUi(player, container);
            UI_DrawVehicles(player);
            UI_DrawPages(player);
        }
        private int GetPages() => Mathf.CeilToInt(cfg.Vehicles.Count(x => x.Value.Show) / 8f);
        private void UI_DrawPages(BasePlayer player, int page = 0) {
            var container = new CuiElementContainer();
            container.Add(new CuiElement {
                Name = Layer + ".page.number", Parent = Layer, Components = {
  
// ... [Code preview truncated due to length. Full source in attached file] ...

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