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

FREE CarTurrets : 1.6.3 1.6.3

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

namespace Oxide.Plugins
{
    [Info("Car Turrets", "WhiteThunder", "1.6.3")]
    [Description("Allows players to deploy auto turrets onto modular cars.")]
    internal class CarTurrets : CovalencePlugin
    {
        #region Fields

        [PluginReference]
        private readonly Plugin VehicleDeployedLocks;

        private Configuration _config;

        private const string PermissionDeployCommand = "carturrets.deploy.command";
        private const string PermissionDeployInventory = "carturrets.deploy.inventory";
        private const string PermissionFree = "carturrets.free";
        private const string PermissionControl = "carturrets.control";
        private const string PermissionRemoveAll = "carturrets.removeall";

        private const string PermissionLimit2 = "carturrets.limit.2";
        private const string PermissionLimit3 = "carturrets.limit.3";
        private const string PermissionLimit4 = "carturrets.limit.4";

        private const string PermissionSpawnWithCar = "carturrets.spawnwithcar";

        private const string PermissionAllModules = "carturrets.allmodules";
        private const string PermissionModuleFormat = "carturrets.{0}";

        private const string PrefabEntityAutoTurret = "assets/prefabs/npc/autoturret/autoturret_deployed.prefab";
        private const string PrefabEntityElectricSwitch = "assets/prefabs/deployable/playerioents/simpleswitch/switch.prefab";
        private const string PrefabEffectDeployAutoTurret = "assets/prefabs/npc/autoturret/effects/autoturret-deploy.prefab";
        private const string PrefabEffectCodeLockDenied = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";

        private const int ItemIdAutoTurret = -2139580305;

        private static readonly Vector3 TurretSwitchPosition = new Vector3(0, 0.36f, -0.32f);
        private static readonly Quaternion TurretBackwardRotation = Quaternion.Euler(0, 180, 0);
        private static readonly Quaternion TurretSwitchRotation = Quaternion.Euler(0, 180, 0);

        private readonly object False = false;

        private DynamicHookSubscriber<NetworkableId> _carTurretTracker;
        private ProtectionProperties ImmortalProtection;

        #endregion

        #region Hooks

        private void Init()
        {
            permission.RegisterPermission(PermissionDeployCommand, this);
            permission.RegisterPermission(PermissionDeployInventory, this);
            permission.RegisterPermission(PermissionFree, this);
            permission.RegisterPermission(PermissionControl, this);
            permission.RegisterPermission(PermissionRemoveAll, this);

            permission.RegisterPermission(PermissionLimit2, this);
            permission.RegisterPermission(PermissionLimit3, this);
            permission.RegisterPermission(PermissionLimit4, this);

            permission.RegisterPermission(PermissionSpawnWithCar, this);

            permission.RegisterPermission(PermissionAllModules, this);
            foreach (var moduleItemShortName in _config.ModulePositions.Keys)
            {
                permission.RegisterPermission(GetAutoTurretPermission(moduleItemShortName), this);
            }

            Unsubscribe(nameof(OnEntitySpawned));

            var dynamicHookNames = new List<string>()
            {
                nameof(OnItemDropped),
                nameof(OnEntityKill),
                nameof(OnSwitchToggle),
                nameof(OnSwitchToggled),
                nameof(OnTurretTarget),
            };

            if (_config.EnableTurretPickup)
            {
                Unsubscribe(nameof(CanPickupEntity));
                Unsubscribe(nameof(canRemove));
            }
            else
            {
                dynamicHookNames.Add(nameof(CanPickupEntity));
                dynamicHookNames.Add(nameof(canRemove));
            }

            if (!_config.OnlyPowerTurretsWhileEngineIsOn)
            {
                Unsubscribe(nameof(OnEngineStartFinished));
                Unsubscribe(nameof(OnEngineStopped));
                Unsubscribe(nameof(OnTurretStartup));
            }
            else
            {
                dynamicHookNames.Add(nameof(OnEngineStartFinished));
                dynamicHookNames.Add(nameof(OnEngineStopped));
                dynamicHookNames.Add(nameof(OnTurretStartup));
            }

            if (!_config.RequirePermissionToControl)
            {
                Unsubscribe(nameof(OnBookmarkControlStarted));
            }
            else
            {
                dynamicHookNames.Add(nameof(OnBookmarkControlStarted));
            }

            _carTurretTracker = new DynamicHookSubscriber<NetworkableId>(this, dynamicHookNames.ToArray());
            _carTurretTracker.UnsubscribeAll();
        }

        private void Unload()
        {
            if (ImmortalProtection != null)
            {
                UnityEngine.Object.Destroy(ImmortalProtection);
                ImmortalProtection = null;
            }
        }

        private void OnServerInitialized()
        {
            ImmortalProtection = ScriptableObject.CreateInstance<ProtectionProperties>();
            ImmortalProtection.name = "CarTurretsSwitchProtection";
            ImmortalProtection.Add(1);

            foreach (var car in BaseNetworkable.serverEntities.OfType<ModularCar>().ToArray())
            {
                
                foreach (var module in car.AttachedModuleEntities)
                {
                    var turret = GetModuleAutoTurret(module);
                    if (turret == null)
                        continue;

                    try { RefreshCarTurret(turret); } catch {}
                }

                if (_config.OnlyPowerTurretsWhileEngineIsOn)
                {
                    if (car.IsOn())
                    {
                        OnEngineStartFinished(car);
                    }
                    else
                    {
                        OnEngineStopped(car);
                    }
                }
            }

            if (_config.SpawnWithCarConfig.Enabled)
            {
                Subscribe(nameof(OnEntitySpawned));
            }
        }

        private void OnEntitySpawned(ModularCar car)
        {
            if (!ShouldSpawnTurretsWithCar(car))
                return;

            // Intentionally using both NextTick and Invoke.// Using NextTick to delay until the items have been added to the module inventory.// Using Invoke since that's what the game uses to delay spawning module entities.NextTick(() =>
            {
                if (car == null)
                    return;

                car.Invoke(() =>
                {
                    var ownerIdString = car.OwnerID != 0 ? car.OwnerID.ToString() : string.Empty;
                    var ownerPlayer = FindEntityOwner(car);

                    var allowedTurretsRemaining = GetCarAutoTurretLimit(car);
                    for (var i = 0; i < car.AttachedModuleEntities.Count && allowedTurretsRemaining > 0; i++)
                    {
                        var vehicleModule = car.AttachedModuleEntities[i];

                        Vector3 position;
                        if (!TryGetAutoTurretPositionForModule(vehicleModule, out position) ||
                            GetModuleAutoTurret(vehicleModule) != null ||
                            ownerIdString != string.Empty && !HasPermissionToVehicleModule(ownerIdString, vehicleModule) ||
                            UnityEngine.Random.Range(0, 100) >= GetAutoTurretChanceForModule(vehicleModule) ||
                            DeployWasBlocked(vehicleModule, ownerPlayer, automatedDeployment: true))
                            continue;

                        if (ownerPlayer == null)
                            DeployAutoTurret(car, vehicleModule, position);
                        else
                            DeployAutoTurretForPlayer(car, vehicleModule, position, ownerPlayer);

                        allowedTurretsRemaining--;
                    }
                }, 0);
            });
        }

        private object CanMoveItem(Item item, PlayerInventory playerInventory, ItemContainerId targetContainerId, int targetSlot, int amount)
        {
            if (item == null || playerInventory == null)
                return null;

            var basePlayer = playerInventory.baseEntity;
            if (basePlayer == null)
                return null;

            if (item.parent == null || item.parent.uid == targetContainerId)
                return null;

            if (playerInventory.loot.containers.Contains(item.parent))
            {
                // Player is moving an item from the loot panel.var fromCar = item.parent.entityOwner as ModularCar;
                if (fromCar == null)
                    return null;

                return HandleRemoveTurret(basePlayer, item, fromCar);
            }

            // Player is moving an item to the loot panel (module inventory is at position 1).var targetContainer = targetContainerId.Value != 0
                ? playerInventory.loot.FindContainer(targetContainerId)
                : (playerInventory.loot.containers != null && playerInventory.loot.containers.Count > 1 ? playerInventory.loot.containers[1] : null);

            var toCar = targetContainer?.entityOwner as ModularCar;
            if ((object)toCar == null)
                return null;

            return HandleAddTurret(basePlayer, item, toCar, targetContainer, targetSlot);
        }

        private object HandleAddTurret(BasePlayer basePlayer, Item item, ModularCar car, ItemContainer targetContainer, int targetSlot)
        {
            var player = basePlayer.IPlayer;

            var itemid = item.info.itemid;
            if (itemid != ItemIdAutoTurret)
                return null;

            // In case a future update or a plugin adds another storage container to the car.if (car.Inventory.ModuleContainer != targetContainer)
                return null;

            if (!player.HasPermission(PermissionDeployInventory))
            {
                ChatMessage(basePlayer, Lang.GenericErrorNoPermission);
                return null;
            }

            if (!VerifyCarHasAutoTurretCapacity(player, car, replyInChat: true))
                return null;

            if (targetSlot == -1)
            {
                targetSlot = FindFirstSuitableSocketIndex(car, basePlayer);
            }

            if (targetSlot == -1)
            {
                ChatMessage(basePlayer, Lang.DeployErrorNoSuitableModule);
                return null;
            }

            var moduleItem = targetContainer.GetSlot(targetSlot);
            if (moduleItem == null)
                return null;

            var vehicleModule = car.GetModuleForItem(moduleItem);
            if (vehicleModule == null)
                return null;

            if (!HasPermissionToVehicleModule(player.Id, vehicleModule))
            {
                ChatMessage(basePlayer, Lang.DeployErrorNoPermissionToModule);
                return null;
            }

            if (GetModuleAutoTurret(vehicleModule) != null)
            {
                ChatMessage(basePlayer, Lang.DeployErrorModuleAlreadyHasTurret);
                return null;
            }

            Vector3 position;
            if (!TryGetAutoTurretPositionForModule(vehicleModule, out position)
                || DeployWasBlocked(vehicleModule, basePlayer))
                return null;

            if (DeployAutoTurretForPlayer(car, vehicleModule, position, basePlayer, GetItemConditionFraction(item)) == null)
                return null;

            if (!player.HasPermission(PermissionFree))
            {
                UseItem(basePlayer, item);
            }

            return False;
        }

        private object HandleRemoveTurret(BasePlayer basePlayer, Item moduleItem, ModularCar car, ItemContainer targetContainer = null)
        {
            if (car.Inventory.ModuleContainer != moduleItem.parent)
                return null;

            var vehicleModule = car.GetModuleForItem(moduleItem);
            if (vehicleModule == null)
                return null;

            var autoTurret = GetModuleAutoTurret(vehicleModule);
            if (autoTurret == null)
                return null;

            if (_config.EnableTurretPickup && autoTurret.pickup.enabled)
            {
                if (autoTurret.pickup.requireEmptyInv && !autoTurret.inventory.IsEmpty() && !autoTurret.inventory.IsLocked())
                {
                    ChatMessage(basePlayer, Lang.RemoveErrorTurretHasItems);
                    return False;
                }

                var turretItem = ItemManager.CreateByItemID(ItemIdAutoTurret);
                if (turretItem == null)
                    return null;

                if (turretItem.info.condition.enabled)
                {
                    turretItem.condition = autoTurret.healthFraction * 100;
                }

                if (targetContainer == null)
                {
                    if (!basePlayer.inventory.GiveItem(turretItem))
                    {
                        turretItem.Remove();
                        return False;
                    }
                }
                else if (!turretItem.MoveToContainer(targetContainer))
                {
                    turretItem.Remove();
                    return False;
                }

                basePlayer.Command("note.inv", ItemIdAutoTurret, 1);
            }

            autoTurret.Kill();
            return null;
        }

        private void OnItemDropped(Item item, BaseEntity itemEntity)
        {
            if (item?.parent == null)
                return;

            var car = item.parent.entityOwner as ModularCar;
            if (car == null)
                return;

            if (item.info.GetComponent<ItemModVehicleModule>() == null)
                return;

            var vehicleModule = car.GetModuleForItem(item);
            if (vehicleModule == null)
                return;

            var autoTurret = GetModuleAutoTurret(vehicleModule);
            if (autoTurret == null)
                return;

            if (_config.EnableTurretPickup && autoTurret.pickup.enabled)
            {
                var turretItem = CreateItemFromAutoTurret(autoTurret);
                if (turretItem == null)
                    return;

                var rigidBody = itemEntity.GetComponent<Rigidbody>();
                turretItem.Drop(itemEntity.transform.position, rigidBody?.velocity ?? Vector3.zero, itemEntity.transform.rotation);
            }
        }

        // Automatically move a deployed turret when a module moves.// This is not done in the CanMoveItem hook since we don't know if it's being moved yet.private void OnEntityKill(BaseVehicleModule vehicleModule)
        {
            var moduleItem = vehicleModule.AssociatedItemInstance;
            if (moduleItem == null)
                return;

            var car = vehicleModule.Vehicle as ModularCar;
            if (car == null)
                return;

            var autoTurret = GetModuleAutoTurret(vehicleModule);
            if (autoTurret == null)
                return;

            autoTurret.SetParent(null);

            var moduleItem2 = moduleItem;
            var car2 = car;
            var autoTurret2 = autoTurret;

            NextTick(() =>
            {
                if (car2 == null)
                {
                    autoTurret2.Kill();
                }
                else
                {
                    var newModule = car2.GetModuleForItem(moduleItem2);
                    if (newModule == null)
                    {
                        autoTurret2.Kill();
                    }
                    else
                    {
                        autoTurret2.SetParent(newModule);
                    }
                }
            });
        }

        private void OnEntityKill(AutoTurret turret)
        {
            _carTurretTracker.Remove(turret.net.ID);
        }

        private object OnSwitchToggle(ElectricSwitch electricSwitch, BasePlayer player)
        {
            var turret = GetParentTurret(electricSwitch);
            if (turret == null)
                return null;

            var vehicleModule = GetParentVehicleModule(turret);
            if (vehicleModule == null)
                return null;

            var car = vehicleModule.Vehicle as ModularCar;
            if (car == null)
                return null;

            if (!player.CanBuild())
            {
                // Disallow switching the turret on and off while building blocked.Effect.server.Run(PrefabEffectCodeLockDenied, electricSwitch, 0, Vector3.zero, Vector3.forward);
                return False;
            }

            return null;
        }

        private void OnSwitchToggled(ElectricSwitch electricSwitch, BasePlayer player)
        {
            var turret = GetParentTurret(electricSwitch);
            if (turret == null)
                return;

            var vehicleModule = GetParentVehicleModule(turret);
            if (vehicleModule == null)
                return;

            var car = vehicleModule.Vehicle as ModularCar;
            if (car == null)
                return;

            if (electricSwitch.IsOn())
            {
                if (_config.OnlyPowerTurretsWhileEngineIsOn && !car.IsOn())
                {
                    ChatMessage(player, Lang.InfoPowerRequiresEngine);
                }
                else
                {
                    try { turret.InitiateStartup(); } catch {}
                }
            }
            else
            {
                try { turret.InitiateShutdown(); } catch {}
            }
        }

        private object OnTurretTarget(AutoTurret turret, BaseCombatEntity target)
        {
            if (turret == null || target == null || GetParentVehicleModule(turret) == null)
                return null;

            if (!_config.TargetAnimals && target is BaseAnimalNPC)
                return False;

            var basePlayer = target as BasePlayer;
            if (basePlayer != null)
            {
                if (!_config.TargetNPCs && basePlayer.IsNpc)
                    return False;

                if (!_config.TargetPlayers && basePlayer.userID.IsSteamId())
                    return False;

                // Don't target human or NPC players in safe zones, unless they are hostile.if (basePlayer.InSafeZone() && (basePlayer.IsNpc || !basePlayer.IsHostile()))
                    return False;

                return null;
            }

            return null;
        }

        private void OnBookmarkControlStarted(ComputerStation station, BasePlayer player, string bookmarkName, AutoTurret turret)
        {
            var vehicleModule = GetParentVehicleModule(turret);
            if (vehicleModule == null)
                return;

            if (!RCUtils.HasController(turret, player))
                return;

            if (!HasPermissionToControl(player))
            {
                RCUtils.RemoveController(turret);
                RCUtils.AddFakeViewer(turret);
                RCUtils.AddViewer(turret, player);
                RCUtils.RemoveController(turret);
                station.SetFlag(ComputerStation.Flag_HasFullControl, false);
            }
        }

        // This is only subscribed while config option EnableTurretPickup is false.private object CanPickupEntity(BasePlayer player, AutoTurret turret)
        {
            if (GetParentVehicleModule(turret) != null)
                return False;

            return null;
        }

        // This hook is exposed by plugin: Remover Tool (RemoverTool).// Only subscribed while config option EnableTurretPickup is false.private object canRemove(BasePlayer player, AutoTurret turret)
        {
            if (GetParentVehicleModule(turret) != null)
                return False;

            return null;
        }

        // This is only subscribed while OnlyPowerTurretsWhileEngineIsOn is true.private void OnEngineStartFinished(ModularCar car)
        {
            foreach (var module in car.AttachedModuleEntities)
            {
                var turret = GetModuleAutoTurret(module);
                if (turret == null || turret.booting || turret.IsOn())
                    continue;

                var electricSwitch = GetTurretSwitch(turret);
                if (electricSwitch == null || !electricSwitch.IsOn())
                    continue;

                try { turret.InitiateStartup(); } catch {}
            }
        }

        // This is only subscribed while OnlyPowerTurretsWhileEngineIsOn is true.private void OnEngineStopped(ModularCar car)
        {
            foreach (var module in car.AttachedModuleEntities)
            {
                var turret = GetModuleAutoTurret(module);
                if (turret == null || !turret.booting && !turret.IsOn())
                    continue;

                var electricSwitch = GetTurretSwitch(turret);
                if (electricSwitch == null)
                    continue;

                try { turret.InitiateShutdown(); } catch {}
            }
        }

        // This is only subscribed while OnlyPowerTurretsWhileEngineIsOn is true.private object OnTurretStartup(AutoTurret turret)
        {
            var module = GetParentVehicleModule(turret);
            if (module == null)
                return null;

            var car = module.Vehicle as ModularCar;
            if (car == null)
                return null;

            if (!car.IsOn())
                return False;

            return null;
        }

        #endregion

        #region API

        [HookMethod(nameof(API_DeployAutoTurret))]
        public AutoTurret API_DeployAutoTurret(BaseVehicleModule vehicleModule, BasePlayer basePlayer)
        {
            var car = vehicleModule.Vehicle as ModularCar;
            if (car == null)
                return null;

            Vector3 position;
            if (!TryGetAutoTurretPositionForModule(vehicleModule, out position) ||
                GetModuleAutoTurret(vehicleModule) != null ||
                DeployWasBlocked(vehicleModule, basePlayer))
                return null;

            return basePlayer == null
                ? DeployAutoTurret(car, vehicleModule, position)
                : DeployAutoTurretForPlayer(car, vehicleModule, position, basePlayer);
        }

        #endregion

        private object OnEntityUse(BaseEntity entity, BasePlayer player)
        {
            if (player == null || entity == null)
                return null;

            // If a seat was directly used, try mounting it first to prevent engine UI from opening.var directSeat = entity as BaseMountable;
            if (directSeat != null)
            {
                if (!directSeat.IsMounted())
                {
                    try
                    {
                        directSeat.MountPlayer(player);
                        if (player.isMounted)
                            return False;
                    }
                    catch {}
                }
            }

            ModularCar car = entity as ModularCar;
            if (car == null)
            {
                var module = entity as BaseVehicleModule;
                car = module != null ? module.Vehicle as ModularCar : null;
            }

            if (car == null)
                return null;

            // Try to mount the closest available seat to the player's aim to prioritize entering over opening engine UI
            try
            {
                // First, raycast to detect a seat or car surface under the crosshair (e.g., when clicking the door area)
                var headRay = player.eyes.HeadRay();
                RaycastHit hitInfo;
                if (Physics.Raycast(headRay, out hitInfo, 5f, Physics.DefaultRaycastLayers, QueryTriggerInteraction.Collide))
                {
                    var hitEntity = hitInfo.GetEntity();
                    var hitSeat = hitEntity as BaseMountable ?? hitInfo.collider?.GetComponentInParent<BaseMountable>();
                    if (hitSeat != null && !hitSeat.IsMounted())
                    {
                        hitSeat.MountPlayer(player);
                        if (player.isMounted)
                            return False;
                    }

                    // If we clicked the car/module (e.g., door), choose the nearest seat to the hit point
                    if (hitEntity is ModularCar || hitEntity is BaseVehicleModule)
                    {
                        BaseMountable nearestToDoor = null;
                        float nearestDist = float.MaxValue;
                        var seats = car.GetComponentsInChildren<BaseMountable>();
                        foreach (var seat in seats)
                        {
                            if (seat == null || !seat.isActiveAndEnabled || seat.IsMounted())
                                continue;

                            var dist = Vector3.Distance(seat.CenterPoint(), hitInfo.point);
                            if (dist < nearestDist)
                            {
                                nearestDist = dist;
                                nearestToDoor = seat;
                            }
                        }

                        if (nearestToDoor != null)
                        {
                            nearestToDoor.MountPlayer(player);
                            if (player.isMounted)
                                return False;
                        }
                    }
                }

                headRay = player.eyes.HeadRay();
                BaseMountable bestSeat = null;
                float bestDistance = float.MaxValue;

                var allSeats = car.GetComponentsInChildren<BaseMountable>();
                foreach (var seat in allSeats)
                {
                    if (seat == null || !seat.isActiveAndEnabled || seat.IsMounted())
                        continue;

                    var distance = Vector3.Cross(headRay.direction, seat.CenterPoint() - headRay.origin).magnitude;
                    if (distance < bestDistance)
                    {
                        bestDistance = distance;
                        bestSeat = seat;
                    }
                }

                if (bestSeat != null)
                {
                    bestSeat.MountPlayer(player);
                    if (player.isMounted)
                        return False;
                }
            }
            catch { }

            return null;
        }

        #region Commands

        [Command("carturret")]
        private void CommandDeploy(IPlayer player, string cmd, string[] args)
        {
            if (player.IsServer || !VerifyPermissionAny(player, PermissionDeployCommand))
                return;

            var basePlayer = player.Object as BasePlayer;
            ModularCar car;
            BaseVehicleModule vehicleModule;

            if (!VerifyCanBuild(player) ||
                !VerifyVehicleModuleFound(player, out car, out vehicleModule) ||
                !CanAccessVehicle(car, basePlayer) ||
                !VerifyCarHasAutoTurretCapacity(player, car) ||
                !VerifyPermissionToModule(player, vehicleModule))
                return;

            if (GetModuleAutoTurret(vehicleModule) != null)
            {
                ReplyToPlayer(player, Lang.DeployErrorModuleAlreadyHasTurret);
                return;
            }

            Vector3 position;
            if (!TryGetAutoTurretPositionForModule(vehicleModule, out position))
            {
                ReplyToPlayer(player, Lang.DeployErrorUnsupportedModule);
                return;
            }

            Item autoTurretItem = null;
            var conditionFraction = 1.0f;

            var isFree = player.HasPermission(PermissionFree);
            if (!isFree)
            {
                autoTurretItem = FindPlayerAutoTurretItem(basePlayer);
                if (autoTurretItem == null)
                {
                    ReplyToPlayer(player, Lang.DeployErrorNoTurret);
                    return;
                }

                conditionFraction = GetItemConditionFraction(autoTurretItem);
            }

            if (DeployWasBlocked(vehicleModule, basePlayer))
                return;

            if (DeployAutoTurretForPlayer(car, vehicleModule, position, basePlayer, conditionFraction) != null && !isFree && autoTurretItem != null)
            {
                UseItem(basePlayer, autoTurretItem);
            }
        }

        [Command("carturrets.removeall")]
        private void CommandRemoveAllCarTurrets(IPlayer player, string cmd, string[] args)
        {
            if (!player.IsServer && !VerifyPermissionAny(player, PermissionRemoveAll))
                return;

            var turretsRemoved = 0;
            foreach (var turret in BaseNetworkable.serverEntities.OfType<AutoTurret>().ToArray())
            {
                if (turret.GetParentEntity() is BaseVehicleModule)
                {
                    turret.Kill();
                    turretsRemoved++;
                }
            }

            ReplyToPlayer(player, Lang.RemoveAllSuccess, turretsRemoved);
        }

        #endregion

        #region Helper Methods - Command Checks

        private bool VerifyPermissionAny(IPlayer player, params string[] permissionNames)
        {
            foreach (var perm in permissionNames)
            {
                if (player.HasPermission(perm))
                    return true;
            }

            ReplyToPlayer(player, Lang.GenericErrorNoPermission);
            return false;
        }

        private bool VerifyCanBuild(IPlayer player)
        {
            if ((player.Object as BasePlayer).CanBuild())
                return true;

            ReplyToPlayer(player, Lang.GenericErrorBuildingBlocked);
            return false;
        }

        private bool VerifyVehicleModuleFound(IPlayer player, out ModularCar car, out BaseVehicleModule vehicleModule)
        {
            var basePlayer = player.Object as BasePlayer;
            var entity = GetLookEntity(basePlayer);

            vehicleModule = entity as BaseVehicleModule;
            if (vehicleModule != null)
            {
                car = vehicleModule.Vehicle as ModularCar;
                if (car != null)
                    return true;

                ReplyToPlayer(player, Lang.DeployErrorNoCarFound);
                return false;
            }

            car = entity as ModularCar;
            if (car == null)
            {
                var lift = entity as ModularCarGarage;
                car = lift?.carOccupant;
                if (car == null)
                {
                    ReplyToPlayer(player, Lang.DeployErrorNoCarFound);
                    return false;
                }
            }

            var closestModule = FindClosestModuleToAim(car, basePlayer);
            if (closestModule != null)
            {
                vehicleModule = closestModule;
                return true;
            }

            ReplyToPlayer(player, Lang.DeployErrorNoModules);
            return false;
        }

        private bool VerifyCarHasAutoTurretCapacity(IPlayer player, ModularCar car, bool replyInChat = false)
        {
            var limit = GetCarAutoTurretLimit(car);
            if (GetCarTurretCount(car) < limit)
                return true;

            if (replyInChat)
            {
                ChatMessage(player.Object as BasePlayer, Lang.DeployErrorTurretLimit, limit);
            }
            else
            {
                ReplyToPlayer(player, Lang.DeployErrorTurretLimit, limit);
            }

            return false;
        }

        private bool VerifyPermissionToModule(IPlayer player, BaseVehicleModule vehicleModule)
        {
            if (HasPermissionToVehicleModule(player.Id, vehicleModule))
                return true;

            ReplyToPlayer(player, Lang.DeployErrorNoPermissionToModule);
            return false;
        }

        #endregion

        #region Helpers

        private static class RCUtils
        {
            public static bool HasController(IRemoteControllable controllable, BasePlayer player)
            {
                return controllable.ControllingViewerId?.SteamId == player.userID;
            }

            public static void RemoveController(IRemoteControllable controllable)
            {
                var controllerId = controllable.ControllingViewerId;
                if (controllerId.HasValue)
                {
                    controllable.StopControl(controllerId.Value);
                }
            }

            public static bool AddViewer(IRemoteControllable controllable, BasePlayer player)
            {
                return controllable.InitializeControl(new CameraViewerId(player.userID, 0));
            }

            public static bool AddFakeViewer(IRemoteControllable controllable)
            {
                return controllable.InitializeControl(new CameraViewerId());
            }
        }

        private static bool DeployWasBlocked(BaseVehicleModule vehicleModule, BasePlayer basePlayer, bool automatedDeployment = false)
        {
            var hookResult = Interface.CallHook("OnCarAutoTurretDeploy", vehicleModule, basePlayer, automatedDeployment);
            return hookResult is bool && (bool)hookResult == false;
        }

        private static BaseVehicleModule FindClosestModuleToAim(ModularCar car, BasePlayer basePlayer)
        {
            var headRay = basePlayer.eyes.HeadRay();

            BaseVehicleModule closestModule = null;
            float closestDistance = 0;

            for (var socketIndex = 0; socketIndex < car.TotalSockets; socketIndex++)
            {
                BaseVehicleModule currentModule;
                if (car.TryGetModuleAt(socketIndex, out currentModule) && currentModule.FirstSocketIndex == socketIndex)
                {
                    var currentDistance = Vector3.Cross(headRay.direction, currentModule.CenterPoint() - headRay.origin).magnitude;
                    if (ReferenceEquals(closestModule, null))
                    {
                        closestModule = currentModule;
                        closestDistance = currentDistance;
                    }
                    else if (currentDistance < closestDistance)
                    {
                        closestModule = currentModule;
                        closestDistance = currentDistance;
                    }
                }
            }

            return closestModule;
        }

        private static void UseItem(BasePlayer basePlayer, Item item, int amountToConsume = 1)
        {
            item.amount -= amountToConsume;
            if (item.amount <= 0)
            {
                item.RemoveFromContainer();
                item.Remove();
            }
            else
            {
                item.MarkDirty();
            }

            basePlayer.Command("note.inv", item.info.itemid, -amountToConsume);
        }

        private static float GetItemConditionFraction(Item item)
        {
            return item.hasCondition ? item.condition / item.info.condition.max : 1.0f;
        }

        private static Item FindPlayerAutoTurretItem(BasePlayer basePlayer)
        {
            return basePlayer.inventory.FindItemByItemID(ItemIdAutoTurret);
        }

        private static Item CreateItemFromAutoTurret(AutoTurret autoTurret)
        {
            var turretItem = ItemManager.CreateByItemID(ItemIdAutoTurret);
            if (turretItem == null)
                return null;

            if (turretItem.info.condition.enabled)
            {
                turretItem.condition = autoTurret.healthFraction * 100;
            }

            return turretItem;
        }

        private static string GetAutoTurretPermissionForModule(BaseVehicleModule vehicleModule)
        {
            return GetAutoTurretPermission(vehicleModule.AssociatedItemDef.shortname);
        }

        private static string GetAutoTurretPermission(string moduleItemShortName)
        {
            return string.Format(PermissionModuleFormat, moduleItemShortName);
        }

        private static int GetCarTurretCount(ModularCar car)
        {
            var numTurrets = 0;
            foreach (var module in car.AttachedModuleEntities)
            {
                var turret = GetModuleAutoTurret(module);
                if (turret != null)
                {
                    numTurrets++;
                }
            }

            return numTurrets;
        }

        private static T GetChildOfType<T>(BaseEntity entity) where T : BaseEntity
        {
            foreach (var child in entity.children)
            {
                var childOfType = child as T;
                if (childOfType != null)
                    return childOfType;
            }

            return null;
        }

        private static AutoTurret GetModuleAutoTurret(BaseVehicleModule vehicleModule)
        {
            return GetChildOfType<AutoTurret>(vehicleModule);
        }

        private static ElectricSwitch GetTurretSwitch(AutoTurret turret)
        {
            return GetChildOfType<ElectricSwitch>(turret);
        }

        private static bool IsNaturalCarSpawn(ModularCar car)
        {
            var spawnable = car.GetComponent<Spawnable>();
            return spawnable != null && spawnable.Population != null;
        }

        private static BaseVehicleModule GetParentVehicleModule(BaseEntity entity)
        {
            return entity.GetParentEntity() as BaseVehicleModule;
        }

        private static AutoTurret GetParentTurret(BaseEntity entity)
        {
            return entity.GetParentEntity() as AutoTurret;
        }

        private static void RunOnEntityBuilt(Item turretItem, AutoTurret autoTurret)
        {
            Interface.CallHook("OnEntityBuilt", turretItem.GetHeldEntity(), autoTurret.gameObject);
        }

        private static void HideInputsAndOutputs(IOEntity ioEntity)
        {
            // Hide the inputs and outputs on the client.foreach (var input in ioEntity.inputs)
            {
                input.type = IOEntity.IOType.Generic;
            }

            foreach (var output in ioEntity.outputs)
            {
                output.type = IOEntity.IOType.Generic;
            }
        }

        private static Quaternion GetIdealTurretRotation(ModularCar car, BaseVehicleModule vehicleModule)
        {
            var lastSocketIndex = vehicleModule.FirstSocketIndex + vehicleModule.GetNumSocketsTaken() - 1;

            var faceForward = car.TotalSockets == 2
                ? vehicleModule.FirstSocketIndex == 0
                : car.TotalSockets == 3
                ? lastSocketIndex <= 1
                : vehicleModule.FirstSocketIndex <= 1;

            return faceForward ? Quaternion.identity : TurretBackwardRotation;
        }

        private static void RemoveColliders<T>(BaseEntity entity) where T : Collider
        {
            foreach (var collider in entity.GetComponentsInChildren<T>())
            {
                UnityEngine.Object.DestroyImmediate(collider);
            }
        }

        private static void RemoveGroundWatch(BaseEntity entity)
        {
            UnityEngine.Object.DestroyImmediate(entity.GetComponent<DestroyOnGroundMissing>());
            UnityEngine.Object.DestroyImmediate(entity.GetComponent<GroundWatch>());
        }

        private static BaseEntity GetLookEntity(BasePlayer basePlayer, float maxDistance = 3)
        {
            RaycastHit hit;
            return Physics.Raycast(basePlayer.eyes.HeadRay(), out hit, maxDistance, Physics.DefaultRaycastLayers, QueryTriggerInteraction.Ignore)
                ? hit.GetEntity()
                : null;
        }

        private static BasePlayer FindEntityOwner(BaseEntity entity)
        {
            return entity.OwnerID != 0 ? BasePlayer.FindByID(entity.OwnerID) : null;
        }

        private bool HasPermissionToControl(BasePlayer player)
        {
            if (!_config.RequirePermissionToControl)
                return true;

            return permission.UserHasPermission(player.UserIDString, PermissionControl);
        }

        private void SetupCarTurret(AutoTurret turret)
        {
            turret.gameObject.layer = (int)Rust.Layer.Vehicle_Detailed;
            RemoveColliders<MeshCollider>(turret);
            RemoveGroundWatch(turret);
            _carTurretTracker.Add(turret.net.ID);
        }

        private AutoTurret DeployAutoTurret(ModularCar car, BaseVehicleModule vehicleModule, Vector3 position, float conditionFraction = 1, ulong ownerId = 0)
        {
            var autoTurret = GameManager.server.CreateEntity(PrefabEntityAutoTurret, position, GetIdealTurretRotation(car, vehicleModule)) as AutoTurret;
            if (autoTurret == null)
                return null;

            try
            {
                autoTurret.SetFlag(IOEntity.Flag_HasPower, true);
                autoTurret.SetParent(vehicleModule);
                autoTurret.OwnerID = ownerId;
                autoTurret.Spawn();
                autoTurret.SetHealth(autoTurret.MaxHealth() * conditionFraction);
            }
            catch
            {
                try { autoTurret.Kill(); } catch {}
                return null;
            }

            SetupCarTurret(autoTurret);
            try { AttachTurretSwitch(autoTurret); } catch {}

            try { Effect.server.Run(PrefabEffectDeployAutoTurret, autoTurret.transform.position); } catch {}

            return autoTurret;
        }

        private void RefreshCarTurret(AutoTurret turret)
        {
            SetupCarTurret(turret);

            var turretSwitch = GetTurretSwitch(turret);
            if (turretSwitch != null)
            {
                SetupTurretSwitch(turretSwitch);
            }
        }

        private ElectricSwitch AttachTurretSwitch(AutoTurret autoTurret)
        {
            var turretSwitch = GameManager.server.CreateEntity(PrefabEntityElectricSwitch, autoTurret.transform.TransformPoint(TurretSwitchPosition), autoTurret.transform.rotation * TurretSwitchRotation) as ElectricSwitch;
            if (turretSwitch == null)
                return null;

            try
            {
                SetupTurretSwitch(turretSwitch);
                turretSwitch.Spawn();
                turretSwitch.SetParent(autoTurret, true);
            }
            catch
            {
                try { turretSwitch.Kill(); } catch {}
                return null;
            }

            return turretSwitch;
        }

        private void SetupTurretSwitch(ElectricSwitch electricSwitch)
        {
            electricSwitch.pickup.enabled = false;
            electricSwitch.SetFlag(IOEntity.Flag_HasPower, true);
            electricSwitch.baseProtection = ImmortalProtection;
            RemoveColliders<Collider>(electricSwitch);
            RemoveGroundWatch(electricSwitch);
            HideInputsAndOutputs(electricSwitch);

            if (electricSwitch != null && electricSwitch.HasParent())
            {
                var transform = electricSwitch.transform;
                if (transform.localPosition != TurretSwitchPosition)
                {
                    transform.localPosition = TurretSwitchPosition;
                    try { electricSwitch.InvalidateNetworkCache(); } catch {}
                    try { electricSwitch.SendNetworkUpdate_Position(); } catch {}
                }
            }
        }

        private bool CanAccessVehicle(BaseVehicle vehicle, BasePlayer basePlayer, bool provideFeedback = true)
        {
            if (VehicleDeployedLocks == null)
                return true;

            var canAccess = VehicleDeployedLocks.Call("API_CanAccessVehicle", basePlayer, vehicle, provideFeedback);
            return !(canAccess is bool) || (bool)canAccess;
        }

        private int FindFirstSuitableSocketIndex(ModularCar car, BasePlayer basePlayer)
        {
            for (var socketIndex = 0; socketIndex < car.TotalSockets; socketIndex++)
            {
                BaseVehicleModule currentModule;
                if (car.TryGetModuleAt(socketIndex, out currentModule)
                    && currentModule.FirstSocketIndex == socketIndex
                    && HasPermissionToVehicleModule(basePlayer.UserIDString, currentModule)
                    && GetModuleAutoTurret(currentModule) == null)
                {
                    return socketIndex;
                }
            }

            return -1;
        }

        private int GetCarAutoTurretLimit(ModularCar car)
        {
            var defaultLimit = _config.DefaultLimitPerCar;

            if (car.OwnerID == 0)
                return defaultLimit;

            var ownerIdString = car.OwnerID.ToString();
            if (defaultLimit < 4 && permission.UserHasPermission(ownerIdString, PermissionLimit4))
                return 4;
            if (defaultLimit < 3 && permission.UserHasPermission(ownerIdString, PermissionLimit3))
                return 3;
            if (defaultLimit < 2 && permission.UserHasPermission(ownerIdString, PermissionLimit2))
                return 2;

            return defaultLimit;
        }

        private bool HasPermissionToVehicleModule(string userId, BaseVehicleModule vehicleModule)
        {
            return permission.UserHasPermission(userId, PermissionAllModules)
                || permission.UserHasPermission(userId, GetAutoTurretPermissionForModule(vehicleModule));
        }

        private bool ShouldSpawnTurretsWithCar(ModularCar car)
        {
            var spawnWithCarConfig = _config.SpawnWithCarConfig;
            if (!spawnWithCarConfig.Enabled)
                return false;

            if (IsNaturalCarSpawn(car))
                return spawnWithCarConfig.NaturalCarSpawns.Enabled;

            if (!spawnWithCarConfig.OtherCarSpawns.Enabled)
                return false;

            if (!spawnWithCarConfig.OtherCarSpawns.RequirePermission)
                return true;

            return car.OwnerID != 0 && permission.UserHasPermission(car.OwnerID.ToString(), PermissionSpawnWithCar);
        }

        private bool TryGetAutoTurretPositionForModule(BaseVehicleModule vehicleModule, out Vector3 position)
        {
            return _config.ModulePositions.TryGetValue(vehicleModule.AssociatedItemDef.shortname, out position);
        }

        private int GetAutoTurretChanceForModule(BaseVehicleModule vehicleModule)
        {
            int chance;
            return _config.SpawnWithCarConfig.SpawnChanceByModule.TryGetValue(vehicleModule.AssociatedItemDef.shortname, out chance)
                ? chance
                : 0;
        }

        private AutoTurret DeployAutoTurretForPlayer(ModularCar car, BaseVehicleModule vehicleModule, Vector3 position, BasePlayer basePlayer, float conditionFraction = 1)
        {
            var autoTurret = DeployAutoTurret(car, vehicleModule, position, conditionFraction, basePlayer.userID);
            if (autoTurret == null)
                return null;

            // Other plugins may have already automatically authorized the player.if (!autoTurret.IsAuthed(basePlayer))
            {
                autoTurret.authorizedPlayers.Add(new ProtoBuf.PlayerNameID
                {
                    userid = basePlayer
// ... [Code preview truncated due to length. Full source in attached file] ...

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