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

FREE HeliRefuel : 2.1.5 2.1.5

Нет прав для скачивания
C#:
//Requires: CustomNPC
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Plugins.CustomNPCEx;
using Rust;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;
namespace Oxide.Plugins {
    [Info("HeliRefuel", "k1lly0u", "2.1.5")]
    [Description("A mini-event where a helicopter populated with NPCs needs to land to refuel")]
    class HeliRefuel : RustPlugin, ICustomNPCPlugin {
#region Fields
        [PluginReference]
        Plugin PilotEject;
        private static List<ConfigData.LocationOptions.Monument.CustomOptions> RefuelPoints;
        protected static HeliRefuel Instance {
            get;
            private set;
        }
        private static NavMeshHit navHit;
        private static RaycastHit raycastHit;
        private bool isSubscribed = true;
        private Hash<BasePlayer, Vector3> velocityInheritance = new Hash<BasePlayer, Vector3>();
        private List<CustomNPC.CustomScientistNPC> customNpcs = new List<CustomNPC.CustomScientistNPC>();
        private const string HELICOPTER_PREFAB = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab";
        private const string CHAIR_PREFAB = "assets/prefabs/deployable/chair/chair.deployed.prefab";
        private const string ELITE_CRATE_PREFAB = "assets/bundled/prefabs/radtown/crate_elite.prefab";
        private const string HELI_CRATE_PREFAB = "assets/prefabs/npc/patrol helicopter/heli_crate.prefab";
        private const string ADMIN_PERM = "helirefuel.admin";
        private const int VEHICLE_LAYER = 1 << 13 | 1 << 27;
        private const int TARGET_LAYERS = ~(1 << 10 | 1 << 12 | 1 << 13 | 1 << 17 | 1 << 18 | 1 << 27 | 1 << 28 | 1 << 29);
#endregion
#region Oxide Hooks
        private void Loaded() {
            Instance = this;
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(ADMIN_PERM, this);
        }
        private void OnServerInitialized() {
            PopulateRefuelLocations();
            ToggleSubscriptions(false);
            if (configData.Automation.Enabled) RunAutomatedEvent();
        }
        private void OnEntityTakeDamage(BaseNetworkable networkable, HitInfo info) {
            if (networkable == null || info == null) return;
            BaseMountable mountable = networkable as BaseMountable;
            if (mountable != null) {
                if (mountable.GetComponentInParent<RefuelHelicopter>()) NullifyDamage(info);
            }
            RefuelHelicopter refuelHelicopter = networkable is BaseHelicopter ? networkable.GetComponent<RefuelHelicopter>() : null;
            if (refuelHelicopter != null) refuelHelicopter.OnDamage(info);
        }
        private void OnEntityKill(BaseHelicopter helicopter) {
            RefuelHelicopter refuelHelicopter = helicopter?.GetComponent<RefuelHelicopter>();
            if (refuelHelicopter != null) {
                refuelHelicopter.destroyKill = false;
                UnityEngine.Object.Destroy(refuelHelicopter);
            }
        }
        private void OnEntityKill(CustomNPC.CustomScientistNPC customNpc) => customNpcs.Remove(customNpc);
        private void OnHelicopterRetire(PatrolHelicopterAI helicopterAI) {
            RefuelHelicopter refuelHelicopter = helicopterAI?.helicopterBase?.GetComponent<RefuelHelicopter>();
            if (refuelHelicopter != null) {
                if (refuelHelicopter.hasValidLocation || refuelHelicopter.isLanding || refuelHelicopter.isRefueling) {
                    InvokeHandler.CancelInvoke(refuelHelicopter, refuelHelicopter.ResetStateToPatrol);
                    refuelHelicopter.ResetStateToPatrol();
                }
                refuelHelicopter.isRetiring = true;
                refuelHelicopter.destroyKill = false;
            }
        }
        private object OnNpcTarget(ScientistNPC attacker, CustomNPC.CustomScientistNPC customNpc) => customNpcs.Contains(customNpc) ? (object)true : null;
        private object CanBradleyApcTarget(BradleyAPC bradleyApc, CustomNPC.CustomScientistNPC customNpc) => customNpcs.Contains(customNpc) ? (object)false : null;
        private object OnTurretTarget(NPCAutoTurret turret, CustomNPC.CustomScientistNPC customNpc) => customNpcs.Contains(customNpc) ? (object)true : null;
        private object CanBeTargeted(CustomNPC.CustomScientistNPC customNpc, MonoBehaviour behaviour) {
            if (customNpcs.Contains(customNpc)) {
                if (((behaviour is AutoTurret) || (behaviour is GunTrap) || (behaviour is FlameTurret)) && configData.NPC.TargetedByTurrets) return null;
                return false;
            }
            return null;
        }
        private void OnEntityDeath(CustomNPC.CustomScientistNPC customNpc, HitInfo info) {
            for (int i = 0; i < RefuelHelicopter.allHelicopters.Count; i++) {
                RefuelHelicopter refuelHelicopter = RefuelHelicopter.allHelicopters[i];
                if (refuelHelicopter.NPCs.Contains(customNpc)) {
                    refuelHelicopter.OnNPCKilled(customNpc);
                    return;
                }
            }
        }
        private void OnPlayerCorpseSpawned(CustomNPC.CustomScientistNPC customNpc, BaseCorpse corpse) {
            if (customNpc == null || corpse == null) return;
            Vector3 velocity;
            if (velocityInheritance.TryGetValue(customNpc, out velocity)) {
                velocityInheritance.Remove(customNpc);
                NextTick(() => corpse?.GetComponent<Rigidbody>()?.AddForce(velocity, ForceMode.VelocityChange));
            }
        }
        private void Unload() {
            RefuelPoints.Clear();
            for (int i = RefuelHelicopter.allHelicopters.Count - 1; i >= 0 ; i--) {
                RefuelHelicopter refuelHelicopter = RefuelHelicopter.allHelicopters[i];
                refuelHelicopter.killSilent = true;
                refuelHelicopter.destroyKill = false;
                UnityEngine.Object.Destroy(refuelHelicopter);
            }
            configData = null;
            Instance = null;
        }
#endregion
#region Functions
        private void ToggleSubscriptions(bool subscribe) {
            if (subscribe == isSubscribed) return;
            if (subscribe) {
                Subscribe(nameof(OnEntityTakeDamage));
                Subscribe(nameof(OnNpcTarget));
                Subscribe(nameof(CanBradleyApcTarget));
                Subscribe(nameof(OnTurretTarget));
                Subscribe(nameof(OnEntityKill));
            }
            else {
                Unsubscribe(nameof(OnEntityTakeDamage));
                Unsubscribe(nameof(OnNpcTarget));
                Unsubscribe(nameof(CanBradleyApcTarget));
                Unsubscribe(nameof(OnTurretTarget));
                Unsubscribe(nameof(OnEntityKill));
            }
            isSubscribed = subscribe;
        }
        private void RunAutomatedEvent() {
            timer.In(UnityEngine.Random.Range(configData.Automation.Minimum, configData.Automation.Maximum), () => {
                if (BasePlayer.activePlayerList.Count >= configData.Automation.RequiredPlayers) SpawnEntity();
                RunAutomatedEvent();
            }
            );
        }
        private void SpawnEntity(Vector3 positionOverride = default(Vector3)) {
            BaseHelicopter helicopter = GameManager.server.CreateEntity(HELICOPTER_PREFAB) as BaseHelicopter;
            helicopter.enableSaving = false;
            helicopter.Spawn();
            Broadcast("Notification.OnSpawned");
            NextTick(() => {
                if (helicopter == null) {
                    PrintError("[Plugin Conflict] Another plugin on your server has destroyed the helicopter when it spawned");
                    return;
                }
                helicopter.transform.position = positionOverride == default(Vector3) ? RandomPointOnWorldBounds() : positionOverride;
                helicopter.myAI.State_Patrol_Enter();
                helicopter.gameObject.AddComponent<RefuelHelicopter>();
            }
            );
        }
        private Vector3 RandomPointOnWorldBounds() {
            float size = TerrainMeta.Size.x / 2f;
            Vector3 position;
            if (UnityEngine.Random.value > 0.5f) position = new Vector3(UnityEngine.Random.value > 0.5f ? size : -size, 0, UnityEngine.Random.Range(-size, size));
            else position = new Vector3(UnityEngine.Random.Range(-size, size), 0, UnityEngine.Random.value > 0.5f ? size : -size);
            position.y = TerrainMeta.HeightMap.GetHeight(position) + 30f;
            return position;
        }
        private void PopulateRefuelLocations() {
            RefuelPoints = new List<ConfigData.LocationOptions.Monument.CustomOptions>(configData.Location.Custom.Where(x => x.Enabled));
            ConfigData.LocationOptions.Monument config = configData.Location.Monuments;
            MonumentInfo[] monuments = UnityEngine.Object.FindObjectsOfType<MonumentInfo>();
            for (int i = 0; i < monuments.Length; i++) {
                MonumentInfo monument = monuments[i];
                if (monument.name.Contains("harbor_1", CompareOptions.IgnoreCase)) {
                    if (config.HarbourLarge.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.LargeHarbour"), Position = monument.transform.TransformPoint(config.HarbourLarge.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.HarbourLarge.Rotation)
                        }
                        );
                        config.HarbourLarge.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("harbor_2", CompareOptions.IgnoreCase)) {
                    if (config.HarbourSmall.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.SmallHarbour"), Position = monument.transform.TransformPoint(config.HarbourSmall.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.HarbourSmall.Rotation)
                        }
                        );
                        config.HarbourSmall.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("airfield_1", CompareOptions.IgnoreCase)) {
                    if (config.Airfield.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.Airfield"), Position = monument.transform.TransformPoint(config.Airfield.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.Airfield.Rotation)
                        }
                        );
                        config.Airfield.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("launch_site_1", CompareOptions.IgnoreCase)) {
                    if (config.LaunchSite.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.LaunchSite"), Position = monument.transform.TransformPoint(config.LaunchSite.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.LaunchSite.Rotation)
                        }
                        );
                        config.LaunchSite.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("oilrigai2", CompareOptions.IgnoreCase)) {
                    if (config.LargeOilRig.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.LargeOilRig"), Position = monument.transform.TransformPoint(config.LargeOilRig.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.LargeOilRig.Rotation), IsOilRig = true
                        }
                        );
                        config.LargeOilRig.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("oilrigai", CompareOptions.IgnoreCase)) {
                    if (config.SmallOilRig.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.SmallOilRig"), Position = monument.transform.TransformPoint(config.SmallOilRig.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.SmallOilRig.Rotation), IsOilRig = true
                        }
                        );
                        config.SmallOilRig.Monument.Add(monument);
                    }
                    continue;
                }
                if (monument.name.Contains("powerplant_1", CompareOptions.IgnoreCase)) {
                    if (config.Powerplant.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.PowerPlant"), Position = monument.transform.TransformPoint(config.Powerplant.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.Powerplant.Rotation)
                        }
                        );
                        config.Powerplant.Monument.Add(monument);
                    }
                }
                if (monument.name.Contains("military_tunnel_1", CompareOptions.IgnoreCase)) {
                    if (config.MilitaryTunnels.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.MilitaryTunnel"), Position = monument.transform.TransformPoint(config.MilitaryTunnels.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.MilitaryTunnels.Rotation)
                        }
                        );
                        config.MilitaryTunnels.Monument.Add(monument);
                    }
                }
                if (monument.name.Contains("junkyard_1", CompareOptions.IgnoreCase)) {
                    if (config.Junkyard.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.Junkyard"), Position = monument.transform.TransformPoint(config.Junkyard.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.Junkyard.Rotation)
                        }
                        );
                        config.Junkyard.Monument.Add(monument);
                    }
                }
                if (monument.name.Contains("water_treatment_plant_1", CompareOptions.IgnoreCase)) {
                    if (config.WaterTreatment.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.WaterTreatment"), Position = monument.transform.TransformPoint(config.WaterTreatment.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.WaterTreatment.Rotation)
                        }
                        );
                        config.WaterTreatment.Monument.Add(monument);
                    }
                }
                if (monument.name.Contains("trainyard_1", CompareOptions.IgnoreCase)) {
                    if (config.TrainYard.Enabled) {
                        RefuelPoints.Add(new ConfigData.LocationOptions.Monument.CustomOptions() {
                            Name = Message("Monument.TrainYard"), Position = monument.transform.TransformPoint(config.TrainYard.Position), Rotation = monument.transform.rotation * Quaternion.Euler(config.TrainYard.Rotation)
                        }
                        );
                        config.TrainYard.Monument.Add(monument);
                    }
                }
            }
            Puts($"Found {RefuelPoints.Count} valid refuel points; {RefuelPoints.Select(x => Messages.ContainsKey(x.Name) ? Message(x.Name) : x.Name).ToSentence()}");
        }
        private static void Broadcast(string key, params object[] args) {
            foreach (BasePlayer player in BasePlayer.activePlayerList) player.ChatMessage(args?.Length > 0 ? string.Format(Instance.Message(key, player.userID), args) : Instance.Message(key, player.userID));
        }
        private static void NullifyDamage(HitInfo info) {
            info.damageTypes = new DamageTypeList();
            info.HitEntity = null;
            info.HitMaterial = 0;
            info.PointStart = Vector3.zero;
        }
        private static void ClearContainer(ItemContainer container) {
            if (container == null || container.itemList == null) return;
            for (int i = container.itemList.Count - 1; i >= 0; i--) {
                Item item = container.itemList[i];
                item.RemoveFromContainer();
                item.Remove(0f);
            }
        }
        private static void PopulateLoot(LootContainer container) {
            if (container == null || container.inventory == null) return;
            ClearContainer(container.inventory);
            int amount = UnityEngine.Random.Range(configData.Loot.MinimumItems, configData.Loot.MaximumItems);
            List<ConfigData.LootOptions.LootItem> list = Pool.GetList<ConfigData.LootOptions.LootItem>();
            list.AddRange(configData.Loot.Items);
            for (int i = 0; i < amount; i++) {
                if (list.Count == 0) list = new List<ConfigData.LootOptions.LootItem>(configData.Loot.Items);
                ConfigData.LootOptions.LootItem lootItem = list.GetRandom();
                list.Remove(lootItem);
                Item item = ItemManager.CreateByName(lootItem.Name, UnityEngine.Random.Range(lootItem.Minimum, lootItem.Maximum), lootItem.Skin);
                item.MoveToContainer(container.inventory);
            }
            Pool.FreeList(ref list);
        }
        private bool IsRefuelHelicopter(BaseHelicopter helicopter) => helicopter.GetComponent<RefuelHelicopter>() != null;
#endregion
#region CustomNPC
        public bool InitializeStates(BaseAIBrain<global : : HumanNPC> customNPCBrain) => false;
        public bool WantsToPopulateLoot(CustomNPC.CustomScientistNPC customNpc, NPCPlayerCorpse npcplayerCorpse) => false;
        public byte[] GetCustomDesign() => null;
#endregion
#region Component
        public class RefuelHelicopter : MonoBehaviour {
            internal static List<RefuelHelicopter> allHelicopters = new List<RefuelHelicopter>();
            protected BaseHelicopter Helicopter {
                get;
                private set;
            }
            protected PatrolHelicopterAI AI {
                get;
                private set;
            }
            protected List<BaseMountable> Mounts = new List<BaseMountable>();
            internal List<CustomNPC.CustomScientistNPC> NPCs = new List<CustomNPC.CustomScientistNPC>();
            protected List<LootContainer> Containers = new List<LootContainer>();
            internal bool hasValidLocation = false;
            internal bool isLanding = false;
            internal bool isRefueling = false;
            internal bool isRetiring = false;
            internal bool killSilent = false;
            private bool isOilRig = false;
            private bool enemiesInVicinity = false;
            private bool isDying = false;
            private bool hasDroppedOnDeath = false;
            internal bool destroyKill = true;
            private float actualHealth;
            private string locationName;
            private Vector3 targetLocation;
            private Quaternion targetRotation;
            private Vector3 hoverDistance = new Vector3(0f, 20f, 0f);
            private Vector3 landingLocation;
            private Quaternion landingRotation;
            private MapMarkerGenericRadius mapMarker;
            private float nextValidationTime;
            private const float TIME_TO_LAND = 5f;
            private float landTimeTaken = 0f;
            private const string MAP_MARKER_PREFAB = "assets/prefabs/tools/map/genericradiusmarker.prefab";
            private List<KeyValuePair<Vector3, float>> mountLocations = new List<KeyValuePair<Vector3, float>> {
                new KeyValuePair<Vector3, float>(new Vector3(-0.6f, 0.65f, 2.8f), 0f), new KeyValuePair<Vector3, float>(new Vector3(0.6f, 0.65f, 2.8f), 0f), new KeyValuePair<Vector3, float>(new Vector3(-0.8f, 0.68f, -0.5f), -90f), new KeyValuePair<Vector3, float>(new Vector3(0.8f, 0.68f, -0.5f), 90f), new KeyValuePair<Vector3, float>(new Vector3(-0.3f, 0.68f, 0.6f), 0f), new KeyValuePair<Vector3, float>(new Vector3(0.3f, 0.68f, 0.6f), 0f)
            }
            ;
            private void Awake() {
                Helicopter = GetComponent<BaseHelicopter>();
                AI = GetComponent<PatrolHelicopterAI>();
                Helicopter.maxCratesToSpawn = 0;
                actualHealth = Helicopter.health;
                InvokeHandler.Invoke(this, TriggerRefuel, UnityEngine.Random.Range(configData.Helicopter.MinRefuelTime, configData.Helicopter.MaxRefuelTime));
                CreateMountPoints();
                CreateNPCs();
                allHelicopters.Add(this);
                Instance.ToggleSubscriptions(true);
            }
            private void OnDestroy() {
                if (mapMarker != null && !mapMarker.IsDestroyed) mapMarker.Kill();
                if (!isDying) {
                    for (int i = 0; i < NPCs?.Count; i++) {
                        CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                        if (customNpc != null && !customNpc.IsDestroyed) customNpc.Kill();
                    }
                }
                for (int i = 0; i < Mounts?.Count; i++) {
                    BaseMountable mountable = Mounts[i];
                    if (mountable != null && !mountable.IsDestroyed) mountable.Kill();
                }
                if (killSilent) {
                    for (int i = 0; i < Containers?.Count; i++) {
                        LootContainer container = Containers[i];
                        if (container != null && !container.IsDestroyed) {
                            ClearContainer(container.inventory);
                            container.Kill();
                        }
                    }
                }
                allHelicopters?.Remove(this);
                if (allHelicopters.Count == 0) Instance?.ToggleSubscriptions(false);
                if (destroyKill && Helicopter != null && !Helicopter.IsDestroyed) Helicopter.Kill();
            }
            private void Update() {
                if (!hasValidLocation || (AI.enabled && isRetiring)) return;
                if (isLanding) {
                    landTimeTaken += Time.deltaTime;
                    float delta = Mathf.InverseLerp(0f, TIME_TO_LAND, landTimeTaken);
                    transform.position = Vector3.Lerp(landingLocation, targetLocation, delta);
                    transform.rotation = Quaternion.Slerp(landingRotation, targetRotation, delta);
                    if (delta >= 1f) {
                        isLanding = false;
                        hasValidLocation = false;
                        isRefueling = true;
                        DismountAll();
                        CreateLoot();
                        CreateMapMarker();
                        if (configData.Notification.BeginRefuelling) Broadcast("Notification.BeginRefuelling2", locationName);
                        InvokeHandler.Invoke(this, ResetStateToPatrol, configData.Helicopter.RefuelTime);
                    }
                    return;
                }
                float distanceFromTarget = Vector3Ex.Distance2D(transform.position, targetLocation);
                if (Time.realtimeSinceStartup > nextValidationTime) {
                    if (!IsClearToLand()) {
                        hasValidLocation = false;
                        if (configData.Notification.IntendedDestination) Broadcast("Notification.LocationOccupied");
                        InvokeHandler.Invoke(this, FindTargetLocation, 5f);
                        return;
                    }
                    FindEnemiesInVicinity();
                    nextValidationTime = Time.realtimeSinceStartup + 5f;
                }
                AIUpdate();
                SetTargetDestination(targetLocation + hoverDistance);
                if (enemiesInVicinity) return;
                if (distanceFromTarget < 5) {
                    isLanding = true;
                    landTimeTaken = 0f;
                    AI.enabled = false;
                    AI.ClearAimTarget();
                    landingLocation = transform.position;
                    landingRotation = transform.rotation;
                    for (int i = 0; i < NPCs.Count; i++) {
                        CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                        if (isOilRig) {
                            customNpc.NavAgent.areaMask = 25;
                            customNpc.NavAgent.agentTypeID = 0;
                        }
                        else {
                            customNpc.NavAgent.areaMask = 1;
                            customNpc.NavAgent.agentTypeID = -1372625422;
                        }
                    }
                }
            }
            private void SetTargetDestination(Vector3 targetDest) {
                AI.destination = targetDest;
                float distance = Vector3.Distance(targetDest, transform.position);
                if (distance > 30) AI.SetIdealRotation(AI.GetYawRotationTo(targetDest), -1f);
                AI.targetThrottleSpeed = 0.25f;
            }
            internal void ResetStateToPatrol() {
                if (mapMarker != null && !mapMarker.IsDestroyed) mapMarker.Kill();
                if (configData.NPC.Amount > 0 && NPCs.Count == 0) {
                    if (configData.Helicopter.SelfDestruct) {
                        if (configData.Helicopter.SelfDestructTime == 0) configData.Helicopter.SelfDestructTime = 300;
                        if (!InvokeHandler.IsInvoking(this, Helicopter.DieInstantly)) {
                            Broadcast("Notification.SelfDestruct", configData.Helicopter.SelfDestructTime);
                            InvokeHandler.Invoke(this, Helicopter.DieInstantly, configData.Helicopter.SelfDestructTime);
                        }
                        return;
                    }
                    else {
                        Broadcast("Notification.EventFinished");
                        destroyKill = false;
                        InvokeHandler.Invoke(this, ()=> {
                            AI.enabled = true;
                            AI.ClearAimTarget();
                            AI.State_Patrol_Enter();
                            Destroy(this);
                        }
                        , 5f);
                        return;
                    }
                }
                if (configData.Notification.FinishRefuelling) Broadcast("Notification.FinishRefuellingPre3", locationName, configData.Helicopter.IdleTime);
                for (int i = 0; i < NPCs.Count; i++) {
                    CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                    CustomNPC.SetDestination(customNpc, Helicopter.transform.position, () => MountAny(customNpc));
                }
                PackLoot();
                InvokeHandler.Invoke(this, ResetState, configData.Helicopter.IdleTime);
            }
            private void ResetState() {
                for (int i = 0; i < NPCs.Count; i++) {
                    CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                    if (customNpc != null && !customNpc.isMounted) {
                        MountAny(customNpc);
                    }
                }
                isRefueling = false;
                enabled = true;
                AI.enabled = true;
                AI.ClearAimTarget();
                AI.State_Patrol_Enter();
                hasValidLocation = false;
                if (configData.Notification.FinishRefuelling) Broadcast("Notification.FinishRefuelling2", locationName);
                InvokeHandler.Invoke(this, TriggerRefuel, UnityEngine.Random.Range(configData.Helicopter.MinRefuelTime, configData.Helicopter.MaxRefuelTime));
            }
            private void AIUpdate() {
                AI.MoveToDestination();
                AI.UpdateRotation();
                AI.UpdateSpotlight();
                AI.AIThink();
                AI.DoMachineGuns();
            }
            private bool IsClearToLand() => !Vis.AnyColliders(targetLocation, 10f, VEHICLE_LAYER);
            private void FindEnemiesInVicinity() {
                enemiesInVicinity = false;
                List<BasePlayer> players = Pool.GetList<BasePlayer>();
                Vis.Entities(targetLocation, 30f, players);
                players.RemoveAll(x => x.IsNpc);
                for (int i = players.Count - 1; i >= 0; i--) {
                    if (!AI.PlayerVisible(players[i])) players.RemoveAt(i);
                }
                if (players.Count > 0) {
                    enemiesInVicinity = true;
                    AI._targetList.Clear();
                    players.ForEach(x => AI._targetList.Add(new PatrolHelicopterAI.targetinfo(x, x)));
                }
                Pool.FreeList(ref players);
            }
            internal void TriggerRefuel() {
                if (isRetiring) return;
                FindTargetLocation();
                if (!hasValidLocation) InvokeHandler.Invoke(this, TriggerRefuel, UnityEngine.Random.Range(configData.Helicopter.MinRefuelTime, configData.Helicopter.MaxRefuelTime));
                else {
                    if (configData.Notification.IntendedDestination) Broadcast("Notification.TargetLocation", locationName);
                    nextValidationTime = Time.realtimeSinceStartup + 20f;
                    AI.ClearAimTarget();
                }
            }
            private void FindTargetLocation() {
                targetLocation = Vector3.zero;
                targetRotation = Quaternion.identity;
                if (configData.Location.RefuelDetermination == "Closest") {
                    IOrderedEnumerable<ConfigData.LocationOptions.Monument.CustomOptions> points = RefuelPoints.OrderBy(x => Vector3.Distance(x.Position, transform.position));
                    for (int i = 0; i < points.Count();
                    i++) {
                        ConfigData.LocationOptions.Monument.CustomOptions point = points.ElementAt(i);
                        if (Vis.AnyColliders(point.Position, 10f, VEHICLE_LAYER)) continue;
                        locationName = point.Name;
                        targetLocation = point.Position;
                        targetRotation = Quaternion.Euler(0f, point.Rotation.y, 0f);
                        hasValidLocation = true;
                        isOilRig = point.IsOilRig;
                        return;
                    }
                }
                else {
                    List<ConfigData.LocationOptions.Monument.CustomOptions> points = new List<ConfigData.LocationOptions.Monument.CustomOptions>(RefuelPoints);
                    for (int i = 0; i < points.Count; i++) {
                        ConfigData.LocationOptions.Monument.CustomOptions point = points.GetRandom();
                        if (Vis.AnyColliders(point.Position, 10f, VEHICLE_LAYER)) {
                            points.Remove(point);
                            continue;
                        }
                        locationName = point.Name;
                        targetLocation = point.Position;
                        targetRotation = Quaternion.Euler(0f, point.Rotation.y, 0f);
                        hasValidLocation = true;
                        isOilRig = point.IsOilRig;
                        return;
                    }
                }
                hasValidLocation = false;
                print($"[HeliRefuel] - Unable to land for refuel.All refuel points are occupied by players or vehicles");
            }
            private void CreateMapMarker() {
                if (!configData.Helicopter.UseMapMarker) return;
                mapMarker = GameManager.server.CreateEntity(MAP_MARKER_PREFAB, transform.position) as MapMarkerGenericRadius;
                mapMarker.enableSaving = false;
                mapMarker.Spawn();
                mapMarker.color1 = mapMarker.color2 = ConvertToColor(configData.Helicopter.MarkerColor);
                mapMarker.alpha = configData.Helicopter.MarkerOpacity;
                mapMarker.radius = configData.Helicopter.MarkerSize;
                mapMarker.SendUpdate();
            }
            private Color ConvertToColor(string color) {
                if (color.StartsWith("#")) color = color.Substring(1);
                int red = int.Parse(color.Substring(0, 2), NumberStyles.AllowHexSpecifier);
                int green = int.Parse(color.Substring(2, 2), NumberStyles.AllowHexSpecifier);
                int blue = int.Parse(color.Substring(4, 2), NumberStyles.AllowHexSpecifier);
                return new Color((float)red / 255, (float)green / 255, (float)blue / 255);
            }
#region Death and Damage
            internal void OnDamage(HitInfo info) {
                actualHealth -= info.damageTypes.Total();
                if (actualHealth < 0f) {
                    if (isRefueling || isLanding) {
                        OnDeath(info);
                        NullifyDamage(info);
                    }
                    else {
                        if (isDying && info.damageTypes.GetMajorityDamageType() == DamageType.Generic) DropOnDeath(info);
                        if (!isDying) CrashToDeath();
                    }
                }
            }
            internal void OnDeath(HitInfo info) {
                if (isDying) return;
                isDying = true;
                if (isRefueling || isLanding) {
                    AI.moveSpeed = 0;
                    typeof(PatrolHelicopterAI).GetField("_lastMoveDir", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).SetValue(AI, Vector3.zero);
                }
                DropOnDeath(info);
                Interface.CallHook("OnEntityDeath", Helicopter);
                Helicopter.DieInstantly();
            }
            internal void CrashToDeath() {
                isDying = true;
                AI.CriticalDamage();
            }
            private void DropOnDeath(HitInfo info) {
                if (hasDroppedOnDeath) return;
                hasDroppedOnDeath = true;
                if (!isRefueling) {
                    if (configData.Helicopter.DropCratesOnDeath) DropLoot();
                    if (configData.Helicopter.DropNPCsOnDeath) {
                        Vector3 direction = (AI.GetLastMoveDir() * AI.GetMoveSpeed()) * 0.75f;
                        for (int i = NPCs.Count - 1; i >= 0; i--) {
                            CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                            if (customNpc != null && !customNpc.IsDestroyed) {
                                Instance.velocityInheritance[customNpc] = direction + (UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(2f, 5f));
                                DismountObject(customNpc, true);
                                customNpc.Die(new HitInfo(info != null ? info.Initiator : Helicopter, customNpc, DamageType.Explosion, 1000f));
                            }
                        }
                    }
                    else {
                        for (int i = NPCs.Count - 1; i >= 0; i--) {
                            CustomNPC.CustomScientistNPC customNpc = NPCs[i];
                            if (customNpc != null && !customNpc.IsDestroyed) {
                                DismountObject(customNpc, true);
                                customNpc.Kill();
                            }
                        }
                    }
                }
                else {
                    if (configData.Helicopter.DropCratesOnDeathLanded) DropLoot();
                }
            }
#endregion
#region NPCs and Mounting
            private void CreateMountPoints() {
                for (int i = 0; i < Mathf.Clamp(configData.NPC.Amount, 0, 6);
                i++) {
                    BaseMountable mountable = GameManager.server.CreateEntity(CHAIR_PREFAB, transform.position) as BaseMountable;
                    mountable.enableSaving = false;
                    mountable.isMobile = true;
                    mountable.skinID = (ulong)1169930802;
                    mountable.Spawn();
                    Destroy(mountable.GetComponent<DestroyOnGroundMissing>());
                    Destroy(mountable.GetComponent<GroundWatch>());
                    mountable.GetComponent<MeshCollider>().convex = true;
                    mountable.SetParent(Helicopter);
                    KeyValuePair<Vector3, float> mountOffset = mountLocations[i];
                    mountable.transform.localPosition = mountOffset.Key;
                    mountable.transform.localRotation = Quaternion.Euler(0, mountOffset.Value, 0);
                    Mounts.Add(mountable);
                }
            }
            private void CreateNPCs() {
                configData.NPC.CustomNPCSettings.EnableNavMesh = false;
                configData.NPC.CustomNPCSettings.CanUseWeaponMounted = false;
                configData.NPC.CustomNPCSettings.EquipWeapon = false;
                for (int i = 0; i < Mathf.Clamp(configData.NPC.Amount, 0, 6);
                i++) {
                    CustomNPC.CustomScientistNPC customNpc = CustomNPC.SpawnNPC(Instance, transform.position, configData.NPC.CustomNPCSettings);
                    if (customNpc != null) {
                        Instance.customNpcs.Add(customNpc);
                        NPCs.Add(customNpc);
                        MountAny(customNpc);
                    }
                }
            }
            internal void MountAny(CustomNPC.CustomScientistNPC customNpc) {
                for (int i = 0; i < Mounts.Count; i++) {
                    BaseMountable mountable = Mounts[i];
                    if (!mountable.IsMounted()) {
                        customNpc.SetPaused(true);
                        customNpc.HolsterWeapon();
                        MountObject(customNpc, mountable);
                        return;
                    }
                }
            }
            private void MountObject(CustomNPC.CustomScientistNPC customNpc, BaseMountable mountable) {
                customNpc.EnsureDismounted();
                mountable._mounted = customNpc;
                customNpc.MountObject(mountable, 0);
                customNpc.MovePosition(mountable.mountAnchor.transform.position);
                customNpc.transform.rotation = mountable.mountAnchor.transform.rotation;
                customNpc.ServerRotation = mountable.mountAnchor.transform.rotation;
                customNpc.OverrideViewAngles(mountable.mountAnchor.transform.rotation.eulerAngles);
                customNpc.eyes.NetworkUpdate(mountable.mountAnchor.transform.rotation);
                customNpc.ClientRPCPlayer(null, customNpc, "ForcePositionTo", mountable.transform.position);
                mountable.SetFlag(BaseEntity.Flags.Busy, true, false);
            }
            private void DismountAll() {
                for (int i = 0; i < NPCs.Count; i++) {
                    DismountObject(NPCs[i]);
                }
            }
            private void DismountObject(CustomNPC.CustomScientistNPC customNpc, bool isDead = false) {
                if (!customNpc.isMounted) return;
                BaseMountable mountable = customNpc.GetMounted();
                Vector3 dismountPosition = transform.position + (transform.forward * UnityEngine.Random.Range(-2f, 2f)) + ((UnityEngine.Random.value > 0.5f ? transform.right : -transform.right) * 3f);
                if (NavMesh.SamplePosition(dismountPosition, out navHit, 3f, -1)) dismountPosition = navHit.position;
                customNpc.mounted.Set(null);
                customNpc.SendNetworkUpdate(BasePlayer.NetworkQueue.Update);
                mountable._mounted = null;
                mountable.SetFlag(BaseEntity.Flags.Busy, false, false);
                customNpc.transform.position = dismountPosition;
                customNpc.transform.rotation = Quaternion.identity;
                customNpc.NavAgent.Warp(dismountPosition);
                customNpc.EquipWeapon();
                CustomNPC.SetRoamHomePosition(customNpc, customNpc.transform.position);
                customNpc.SetPaused(false);
            }
            internal void OnNPCKilled(CustomNPC.CustomScientistNPC customNpc) {
                if (killSilent) return;
                NPCs.Remove(customNpc);
                if (!isDying && NPCs.Count == 0) {
                    if (!isRefueling) CrashToDeath();
                    else {
                        InvokeHandler.CancelInvoke(this, ResetStateToPatrol);
                        ResetStateToPatrol();
                    }
                }
            }
#endregion
#region Loot
            private void CreateLoot() {
                int amount = UnityEngine.Random.Range(configData.Loot.MinimumCrates, configData.Loot.MaximumCrates);
                for (int i = 0; i < amount; i++) {
                    LootContainer container = CreateContainer();
                    if (container != null) {
                        Rigidbody rigidbody = container.gameObject.GetComponent<Rigidbody>();
                        if (rigidbody != null) rigidbody.useGravity = false;
                        Containers.Add(container);
                    }
                }
            }
            private void DropLoot() {
                int amount = UnityEngine.Random.Range(configData.Loot.MinimumCrates, configData.Loot.MaximumCrates);
                Vector3 direction = (AI.GetLastMoveDir() * AI.GetMoveSpeed()) * 0.75f;
                for (int i = 0; i < amount; i++) {
                    LootContainer container = CreateContainer(true);
                    if (container != null) {
                        container.Invoke(container.RemoveMe, 1800f);
                        Rigidbody rigidbody = container.gameObject.AddComponent<Rigidbody>();
                        rigidbody.useGravity = true;
                        rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
                        rigidbody.mass = 2f;
                        rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
                        rigidbody.velocity = direction + (UnityEngine.Random.onUnitSphere * UnityEngine.Random.Range(1f, 3f));
                        rigidbody.angularVelocity = Vector3Ex.Range(-1.75f, 1.75f);
                        rigidbody.drag = 0.5f * (rigidbody.mass / 5f);
                        rigidbody.angularDrag = 0.2f * (rigidbody.mass / 5f);
                        FireBall fireBall = GameManager.server.CreateEntity(Helicopter.fireBall.resourcePath) as FireBall;
                        if (fireBall) {
                            fireBall.SetParent(container, false, false);
                            fireBall.Spawn();
                            fireBall.GetComponent<Rigidbody>().isKinematic = true;
                            fireBall.GetComponent<Collider>().enabled = false;
                        }
                        container.SendMessage("SetLockingEnt", fireBall.gameObject, SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
            private LootContainer CreateContainer(bool ignoreRaycast = false) {
                string prefab = UnityEngine.Random.Range(0, 1) == 1 ? ELITE_CRATE_PREFAB : HELI_CRATE_PREFAB;
                Vector2 random = UnityEngine.Random.insideUnitCircle.normalized;
                Vector3 rayPosition = transform.position + (new Vector3(random.x, 0f, random.y) * 6f) + (Vector3.up * 5f);
                if (ignoreRaycast || Physics.Raycast(new Ray(rayPosition, Vector3.down), out raycastHit, 10f, TARGET_LAYERS, QueryTriggerInteraction.Ignore)) {
                    Vector3 point = ignoreRaycast ? rayPosition : raycastHit.point;
                    LootContainer container = GameManager.server.CreateEntity(prefab, point, Quaternion.Euler(0f, UnityEngine.Random.Range(0, 360), 0f)) as LootContainer;
                    container.enableSaving = false;
                    container.Spawn();
                    if (configData.Loot.CustomLoot) PopulateLoot(container);
                    return container;
                }
                return null;
            }
            private void PackLoot() {
                for (int i = Containers.Count - 1; i >= 0; i--) {
                    LootContainer container = Containers[i];
                    if (container != null && !container.IsDestroyed) {
                        Containers.Remove(container);
                        ClearContainer(container.inventory);
                        container.Kill();
                    }
                }
            }
#endregion
        }
#endregion
#region Commands
        [ConsoleCommand("hr")]
        private void ccmdHR(ConsoleSystem.Arg arg) {
            if (arg.Connection != null) return;
            if (arg.Args == null || arg.Args.Length == 0) {
                Puts("hr call - Call a refueling helicopter");
                Puts("hr killall - Kill all refueling helicopters");
                Puts("hr forcerf - Force all active helicopters to refuel");
                Puts("hr cancelrf - Force all active helicopters to finish refuelling");
                return;
            }
            switch (arg.Args[0].ToLower()) {
                case "call" : SpawnEntity();
                return;
                case "killall" : Puts($"Killing {RefuelHelicopter.allHelicopters.Count} refuel helicopters");
                for (int i = 0; i < RefuelHelicopter.allHelicopters.Count; i++) {
                    RefuelHelicopter refuelHelicopter = RefuelHelicopter.allHelicopters[i];
                    refuelHelicopter.killSilent = true;
                    UnityEngine.Object.Destroy(refuelHelicopter);
                }
                return;
                case "forcerf" : for (int i = 0; i < RefuelHelicopter.allHelicopters.Count; i++) {
                    RefuelHelicopter refuelHelicopter = RefuelHelicopter.allHelicopters[i];
                    if (!refuelHelicopter.ha
// ... [Code preview truncated due to length. Full source in attached file] ...

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

Другие ресурсы пользователя 15FPS

Сверху