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

FREE HeliCommander : 0.3.4 0.3.4

Нет прав для скачивания
C#:
using Facepunch;
using Network;
using Network.Visibility;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("HeliCommander", "k1lly0u", "0.3.4")]
    [Description("Custom controllers and options for all types of helicopters")]
    class HeliCommander : RustPlugin {
#region Fields
        [PluginReference]
        Plugin Clans, Friends, RandomSpawns, Spawns;
        private RestoreData restoreData;
        private Dictionary<ulong, double> userCooldowns = new Dictionary<ulong, double>();
        private DynamicConfigFile restorationdata, cooldowns;
        private List<BaseController> spawnedHelis = new List<BaseController>();
        private List<BaseController> saveableHelis = new List<BaseController>();
        private static Controls Control;
        private static RaycastHit raycastHit;
        private const string UH1Y_PREFAB = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab";
        private const string CH47_PREFAB = "assets/prefabs/npc/ch47/ch47.entity.prefab";
        private const string MINI_PREFAB = "assets/content/vehicles/minicopter/minicopter.entity.prefab";
        private const string TRANS_PREFAB = "assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab";
        private const string CHAIR_PREFAB = "assets/prefabs/vehicle/seats/passenger.prefab";
        private const string FUEL_STORAGE = "assets/content/vehicles/minicopter/subents/fuel_storage.prefab";
        private const string ROCKET_NORMAL_PREFAB = "assets/prefabs/ammo/rocket/rocket_basic.prefab";
        private const string ROCKET_NAPALM_PREFAB = "assets/prefabs/ammo/rocket/rocket_fire.prefab";
        private const string ROCKET_HV_PREFAB = "assets/prefabs/ammo/rocket/rocket_hv.prefab";
        private const string UI_HEALTH = "HCUI_Health";
        private const string UI_AMMO_MG = "HCUI_Ammo_MG";
        private const string UI_AMMO_ROCKET = "HCUI_Ammo_Rocket";
        private const string UI_FUEL = "HCUI_Fuel";
        private const string UI_AIM = "HCUI_Aim";
        private const string USE_PERMISSION = "helicommander.use.";
        private const string BUILD_PERMISSION = "helicommander.canbuild.";
        private const string SPAWN_PERMISSION = "helicommander.canspawn.";
        private const string COOLDOWN_PERMISSION = "helicommander.ignorecooldown.";
        private const string PASSENGER_PERMISSION = "helicommander.passenger.";
        private static GameObjectRef FUEL_STORAGE_REF;
#endregion
#region Oxide Hooks
        private void Loaded() {
            Unsubscribe(nameof(OnEntitySpawned));
            foreach (HelicopterType type in Enum.GetValues(typeof(HelicopterType)) as HelicopterType[]) {
                if (type == HelicopterType.Invalid) continue;
                permission.RegisterPermission(string.Concat(BUILD_PERMISSION, type), this);
                permission.RegisterPermission(string.Concat(SPAWN_PERMISSION, type), this);
                permission.RegisterPermission(string.Concat(USE_PERMISSION, type), this);
                permission.RegisterPermission(string.Concat(PASSENGER_PERMISSION, type), this);
                permission.RegisterPermission(string.Concat(COOLDOWN_PERMISSION, type), this);
            }
            lang.RegisterMessages(Messages, this);
            GetMessage = Message;
            Control = new Controls();
        }
        private void OnServerInitialized() {
            FUEL_STORAGE_REF = GameManager.server.FindPrefab("assets/content/vehicles/minicopter/minicopter.entity.prefab").GetComponent<MiniCopter>().fuelStoragePrefab;
            LoadData();
            if (Configuration.Mini.Convert || Configuration.Transport.Convert) Subscribe(nameof(OnEntitySpawned));
            restoreData.RestoreVehicles(SpawnAtLocation);
            timer.In(5, () => CheckForSpawns(HelicopterType.CH47));
            timer.In(10, () => CheckForSpawns(HelicopterType.UH1Y));
            timer.In(15, () => CheckForSpawns(HelicopterType.Mini));
            timer.In(20, () => CheckForSpawns(HelicopterType.Transport));
        }
        private void OnEntitySpawned(MiniCopter miniCopter) {
            if (miniCopter == null) return;
            if ((miniCopter is ScrapTransportHelicopter && !Configuration.Transport.Convert) || !Configuration.Mini.Convert) return;
            if (!miniCopter.GetComponent<BaseController>() && !restoreData.HasRestoreData(miniCopter.net.ID)) {
                NextTick(() => {
                    if (miniCopter == null || miniCopter.GetComponent<BaseController>()) return;
                    MiniController controller = miniCopter is ScrapTransportHelicopter ? miniCopter.gameObject.AddComponent<TransportController>() : miniCopter.gameObject.AddComponent<MiniController>();
                    saveableHelis.Add(controller);
                }
                );
            }
        }
        private void OnSamSiteTargetScan(SamSite samsite, List<SamSite.ISamSiteTarget> list) {
            if (spawnedHelis.Count == 0 && saveableHelis.Count == 0) return;
            for (int i = 0; i < spawnedHelis.Count; i++) {
                BaseController baseController = spawnedHelis[i];
                if (!(baseController is CH47Controller) && !(baseController is UH1YController)) continue;
                if (Vector3.Distance(baseController.Transform.position, samsite.transform.position) < SamSite.targetTypeVehicle.scanRadius) list.Add(baseController as SamSite.ISamSiteTarget);
            }
            for (int i = 0; i < saveableHelis.Count; i++) {
                BaseController baseController = saveableHelis[i];
                if (!(baseController is CH47Controller) && !(baseController is UH1YController)) continue;
                if (Vector3.Distance(baseController.Transform.position, samsite.transform.position) < SamSite.targetTypeVehicle.scanRadius) list.Add(baseController as SamSite.ISamSiteTarget);
            }
        }
        private object CanConvertToPilotEject(BaseHelicopter baseHelicopter) => baseHelicopter != null && baseHelicopter.GetComponent<UH1YController>() != null ? (object)false : null;
        private void OnEntityKill(BaseNetworkable baseNetworkable) {
            BaseController baseController = baseNetworkable.GetComponent<BaseController>();
            if (baseController != null) {
                baseController.EjectAllPlayers();
                spawnedHelis.Remove(baseController);
                saveableHelis.Remove(baseController);
            }
        }
        private void OnEntityTakeDamage(BaseCombatEntity baseCombatEntity, HitInfo hitInfo) {
            if (baseCombatEntity == null || hitInfo == null) return;
            BaseController baseController = baseCombatEntity.GetComponent<BaseController>();
            if (baseController != null) {
                baseController.ManageDamage(hitInfo);
                return;
            }
        }
        private void OnHammerHit(BasePlayer player, HitInfo hitInfo) {
            if (player == null || hitInfo == null || hitInfo.HitEntity == null) return;
            BaseController baseController = hitInfo.HitEntity.GetComponent<BaseController>();
            if (baseController != null) baseController.TryRepair(player);
        }
        private void OnPlayerInput(BasePlayer player, InputState inputState) {
            if (player == null) return;
            if (Control.JustPressed(player, BUTTON.USE)) {
                if (Physics.SphereCast(player.eyes.position, 0.5f, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward, out raycastHit, 3f)) {
                    BaseController baseController = raycastHit.collider.GetComponentInParent<BaseController>();
                    if (baseController != null && baseController.Type == HelicopterType.UH1Y) {
                        if (!baseController.IsOccupant(player)) {
                            BaseVehicle.MountPointInfo mountPointInfo = baseController.GetIdealMountPoint(player);
                            if (mountPointInfo != null && CanMountHelicopter(baseController, mountPointInfo, player) == null) {
                                ForceMountPlayerTo(player, mountPointInfo.mountable, baseController);
                            }
                        }
                    }
                }
                return;
            }
            if (Control.JustPressed(player, Controls.Type.Inventory)) {
                if (Physics.SphereCast(player.eyes.position, 0.5f, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward, out raycastHit, 3f)) {
                    BaseController baseController = raycastHit.collider.GetComponentInParent<BaseController>();
                    if (baseController != null && baseController.Config.Inventory.Enabled && baseController.Commander == null && !baseController.IsOccupant(player)) {
                        baseController.OpenInventory(player);
                    }
                }
                return;
            }
            if (Control.JustPressed(player, Controls.Type.FuelTank)) {
                if (Physics.SphereCast(player.eyes.position, 0.5f, Quaternion.Euler(player.serverInput.current.aimAngles) * Vector3.forward, out raycastHit, 3f)) {
                    BaseController baseController = raycastHit.collider.GetComponentInParent<BaseController>();
                    if (baseController != null && baseController.ConsumeFuel && baseController.Commander == null && !baseController.IsOccupant(player)) {
                        if ((int)baseController.Type < 3) {
                            baseController.OpenFuel(player);
                        }
                    }
                }
                return;
            }
        }
        private void OnServerSave() {
            restoreData.Clear();
            for (int i = saveableHelis.Count - 1; i >= 0; i--) {
                BaseController controller = saveableHelis[i];
                BaseCombatEntity baseCombatEntity = controller.GetEntity();
                if (controller == null || baseCombatEntity == null || !baseCombatEntity.IsValid() || baseCombatEntity.IsDestroyed) {
                    saveableHelis.RemoveAt(i);
                    continue;
                }
                restoreData.AddData(controller);
            }
            SaveData();
        }
        private void Unload() {
            BaseController[] baseControllers = UnityEngine.Object.FindObjectsOfType<BaseController>();
            if (baseControllers != null) {
                foreach (BaseController baseController in baseControllers) {
                    BaseCombatEntity baseCombatEntity = baseController.GetEntity();
                    UnityEngine.Object.DestroyImmediate(baseController);
                    if (baseCombatEntity != null && !baseCombatEntity.IsDestroyed) baseCombatEntity.Kill(BaseNetworkable.DestroyMode.None);
                }
            }
            foreach (BasePlayer player in BasePlayer.activePlayerList) DestroyAllUI(player);
            Configuration = null;
        }
        private object CanMountHelicopter(BaseController baseController, BaseVehicle.MountPointInfo mountPointInfo, BasePlayer player) {
            if (baseController != null) {
                if (player.isMounted) return false;
                if (baseController.MountLocked) return false;
                if (baseController.IsDying) return false;
                bool canPilot = permission.UserHasPermission(player.UserIDString, string.Concat(USE_PERMISSION, baseController.Type));
                bool canPassenger = permission.UserHasPermission(player.UserIDString, string.Concat(PASSENGER_PERMISSION, baseController.Type));
                if (!canPilot && !canPassenger) {
                    SendReply(player, Message("nopermission", player.userID));
                    return false;
                }
                if (mountPointInfo != null) {
                    if (mountPointInfo.isDriver) {
                        if (!canPilot) {
                            SendReply(player, Message("noflypermission", player.userID));
                            return false;
                        }
                        return null;
                    }
                    else {
                        if (baseController.Config.Passengers.Enabled) {
                            if (baseController.Commander == null) return null;
                            else {
                                if (!baseController.Config.Passengers.UseFriends && !baseController.Config.Passengers.UseClans) return null;
                                if (IsFriendlyPlayer(baseController.Commander.userID, player.userID, baseController.Type)) return null;
                                SendReply(player, Message("not_friend", player.userID));
                                return false;
                            }
                        }
                        else {
                            SendReply(player, Message("passenger_not_enabled", player.userID));
                            return false;
                        }
                    }
                }
            }
            return null;
        }
        private object CanMountEntity(BasePlayer player, BaseMountable baseMountable) {
            BaseController baseController = baseMountable.GetParentEntity()?.GetComponent<BaseController>();
            if (baseController != null && !baseController.IsOccupant(player)) {
                BaseVehicle.MountPointInfo mountPointInfo = baseController.FindMountPointOf(baseMountable);
                if (mountPointInfo != null) return CanMountHelicopter(baseController, mountPointInfo, player);
            }
            return null;
        }
        private void OnPlayerDismountFailed(BasePlayer player, BaseMountable baseMountable) {
            BaseEntity parentEntity = baseMountable.GetParentEntity();
            if (parentEntity != null && !parentEntity.IsDestroyed) {
                BaseController baseController = parentEntity.GetComponentInParent<BaseController>();
                if (baseController != null) {
                    if (baseController.MountLocked) return;
                    if (baseController.Type == HelicopterType.UH1Y) ForceDismountPlayerFrom(player, baseMountable, baseController);
                }
            }
        }
        private object CanDismountEntity(BasePlayer player, BaseMountable baseMountable) {
            BaseEntity parentEntity = baseMountable.GetParentEntity();
            if (parentEntity != null && !parentEntity.IsDestroyed) {
                BaseController baseController = parentEntity.GetComponentInParent<BaseController>();
                if (baseController != null) {
                    if (baseController.MountLocked) return false;
                    if (baseController.Type == HelicopterType.UH1Y) {
                        ForceDismountPlayerFrom(player, baseMountable, baseController);
                        return false;
                    }
                }
            }
            return null;
        }
        private void OnEntityMounted(BaseMountable baseMountable, BasePlayer player) {
            BaseEntity parentEntity = baseMountable.GetParentEntity();
            if (parentEntity != null && !parentEntity.IsDestroyed) {
                BaseController baseController = parentEntity.GetComponentInParent<BaseController>();
                if (baseController != null) {
                    baseController.OnPlayerMounted(baseMountable, player);
                }
            }
        }
        private void OnEntityDismounted(BaseMountable baseMountable, BasePlayer player) {
            BaseEntity parentEntity = baseMountable.GetParentEntity();
            if (parentEntity != null && !parentEntity.IsDestroyed) {
                BaseController baseController = parentEntity.GetComponentInParent<BaseController>();
                if (baseController != null) {
                    baseController.OnPlayerDismounted(baseMountable, player);
                    DestroyAllUI(player);
                }
            }
        }
#endregion
#region Functions
        private static T ParseType<T>(string type) {
            try {
                T value = (T)Enum.Parse(typeof(T), type, true);
                if (Enum.IsDefined(typeof(T), value)) return value;
            }
            catch {
                if (typeof(T) == typeof(BUTTON)) Debug.LogError($"INVALID CONFIG OPTION DETECTED! The value \"{type}\" is an incorrect selection.\nAvailable options are: {Enum.GetNames(typeof(T)).ToSentence()}");
                return default(T);
            }
            return default(T);
        }
        private class Controls {
            private Hash<Type, BUTTON> _controls = new Hash<Type, BUTTON>();
            public Controls() {
                _controls[Type.Lights] = ParseType<BUTTON>(Configuration.Buttons.Lights);
                _controls[Type.Inventory] = ParseType<BUTTON>(Configuration.Buttons.Inventory);
                _controls[Type.MG] = ParseType<BUTTON>(Configuration.Buttons.MG);
                _controls[Type.Rockets] = ParseType<BUTTON>(Configuration.Buttons.Rockets);
                _controls[Type.PitchF] = ParseType<BUTTON>(Configuration.Buttons.PitchForward);
                _controls[Type.PitchB] = ParseType<BUTTON>(Configuration.Buttons.PitchBackward);
                _controls[Type.RollL] = ParseType<BUTTON>(Configuration.Buttons.RollLeft);
                _controls[Type.RollR] = ParseType<BUTTON>(Configuration.Buttons.RollRight);
                _controls[Type.ThrottleUp] = ParseType<BUTTON>(Configuration.Buttons.ThrottleUp);
                _controls[Type.ThrottleDown] = ParseType<BUTTON>(Configuration.Buttons.ThrottleDown);
                _controls[Type.FuelTank] = ParseType<BUTTON>(Configuration.Buttons.FuelTank);
                _controls[Type.LockYaw] = ParseType<BUTTON>(Configuration.Buttons.LockYaw);
            }
            public bool IsDown(BasePlayer player, Type commandType) {
                BUTTON button = _controls[commandType];
                return player.serverInput.WasJustPressed(button) || player.serverInput.IsDown(button);
            }
            public bool IsDown(BasePlayer player, BUTTON button) {
                return player.serverInput.WasJustPressed(button) || player.serverInput.IsDown(button);
            }
            public bool JustPressed(BasePlayer player, Type commandType) {
                return player.serverInput.WasJustPressed(_controls[commandType]);
            }
            public bool JustPressed(BasePlayer player, BUTTON button) {
                return player.serverInput.WasJustPressed(button);
            }
            public BUTTON GetButtonOf(Type type) => _controls[type];
            public enum Type {
                Lights, Inventory, MG, Rockets, RollL, RollR, PitchF, PitchB, ThrottleUp, ThrottleDown, LockYaw, FuelTank
            }
        }
        private void CheckForSpawns(HelicopterType type) {
            ConfigData.BaseHelicopter config = type == HelicopterType.CH47 ? Configuration.CH47 : type == HelicopterType.Transport ? Configuration.Transport as ConfigData.BaseHelicopter : type == HelicopterType.Mini ? Configuration.Mini as ConfigData.BaseHelicopter : Configuration.UH1Y;
            if (config.Spawnable.Enabled) {
                if ((spawnedHelis.Count + saveableHelis.Count) < config.Spawnable.Max) {
                    object position = null;
                    if (config.Spawnable.RandomSpawns) {
                        if (!RandomSpawns) {
                            PrintError("RandomSpawns can not be found! Unable to autospawn helicopters");
                            return;
                        }
                        object success = RandomSpawns.Call("GetSpawnPoint");
                        if (success != null) position = (Vector3)success;
                        else PrintError("Unable to find a valid spawnpoint from RandomSpawns");
                    }
                    else {
                        if (string.IsNullOrEmpty(config.Spawnable.Spawnfile)) return;
                        if (!Spawns) {
                            PrintError("Spawns Database can not be found! Unable to autospawn helicopters");
                            return;
                        }
                        object success = Spawns.Call("GetSpawnsCount", config.Spawnable.Spawnfile);
                        if (success is string) {
                            PrintError($"An invalid {type} spawnfile has been set in the config.Unable to autospawn helicopters : " + (string)success);
                            return;
                        }
                        success = Spawns.Call("GetRandomSpawn", config.Spawnable.Spawnfile);
                        if (success is string) {
                            PrintError((string)success);
                            return;
                        }
                        else position = (Vector3)success;
                    }
                    if (position != null) {
                        int count = 0;
                        switch (type) {
                            case HelicopterType.UH1Y : {
                                List<BaseHelicopter> entities = Facepunch.Pool.GetList<BaseHelicopter>();
                                Vis.Entities((Vector3)position, 5f, entities);
                                count = entities.Count;
                                Facepunch.Pool.FreeList(ref entities);
                                if (count > 0) {
                                    timer.In(10, () => CheckForSpawns(type));
                                    return;
                                }
                                else SpawnAtLocation((Vector3)position, Quaternion.identity, type, config.Spawnable.Save);
                            }
                            break;
                            case HelicopterType.CH47 : {
                                List<CH47Helicopter> entities = Facepunch.Pool.GetList<CH47Helicopter>();
                                Vis.Entities((Vector3)position, 5f, entities);
                                count = entities.Count;
                                Facepunch.Pool.FreeList(ref entities);
                                if (count > 0) {
                                    timer.In(10, () => CheckForSpawns(type));
                                    return;
                                }
                                else SpawnAtLocation((Vector3)position, Quaternion.identity, type, config.Spawnable.Save);
                            }
                            break;
                            case HelicopterType.Transport : case HelicopterType.Mini : {
                                List<MiniCopter> entities = Facepunch.Pool.GetList<MiniCopter>();
                                Vis.Entities((Vector3)position, 5f, entities);
                                count = entities.Count;
                                Facepunch.Pool.FreeList(ref entities);
                                if (count > 0) {
                                    timer.In(10, () => CheckForSpawns(type));
                                    return;
                                }
                                else SpawnAtLocation((Vector3)position, Quaternion.identity, type, config.Spawnable.Save);
                            }
                            break;
                        }
                    }
                }
                timer.In(config.Spawnable.Time, () => CheckForSpawns(type));
            }
        }
        private double GrabCurrentTime() => DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        private string FormatTime(double time) {
            TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
            var days = dateDifference.Days;
            var hours = dateDifference.Hours;
            hours += (days * 24);
            var mins = dateDifference.Minutes;
            var secs = dateDifference.Seconds;
            return string.Format("{0:00}:{1:00}:{2:00}", hours, mins, secs);
        }
        private string GetPrefabPath(HelicopterType type) {
            switch (type) {
                case HelicopterType.UH1Y : return UH1Y_PREFAB;
                case HelicopterType.CH47 : return CH47_PREFAB;
                case HelicopterType.Mini : return MINI_PREFAB;
                case HelicopterType.Transport : return TRANS_PREFAB;
                case HelicopterType.Invalid : default : return string.Empty;
            }
        }
        private int GetCooldown(HelicopterType type) {
            switch (type) {
                case HelicopterType.UH1Y : return Configuration.UH1Y.Spawnable.Cooldown;
                case HelicopterType.CH47 : return Configuration.CH47.Spawnable.Cooldown;
                case HelicopterType.Mini : return Configuration.Mini.Spawnable.Cooldown;
                case HelicopterType.Transport : return Configuration.Transport.Spawnable.Cooldown;
                case HelicopterType.Invalid : default : return 0;
            }
        }
        private List<ConfigData.BaseHelicopter.BuildOptions.BuildOption> GetBuildCosts(HelicopterType type) {
            switch (type) {
                case HelicopterType.UH1Y : return Configuration.UH1Y.Build.Costs;
                case HelicopterType.CH47 : return Configuration.CH47.Build.Costs;
                case HelicopterType.Mini : return Configuration.Mini.Build.Costs;
                case HelicopterType.Transport : return Configuration.Transport.Build.Costs;
                case HelicopterType.Invalid : default : return new List<ConfigData.BaseHelicopter.BuildOptions.BuildOption>();
            }
        }
        private bool HasBuildCooldown(HelicopterType type) {
            switch (type) {
                case HelicopterType.UH1Y : return Configuration.UH1Y.Build.Cooldown;
                case HelicopterType.CH47 : return Configuration.CH47.Build.Cooldown;
                case HelicopterType.Mini : return Configuration.Mini.Build.Cooldown;
                case HelicopterType.Transport : return Configuration.Transport.Build.Cooldown;
                case HelicopterType.Invalid : default : return true;
            }
        }
        private static BaseMountable SpawnMountPoint(BaseVehicle.MountPointInfo mountToSpawn, Model model, BaseCombatEntity parent) {
            Vector3 localForward = Quaternion.Euler(mountToSpawn.rot) * Vector3.forward;
            Vector3 position = mountToSpawn.pos;
            Vector3 localUp = Vector3.up;
            if (!string.IsNullOrEmpty(mountToSpawn.bone)) {
                position = model.FindBone(mountToSpawn.bone).transform.position + parent.transform.TransformDirection(mountToSpawn.pos);
                localForward = parent.transform.TransformDirection(localForward);
                localUp = parent.transform.up;
            }
            BaseMountable baseMountable = GameManager.server.CreateEntity(CHAIR_PREFAB, position, Quaternion.LookRotation(localForward, localUp), true) as BaseMountable;
            if (baseMountable != null) {
                if (string.IsNullOrEmpty(mountToSpawn.bone)) baseMountable.SetParent(parent, false, false);
                else baseMountable.SetParent(parent, mountToSpawn.bone, true, true);
                baseMountable.Spawn();
                mountToSpawn.mountable = baseMountable;
            }
            return baseMountable;
        }
#endregion
#region Component
        public enum HelicopterType {
            Invalid, UH1Y, CH47, Mini, Transport
        }
        private abstract class BaseController : MonoBehaviour {
            internal virtual HelicopterType Type => HelicopterType.Invalid;
            internal virtual ConfigData.BaseHelicopter Config {
                get;
            }
            protected ConfigData.BaseHelicopter.MovementSettings Movement {
                get;
                set;
            }
            internal EntityFuelSystem FuelSystem {
                get;
                set;
            }
            internal ItemContainer Inventory {
                get;
                private set;
            }
            protected Rigidbody Rigidbody {
                get;
                set;
            }
            internal Transform Transform {
                get;
                set;
            }
            internal BasePlayer Commander {
                get {
                    return _commander;
                }
                set {
                    _commander = value;
                    OnCommanderSet(value);
                }
            }
            internal abstract bool UseCustomControls {
                get;
            }
            internal bool MountLocked {
                get;
                set;
            }
            private BasePlayer _commander;
            protected List<BaseVehicle.MountPointInfo> mountPoints = Pool.GetList<BaseVehicle.MountPointInfo>();
            protected List<BasePlayer> occupants = Pool.GetList<BasePlayer>();
            internal int OccupantCount => occupants.Count;
            internal bool IsDying {
                get;
                private set;
            }
            protected virtual void OnDestroy() {
                EjectAllPlayers();
                DestroyAllMounts();
                Pool.FreeList(ref mountPoints);
                Pool.FreeList(ref occupants);
            }
            internal abstract BaseCombatEntity GetEntity();
            internal abstract bool IsGrounded();
            internal bool IsNearGround() {
                const int GROUND_LAYER = 1 << 16 | 1 << 21 | 1 << 23;
                return Physics.Raycast(new Ray(Transform.position, Vector3.down), 1f, GROUND_LAYER);
            }
            protected virtual void UpdateAimTarget() {
            }
            protected virtual void ToggleLights() {
            }
#region Mounting
            internal bool IsOccupant(BasePlayer player) => occupants.Contains(player);
            internal List<BasePlayer> GetOccupants() => occupants;
            internal virtual void CreateMountPoints() {
            }
            internal BaseVehicle.MountPointInfo FindMountPointOf(BaseMountable baseMountable) {
                for (int i = 0; i < mountPoints.Count; i++) {
                    BaseVehicle.MountPointInfo mountPointInfo = mountPoints[i];
                    if (mountPointInfo.mountable == baseMountable) return mountPointInfo;
                }
                return null;
            }
            internal BaseVehicle.MountPointInfo FindMountPoint(Func<BaseVehicle.MountPointInfo, bool> func) {
                for (int i = 0; i < mountPoints.Count; i++) {
                    BaseVehicle.MountPointInfo mountPointInfo = mountPoints[i];
                    if (func(mountPointInfo)) return mountPointInfo;
                }
                return null;
            }
            internal virtual void OnPlayerMounted(BaseMountable baseMountable, BasePlayer player) {
                bool isDriver = FindMountPointOf(baseMountable).isDriver;
                if (isDriver) {
                    string message = UseCustomControls ? string.Format(GetMessage((int)Type > 2 ? "controls_new_mini" : "controls_new", player.userID), Control.GetButtonOf(Controls.Type.PitchF), Control.GetButtonOf(Controls.Type.PitchB), Control.GetButtonOf(Controls.Type.RollL), Control.GetButtonOf(Controls.Type.RollR), Control.GetButtonOf(Controls.Type.ThrottleUp), Control.GetButtonOf(Controls.Type.ThrottleDown), Control.GetButtonOf(Controls.Type.LockYaw)) : string.Empty;
                    player.ChatMessage(message);
                    message = Type == HelicopterType.CH47 || Type == HelicopterType.Transport ? $"{string.Format(GetMessage("toggle_lights", player.userID), Configuration.Buttons.Lights)}\n" : string.Empty;
                    if (this is UH1YController) {
                        if ((this as UH1YController).GetWeapons()?.Rocket.Enabled ?? false) message += $"{string.Format(GetMessage("fire_rocket", player.userID), Configuration.Buttons.Rockets)}\n";
                        if ((this as UH1YController).GetWeapons()?.MG.Enabled ?? false) message += $"{string.Format(GetMessage("fire_mg", player.userID), Configuration.Buttons.MG)}\n";
                    }
                    if (Inventory != null) message += $"{string.Format(GetMessage("access_inventory", player.userID), Configuration.Buttons.Inventory)}\n";
                    if (ConsumeFuel && GetFuelItem() != null) {
                        if ((int)Type < 3) message += $"{string.Format(GetMessage("access_fuel", player.userID), Control.GetButtonOf(Controls.Type.FuelTank))}\n";
                        message += $"{string.Format(GetMessage("fuel_type", player.userID), GetFuelItem().displayName.english)}";
                    }
                    if (!string.IsNullOrEmpty(message)) player.ChatMessage(message);
                    if (Config.Repair.Enabled && GetRepairItem() != null) player.ChatMessage(string.Format(GetMessage("repairhelp", player.userID), Config.Repair.Amount, GetRepairItem().displayName.english));
                }
                else {
                    string message = string.Empty;
                    if (Inventory != null) message += $"{string.Format(GetMessage("access_inventory", player.userID), Control.GetButtonOf(Controls.Type.Inventory))}\n";
                    if (ConsumeFuel && GetFuelItem() != null) {
                        if ((int)Type < 3) message += $"{string.Format(GetMessage("access_fuel", player.userID), Control.GetButtonOf(Controls.Type.FuelTank))}\n";
                        message += $"{string.Format(GetMessage("fuel_type", player.userID), GetFuelItem().displayName.english)}";
                    }
                    if (!string.IsNullOrEmpty(message)) player.ChatMessage(message);
                }
                OnEntityMounted(player, isDriver);
            }
            internal virtual void OnEntityMounted(BasePlayer player, bool isDriver) {
                occupants.Add(player);
                if (isDriver) {
                    Commander = player;
                    if ((int)Type < 3) {
                        CreateHealthUI(player, this);
                        if (ConsumeFuel) UpdateFuelUI();
                    }
                }
            }
            internal virtual void OnPlayerDismounted(BaseMountable mountable, BasePlayer player) {
                if (player == Commander) Commander = null;
                occupants.Remove(player);
                DestroyAllUI(player);
            }
            protected virtual void OnCommanderSet(BasePlayer player) {
            }
            internal virtual void EjectAllPlayers() {
                if (mountPoints != null) {
                    for (int i = 0; i < mountPoints.Count; i++) mountPoints[i].mountable.DismountAllPlayers();
                }
            }
            protected abstract void DestroyAllMounts();
            internal BaseVehicle.MountPointInfo GetIdealMountPoint(BasePlayer player) {
                BaseVehicle.MountPointInfo mountPointInfo = null;
                float closestDistance = float.PositiveInfinity;
                foreach (BaseVehicle.MountPointInfo mountPoint in mountPoints) {
                    if (mountPoint.mountable.IsMounted()) continue;
                    float distance = Vector3.Distance(mountPoint.mountable.mountAnchor.position, player.transform.position);
                    if (distance > closestDistance) continue;
                    mountPointInfo = mountPoint;
                    closestDistance = distance;
                }
                return mountPointInfo;
            }
            internal class DriverMount : MonoBehaviour {
                private BaseMountable baseMountable;
                private void Awake() {
                    baseMountable = GetComponent<BaseMountable>();
                    InvokeHandler.InvokeRepeating(baseMountable, UpdateHeldItems, 0.5f, 0.5f);
                }
                public void UpdateHeldItems() {
                    if (baseMountable._mounted == null) return;
                    Item item = baseMountable._mounted.GetActiveItem();
                    if (item == null || item.GetHeldEntity() == null) return;
                    int slot = item.position;
                    item.SetParent(null);
                    item.MarkDirty();
                    InvokeHandler.Invoke(baseMountable, () => {
                        if (item == null) return;
                        item.SetParent(baseMountable._mounted.inventory.containerBelt);
                        item.position = slot;
                        item.MarkDirty();
                    }
                    , 0.15f);
                }
            }
#endregion
#region Inventory
            protected void InitializeInventory() {
                if (Config.Inventory.Enabled) {
                    Inventory = new ItemContainer();
                    Inventory.ServerInitialize(null, Config.Inventory.Size);
                    if ((int)Inventory.uid == 0) Inventory.GiveUID();
                }
            }
            internal virtual void OpenInventory(BasePlayer player) {
            }
            internal void DropInventory() {
                if (Inventory == null) return;
                Inventory.Drop("assets/prefabs/misc/item drop/item_drop.prefab", (Transform.position + new Vector3(0f, 1.5f, 0f)) + (UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(2f, 3f)), Quaternion.identity);
            }
#endregion
#region Fuel
            private float lastFuelAmount;
            private bool fuelDisabled = false;
            internal bool ConsumeFuel => Config.Fuel.Enabled && !fuelDisabled;
            protected abstract ItemDefinition GetFuelItem();
            protected virtual void InitializeFuel() {
            }
            protected void CreateFuelSystem() {
                StorageContainer fuelStorage = GameManager.server.CreateEntity(FUEL_STORAGE, Transform.position, Quaternion.identity, true) as StorageContainer;
                fuelStorage.SetParent(GetEntity(), false, true);
                fuelStorage.transform.localPosition = Vector3.zero;
                fuelStorage.GetComponent<Collider>().enabled = false;
                fuelStorage.Spawn();
                FuelSystem = new EntityFuelSystem(true, FUEL_STORAGE_REF, new List<BaseEntity>());
                FuelSystem.fuelStorageInstance.Set(fuelStorage);
                ItemContainer itemContainer = FuelSystem.GetFuelContainer().inventory;
                itemContainer.onlyAllowedItems = new ItemDefinition[] {
                    GetFuelItem()
                }
                ;
                if (!Config.Fuel.Enabled) itemContainer.SetFlag(ItemContainer.Flag.IsLocked, true);
                else if (Config.Fuel.GiveFuel) ItemManager.Create(GetFuelItem(), UnityEngine.Random.Range(Config.Fuel.FuelAmountMin, Config.Fuel.FuelAmountMax)).MoveToContainer(itemContainer);
            }
            internal virtual void OpenFuel(BasePlayer player) {
            }
            internal void DropFuel() {
                StorageContainer storageContainer = FuelSystem.GetFuelContainer();
                if (storageContainer == null) return;
                storageContainer.inventory.Drop("assets/prefabs/misc/item drop/item_drop.prefab", (Transform.position + new Vector3(0f, 1.5f, 0f)) + (UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(2f, 3f)), Quaternion.identity);
            }
            protected void UpdateFuelUI() {
                if (Commander != null) {
                    int currentFuelAmount = FuelSystem.GetFuelAmount();
                    if (currentFuelAmount != lastFuelAmount) {
                        CreateFuelUI(Commander, this, currentFuelAmount);
                        lastFuelAmount = currentFuelAmount;
                    }
                    InvokeHandler.Invoke(this, UpdateFuelUI, 1f);
                }
            }
            internal void SetFuelRequirement(bool fuelEnabled) {
                fuelDisabled = !fuelEnabled;
                if (Commander != null) DestroyUI(Commander, UI_FUEL);
            }
#endregion
#region Repair
            protected abstract ItemDefinition GetRepairItem();
            internal void TryRepair(BasePlayer player) {
                BaseCombatEntity baseCombatEntity = GetEntity();
                if (baseCombatEntity != null && Config.Repair.Enabled) {
                    if (baseCombatEntity.health < baseCombatEntity.MaxHealth()) {
                        ItemDefinition repairItem = GetRepairItem();
                        if (repairItem == null) {
                            Debug.Log($"[HeliCommander] Attempted repair for type {GetType()} but invalid repair item set in config");
                            return;
                        }
                        if (player.inventory.GetAmount(repairItem.itemid) < Config.Repair.Amount) {
                            player.ChatMessage(string.Format(GetMessage("noresources", player.userID), Config.Repair.Amount, repairItem.displayName.english));
                            return;
                        }
                        player.inventory.Take(null, repairItem.itemid, Config.Repair.Amount);
                        baseCombatEntity.Heal(Config.Repair.Damage);
                        player.Command("note.inv", new object[] {
                            repairItem.itemid, Config.Repair.Amount * -1
                        }
                        );
                    }
                    else player.ChatMessage(GetMessage("fullhealth", player.userID));
                }
            }
#endregion
#region Death
            internal void ManageDamage(HitInfo info) {
                if (IsDying) return;
                if (IsDead()) {
                    OnDeath();
                    return;
                }
                foreach (KeyValuePair<DamageType, float> damageType in Config.Damage.Modifiers) {
                    if (info.damageTypes.Has(damageType.Key)) {
                        info.damageTypes.Scale(damageType.Key, damageType.Value);
                    }
                }
                if (Type == HelicopterType.Mini || Type == HelicopterType.Transport) return;
                foreach (BasePlayer occupant in occupants) CreateHealthUI(occupant, this);
            }
            protected void StopToDie() {
                enabled = false;
                IsDying = true;
                Rigidbody.velocity = Vector3.zero;
                EjectAllPlayers();
                GetEntity().Invoke(OnDeath, 5f);
            }
            protected virtual bool IsDead() => false;
            protected virtual void OnDeath() {
                enabled = false;
                IsDying = true;
                EjectAllPlayers();
                if (Config.Inventory.DropInv && Inventory != null) DropInventory();
            }
#endregion
        }
        private abstract class BaseController<T> : BaseController where T : BaseCombatEntity {
            public T Component {
                get;
                private set;
            }
            private bool isInvincible;
            protected bool isGrounded = false;
            protected HelicopterInput input = new HelicopterInput();
#region Initialization
            protected virtual void Awake() {
                Component = GetComponent<T>();
                Transform = Component.transform;
                isInvincible = true;
                InvokeHandler.Invoke(this, () => {
                    isInvincible = false;
                }
                , 3f);
                InitializeSettings();
                InitializeInventory();
                InitializeFuel();
                CreateMountPoints();
            }
            protected virtual void InitializeSettings() {
                Movement = Config.Movement;
                Component.InitializeHealth(Config.Damage.Health, Config.Damage.Health);
                Component.SendNetworkUpdate();
            }
            internal override BaseCombatEntity GetEntity() => Component;
#endregion
#region Inventory
            internal override void OpenInventory(BasePlayer player) {
                if (Config.Inventory.Enabled && Inventory != null) OpenContainer(player, Inventory);
            }
            private void OpenContainer(BasePlayer player, ItemContainer container) {
                player.inventory.loot.Clear();
                player.inventory.loot.entitySource = Component;
                player.inventory.loot.itemSource = null;
                player.inventory.loot.AddContainer(container);
                player.inventory.loot.SendImmediate();
                player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", "generic");
                player.SendNetworkUpdate();
            }
#endregion
#region Fuel
            internal override void OpenFuel(BasePlayer player) {
                if (ConsumeFuel) OpenContainer(player, FuelSystem.GetFuelContainer().inventory);
            }
#endregion
#region Movement
            private void FixedUpdate() {
                if (WaterLevel.Factor(Component.WorldSpaceBounds().ToBounds()) > 0.7f) {
                    StopToDie();
                    return;
                }
                if (!UseCustomControls) return;
                OnFixedUpdate();
                if (Vector3.Dot(Component.transform.up, Vector3.up) < 0) {
                    StopToDie();
                    return;
                }
                MovementUpdate();
                if (IsEngineOn() && (Commander == null || (ConsumeFuel && !FuelSystem.HasFuel()))) EngineOff();
                if (IsEngineOn() && ConsumeFuel) FuelSystem.TryUseFuel(Time.fixedDeltaTime, IsGrounded() ? Config.Fuel.Consumption * 0.1f : Config.Fuel.Consumption);
            }
            private void MovementUpdate() {
                if (input.lights) ToggleLights();
                if (ConsumeFuel && !FuelSystem.HasFuel()) return;
                if (IsGrounded()) ApplyForceAtWheels();
                if (IsEngineOn() && !(IsGrounded() && input.throttle < 0f)) {
                    LiftForce();
                    TiltForce();
                    YawForce();
                }
            }
            protected virtual void OnFixedUpdate() {
            }
            private void LateUpdate() {
                if (!UseCustomControls) return;
                float levelPitch = pitchRoll.y > 0f ? -Time.deltaTime : pitchRoll.y < 0f ? Time.deltaTime : 0f;
                float levelRoll = pitchRoll.x > 0f ? -Time.deltaTime : pitchRoll.x < 0f ? Time.deltaTime : 0f;
                if (Commander == null) {
                    input.Clear();
                    pitchRoll.x = Mathf.Clamp(pitchRoll.x + levelPitch, -1f, 1f);
                    pitchRoll.y = Ma
// ... [Code preview truncated due to length. Full source in attached file] ...

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