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

FREE PlaneCrash : 0.1.99 0.1.99

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Core.Plugins;
using Rust;
using Oxide.Core;
using Newtonsoft.Json;
using UnityEngine.AI;

namespace Oxide.Plugins
{
    [Info("PlaneCrash", "k1lly0u", "0.1.99", ResourceId = 0)]
      //  Слив плагинов server-rust by Apolo YouGame
    class PlaneCrash : RustPlugin
    {
        #region Fields
        [PluginReference] Plugin FancyDrop, LustyMap, Kits;

        static PlaneCrash ins;

        static float initialHeight;
        private float mapSize;

        private Timer callTimer;
        private bool initialized;

        // Effects
        const string c4Explosion = "assets/prefabs/tools/c4/effects/c4_explosion.prefab";
        const string heliExplosion = "assets/prefabs/npc/patrol helicopter/effects/heli_explosion.prefab";
        const string debris = "assets/prefabs/npc/patrol helicopter/damage_effect_debris.prefab";
        const string fireball = "assets/bundled/prefabs/oilfireballsmall.prefab";
        const string smokeSignal = "assets/bundled/prefabs/fx/smoke_signal_full.prefab";

        // Prefabs
        const string cargoPlanePrefab = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
        const string gibs = "assets/prefabs/npc/patrol helicopter/servergibs_patrolhelicopter.prefab";
        const string crates = "assets/prefabs/npc/patrol helicopter/heli_crate.prefab";
        const string supply = "assets/prefabs/misc/supply drop/supply_drop.prefab";
        const string zombiePrefab = "assets/prefabs/npc/murderer/murderer.prefab";
        const string scientistPrefab = "assets/prefabs/npc/scientist/scientist.prefab";
        const string debrisMarker = "assets/prefabs/tools/map/explosionmarker.prefab";
        #endregion

        #region Oxide Hooks
        private void Loaded()
        {           
            mapSize = TerrainMeta.Size.x;
            permission.RegisterPermission("planecrash.cancall", this);
        }

        private void OnServerInitialized()
        {
            ins = this;
            initialized = true;
            initialHeight = 150 + configData.Plane.Height;

            if (configData.EventTimers.Random)
                StartCrashTimer();
        }

        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (!initialized || !configData.Plane.ApplyToAll) return;

            if (entity is CargoPlane)
            {
                NextTick(() =>
                {
                    if (entity == null) return;
                    var success = Interface.Call("isStrikePlane", entity as CargoPlane);
                    if (success is bool && (bool)success)
                        return;

                    object location = (entity as CargoPlane).dropPosition;
                    if (!(location is Vector3))
                        location = Vector3Ex.Range(-(mapSize / 6f), mapSize / 6f);
                    timer.In(2, () => AddCrashComponent(entity as CargoPlane, (Vector3)location, true));
                });
            }
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            if (entity == null) return;
            if (entity.GetComponent<CrashPlane>())
                UnityEngine.Object.Destroy(entity.GetComponent<CrashPlane>());
        }

        private void Unload()
        {
            var planes = UnityEngine.Object.FindObjectsOfType<CrashPlane>();
            if (planes != null)
            {
                foreach (var obj in planes)
                    UnityEngine.Object.Destroy(obj);
            }
        }
        #endregion

        #region Components
        enum FlightStatus { Flying, Crashing }

        class CrashPlane : MonoBehaviour
        {
            private CargoPlane entity;
            private FlightStatus status;

            private FireBall[] engineFires;

            private Vector3 startPos;
            private Vector3 endPos;
            
            private int rocketHits;

            private float speed;
            private float currentSpeed;

            private float crashTimeTaken;
            private float crashTimeToTake;
            private float timeTaken;
            private float timeToTake;

            private bool isDying;
            private bool isSmoking;
            private bool hasDropped;
            private bool isDropPlane;

            private bool isFancyDrop;

            private Type[] interactableTypes = new Type[] { typeof(TreeEntity), typeof(ResourceEntity), typeof(BuildingBlock), typeof(SimpleBuildingBlock), typeof(BaseHelicopter) };

            private void Awake()
            {
                entity = GetComponent<CargoPlane>();
                entity.enabled = false;

                gameObject.layer = (int)Layer.Reserved1;
                gameObject.name = "CrashPlane";

                AttachCollider();

                speed = ins.configData.Plane.Speed;
                currentSpeed = speed;
                crashTimeTaken = 0;
                crashTimeToTake = 20;
                status = FlightStatus.Flying;
            }

            private void FixedUpdate()
            {
                if (entity.transform.position.y <= -5)
                {
                    if (!isDying)
                        Die();
                    return;
                }

                if (status == FlightStatus.Crashing)
                {
                    crashTimeTaken = crashTimeTaken + UnityEngine.Time.deltaTime;
                    var single = Mathf.InverseLerp(0, crashTimeToTake, crashTimeTaken);
                    if (single < 1)
                    {
                        currentSpeed = speed + Mathf.Lerp(0, 10, single);
                        entity.transform.transform.eulerAngles = new Vector3(Mathf.Lerp(0, 25f, single), entity.transform.transform.eulerAngles.y, entity.transform.transform.eulerAngles.z);
                    }

                    entity.transform.position = Vector3.MoveTowards(entity.transform.position, entity.transform.position + (entity.transform.forward * 10), currentSpeed * UnityEngine.Time.deltaTime);
                }
                else
                {
                    entity.transform.position = Vector3.MoveTowards(entity.transform.position, endPos, currentSpeed * UnityEngine.Time.deltaTime);

                    if (isDropPlane)
                    {
                        timeTaken = timeTaken + UnityEngine.Time.deltaTime;
                        entity.secondsTaken = timeTaken;
                        var single = Mathf.InverseLerp(0, timeToTake, timeTaken);
                        if (!hasDropped && single >= 0.5f)
                        {
                            hasDropped = true;
                            if (!ins.FancyDrop || !isFancyDrop)
                            {
                                BaseEntity drop = GameManager.server.CreateEntity(supply, entity.transform.position);
                                drop.globalBroadcast = true;
                                drop.Spawn();
                            }
                        }
                    }
                }
                entity.transform.hasChanged = true;
            }

            private void OnDestroy()
            {
                enabled = false;
                CancelInvoke();
                if (engineFires != null)
                {
                    foreach (var fire in engineFires)
                    {
                        if (fire != null && !fire.IsDestroyed)
                            fire.Extinguish();
                    }
                }
                if (!entity.IsDestroyed)
                    entity.Kill();
            }

            private void OnTriggerEnter(Collider col)
            {
                if (col.gameObject.GetComponentInParent<Terrain>() != null)
                {
                    Die();
                    return;
                }

                if (col.gameObject.GetComponentInParent<BasePlayer>() != null && col.gameObject.layer == 17)
                {
                    col.gameObject.GetComponentInParent<BasePlayer>().Die();
                    return;
                }

                if (col.GetComponentInParent<ServerProjectile>())
                {
                    SmallExplosion();
                    col.GetComponentInParent<TimedExplosive>()?.Explode();
                    rocketHits++;

                    SpawnLoot(ins.configData.Loot.CrateHit, false);
                    SpawnLoot(ins.configData.Loot.SupplyHit, true);

                    if (rocketHits == 1)
                        AddFire();

                    if (rocketHits >= ins.configData.Plane.DestroyHits)
                    {
                        string attackerName = col.GetComponent<BaseEntity>()?.creatorEntity?.ToPlayer()?.displayName ?? "";

                        if (ins.configData.Messages.DisplayAttacker && !string.IsNullOrEmpty(attackerName))
                            ins.PrintToChat(string.Format(ins.configData.Messages.AttackerMessage2, attackerName));

                        Die();
                        return;
                    }

                    if (rocketHits >= ins.configData.Plane.DownHits && status == FlightStatus.Flying)
                    {
                        endPos = new Vector3(endPos.x, 0, endPos.z);
                        status = FlightStatus.Crashing;
                        string attackerName = col.GetComponent<BaseEntity>()?.creatorEntity?.ToPlayer()?.displayName ?? "";

                        if (ins.configData.Messages.DisplayAttacker && !string.IsNullOrEmpty(attackerName))
                            ins.PrintToChat(string.Format(ins.configData.Messages.AttackerMessage1, attackerName));
                        BeginCrash();
                    }
                    return;
                }

                if (ins.configData.Plane.Destruction)
                {
                    foreach (Type type in interactableTypes)
                    {
                        if (col.GetComponentInParent(type) != null)
                        {
                            BaseCombatEntity combatEntity = col.GetComponentInParent<BaseCombatEntity>();
                            if (combatEntity != null)
                            {
                                combatEntity.Die();
                                return;
                            }
                            BaseEntity baseEntity = col.GetComponentInParent<BaseEntity>();
                            if (baseEntity != null)
                            {
                                baseEntity.Kill(BaseNetworkable.DestroyMode.Gib);
                                return;
                            }
                        }
                    }            
                } 
            }
            
            public void SetFlightPath(Vector3 newDropPosition, bool isStandard = false)
            {
                if (!isStandard)
                {
                    float size = TerrainMeta.Size.x;
                    startPos = Vector3Ex.Range(-1f, 1f);
                    startPos.y = 0f;
                    startPos.Normalize();
                    startPos = startPos * (size * 2f);
                    endPos = startPos * -1f;
                    startPos = startPos + newDropPosition;
                    endPos = endPos + newDropPosition;
                    startPos.y = initialHeight;
                    endPos.y = startPos.y;

                    startPos.x = Mathf.Clamp(startPos.x + (UnityEngine.Random.Range(size / 3, -(size / 3))), -(size + 1000), size + 1000);
                    startPos.z = Mathf.Clamp(startPos.z + (UnityEngine.Random.Range(size / 3, -(size / 3))), -(size + 1000), size + 1000);
                    endPos.x = Mathf.Clamp(endPos.x + (UnityEngine.Random.Range(size / 3, -(size / 3))), -(size + 1000), size + 1000);
                    endPos.z = Mathf.Clamp(endPos.z + (UnityEngine.Random.Range(size / 3, -(size / 3))), -(size + 1000), size + 1000);
                    
                    if (ins.configData.Plane.SmokeTrail)
                        ins.RunEffect(smokeSignal, entity, new Vector3(), Vector3.up * 3);
                }
                else
                {
                    startPos = entity.startPos;
                    endPos = entity.endPos;
                    isDropPlane = true;
                }
                entity.transform.position = startPos;
                entity.transform.rotation = Quaternion.LookRotation(endPos - startPos);

                timeToTake = Vector3.Distance(startPos, endPos) / speed;
                entity.secondsToTake = timeToTake;

                isFancyDrop = ins.FancyDrop ? (bool)ins.FancyDrop.CallHook("IsFancyDrop", entity) : false;
                if (isDropPlane && isFancyDrop)
                    ins.FancyDrop.CallHook("OverrideDropTime", entity, timeToTake);

                Destroy(this, timeToTake);
            }

            private void AttachCollider()
            {
                var rigidbody = gameObject.AddComponent<Rigidbody>();
                rigidbody.useGravity = false;
                rigidbody.isKinematic = true;
                rigidbody.detectCollisions = true;
                rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;

                var collider = gameObject.AddComponent<BoxCollider>();
                collider.isTrigger = true;
                collider.size = new Vector3(50, 10, 50);
                collider.transform.localPosition = Vector3.up * 6;
            }

            private void BeginCrash()
            {
                SmallExplosion();
                AddFire();
            }

            private void BigExplosion()
            {
                ins.RunEffect(heliExplosion, null, entity.transform.position);
                ins.RunEffect(debris, null, entity.transform.position);
            }

            private void SmallExplosion()
            {
                ins.RunEffect(c4Explosion, null, entity.transform.position);
                ins.RunEffect(debris, null, entity.transform.position);
            }

            private void AddFire()
            {
                if (engineFires == null)
                {
                    engineFires = new FireBall[]
                    {
                        SpawnFireball(entity, new Vector3(-10, 6, 10), 600),
                        SpawnFireball(entity, new Vector3(10, 6, 10), 600)
                    };
                }
            }

            private void Die()
            {
                if (isDying)
                    return;
                isDying = true;
                BigExplosion();
                CreateLootSpawns();
                CreateNPCs(entity.transform.position);

                if (ins.configData.LustyOptions.CrashIcon)
                    InvokeHandler.Invoke(this, UpdateCrashMarker, 1.5f);
                if (ins.configData.MapOptions.CrashIcon)
                    InvokeHandler.Invoke(this, UpdateMapMarker, 1.5f);

                InvokeHandler.Invoke(this, SmallExplosion, 0.25f);
                InvokeHandler.Invoke(this, SmallExplosion, 0.5f);
                InvokeHandler.Invoke(this, BigExplosion, 1.25f);
                InvokeHandler.Invoke(this, SmallExplosion, 1.75f);
                InvokeHandler.Invoke(this, BigExplosion, 2.25f);
                InvokeHandler.Invoke(this, () =>
                {                    
                    enabled = false;
                    Destroy(this);
                }, 2.5f);
            }

            private void CreateLootSpawns()
            {
                List<ServerGib> serverGibs = ServerGib.CreateGibs(gibs, gameObject, entity.gameObject, entity.transform.forward * 2, 5f);
                for (int i = 0; i < 12; i++)
                {
                    BaseEntity fireb = GameManager.server.CreateEntity(fireball, entity.transform.position, entity.transform.rotation, true);
                    if (fireb)
                    {
                        Vector3 randsphere = UnityEngine.Random.onUnitSphere;
                        fireb.transform.position = (entity.transform.position + new Vector3(0f, 1.5f, 0f)) + (randsphere * UnityEngine.Random.Range(-4f, 4f));
                        Collider collider = fireb.GetComponent<Collider>();
                        fireb.Spawn();
                        fireb.SetVelocity(entity.transform.forward + (randsphere * UnityEngine.Random.Range(3, 10f)));
                        foreach (ServerGib serverGib in serverGibs)
                            Physics.IgnoreCollision(collider, serverGib.GetCollider(), true);
                    }
                }

                SpawnLoot(ins.configData.Loot.CrateCrash, false, true);
                SpawnLoot(ins.configData.Loot.SupplyCrash, true, true);

                if (ins.configData.Messages.DisplayDestroy)
                    ins.PrintToChat(ins.configData.Messages.DestroyMessage.Replace("{x}", entity.transform.position.x.ToString()).Replace("{z}", entity.transform.position.z.ToString()));                
            }

            private void SpawnLoot(int amount, bool isDrop, bool isCrashing = false)
            {               
                if (amount == 0)
                    return;

                for (int j = 0; j < amount; j++)
                {
                    Vector3 randsphere = UnityEngine.Random.onUnitSphere;
                    Vector3 entpos = (entity.transform.position + new Vector3(0f, 1.5f, 0f)) + (randsphere * UnityEngine.Random.Range(-2f, 3f));

                    var ent = isDrop ? supply : crates;
                    BaseEntity crate = GameManager.server.CreateEntity(ent, entpos, Quaternion.LookRotation(randsphere), true);
                    crate.Spawn();

                    if (j == 0 && ins.configData.Plane.Smoke && isCrashing && !isSmoking)
                    {
                        ins.RunEffect(smokeSignal, crate);
                        isSmoking = true;
                    }

                    Rigidbody rigidbody;
                    if (!isDrop)
                        rigidbody = crate.gameObject.AddComponent<Rigidbody>();
                    else
                    {
                        crate.GetComponent<SupplyDrop>().RemoveParachute();
                        rigidbody = crate.GetComponent<Rigidbody>();
                    }

                    if (rigidbody != null)
                    {
                        rigidbody.isKinematic = false;
                        rigidbody.useGravity = true;
                        rigidbody.mass = 1.25f;
                        rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
                        rigidbody.drag = 0.25f;
                        rigidbody.angularDrag = 0.1f;
                        rigidbody.AddForce((entity.transform.forward + (entity.transform.right * UnityEngine.Random.Range(-10f, 10f))) * 100);
                    }

                    FireBall fireBall = SpawnFireball(crate, null);
                    ins.timer.In(2, () => ins.FillLootContainer(crate, isDrop));
                }
            }

            private FireBall SpawnFireball(BaseEntity parent, object offset = null, float lifetime = 0)
            {
                FireBall fireBall = GameManager.server.CreateEntity(fireball, parent.transform.position, new Quaternion(), true) as FireBall;
                if (fireBall)
                {        
                    if (offset is Vector3)
                        fireBall.transform.localPosition = (Vector3)offset;

                    fireBall.Spawn();
                    fireBall.SetParent(parent, false, true);

                    fireBall.GetComponent<Rigidbody>().isKinematic = true;
                    fireBall.GetComponent<Collider>().enabled = false;

                    fireBall.Invoke(fireBall.Extinguish, lifetime == 0 ? ins.configData.Loot.FireLife : lifetime);
                    return fireBall;
                }
                return null;
            }

            private void CreateNPCs(Vector3 position)
            {
                if (ins.configData.NPCOptions.Enabled)
                {
                    bool isMurderer = ins.configData.NPCOptions.Type.ToLower() == "murderer";
                    for (int i = 0; i < ins.configData.NPCOptions.Amount; i++)
                    {
                        Vector3 newPosition = position + (UnityEngine.Random.onUnitSphere * 20);
                        object point = ins.FindPointOnNavmesh(newPosition);
                        if (point is Vector3)
                            newPosition = (Vector3)point;
                        else newPosition.y = TerrainMeta.HeightMap.GetHeight(newPosition);

                        NPCPlayer entity = InstantiateEntity(isMurderer ? zombiePrefab : scientistPrefab, newPosition);
                        entity.enableSaving = false;
                        entity.Spawn();

                        (entity as NPCPlayerApex).CommunicationRadius = -1f;
                        entity.displayName = isMurderer ? "Zombie" : "Scientist";
                        entity.InitializeHealth(ins.configData.NPCOptions.Health, ins.configData.NPCOptions.Health);

                        if (isMurderer)
                            (entity as NPCMurderer).LootSpawnSlots = new LootContainer.LootSpawnSlot[0];

                        if (!string.IsNullOrEmpty(ins.configData.NPCOptions.Kit))
                        {
                            if (entity.IsInvoking(entity.EquipTest))
                                entity.CancelInvoke(entity.EquipTest);

                            entity.inventory.Strip();
                            ins.NextTick(()=> 
                            {
                                ins.Kits?.Call("GiveKit", entity, ins.configData.NPCOptions.Kit);
                                ins.NextTick(() => entity.EquipTest());
                            });
                        }

                        entity.gameObject.AddComponent<NPCMonitor>();

                        InvokeHandler.Invoke(entity, ()=> DespawnNPC(entity), ins.configData.NPCOptions.DespawnTime);
                    }
                }
            }

            private void DespawnNPC(NPCPlayer npcPlayer)
            {
                if (npcPlayer == null || npcPlayer.IsDestroyed || npcPlayer.IsDead())
                    return;

                npcPlayer.inventory.Strip();
                npcPlayer.DieInstantly();
            }

            private NPCPlayer InstantiateEntity(string type, Vector3 position)
            {
                var gameObject = Facepunch.Instantiate.GameObject(GameManager.server.FindPrefab(type), position, new Quaternion());
                gameObject.name = type;

                UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);

                Destroy(gameObject.GetComponent<Spawnable>());

                if (!gameObject.activeSelf)
                    gameObject.SetActive(true);

                NPCPlayer component = gameObject.GetComponent<NPCPlayer>();
                return component;
            }

            private void UpdateCrashMarker()
            {
                if (!ins.LustyMap || entity == null)
                    return;

                ins.LustyMap.Call("AddTemporaryMarker", entity.transform.position.x, entity.transform.position.z, "Crashed Plane", ins.configData.LustyOptions.IconURL, 0);
                ins.timer.In(ins.configData.LustyOptions.CrashIconTime, () => ins.LustyMap.Call("RemoveTemporaryMarker", "Crashed Plane"));
            }

            private void UpdateMapMarker()
            {
                if (entity == null)
                    return;

                BaseEntity baseEntity = GameManager.server.CreateEntity(debrisMarker, entity.transform.position, Quaternion.identity, true);
                baseEntity.Spawn();
                baseEntity.SendMessage("SetDuration", ins.configData.MapOptions.CrashIconTime, SendMessageOptions.DontRequireReceiver);
            }
        }

        public class NPCMonitor : MonoBehaviour
        {
            public NPCPlayer entity;
            private Vector3 homePosition;

            private void Awake()
            {
                entity = GetComponent<NPCPlayer>();
                enabled = false;
                homePosition = entity.transform.position;

                InvokeHandler.InvokeRepeating(this, CheckNPCLocation, 1f, 5f);
            }

            public void CheckNPCLocation()
            {
                if (Vector3.Distance(entity.transform.position, homePosition) > 30)                
                    ResetPosition(); 
            }
            
            private void ResetPosition() => entity.SetDestination(homePosition);            
        }
        #endregion

        #region Functions
        private void StartCrashTimer()
        {
            callTimer = timer.In(UnityEngine.Random.Range(configData.EventTimers.Min, configData.EventTimers.Max) * 60, () =>
            {
                CargoPlane plane = (CargoPlane)GameManager.server.CreateEntity(cargoPlanePrefab, new Vector3(), new Quaternion(), true);
                plane.Spawn();
                var crash = plane.gameObject.AddComponent<CrashPlane>();
                crash.SetFlightPath(Vector3Ex.Range(-(mapSize / 6f), mapSize / 6f));

                if (configData.Messages.DisplayIncoming)
                    PrintToChat(configData.Messages.IncomingMessage);

                StartCrashTimer();
            });
        }

        private 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 AddCrashComponent(CargoPlane plane, Vector3 location, bool isStandard = false)
        {
            if (plane.GetComponent<CrashPlane>()) return;
            var crash = plane.gameObject.AddComponent<CrashPlane>();
            crash.SetFlightPath(location, isStandard);

            if (!isStandard && configData.Messages.DisplayIncoming)
                PrintToChat(configData.Messages.IncomingMessage);
        }

        private void FillLootContainer(BaseEntity entity, bool isDrop)
        {
            if (entity == null) return;

            ItemContainer container = isDrop ? entity.GetComponent<SupplyDrop>()?.inventory : entity.GetComponentInParent<LootContainer>()?.inventory;
            ConfigData.LootSettings.LootTables lootTable = isDrop ? configData.Loot.SupplyLoot : configData.Loot.CrateLoot;
           
            if (container == null || lootTable == null) return;
            if (lootTable.Enabled)
            {
                while (container.itemList.Count > 0)
                {
                    var item = container.itemList[0];
                    item.RemoveFromContainer();
                    item.Remove(0f);
                }
                int count = UnityEngine.Random.Range(lootTable.Minimum, lootTable.Maximum);
                for (int i = 0; i < count; i++)
                {
                    var lootItem = lootTable.Items.GetRandom();
                    if (lootItem == null) continue;
                    Item item = ItemManager.CreateByName(lootItem.Shortname, UnityEngine.Random.Range(lootItem.Min, lootItem.Max));
                    if (item != null)
                        item.MoveToContainer(container);
                }
            }
            if (configData.Loot.LockCrates)
            {
                entity.SetFlag(BaseEntity.Flags.Locked, true, false);
                InvokeHandler.Invoke(entity, () => { entity.SetFlag(BaseEntity.Flags.Locked, false, false); }, configData.Loot.LockTimer);                
            }
        }

        private object FindPointOnNavmesh(Vector3 targetPosition)
        {
            NavMeshHit navHit;
            if (NavMesh.SamplePosition(targetPosition, out navHit, 100, 1))
                return navHit.position;
            return null;
        }

        private bool IsCrashPlane(CargoPlane plane) => plane.GetComponent<CrashPlane>();
        
        #endregion

        #region Commands
        [ConsoleCommand("callcrash")]
        void ccmdSendCrash(ConsoleSystem.Arg arg)
        {
            if (arg.Connection != null) return;
            Vector3 location = Vector3.zero;
            if (arg.Args != null)
            {
                if (arg.Args.Length == 1 && arg.Args[0].ToLower() == "help")
                {
                    SendReply(arg, $"{Title}  v{Version} - k1lly0u @ chaoscode.io");
                    SendReply(arg, "callcrash - Send a random crash plane");
                    SendReply(arg, "callcrash \"X\" \"Z\" - Send a crash plane towards the specified X and Z co-ordinates");
                    SendReply(arg, "callcrash \"playername\" - Send a crash plane towards the specified player's position");
                    return;
                }
                if (arg.Args.Length > 0)
                {
                    if (arg.Args.Length == 2)
                    {
                        float x;
                        float z;
                        if (float.TryParse(arg.Args[0], out x) && float.TryParse(arg.Args[1], out z))
                        {
                            location = new Vector3(x, 0, z);
                            SendReply(arg, $"Crash plane sent to X: {x}, Z: {z}");
                        }
                    }
                    if (arg.Args.Length == 1)
                    {
                        var targetPlayer = covalence.Players.FindPlayer(arg.Args[0]);
                        if (targetPlayer != null && targetPlayer.IsConnected)
                        {
                            var target = targetPlayer?.Object as BasePlayer;
                            if (target != null)
                            {
                                location = target.transform.position;
                                SendReply(arg, $"Crash plane sent towards {target.displayName}'s current position");
                            }
                        }
                        else
                        {
                            SendReply(arg, "Could not locate the specified player");
                            return;
                        }
                    }
                    else
                    {
                        location = Vector3Ex.Range(-(mapSize / 6f), mapSize / 6f);
                        SendReply(arg, "Crash plane sent to random location");
                    }
                }
            }
            else
            {
                location = Vector3Ex.Range(-(mapSize / 6f), mapSize / 6f);
                SendReply(arg, "Crash plane sent to random location");
            }

            CargoPlane plane = (CargoPlane)GameManager.server.CreateEntity(cargoPlanePrefab, new Vector3(), new Quaternion(), true);
            plane.Spawn();
            AddCrashComponent(plane, location);
        }

        [ChatCommand("callcrash")]
        void cmdSendCrash(BasePlayer player, string command, string[] args)
        {
            if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, "planecrash.cancall")) return;
            if (args.Length == 1 && args[0].ToLower() == "help")
            {
                SendReply(player, $"<color=#ce422b>{Title}</color>  <color=#939393>v</color><color=#ce422b>{Version}</color> <color=#939393>-</color> <color=#ce422b>k1lly0u</color><color=#939393> @</color> <color=#ce422b>chaoscode.io</color>");
                SendReply(player, "<color=#ce422b>/callcrash</color><color=#939393> - Send a random crash plane</color>");
                SendReply(player, "<color=#ce422b>/callcrash \"X\" \"Z\" </color><color=#939393>- Send a crash plane towards the specified X and Z co-ordinates</color>");
                SendReply(player, "<color=#ce422b>/callcrash \"playername\" </color><color=#939393>- Send a crash plane towards the specified player's position</color>");
                return;
            }
            Vector3 location = Vector3.zero;
            if (args.Length > 0)
            {
                if (args.Length == 2)
                {
                    float x;
                    float z;
                    if (float.TryParse(args[0], out x) && float.TryParse(args[1], out z))
                    {
                        location = new Vector3(x, 0, z);
                        SendReply(player, $"<color=#939393>Crash plane sent to</color> <color=#ce422b>X: {x}, Z: {z}</color>");
                    }
                }
                if (args.Length == 1)
                {
                    var targetPlayer = covalence.Players.FindPlayer(args[0]);
                    if (targetPlayer != null && targetPlayer.IsConnected)
                    {
                        var target = targetPlayer?.Object as BasePlayer;
                        if (target != null)
                        {
                            location = target.transform.position;
                            SendReply(player, $"<color=#939393>Crash plane sent towards </color><color=#ce422b>{target.displayName}'s</color><color=#939393> current position</color>");
                        }
                    }
                    else
                    {
                        SendReply(player, "<color=#ce422b>Could not locate the specified player</color>");
                        return;
                    }
                }
            }
            else
            {
                location = Vector3Ex.Range(-(mapSize / 6f), mapSize / 6f);
                SendReply(player, "<color=#ce422b>Crash plane sent to random location</color>");
            }

            CargoPlane plane = (CargoPlane)GameManager.server.CreateEntity(cargoPlanePrefab, new Vector3(), new Quaternion(), true);
            plane.Spawn();
            AddCrashComponent(plane, location);
        }
        #endregion

        #region Config        
        private ConfigData configData;        
        class ConfigData
        {
            [JsonProperty(PropertyName = "Plane Settings")]
            public PlaneSettings Plane { get; set; }
            [JsonProperty(PropertyName = "Loot Settings")]
            public LootSettings Loot { get; set; }
            [JsonProperty(PropertyName = "Message Options")]
            public Messaging Messages { get; set; }
            [JsonProperty(PropertyName = "Timer Settings")]
            public Timers EventTimers { get; set; }
            [JsonProperty(PropertyName = "LustyMap Integration")]
            public Lusty LustyOptions { get; set; }
            [JsonProperty(PropertyName = "Ingame Map Integration")]
            public Map MapOptions { get; set; }
            [JsonProperty(PropertyName = "NPC Options")]
            public Bots NPCOptions { get; set; }

            public class PlaneSettings
            {
                [JsonProperty(PropertyName = "Apply crash mechanics to all spawned planes")]
                public bool ApplyToAll { get; set; }
                [JsonProperty(PropertyName = "Flight speed")]
                public float Speed { get; set; }
                [JsonProperty(PropertyName = "Show smoke on crash site")]
                public bool Smoke { get; set; }
                [JsonProperty(PropertyName = "Height modifier to default flight height")]
                public float Height { get; set; }
                [JsonProperty(PropertyName = "Amount of rocket hits to destroy mid-flight")]
                public int DestroyHits { get; set; }
                [JsonProperty(PropertyName = "Amount of rocket hits to make the plane crash")]
                public int DownHits { get; set; }
                [JsonProperty(PropertyName = "Show smoke trail behind plane")]
                public bool SmokeTrail { get; set; }
                [JsonProperty(PropertyName = "Destroy objects that get in the way of a crashing plane")]
                public bool Destruction { get; set; }
            }
            public class LootSettings
            {
                [JsonProperty(PropertyName = "Fireball lifetime (seconds)")]
                public int FireLife { get; set; }
                [JsonProperty(PropertyName = "Crate amount (Crash)")]
                public int CrateCrash { get; set; }
                [JsonProperty(PropertyName = "Supply drop amount (Crash)")]
                public int SupplyCrash { get; set; }
                [JsonProperty(PropertyName = "Crate amount (Rocket hit)")]
                public int CrateHit { get; set; }
                [JsonProperty(PropertyName = "Supply drop amount (Rocket hit)")]
                public int SupplyHit { get; set; }
                [JsonProperty(PropertyName = "Supply drop loot table")]
                public LootTables SupplyLoot { get; set; }
                [JsonProperty(PropertyName = "Crate loot table")]
                public LootTables CrateLoot { get; set; }

                [JsonProperty(PropertyName = "Lock dropped crates and supply drops")]
                public bool LockCrates { get; set; }
                [JsonProperty(PropertyName = "Locked crates and supply drop timer (seconds)")]
                public int LockTimer { get; set; }

                public class LootTables
                {
                    [JsonProperty(PropertyName = "Use this loot table")]
                    public bool Enabled { get; set; }
                    [JsonProperty(PropertyName = "Minimum amount of items to drop")]
                    public int Minimum { get; set; }
                    [JsonProperty(PropertyName = "Maximum amount of items to drop")]
                    public int Maximum { get; set; }
                    [JsonProperty(PropertyName = "Item list")]
                    public List<LootItem> Items { get; set; }

                    public class LootItem
                    {
                        [JsonProperty(PropertyName = "Item shortname")]
                        public string Shortname { get; set; }
                        [JsonProperty(PropertyName = "Minimum amount")]
                        public int Min { get; set; }
                        [JsonProperty(PropertyName = "Maximum amount")]
                        public int Max { get; set; }
                    }
                }
            }   
            public class Lusty
            {
                [JsonProperty(PropertyName = "Show icon on crash site")]
                public bool CrashIcon { get; set; }
                [JsonProperty(PropertyName = "Amount of time the crash icon will be displayed on LustyMap (seconds)")]
                public int CrashIconTime { get; set; }
                [JsonProperty(PropertyName = "Crash icon URL")]
                public string IconURL { get; set; }               
            }
            public class Map
            {
                [JsonProperty(PropertyName = "Show ingame map marker on crash site")]
                public bool CrashIcon { get; set; }
                [JsonProperty(PropertyName = "Amount of time the crash icon will be displayed on the ingame map (minutes)")]
                public int CrashIconTime { get; set; }               
            }
            public class Messaging
            {
                [JsonProperty(PropertyName = "Display incoming crash plane message")]
                public bool DisplayIncoming { get; set; }
                [JsonProperty(PropertyName = "Display destroyed crash plane message")]
                public bool DisplayDestroy { get; set; }
                [JsonProperty(PropertyName = "Display message stating who shot down the plane")]
                public bool DisplayAttacker { get; set; }
                [JsonProperty(PropertyName = "Incoming crash plane message")]
                public string IncomingMessage { get; set; }
                [JsonProperty(PropertyName = "Destroyed crash plane message")]
                public string DestroyMessage { get; set; }
                [JsonProperty(PropertyName = "Plane shot down by...message")]
                public string AttackerMessage1 { get; set; }
                [JsonProperty(PropertyName = "Plane blew up in the sky by...message")]
                public string AttackerMessage2 { get; set; }
            }
            public class Timers
            {
                [JsonProperty(PropertyName = "Autospawn crash planes with a random spawn timer")]
                public bool Random { get; set; }
                [JsonProperty(PropertyName = "Minimum time between autospawned planes (minutes)")]
                public int Min { get; set; }
                [JsonProperty(PropertyName = "Maximum time between autospawned planes (minutes)")]
                public int Max { get; set; }
            }
            public class Bots
            {
                [JsonProperty(PropertyName = "Spawn NPCs at the crash site")]
                public bool Enabled { get; set; }
                [JsonProperty(PropertyName = "Amount of NPCs to spawn")]
                public int Amount { get; set; }
                [JsonProperty(PropertyName = "Type of NPCs to spawn (Murderer / Scientist)")]
                public string Type { get; set; }
                [JsonProperty(PropertyName = "Custom kit for the NPC")]
                public string Kit { get; set; }
                [JsonProperty(PropertyName = "Initial health for the NPC")]
                public float Health { get; set; }
                [JsonProperty(PropertyName = "Despawn time for NPCs (seconds)")]
                public int DespawnTime { get; set; }
            }

            public Oxide.Core.VersionNumber Version { get; set; }
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            configData = Config.ReadObject<ConfigData>();

            if (configData.Version < Version)
                UpdateConfigValues();

            Config.WriteObject(configData, true);
        }

        protected override void LoadDefaultConfig() => configData = GetBaseConfig();

        private ConfigData GetBaseConfig()
        {
            return new ConfigData
            {
                EventTimers = new ConfigData.Timers
                {
                    Max = 60,
                    Min = 45,
                    Random = true
                },
                Plane = new ConfigData.PlaneSettings
                {
                    ApplyToAll = false,
                    Smoke = true,
                    Speed = 35f,
                    Height = 0f,
                    DestroyHits = 3,
                    Destruction = true,
                    DownHits = 1,
                    SmokeTrail = true
                },
                Loot = new ConfigData.LootSettings
                {
                    CrateCrash = 3,
                    SupplyCrash = 3,
                    FireLife = 300,
                    CrateHit = 1,
                    SupplyHit = 1,
                    LockCrates = true,
                    LockTimer = 120,
                    CrateLoot = new ConfigData.LootSettings.LootTables
                    {
                        Maximum = 4,
                        Minimum = 1,
                        Items = new List<ConfigData.LootSettings.LootTables.LootItem>
                        {
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "metal.refined", Max = 100, Min = 10 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "explosive.timed", Max = 2, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "grenade.f1", Max = 3, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "supply.signal", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "cctv.camera", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "targeting.computer", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "ammo.rifle", Max = 60, Min = 20 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "ammo.pistol", Max = 60, Min = 20 }
                        },
                        Enabled = false
                    },
                    SupplyLoot = new ConfigData.LootSettings.LootTables
                    {
                        Maximum = 6,
                        Minimum = 2,
                        Items = new List<ConfigData.LootSettings.LootTables.LootItem>
                        {
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "rifle.ak", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "pistol.m92", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "pistol.semiauto", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "shotgun.double", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "smg.thompson", Max = 1, Min = 1 },
                            new ConfigData.LootSettings.LootTables.LootItem {Shortname = "rifle.bolt", Max = 1, Min = 1 }
                        },
                        Enabled = false
                    }
                },
                LustyOptions = new ConfigData.Lusty
                {
                    CrashIcon = true,
                    CrashIconTime = 300,
                    IconURL = "http://www.chaoscode.io/oxide/Images/crashicon.png"
                },
                MapOptions = new ConfigData.Map
                {
                    CrashIcon = true,
                    CrashIconTime = 5
                },
                Messages = new ConfigData.Messaging
                {
                    DestroyMessage = "<color=#939393>A plane carrying cargo has just crashed at co-ordinates </color><color=#ce422b>X: {x}, Z: {z}</color>",
                    DisplayDestroy = true,
                    DisplayIncoming = true,
                    DisplayAttacker = true,
                    IncomingMessage = "<color=#ce422b>A low flying plane carrying cargo is about to fly over!</color><color=#939393>\nIf you are skilled enough you can shoot it down with a rocket launcher!</color>",
                    AttackerMessage1 = "<color=#ce422b>{0}</color><color=#939393> has shot down the plane!</color>",
                    AttackerMessage2 = "<color=#ce422b>{0}</color><color=#939393> has shot the plane out of the sky!</color>"
                },
                NPCOptions = new ConfigData.Bots
                {
                    Amount = 5,
                    Enabled = true,
                    Type = "Murderer",
                    Kit = "",
                    Health = 100,
                    DespawnTime = 300
                },
                Version = Version
            };            
        }

        protected override void SaveConfig() => Config.WriteObject(configData, true);

        private void UpdateConfigValues()
        {
            PrintWarning("Config update detected! Updating config values...");

            ConfigData baseConfig = GetBaseConfig();
            if (configData.Version < new VersionNumber(0, 1, 9))
            {
                configData.Messages.DisplayAttacker = b
// ... [Code preview truncated due to length. Full source in attached file] ...

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