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

FREE AFDrops : 1.5.3 1.5.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using System.Globalization;
using System.Linq;
using Facepunch;
using UnityEngine.AI;
using Rust;
namespace Oxide.Plugins {
    [Info("AFDrops", "ZTL/FastBurst", "1.5.3", ResourceId = 81)]
    [Description("Cargo Plane circling airfield, then dropping crates during low-pass of runway.")]
    class AFDrops : RustPlugin {
        [PluginReference]
        Plugin PlaneCrashRandom, PlaneCrash, AdvAirstrike;
#region Vars
        private const string PERM_ADMIN = "afdrops.admin";
        bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
        private const string CARGOPLANE_PREFAB = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
        private const string SUPPLYDROP_PREFAB = "assets/prefabs/misc/supply drop/supply_drop.prefab";
        private const string SMOKE_EFFECT = "assets/bundled/prefabs/fx/smoke_signal_full.prefab";
        private const string SIRENLIGHT_EFFECT = "assets/prefabs/io/electric/lights/sirenlightorange.prefab";
        private const string SIRENALARM_EFFECT = "assets/prefabs/deployable/playerioents/alarms/audioalarm.prefab";
        private const string MAPMARKER_PREFAB = "assets/prefabs/tools/map/genericradiusmarker.prefab";
        private const string VENDING_PREFAB = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
        private const string FIRECANNON_EFFECT = "assets/prefabs/npc/m2bradley/effects/maincannonattack.prefab";
        private const string HELIEXPLOSION_EFFECT = "assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab";
        private const string DEBRIS_EFFECT = "assets/prefabs/npc/patrol helicopter/damage_effect_debris.prefab";
        private const string HELICOPTER_PREFAB = "assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab";
        private const string MLRS_PREFAB = "assets/content/vehicles/mlrs/rocket_mlrs.prefab";
        public int FlightNumber = 0;
        private bool statusPC = false;
        private bool statusPCR = false;
        private static bool debug = false;
        private static AFDrops Instance;
        private static AirfieldPlaneMono airfieldMono;
        private List<SupplyDrop> drops = new List<SupplyDrop>();
        private readonly System.Random _random = new System.Random();
        MonumentInfo monumentInfo;
        private List<MapMarkerGenericRadius> dropZoneMarkerList = new List<MapMarkerGenericRadius>();
        private List<VendingMachineMapMarker> dropVendingMarkerList = new List<VendingMachineMapMarker>();
        private MapMarkerGenericRadius mapMarker;
        private VendingMachineMapMarker vendingMarker;
        List<AF> Airfields = new List<AF>();
#endregion
#region Oxide Hooks
        private void Init() {
            Instance = this;
        }
        private void OnServerInitialized() {
            permission.RegisterPermission(PERM_ADMIN, this);
            if (!configData.GlobalSettings.enabled) return;
            lang.RegisterMessages(Messages, this);
            CheckMonuments();
            configData.GlobalSettings.RandomTimerMin = Mathf.Max(1, configData.GlobalSettings.RandomTimerMin);
            configData.GlobalSettings.RandomTimerMax = Mathf.Max(2, configData.GlobalSettings.RandomTimerMax);
            if (configData.GlobalSettings.EnableTimedEvents) StartTimedEvent();
        }
        // HotFix for Mounument Bradley to disallow Bradley from killing Supply Drops
        private void OnEntityTakeDamage(SupplyDrop entity, HitInfo info) {
            if (entity == null || info == null) return;
            if ((entity is SupplyDrop && drops.Contains(entity)) && info.Initiator is BradleyAPC) info.damageTypes.ScaleAll(0);
        }
        private void Unload() {
            if (airfieldMono != null) UnityEngine.Object.Destroy(airfieldMono);
            foreach (var drop in drops) if (!drop.IsDestroyed) drop.Kill();
            WipeZoneMarkers(dropZoneMarkerList.ToList());
            WipeVendingMarkers(dropVendingMarkerList.ToList());
            statusPC = false;
            statusPCR = false;
            Instance = null;
            configData = null;
            for (int i = EventHelicopter.allHelicopters.Count - 1; i >= 0; i--) {
                EventHelicopter exHelicopter = EventHelicopter.allHelicopters[i];
                exHelicopter.killSilent = true;
                UnityEngine.Object.Destroy(exHelicopter);
            }
        }
#endregion
#region Event Checks
        AF GetAF(Vector3 loc, float rot) => new AF() {
            loc = loc, rot = rot
        }
        ;
        private void CheckMonuments() {
            bool hasAirfield = false;
            foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>()) {
                var monumentName = GetMonumentName(monument);
                if (monumentName == null || !monumentName.Contains("airfield")) continue;
                hasAirfield = true;
                monumentInfo = monument;
                var go = monumentInfo.gameObject.transform;
                var loc = go.position;
                var rot = go.eulerAngles.y;
                hasAirfield = true;
                Airfields.Add(GetAF(loc, rot));
                PrintWarning("AirField was found on this map.");
            }
            if (!hasAirfield) {
                PrintWarning("No AirField found on your map PLUGIN UNLOADED.");
                covalence.Server.Command("o.unload AirFieldEvent");
                return;
            }
        }
        private void StartTimedEvent() {
            float nextEvent = UnityEngine.Random.Range(configData.GlobalSettings.RandomTimerMin, configData.GlobalSettings.RandomTimerMax + 1);
            timer.Repeat(nextEvent, 0, () => {
                if (airfieldMono != null) Puts("There is already an active Airfield Drops event.");
                else {
                    if (CallAFDrop()) Puts("Attempting to start Airfield Drops event.");
                }
            }
            );
        }
#endregion
#region API Event Running Checks
        private bool IsAFPlane(CargoPlane cargoplane) => isAFPlane(cargoplane);
        private bool isAFPlane(CargoPlane cargoplane) {
            if (airfieldMono != null) {
                cargoplane.GetComponent<AirfieldPlaneMono>();
                return true;
            }
            else return false;
        }
#endregion
#region Functions
        public string GetMonumentName(MonumentInfo monument) {
            var gameObject = monument.gameObject;
            while (gameObject.name.StartsWith("assets/") == false && gameObject.transform.parent != null) {
                gameObject = gameObject.transform.parent.gameObject;
            }
            return gameObject?.name;
        }
        private bool CallAFDrop() {
            if (!configData.GlobalSettings.enabled) {
                Puts("Plugin is disabled in config.");
                return false;
            }
            if (Airfields.Count == 0) {
                PrintWarning("No Airfield found on this map.");
                return false;
            }
            if (BasePlayer.activePlayerList.Count < configData.GlobalSettings.MinRequiredPlayers) {
                Puts("Skipping Airfield Drops  event : Not enough players.");
                return false;
            }
            FlightNumber = UnityEngine.Random.Range(3000, 9999);
            AF af = Airfields[0];
            var entity = (CargoPlane)GameManager.server.CreateEntity(CARGOPLANE_PREFAB, new Vector3(), new Quaternion(), true);
            if (configData.GlobalSettings.CheckPlugins) {
                if (PlaneCrashRandom && (bool)PlaneCrashRandom.Call("IsRandomCrashPlane", entity)) {
                    PrintWarning("Currently there is an active Random Plane Crash event.Restarting Event countdown.");
                    StartTimedEvent();
                    statusPCR = true;
                    return false;
                }
                else if (PlaneCrash && (bool)PlaneCrash.Call("IsCrashPlane", entity)) {
                    PrintWarning("Currently there is an active Plane Crash event.Restarting Event countdown.");
                    StartTimedEvent();
                    statusPC = true;
                    return false;
                }
                else PrintWarning("There is no active plane crash events.");
            }
            // Wipe Map Markers and Drops before next event.WipeZoneMarkers(Instance.dropZoneMarkerList.ToList());
            WipeVendingMarkers(Instance.dropVendingMarkerList.ToList());
            foreach (var drop in drops) if (!drop.IsDestroyed) drop.Kill();
            for (int i = EventHelicopter.allHelicopters.Count - 1; i >= 0; i--) {
                EventHelicopter exHelicopter = EventHelicopter.allHelicopters[i];
                exHelicopter.killSilent = true;
                UnityEngine.Object.Destroy(exHelicopter);
            }
            // Start New Event Entities
            entity.Spawn();
            airfieldMono = entity.gameObject.AddComponent<AirfieldPlaneMono>();
            UnityEngine.Object.Destroy(entity.GetComponent<SaveRestore>());
            SpawnMapMarker();
            return true;
        }
        private static void RunEffect(string name, BaseEntity entity = null, Vector3 position = new Vector3(), Vector3 offset = new Vector3()) {
            if (entity != null) Effect.server.Run(name, entity, 0, offset, position, null, true);
            else Effect.server.Run(name, position, Vector3.up, null, true);
        }
        private void DropMRLS(Vector3 pos) {
            int MLRSAmount = configData.MissleSettings.MRSLAmount;
            if (MLRSAmount == 0) return;
            float RandomRange = configData.MissleSettings.mrlsRadius;
            Instance.timer.Repeat(1.8f, MLRSAmount, () => {
                BaseEntity AirfieldMLRS = GameManager.server.CreateEntity(MLRS_PREFAB, pos + new Vector3(UnityEngine.Random.Range(-(RandomRange), (RandomRange)), 450, UnityEngine.Random.Range(-(RandomRange), (RandomRange))), new Quaternion(), true);
                AirfieldMLRS.Spawn();
                AirfieldMLRS.skinID = 29051978;
            }
            );
        }
#endregion
#region Map Markers
        private void SpawnMapMarker() {
            if (!configData.MapMarkerSettings.EnableMapMarker) return;
            AF af = Airfields[0];
            mapMarker = GameManager.server.CreateEntity(MAPMARKER_PREFAB, af.loc) as MapMarkerGenericRadius;
            mapMarker.Spawn();
            mapMarker.radius = configData.MapMarkerSettings.DropZoneRadius;
            mapMarker.alpha = configData.MapMarkerSettings.DropZoneAlpha;
            mapMarker.color1 = Color.red;
            mapMarker.SendUpdate();
            vendingMarker = GameManager.server.CreateEntity(VENDING_PREFAB, af.loc) as VendingMachineMapMarker;
            vendingMarker.markerShopName = configData.MapMarkerSettings.EventName;
            vendingMarker.Spawn();
            vendingMarker.SendNetworkUpdate();
            dropZoneMarkerList.Add(mapMarker);
            dropVendingMarkerList.Add(vendingMarker);
        }
        private void WipeZoneMarkers(List<MapMarkerGenericRadius> markers) {
            foreach (var mapMarker in markers) {
                if (mapMarker == null || mapMarker.IsDestroyed) {
                    continue;
                }
                mapMarker.Kill();
                mapMarker.SendUpdate();
            }
            markers.Clear();
        }
        private void WipeVendingMarkers(List<VendingMachineMapMarker> markers) {
            foreach (var mapMarker in markers) {
                if (mapMarker == null || mapMarker.IsDestroyed) {
                    continue;
                }
                mapMarker.Kill();
                mapMarker.SendNetworkUpdate();
            }
            markers.Clear();
        }
#endregion
#region AFDropPlane Class
        public class AirfieldPlaneMono : FacepunchBehaviour {
            List<bool> dropped = new List<bool> {
                false, false, false, false, false
            }
            ;
            Vector3 ZeroY(Vector3 input) => new Vector3(input.x, 0, input.z);
            AF Airfield = Instance.Airfields[0];
            Vector3 posRef = Vector3.zero;
            public CargoPlane plane;
            public bool started;
            Vector3 targetDir;
            int turn = 1, circles = 0;
            bool CircleBlocked = false;
            bool exitSent = false;
            int speedmult = 10;
            public List<TargetInfo> targets = new List<TargetInfo>();
            public class TargetInfo {
                public bool Direct = false, Started = false;
                public Vector3 TargetPos = new Vector3();
                public Vector3 AimTarget = new Vector3();
                public Vector3 PivotPoint;
                public GameObject Trans = new GameObject();
                public Vector3 Adjust => new Vector3(pitch, yaw, roll);
                public float rotatemulti, roll = 0, pitch = 0, yaw = 0;
            }
#region Flight Movements
            public void Awake() {
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-configData.PlaneSettings.CircleRadius, configData.PlaneSettings.Height, 0)), Direct = true, rotatemulti = 40
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-configData.PlaneSettings.CircleRadius, configData.PlaneSettings.Height, 0)), Direct = true, rotatemulti = 40
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-configData.PlaneSettings.CircleRadius, configData.PlaneSettings.Height, 0)), Direct = true, rotatemulti = 40
                }
                );
                // Start Landing Pattern
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-2175, configData.PlaneSettings.Height, -221)), Direct = true, rotatemulti = 1.1f
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-1897, 100, 225)), Direct = true, rotatemulti = 1.1f
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-1460, 70, 225)), Direct = true, rotatemulti = 1.1f
                }
                );
                // End Turns Begin Runway Approach & Centering
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-716, 55, 100)), Direct = true, rotatemulti = 20
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-316, 40, 40)), Direct = true, rotatemulti = 20
                }
                );
                // Start Runway run
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(-94, -5, 5)), Direct = true, rotatemulti = 20
                }
                );
                // End Runway Run
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(120, -5, -40)), Direct = true, rotatemulti = 1
                }
                );
                // Start Take off
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(230, 60, -65)), Direct = true, rotatemulti = 1
                }
                );
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(562, 200, -302)), Direct = true, rotatemulti = 1
                }
                );
                // Leave Map
                targets.Add(new TargetInfo() {
                    TargetPos = RelativePos(new Vector3(2850, 500, -4020)), Direct = true, rotatemulti = 1
                }
                );
                plane = GetComponentInParent<CargoPlane>();
                plane.enabled = false;
                plane.transform.position = RelativePos(new Vector3(-265.5f, configData.PlaneSettings.Height, 4333.5f));
                UpdateDirectionaAndRotation();
                started = true;
                SendChatMessage("Notification.Inbound", Instance.FlightNumber.ToString());
                if (configData.PlaneSettings.SmokeTrail) {
                    RunEffect(SMOKE_EFFECT, plane, new Vector3(), Vector3.up * 3);
                    RunEffect(SMOKE_EFFECT, plane, new Vector3(), Vector3.up * 3);
                }
            }
            public void FixedUpdate() {
                if (!started) return;
                if (turn == 2 && circles < 6) {
                    DoCircle();
                    UpdateDirectionaAndRotation();
                    return;
                }
                if (Vector3.Distance(targets[turn].TargetPos, this.transform.position) < 40f) {
                    turn++;
                    if (targets.Count > turn) targets[turn].roll = targets[turn - 1].roll;
                }
                if (targets.Count == turn) {
                    plane.Kill();
                    return;
                }
                else if (targets[turn].Direct) GotoDirect();
                else GotoIndirect();
                UpdateDirectionaAndRotation();
            }
            public void OnDestroy() {
                if (plane?.IsDestroyed == false) plane.Kill();
                Instance.WipeZoneMarkers(Instance.dropZoneMarkerList.ToList());
                Instance.WipeVendingMarkers(Instance.dropVendingMarkerList.ToList());
            }
#endregion
#region Movements
            public void DoCircle() {
                plane.transform.RotateAround(Airfield.loc, Vector3.down, configData.PlaneSettings.PlaneSpeed * 0.8f * Time.deltaTime);
                if (!CircleBlocked && Vector3.Distance(transform.position, targets[turn].TargetPos) < 30) {
                    CircleBlocked = true;
                    Instance.timer.Once(1f, () => CircleBlocked = false);
                    circles++;
                    string msgs = circles == 1 ? "Notification.FirstCircle" : circles == 2 ? "Notification.SecondCircle" : circles == 3 ? "Notification.ThirdCircle" : circles == 4 ? "Notification.FourthCircle" : circles == 5 ? "Notification.FifthCircle" : circles == 6 ? "Notification.ApproachBound" : "";
                    if (circles < 7) SendChatMessage(msgs, Instance.FlightNumber.ToString());
                }
            }
            public void GotoDirect() {
#region Areas to Drop Supply Drops
                if (turn > 6) {
                    if (!dropped[2] && Vector3.Distance(MakeRealPos(transform.position), new Vector3(-88.4f, 0, -6.4f)) < 20) if (configData.SupplyDropSettings.NumberOfDroppedCrates > 2) {
                        DoCrateDrop(2);
                        if (configData.GlobalSettings.HeliChance == 100 || UnityEngine.Random.Range(0, 100) < configData.GlobalSettings.HeliChance) {
                            Instance.SpawnHeli();
                            Instance.timer.Once(0.5f, () => SendChatMessage("Notification.Heli", Instance.FlightNumber.ToString()));
                        }
                        if (Instance.AdvAirstrike && configData.AdvAirstrikeSettings.enableAdvAirstrike) {
                            string[] msg = configData.AdvAirstrikeSettings.StrikeTypes;
                            string command = configData.AdvAirstrikeSettings.AdvAirstrikeCommand;
                            Instance.Server.Command($"{command} {msg.GetRandom()} {Airfield.loc.x} {Airfield.loc.z}");
                        }
                        SendChatMessage("Notification.LandingMessage", Instance.FlightNumber.ToString());
                        if (configData.MissleSettings.enabled) Instance.timer.Once(2.5f, () => Instance.DropMRLS(Airfield.loc));
                    }
                    if (!dropped[3] && Vector3.Distance(MakeRealPos(transform.position), new Vector3(-45.3f, 0, -6.9f)) < 20) if (configData.SupplyDropSettings.NumberOfDroppedCrates > 3) DoCrateDrop(3);
                    if (!dropped[0] && Vector3.Distance(MakeRealPos(transform.position), new Vector3(1.5f, 0, -6.6f)) < 20) if (configData.SupplyDropSettings.NumberOfDroppedCrates > 0) DoCrateDrop(0);
                    if (!dropped[4] && Vector3.Distance(MakeRealPos(transform.position), new Vector3(54.0f, 0, -6.4f)) < 20) if (configData.SupplyDropSettings.NumberOfDroppedCrates > 4) DoCrateDrop(4);
                    if (!dropped[1] && Vector3.Distance(MakeRealPos(transform.position), new Vector3(99.6f, 0, -6.8f)) < 20) if (configData.SupplyDropSettings.NumberOfDroppedCrates > 1) DoCrateDrop(1);
                }
#endregion
                if (turn == 10 && !exitSent) {
                    exitSent = true;
                    SendChatMessage("Notification.Outbound", Instance.FlightNumber.ToString());
                }
                if (!targets[turn].Started) {
                    if (turn == 1) targets[turn].Trans.transform.position = targets[2].TargetPos;
                    else targets[turn].Trans.transform.position = transform.position + (transform.forward * Vector3.Distance(targets[turn].TargetPos, transform.position));
                    targets[turn].Started = true;
                }
                if (Vector3.Distance(targets[turn].Trans.transform.position, targets[turn].TargetPos) > 10f) {
                    targets[turn].Trans.transform.position = Vector3.MoveTowards(targets[turn].Trans.transform.position, targets[turn].TargetPos, Time.deltaTime * (configData.PlaneSettings.PlaneSpeed * targets[turn].rotatemulti) * 10);
                    targets[turn].AimTarget = targets[turn].Trans.transform.position;
                }
                else targets[turn].AimTarget = targets[turn].TargetPos;
                speedmult = turn == 7 ? 9 : turn == 8 ? 7 : turn == 9 ? 8 : 10;
                transform.position = Vector3.MoveTowards(transform.position, targets[turn].AimTarget, Time.deltaTime * configData.PlaneSettings.PlaneSpeed * speedmult);
            }
            public void GotoIndirect() {
                if (!targets[turn].Started) {
                    targets[turn].Trans.transform.position = transform.position + (transform.position - targets[turn].TargetPos);
                    targets[turn].Trans.transform.position = new Vector3(targets[turn].Trans.transform.position.x, targets[turn].TargetPos.y, targets[turn].Trans.transform.position.z);
                    targets[turn].PivotPoint = transform.position;
                    targets[turn].PivotPoint.y = targets[turn].TargetPos.y;
                    targets[turn].AimTarget = targets[turn].Trans.transform.position;
                    targets[turn].Started = true;
                }
                if (Vector3.Distance(targets[turn].Trans.transform.position, targets[turn].TargetPos) > 10f) {
                    targets[turn].Trans.transform.RotateAround(targets[turn].PivotPoint, Vector3.up, configData.PlaneSettings.PlaneSpeed / targets[turn].rotatemulti);
                    targets[turn].AimTarget = targets[turn].Trans.transform.position;
                }
                else targets[turn].AimTarget = targets[turn].TargetPos;
                transform.position = Vector3.MoveTowards(transform.position, targets[turn].AimTarget, Time.deltaTime * configData.PlaneSettings.PlaneSpeed * 10);
                //move plane towards that moving target
            }
            public void UpdateDirectionaAndRotation() {
                targetDir = (turn < 3 && turn > 1) ? Airfield.loc - plane.transform.position : targets[turn].TargetPos - plane.transform.position;
                float angle = Vector3.SignedAngle(targetDir, plane.transform.position - posRef, Vector3.up);
                if (angle > 10 && targets[turn].roll > -55) targets[turn].roll += -1.2f;
                else if (angle < -10 && targets[turn].roll < 55) targets[turn].roll += 1.2f;
                else {
                    if (plane.transform.rotation.eulerAngles.z > 1 && plane.transform.rotation.eulerAngles.z < 180) targets[turn].roll += 1.2f;
                    else if (plane.transform.rotation.eulerAngles.z > 180 && plane.transform.rotation.eulerAngles.z < 359) targets[turn].roll += -1.2f;
                    else {
                        targets[turn].roll = 0f;
                        plane.transform.rotation = Quaternion.Euler(plane.transform.rotation.eulerAngles.x, plane.transform.rotation.eulerAngles.y, 0);
                    }
                }
                if (ZeroY(plane.transform.position) != ZeroY(posRef)) plane.transform.rotation = Quaternion.LookRotation(ZeroY(plane.transform.position) - ZeroY(posRef));
                posRef = plane.transform.position;
                plane.transform.rotation = Quaternion.Euler(plane.transform.rotation.eulerAngles - targets[turn].Adjust);
            }
            Vector3 RelativePos(Vector3 pos) {
                var newTrans = new GameObject().transform;
                newTrans.transform.position = Instance.Airfields[0].loc + pos;
                newTrans.transform.RotateAround(Instance.Airfields[0].loc, Vector3.down, -Instance.Airfields[0].rot + 11);
                return newTrans.transform.position;
            }
            Vector3 MakeRealPos(Vector3 pos) {
                var newTrans = new GameObject().transform;
                newTrans.transform.position = pos - Instance.Airfields[0].loc;
                newTrans.transform.RotateAround(new Vector3(0, 0, 0), Vector3.down, Instance.Airfields[0].rot);
                return new Vector3(newTrans.transform.position.x, 0, newTrans.transform.position.z);
            }
#endregion
            private void DoCrateDrop(int d) {
                dropped[d] = true;
                SpawnCrates();
            }
#region Spawn Drops and Effects
            private static void CreateSirenLights(BaseEntity entity) {
                var SirenLight = GameManager.server.CreateEntity(SIRENLIGHT_EFFECT, default(Vector3), default(Quaternion), true);
                SirenLight.gameObject.Identity();
                SirenLight.SetParent(entity as LootContainer, "parachute_attach");
                SirenLight.Spawn();
                SirenLight.SetFlag(BaseEntity.Flags.Reserved8, true);
            }
            private static void CreateSirenAlarms(BaseEntity entity) {
                var SirenAlarm = GameManager.server.CreateEntity(SIRENALARM_EFFECT, new Vector3(0f, 0f, 0f), default(Quaternion), true);
                SirenAlarm.gameObject.Identity();
                SirenAlarm.SetParent(entity);
                SirenAlarm.Spawn();
                SirenAlarm.SetFlag(BaseEntity.Flags.Reserved8, true);
            }
            private static void CreateDropEffects(BaseEntity entity) {
                if (entity == null) return;
                if (configData.SupplyDropSettings.SupplyDropEffects.enableSmoke) Effect.server.Run(SMOKE_EFFECT, entity, 0, Vector3.zero, Vector3.zero, null, true);
                // Create Siren Alams on Supply Drops
                if (configData.SupplyDropSettings.SupplyDropEffects.useSirenAlarmOnDrop && configData.SupplyDropSettings.SupplyDropEffects.useSirenAlarmAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenAlarms(entity);
                else if (configData.SupplyDropSettings.SupplyDropEffects.useSirenAlarmAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenAlarms(entity);
                else if (configData.SupplyDropSettings.SupplyDropEffects.useSirenAlarmOnDrop) CreateSirenAlarms(entity);
                else return;
                // Create Spinning Siren Lights on Supply Drops
                if (configData.SupplyDropSettings.SupplyDropEffects.useSirenLightOnDrop && configData.SupplyDropSettings.SupplyDropEffects.useSirenLightAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenLights(entity);
                else if (configData.SupplyDropSettings.SupplyDropEffects.useSirenLightAtNightOnly && TOD_Sky.Instance.IsNight) CreateSirenLights(entity);
                else if (configData.SupplyDropSettings.SupplyDropEffects.useSirenLightOnDrop) CreateSirenLights(entity);
                else return;
            }
            private void SpawnCrates() {
                SupplyDrop drop = GameManager.server.CreateEntity(SUPPLYDROP_PREFAB, transform.position + Vector3.up * configData.SupplyDropSettings.SupplyDropHeight, new Quaternion(), true) as SupplyDrop;
                drop.Spawn();
                Rigidbody rigidbody = drop.GetComponent<Rigidbody>();
                rigidbody.drag = 0f;
                rigidbody.mass = 1000;
                rigidbody.AddForce((plane.transform.forward + (plane.transform.right * UnityEngine.Random.Range(-10f, 10f))) * 25);
                drop.transform.rotation = Quaternion.LookRotation(drop.transform.position - new Vector3(0, UnityEngine.Random.Range(0, 180), 0));
                int slots = 36;
                drop.inventory.capacity = 36;
                drop.panelName = "generic";
                drop.inventory.ServerInitialize(null, slots);
                drop.inventory.MarkDirty();
                if (configData.SupplyDropSettings.RemoveChutes) drop.RemoveParachute();
                Instance.drops.Add(drop);
                if (configData.SupplyDropSettings.enableEffects) CreateDropEffects(drop);
                Instance.timer.Once(configData.SupplyDropSettings.DespawnTimerMinutes * 60, () => {
                    if (drop != null) drop.Kill();
                }
                );
                Interface.CallHook("OnLootSpawn", drop);
            }
#endregion
        }
#endregion
#region Event Heli Controller
        private void SpawnHeli() {
            PatrolHelicopter helicopter = GameManager.server.CreateEntity(HELICOPTER_PREFAB) as PatrolHelicopter;
            helicopter.enableSaving = false;
            helicopter.Spawn();
            //NextTick(() =>
            //{
            //    if (helicopter == null)
            //    {
            //        PrintError("[Plugin Conflict] Another plugin on your server has destroyed the helicopter when it spawned");
            //        return;
            //    }
            helicopter.transform.position = RandomPointOnWorldBounds();
            helicopter.myAI.State_Patrol_Enter();
            helicopter.gameObject.AddComponent<EventHelicopter>();
            //});
        }
        private Vector3 RandomPointOnWorldBounds() {
            Vector3 position;
            position = new Vector3(150, 0, 150);
            position.y = TerrainMeta.HeightMap.GetHeight(position) + 150f;
            return position;
        }
        private static void NullifyDamage(HitInfo info) {
            info.damageTypes = new DamageTypeList();
            info.HitEntity = null;
            info.HitMaterial = 0;
            info.PointStart = Vector3.zero;
        }
        private class EventHelicopter : FacepunchBehaviour {
            internal static List<EventHelicopter> allHelicopters = new List<EventHelicopter>();
            protected PatrolHelicopter Helicopter {
                get;
                private set;
            }
            protected PatrolHelicopterAI HeliAI {
                get;
                private set;
            }
            private bool enemiesInVicinity = false;
            internal bool hasValidLocation = false;
            private float nextValidationTime;
            public DateTime born = DateTime.UtcNow;
            public bool killSilent = false;
            private bool isDying = false;
            private float actualHealth;
            internal bool retired = false;
            public bool bored = false;
            internal bool destroyKill = true;
            AF Airfield = Instance.Airfields[0];
            private void Start() {
                Helicopter = GetComponent<PatrolHelicopter>();
                HeliAI = GetComponent<PatrolHelicopterAI>();
                actualHealth = Helicopter.health;
                FindTargetLocation();
                InvokeRepeating("UpdatePos", 0f, 5f);
                InvokeHandler.Invoke(this, ResetStateToPatrol, 90f);
                allHelicopters.Add(this);
            }
            private void UpdatePos() {
                var timeAlive = DateTime.UtcNow - born;
                if (timeAlive.Minutes > configData.GlobalSettings.RetireMinutes - 1) {
                    if (!retired) {
                        Retire();
                        return;
                    }
                }
                if (!bored) {
                    HeliAI.SetTargetDestination(Airfield.loc + new Vector3(0.0f, 50f, 0.0f));
                    if (Vector2.Distance(transform.position, Airfield.loc) < 10f) {
                        HeliAI.State_Orbit_Enter(5f);
                        HeliAI.State_Orbit_Think(5f);
                        HeliAI.State_Patrol_Enter();
                        HeliAI.State_Patrol_Think(60f);
                        HeliAI.maxSpeed = 25f;
                    }
                    else {
                        HeliAI.State_Move_Enter(Airfield.loc + new Vector3(0.0f, 30f, 0.0f));
                        HeliAI.maxSpeed = 70f;
                    }
                }
            }
            private void FindEnemiesInVicinity() {
                AIUpdate();
                enemiesInVicinity = false;
                List<BasePlayer> players = Pool.GetList<BasePlayer>();
                Vis.Entities(Airfield.loc, 30f, players);
                players.RemoveAll(x => x.IsNpc);
                if (players.Count > 0) {
                    enemiesInVicinity = true;
                    HeliAI._targetList.Clear();
                    players.ForEach(x => HeliAI._targetList.Add(new PatrolHelicopterAI.targetinfo(x, x)));
                }
                Pool.FreeList(ref players);
            }
            private void OnDestroy() {
                CancelInvoke("UpdatePos");
                allHelicopters.Remove(this);
                if (Helicopter != null && !Helicopter.IsDestroyed) Helicopter.Kill();
                if (destroyKill && Helicopter != null && !Helicopter.IsDestroyed) Helicopter.Kill();
            }
            public void Kill() {
                Destroy(gameObject);
            }
#region Death and Damage
            internal void OnDamage(HitInfo info) {
                actualHealth -= info.damageTypes.Total();
                if (actualHealth < 0f) {
                    //NullifyDamage(info);
                    //OnDeath(info);
                    if (info.damageTypes.GetMajorityDamageType() == DamageType.Explosion) DropLoot();
                    if (!isDying) CrashToDeath();
                }
            }
            internal void OnDeath(HitInfo info) {
                if (isDying) return;
                isDying = true;
                if (configData.LootBoxes.DropHeliLoot) DropLoot();
                Interface.CallHook("OnEntityDeath", Helicopter);
                Helicopter.DieInstantly();
            }
            internal void CrashToDeath() {
                isDying = true;
                HeliAI.CriticalDamage();
            }
#endregion
#region Loot Drop
            private void DropLoot() {
                if (configData.LootBoxes.Amount <= 0) return;
                for (int i = 0; i < configData.LootBoxes.Amount; i++) {
                    LootContainer container = GameManager.server.CreateEntity(Helicopter.crateToDrop.resourcePath, transform.position) as LootContainer;
                    container.enableSaving = false;
                    container.Spawn();
                    Vector3 velocity = UnityEngine.Random.onUnitSphere;
                    velocity.y = 1;
                    Rigidbody rb = container.gameObject.AddComponent<Rigidbody>();
                    rb.useGravity = true;
                    rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
                    rb.mass = 2f;
                    rb.interpolation = RigidbodyInterpolation.Interpolate;
                    rb.angularVelocity = Vector3Ex.Range(-1.75f, 1.75f);
                    rb.drag = 0.5f * (rb.mass / 5f);
                    rb.angularDrag = 0.2f * (rb.mass / 5f);
                    rb.AddForce(velocity * 5f, ForceMode.Impulse);
                    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);
                    if (configData.LootBoxes.UseCustomLoot) {
                        ClearContainer(container.inventory);
                        PopulateLoot(container.inventory, configData.LootBoxes.RandomItems);
                    }
                }
            }
            private void ClearContainer(ItemContainer container) {
                if (container == null || container.itemList == null) return;
                while (container.itemList.Count > 0) {
                    Item item = container.itemList[0];
                    item.RemoveFromContainer();
                    item.Remove(0f);
                }
            }
            private void PopulateLoot(ItemContainer container, ConfigData.LootContainer loot) {
                if (container == null || loot == null) return;
                ClearContainer(container);
                int amount = UnityEngine.Random.Range(loot.Minimum, loot.Maximum);
                List<ConfigData.LootItem> list = Pool.GetList<ConfigData.LootItem>();
                list.AddRange(loot.Items);
                int itemCount = 0;
                while (itemCount < amount) {
                    int totalWeight = list.Sum((ConfigData.LootItem x) => Mathf.Max(1, x.Weight));
                    int random = UnityEngine.Random.Range(0, totalWeight);
                    for (int i = list.Count - 1; i >= 0; i--) {
                        ConfigData.LootItem lootItem = list[i];
                        totalWeight -= Mathf.Max(1, lootItem.Weight);
                        if (random >= totalWeight) {
                            list.Remove(lootItem);
                            Item item = ItemManager.CreateByName(lootItem.Name, UnityEngine.Random.Range(lootItem.Minimum, lootItem.Maximum), lootItem.Skin);
                            item?.MoveToContainer(container);
                            itemCount++;
                            break;
                        }
                    }
                    if (list.Count == 0) list.AddRange(loot.Items);
                }
                Pool.FreeList(ref list);
            }
#endregion
            internal void ResetStateToPatrol() {
                InvokeHandler.Invoke(this, ResetState, 1f);
            }
            private void ResetState() {
                enabled = true;
                HeliAI.enabled = true;
                HeliAI.ClearAimTarget();
                FindEnemiesInVicinity();
                HeliAI._currentState = PatrolHelicopterAI.aiState.PATROL;
                HeliAI.maxSpeed = 30f;
                hasValidLocation = false;
                //SendChatMessage("Resuming normal patrol");
                bored = true;
                destroyKill = false;
            }
            private void AIUpdate() {
                HeliAI.MoveToDestination();
                HeliAI.UpdateRotation();
                HeliAI.UpdateSpotlight();
                HeliAI.AIThink();
                HeliAI.DoMachineGuns();
            }
            private void Retire() {
                CancelInvoke("UpdatePos");
                HeliAI._targetList.Clear();
                bored = true;
                HeliAI.Retire();
                HeliAI.maxSpeed = 100f;
                retired = true;
                SendChatMessage(msg("Notification.Helicopter.Retire"));
            }
            private void FindTargetLocation() {
                if (Airfield.loc != null) {
                    hasValidLocation = true;
                }
                hasValidLocation = false;
            }
        }
#endregion
#region Commands
        [ConsoleCommand("afdrops")]
        private void afdconsole(ConsoleSystem.Arg arg) {
            if (arg?.Args == null || arg.Args.Length == 0) {
                Puts("Usage for Airfield Drops Event");
                Puts("afdrops start - Starts Airfield Drops Event manually");
                Puts("afdrops stop - Stops and kills Airfield Drop Event manually");
                return;
            }
            if (arg.Player() == null) {
                if (arg.Args[0] == "start") {
                    if (airfieldMono != null) Puts("There is already an active Airfield Drops event.");
                    else {
                        Puts("Attempting to start Airfield Drops event.");
                        if (CallAFDrop()) Puts("Starting Airfield Drops event.");
                    }
                }
                if (arg.Args[0] == "stop") {
                    if (airfieldMono == null) Puts("There is no active Airfield Drops event.");
                    else {
                        airfieldMono.plane.Kill();
                        foreach (var drop in drops) if (!drop.IsDestroyed) drop.Kill();
                        for (int i = EventHelicopter.allHelicopters.Count - 1; i >= 0; i--) {
                            EventHelicopter exHelicopter = EventHelicopter.allHelicopters[i];
                            exHelicopter.killSilent = true;
                            UnityEngine.Object.Destroy(exHelicopter);
                        }
                        Puts("Airfield Drops event was stopped.");
                    }
                }
            }
            else afdchat(arg.Player(), "afdrops", arg.Args);
        }
        [ChatCommand("afdrops")]
        private void afdchat(BasePlayer player, string command, string[] args) {
            if (!HasPermission(player.UserIDString, PERM_ADMIN)) {
                SendReply(player, "You do not have permission to use this command.");
                return;
            }
            if (args == null) return;
            if (args.Length == 0) {
                var helpmsg = new StringBuilder();
                helpmsg.Append("<size=22><color=green>Airfield Drops</color></size> by: ZTL\n");
                helpmsg.Append("<color=orange>/afdrops start</color> - Starts Airfield Drops Event manually\n");
                helpmsg.Append("<color=orange>/afdrops stop</color> - Stops and kills Airfield Drops Event manually\n");
                SendReply(player, helpmsg.ToString().TrimEnd());
                return;
            }
            if (args.Length == 1) {
                if (args[0] == "start") {
                    if (airfieldMono != null) SendReply(player, "There is already an active Airfield Drops event.");
                    else {
                        SendReply(player, "Attempting to start Airfield Drops event");
                        if (CallAFDrop()) SendReply(player, "Starting Airfield Drops event");
                        else {
                            if (statusPC && PlaneCrash) {
                                SendReply(player, "Currently there is an active Plane Crash event.Canceling Event");
                                statusPC = false;
                            }
                            if (statusPCR && PlaneCrashRandom) {
                                SendReply(player, "Currently there is an active Random Plane Crash event.Canceling Event");
                                statusPCR = false;
                            }
                        }
                    }
                }
                if (args[0] == "stop") {
                    if (airfieldMono == null) SendReply(player, "There is no active Airfield Drops event.");
                    else {
                        airfieldMono.plane.Kill();
                        foreach (var drop in drops) if (!drop.IsDestroyed) drop.Kill();
                        for (int i = EventHelicopter.allHelicopters.Count - 1; i >= 0; i--) {
                            EventHelicopter exHelicopter = EventHelicopter.allHelicopters[i];
                            exHelicopter.killSilent = true;
                            UnityEngine.Object.Destroy(exHelicopter);
                        }
                        SendReply(player, "Airfield Drops event was stopped.");
                    }
                }
            }
        }
#endregion
#region Class
        public class AF {
            public Vector3 loc;
            public float rot;
        }
#endregion
#region Config
        private static ConfigData configData;
        private class ConfigData {
            [JsonProperty(PropertyName = "Global Event Settings")]
            public GlobalOptions GlobalSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Event Map Marker Settings")]
            public EventOptions MapMarkerSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Cargo Plane Settings")]
            public PlaneOptions PlaneSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "MRLS Missle Settings")]
            public MRLSOptions MissleSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Supply Drop Settings")]
            public SupplyDropOptions SupplyDropSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Advance Airstrike Plugin Options")]
            public AdvAirstrikeOptions AdvAirstrikeSettings {
                get;
                set;
            }
            [JsonProperty(PropertyName = "Loot Container Options For Patrol Heli")]
            public Loot LootBoxes {
                get;
                set;
            }
            public class GlobalOptions {
                [JsonProperty(PropertyName = "Enable Airfield Air Drops Event")]
                public bool enabled {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Enable random autospawn Airfield Drop Events on random timer")]
                public bool EnableTimedEvents {
                    get;
                    set;
                }
                [JsonProperty(PropertyName = "Minimum required players to start
// ... [Code preview truncated due to length. Full source in attached file] ...

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