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

FREE VehicleBuy : 2.1.16 2.1.16

Нет прав для скачивания
C#:
// #Requires: KaruzaVehiclesCommon

// #define TESTING

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.VehicleBuyExtensionMethods;
using Rust;
using Rust.Modular;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Physics = UnityEngine.Physics;
using Random = UnityEngine.Random;
using Time = UnityEngine.Time;

#if CARBON
using Carbon.Base;
using Carbon.Modules;
#endif

namespace Oxide.Plugins
{
    [Info("Vehicle Buy", "M&B-Studios & Mevent", "2.1.16")]
    internal class VehicleBuy : RustPlugin
    {
        private class LockedVehicleTracker
        {
            public Dictionary<VehicleInfo, HashSet<BaseEntity>> VehiclesWithLocksByType { get; } = new();

            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)
            {
                if (!VehiclesWithLocksByType.TryGetValue(vehicleInfo, out var 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; }
            public string KeyLockPermission { get; }
            public uint[] PrefabIds { get; private set; }

            public Func<BaseEntity, BaseEntity> DetermineLockParent = entity => entity;
            public Func<BaseEntity, float> TimeSinceLastUsed = entity => 0;

            public void OnServerInitialized()
            {
                if (!Instance.permission.PermissionExists(CodeLockPermission, Instance))
                    Instance.permission.RegisterPermission(CodeLockPermission, Instance);

                if (!Instance.permission.PermissionExists(KeyLockPermission, Instance))
                    Instance.permission.RegisterPermission(KeyLockPermission, Instance);

                // 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);
                    }

                    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 Dictionary<uint, VehicleInfo> _prefabIdToVehicleInfo = new();

            private readonly Dictionary<string, VehicleInfo>
                _customVehicleTypes = new();

            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/content/vehicles/horse/ridablehorse.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)?.lastRiddenTime ?? 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();
                    foreach (var prefabId in vehicleInfo.PrefabIds) _prefabIdToVehicleInfo[prefabId] = vehicleInfo;
                }
            }

            public void RegisterCustomVehicleType(VehicleInfo vehicleInfo)
            {
                vehicleInfo.OnServerInitialized();
                _customVehicleTypes[vehicleInfo.VehicleType] = vehicleInfo;
            }

            public VehicleInfo GetVehicleInfo(BaseEntity entity)
            {
                if (_prefabIdToVehicleInfo.TryGetValue(entity.prefabID, out var 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;
            }
        }

        internal struct VendingMachinePosition
        {
            public Vector3 Offset;
            public Transform transform;
            public Vector3 Rotation;

            public VendingMachinePosition(Transform position, Vector3 rotation, Vector3 offset)
            {
                transform = position;
                Rotation = rotation;
                Offset = offset;
            }
        }

        #region Fields

        [PluginReference] private Plugin ImageLibrary = null, Economics = null, ServerRewards = null, BankSystem = null, KaruzaVehicleItemManager = null, Notify = null, UINotify = null;

        private static VehicleBuy Instance;
        
#if CARBON
		private ImageDatabaseModule imageDatabase;
#endif

        private bool _enabledImageLibrary;

        private Dictionary<ulong, ulong> PRM = new();

        private const bool LangRu = false;
        
        private const string 
            Prefab_CodeLock_DeployedEffect = "assets/prefabs/locks/keypad/effects/lock-code-deploy.prefab", 
            Prefab_CodeLock_DeniedEffect = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", 
            Prefab_CodeLock_UnlockEffect = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab", 
            VENDINGMACHINE_PREFAB = "assets/prefabs/deployable/vendingmachine/vendingmachine.deployed.prefab";

        private const string 
            PERM_USE = "vehiclebuy.use", 
            PERM_FREE = "vehiclebuy.free", 
            PERM_PICKUP = "vehiclebuy.pickup", 
            PERM_RECALL = "vehiclebuy.recall";

        private const string PURCHASE_EFFECT =
            "assets/prefabs/deployable/vendingmachine/effects/vending-machine-purchase-human.prefab";

        private VehicleInfoManager _vehicleInfoManager;
        private LockedVehicleTracker _lockedVehicleTracker;
        private List<BaseEntity> VendingMachines = new();

        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();

        #endregion

        #region Data

        private Dictionary<ulong, PlayerData> _players = new();
        
        internal class PlayerData
        {
            public Dictionary<string, int> Cooldowns = new();
            
            public Dictionary<string, int> PurchasedVehicles = new Dictionary<string, int>();
        }

        #endregion
        
        #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 (var socketIndex = 0; socketIndex < car.TotalSockets; socketIndex++)
            {
                if (car.TryGetModuleAt(socketIndex, out var module))
                {
                    var seatingModule = module as VehicleModuleSeating;
                    if (seatingModule != null && seatingModule.HasADriverSeat())
                        return seatingModule;
                }
            }

            return null;
        }

        private void Init()
        {
            _vehicleInfoManager = new VehicleInfoManager();
            _lockedVehicleTracker = new LockedVehicleTracker(_vehicleInfoManager);
            
            if (!_config.DisableVehiclesDamage)
                Unsubscribe(nameof(OnEntityTakeDamage));
        }

        private void OnServerInitialized()
        {
            Outpost = TerrainMeta.Path.Monuments.Find(p =>
                p.name.ToLower().Contains("monument/medium/compound"));
            BanditCamp =
                TerrainMeta.Path.Monuments.Find(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 VendingMachinePosition
            {
                Offset = new Vector3(1.2f, 2f, 4.48f),
                Rotation = new Vector3(0, 180f, 0)
            };
            fvB_POSITION = new VendingMachinePosition
            {
                Offset = new Vector3(-10.04f, 2f, 20.58f),
                Rotation = new Vector3(0, 270f, 0)
            };
            fvC_POSITION = new VendingMachinePosition
            {
                Offset = new Vector3(-8.72f, 2f, 12.23f),
                Rotation = new Vector3(0, 90f, 0)
            };

            var fvA = TerrainMeta.Path.Monuments.FindAll(p =>
                p.name.ToLower().Contains("monument/fishing_village/fishing_village_a"));
            var fvB = TerrainMeta.Path.Monuments.FindAll(p =>
                p.name.ToLower().Contains("monument/fishing_village/fishing_village_b"));
            var fvC = TerrainMeta.Path.Monuments.FindAll(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!");

            RegisterPermissions();
            
            RegisterCommands();

            Instance = this;

            LoadSetupUI();
            
            LoadImages();
            
            _vehicleInfoManager.OnServerInitialized();
            _lockedVehicleTracker.OnServerInitialized();

            foreach (var entity in BaseNetworkable.serverEntities.OfType<BaseEntity>())
            {
                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));

            SpawnVendingMachines();
        }

        private void Unload()
        {
            try
            {
                DestroyVendingMachines();

                foreach (var player in BasePlayer.activePlayerList)
                {
                    CuiHelper.DestroyUi(player, Layer);
                    CuiHelper.DestroyUi(player, "UI.Server.Panel.Content");
                }
            }
            finally
            {
                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()}");
        }

        private 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);

            return false;
        }

        private object CanAdministerVending(BasePlayer player, VendingMachine machine)
        {
            if (VMProducts.ContainsKey(machine.net.ID))
                return false;
            return null;
        }

        private void SpawnVendingMachines()
        {
            if (_config.VendingMachines.BanditCampSpawnMachine && BanditCamp)
            {
                var machine = SpawnVendingMachine(BANDITCAMP_POSITION);
                if (machine != null)
                {

                    if (!machine.TryGetComponent<VendingMachine>(out var comp))
                    {
                        UnityEngine.Object.Destroy(machine.gameObject);
                        return;
                    }

                    SetupVendingMachine(machine, comp, _config.VendingMachines.BanditCampOrders);

                }
            }

            if (_config.VendingMachines.OutpostSpawnMachine && Outpost)
            {
                var machine = SpawnVendingMachine(OUTPOST_POSITION);

                if (machine != null)
                {
                    // BasePlayer.activePlayerList.First().Teleport(machine.transform.position);
                    if (!machine.TryGetComponent<VendingMachine>(out var comp))
                    {
                        UnityEngine.Object.Destroy(machine.gameObject);
                        return;
                    }

                    SetupVendingMachine(machine, comp, _config.VendingMachines.OutpostOrders);
                }
            }


            if (_config.VendingMachines.FishingVillageASpawnMachine && FishingVillagesA.Any())
                foreach (var x in FishingVillagesA)
                {
                    var machine = SpawnVendingMachine(fvA_POSITION, x.transform);

                    if (machine != null)
                    {
                        if (!machine.TryGetComponent<VendingMachine>(out var comp))
                        {
                            UnityEngine.Object.Destroy(machine.gameObject);
                            return;
                        }

                        SetupVendingMachine(machine, comp, _config.VendingMachines.FishingVillageAOrders);
                    }
                }

            if (_config.VendingMachines.FishingVillageBSpawnMachine && FishingVillagesB.Any())
                foreach (var x in FishingVillagesB)
                {
                    var machine = SpawnVendingMachine(fvB_POSITION, x.transform);

                    if (machine != null)
                    {
                        if (!machine.TryGetComponent<VendingMachine>(out var comp))
                        {
                            UnityEngine.Object.Destroy(machine.gameObject);
                            return;
                        }

                        SetupVendingMachine(machine, comp, _config.VendingMachines.FishingVillageBOrders);
                    }
                }

            if (_config.VendingMachines.FishingVillageBSpawnMachine && FishingVillagesB.Any())
                foreach (var x in FishingVillagesC)
                {
                    var machine = SpawnVendingMachine(fvC_POSITION, x.transform);

                    if (machine != null)
                    {
                        if (!machine.TryGetComponent<VendingMachine>(out var comp))
                        {
                            UnityEngine.Object.Destroy(machine.gameObject);
                            return;
                        }

                        SetupVendingMachine(machine, comp, _config.VendingMachines.FishingVillageCOrders);
                    }
                }
        }

        private static void SendEffect(BasePlayer player, string effect)
        {
            if (player == null || string.IsNullOrEmpty(effect)) return;
            
            Effect.server.Run(effect, player, 0, Vector3.zero, Vector3.forward);
        }

        private void SetupVendingMachine(BaseEntity machine, VendingMachine comp, List<VMOrder> items)
        {
            if (comp == null || items == null) return;


            comp.shopName = "VEHICLE SHOP";
            var usedShortnames = new Dictionary<string, string>();

            foreach (var item in items)
            {
                if (!_config.Vehicles.ContainsKey(item.VehicleKey))
                    continue;

                var pricedef = ItemManager.FindItemDefinition(item.Shortname);

                var randDef =
                    ItemManager.itemList.Find(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 (itemShortname, vehicle) in usedShortnames)
            {
                var item = ItemManager.CreateByName(itemShortname, 10000, _config.Vehicles[vehicle].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()
            {
                return Instance._config.Vehicles[VehicleKey];
            }
        }

        private Dictionary<NetworkableId, IEnumerable<VendingMachineCache>> VMProducts = new();

        private void DestroyVendingMachines()
        {
            VendingMachines?.ForEach(x => x.Kill());
        }

        private BaseEntity SpawnVendingMachine(VendingMachinePosition position)
        {
            return SpawnVendingMachine(position, position.transform);
        }

        private BaseEntity SpawnVendingMachine(VendingMachinePosition position, Transform transform)
        {
            var entity = 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 = Pool.Get<List<string>>();
            
            try
            {
                for (var i = 0; i < GameManifest.Current.entities.Length; i++)
                {
                    var entity = GameManager.server.FindPrefab(GameManifest.Current.entities[i])?.GetComponent<T>();
                    if (entity == null) continue;

                    prefabList.Add(entity.PrefabName);
                }

                return prefabList.ToArray();
            }
            finally
            {
                Pool.FreeUnmanaged(ref prefabList);
            }
        }

        private int GetVehiclePurchased(BasePlayer player, string key)
        {
            return _players.TryGetValue(player.userID, out var playerData) &&
                   playerData.PurchasedVehicles.TryGetValue(key, out var purchased)
                ? purchased
                : 0;
        }

        private void SetVehiclePurchased(BasePlayer player, string key)
        {
            _players.TryAdd(player.userID, new PlayerData());

            _players[player.userID].PurchasedVehicles.TryAdd(key, 0);

            _players[player.userID].PurchasedVehicles[key]++;
        }

        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] = Facepunch.Math.Epoch.Current + 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 - Facepunch.Math.Epoch.Current;

            return -1;
        }

        private bool IsCooldown(BasePlayer player, string key)
        {
            return 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, string key)
        {
            if (!permission.UserHasPermission(player.UserIDString, PERM_USE))
            {
                NotifyPlayer(player, NO_PERMISSION);
                return false;
            }

            if (product.MaxPurchases > 0 && GetVehiclePurchased(player, key) >= product.MaxPurchases)
            {
                NotifyPlayer(player, MAX_PURCHASES_EXCEEDED, 1, product.Shortname);
                return false;
            }
            
            if (permission.UserHasPermission(player.UserIDString, PERM_FREE)) return true;
            
            return product.SellCurrency switch
            {
                0 => ItemsCount(player, product.Shortname) >= product.Price,
                1 => GetBalance(player, product) >= product.Price,
                2 => GetBalance(player, product) >= product.Price,
                3 => GetBalance(player, product) >= product.Price,
                _ => false
            };
        }

        private bool Collect(BasePlayer player, VehicleInfoConfig product, string key)
        {
            if (!CanBuy(player, product, key))
                return false;

            switch (product.SellCurrency)
            {
                case 0:
                    player.inventory.Take(null, ItemManager.FindItemDefinition(product.Shortname).itemid,
                        product.Price);
                    return true;
                case 1:
                case 2:
                case 3:
                    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) + " " + _config.CurrencyName,
                2 => product.Price - GetBalance(player, product) + " " + _config.CurrencyNameSR,
                3 => product.Price - GetBalance(player, product) + " " + _config.CurrencyNameBS,
                _ => ""
            };
        }

        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;
            }

            if (product.SellCurrency == 3 && !BankSystem)
            {
                PrintError("BankSystem 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 => Convert.ToInt32(ServerRewards?.Call("CheckPoints", player.userID.Get())),
                3 => Convert.ToInt32(BankSystem?.Call("API_BankSystemBalance", 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;
                case 3:
                    BankSystem?.Call("API_BankSystemWithdraw", player.userID.Get(), price);
                    break;
            }
        }

        private string GetCost(string key)
        {
            if (!_config.Vehicles.ContainsKey(key))
                return "";

            var product = _config.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} {_config.CurrencyName}";
                case 2:
                    return $"{product.Value.Price} {_config.CurrencyNameSR}";
                case 3:
                    return $"{product.Value.Price} {_config.CurrencyNameBS}";
                default:
                    return "ERROR CHECK CFG";
            }
        }

        #region Working with Images

        private Dictionary<string, string> _loadedImages = new Dictionary<string, string>();
		
        private void AddImage(string url, string fileName, ulong imageId = 0)
        {
#if CARBON
			imageDatabase.Queue(true, new Dictionary<string, string>
			{
				[fileName] = url
			});
#else
            ImageLibrary?.Call("AddImage", url, fileName, imageId);
#endif
        }

        private string GetImage(string name)
        {
            if (_loadedImages.TryGetValue(name, out var imageID)) return imageID;
            
#if CARBON
			return imageDatabase.GetImageString(name);
#else
            return Convert.ToString(ImageLibrary?.Call("GetImage", name));
#endif
        }

        private bool HasImage(string name)
        {
#if CARBON
			return Convert.ToBoolean(imageDatabase.HasImage(name));
#else
            return Convert.ToBoolean(ImageLibrary?.Call("HasImage", name));
#endif
        }

        private void LoadImages()
        {
#if CARBON
			imageDatabase = BaseModule.GetModule<ImageDatabaseModule>();
#endif
			
            _enabledImageLibrary = true;

            var imagesList = new Dictionary<string, string>();

            foreach (var (prefab, vehicleSettings) in _config.Vehicles) 
                RegisterImage(ref imagesList, prefab + ".image", vehicleSettings.Image);
            
            foreach (var (name, url) in imagesList.ToArray())
            {
                if (!url.StartsWith("MeventImages/")) continue;
                
                LoadImageFromFS(name, url);

                imagesList.Remove(name);
            }
            
            if (imagesList.Count <= 0) return;

#if CARBON
            imageDatabase.Queue(false, imagesList);
#else
            timer.In(1f, () =>
            {
                if (ImageLibrary is not { IsLoaded: true })
                {
                    _enabledImageLibrary = false;

                    BroadcastILNotInstalled();
                    return;
                }

                ImageLibrary?.Call("ImportImageList", Title, imagesList, 0UL, true);
            });
#endif
        }

        private void RegisterImage(ref Dictionary<string, string> images, string name, string image)
        {
            if (string.IsNullOrEmpty(image) || string.IsNullOrEmpty(name)) return;

            images.TryAdd(name, image);
        }

        private void BroadcastILNotInstalled()
        {
            for (var i = 0; i < 5; i++) PrintError("IMAGE LIBRARY IS NOT INSTALLED.");
        }

        private void Lo
// ... [Code preview truncated due to length. Full source in attached file] ...

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