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

FREE Paratroopers : 4.0.0 4.0.0

Нет прав для скачивания
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using UnityEngine.AI;
using VLB;
using Newtonsoft.Json;
using UnityEngine.SceneManagement;
using Rust;
using Rust.Ai;
using Facepunch;
// Rewrote most of the code
// GetComponent is expensive, store your components in a dictionary
// Added proper static cleanup and usage
// Proper subscription of hooks
// Fixed server not saving
// Fixed OnEntitySpawned cleanup
// Fixed bradley not spawning due to invalid hackable crate prefab
// Removed reflection as it's not allowed - this will make npcs act a bit differently
// Fixed config not loading or saving
// Changed AI to Apex
// Fixed language API usage
// Removed useless and unused code
namespace Oxide.Plugins {
    [Info("Paratroopers", "Skuli Dropek", "4.0.0")]
    [Description("Spawns Paratroopers Event that deploys from the Cargo Plane to random area")]
    class Paratroopers : RustPlugin {
        [PluginReference]
        Plugin Kits, Titan;
        private static Paratroopers plugin;
#region Vars
        private static Paratroopers ins {
            get;
            set;
        }
        private StoredData storedData;
        private DynamicConfigFile data;
        private const string ADMIN_PERM = "paratroopers.admin";
        private const string PLAYER_PERM = "paratroopers.cancall";
        private NavMeshHit navHit;
        private RaycastHit rayHit;
        public List<int> FltNum = new List<int>();
        private const uint CARGOPLANE_PREFABID = 2383782438;
        private const uint NPCPlayer_PREFABID = 4199494415;
        //
        private const uint CORPSE_PREFABID = 2604534927;
        private const uint CHUTE_PREFABID = 1268659691;
        private const uint SUPPLYDROP_PREFABID = 3632568684;
        private const uint HACKABLECRATE_PREFABID = 209286362;
        private const uint BRADLEY_PREFABID = 1456850188;
        private const uint SMOKE_EFFECTID = 2278592883;
        private const uint SIRENLIGHT_EFFECTID = 2436926577;
        private const uint SIRENALARM_EFFECTID = 1056621402;
        private const uint SUPPLYDROP_EFFECTID = 135533567;
        private LootContainer crate;
        const object Null = null;
        public bool IsNight;
        private List<MapMarkerGenericRadius> dropZoneMarkerList = new List<MapMarkerGenericRadius>();
        private Dictionary<ScientistNPC, MapMarkerGenericRadius> botMarkerList = new Dictionary<ScientistNPC, MapMarkerGenericRadius>();
        private Dictionary<ScientistNPC, NPCParatrooper> paratrooperList = new Dictionary<ScientistNPC, NPCParatrooper>();
        private List<ScientistNPC> jumperList = new List<ScientistNPC>();
        private List<ulong> paratrooperCorpseIDs = new List<ulong>();
        public List<ulong> DeadNPCPlayerIds = new List<ulong>();
        //to tracebackpacks
        private Dictionary<CargoPlane, ParatrooperPlane> planes = new Dictionary<CargoPlane, ParatrooperPlane>();
        List<LootContainer> drops = new List<LootContainer>();
        List<StorageContainer> dropsCrate = new List<StorageContainer>();
        List<BradleyAPC> dropBradley = new List<BradleyAPC>();
        private const int LAND_LAYERS = 1 << 4 | 1 << 8 | 1 << 16 | 1 << 21 | 1 << 23;
        private const int WORLD_LAYER = (1 << 0 | 1 << 16) | ~(1 << 18 | 1 << 28 | 1 << 29);
        public const string ChatIcon = "76561198035100747";
#endregion
#region Get Misc Functions
        private Vector3 GetDropPosition() {
            return new Vector3(configData.Automation.JumpPositionX, configData.Automation.jumpHeight, configData.Automation.JumpPositionZ);
        }
        public int GetDefaultJumpSpread() {
            return configData.Paratroopers.defaultJumpSpread;
        }
        public float GetJumpHeight() {
            return configData.Automation.jumpHeight;
        }
        public string GetInboundMessage() {
            return msg("InboundJumpPositionMessageChat");
        }
        public float GetPlaneSpeed() {
            return configData.Automation.PlaneSpeed;
        }
#endregion
#region startup/close/clean-up
        private void OnServerInitialized() {
            //Start Loaded
            Unsubscribe();
            IsNight = TOD_Sky.Instance.IsNight;
            if (configData.Notifications.ConsoleOutput) {
                if (Kits == null) {
                    Puts("WARNING: Kits Plugin is required");
                }
                else Puts("Found dependency Kits");
            }
            ins = this;
            lang.RegisterMessages(Messages, this);
            permission.RegisterPermission(ADMIN_PERM, this);
            permission.RegisterPermission(PLAYER_PERM, this);
            foreach (var kvp in configData.Cooldowns) {
                if (!kvp.Key.StartsWith("paratroopers.")) {
                    permission.RegisterPermission("paratroopers." + kvp.Key, this);
                }
                else permission.RegisterPermission(kvp.Key, this);
            }
            if (configData.MapSettings.CreateBotMarkers) {
                timer.Repeat(configData.MapSettings.BotMarkerRefreshInterval, 0, () => RefreshBotMarkers());
            }
            //End Loaded
            ins = this;
            LoadData();
            if (configData.Automation.AutoSpawn == true) {
                float nextJump = Oxide.Core.Random.Range(configData.Automation.RandomJumpIntervalMinSec, configData.Automation.RandomJumpIntervalMaxSec);
                timer.Once(nextJump, () => RepeatRandomJump());
                if (configData.Notifications.ConsoleOutput) {
                    Puts("Random Paratroopers Events will occur in {0}s", nextJump);
                }
            }
            else if (configData.Notifications.ConsoleOutput) {
                Puts("Random interval Paratroopers Events are turned off");
            }
            Subscribe();
        }
        private void Unload() {
            if (configData.Notifications.ConsoleOutput) {
                Puts("Save files, destroy timers, etc");
            }
            WipeTroopers();
            WipeMarkers(botMarkerList.Values.ToList());
            WipeMarkers(dropZoneMarkerList.ToList());
            ins = null;
            KillEvent();
            configData = null;
            SaveData();
        }
        public void GetFlightNumber() {
            FlightNumber = Core.Random.Range(3000, 9999);
            FltNum.Add(FlightNumber);
        }
        private string FormatTime(double time) {
            TimeSpan dateDifference = TimeSpan.FromSeconds((float)time);
            var days = dateDifference.Days;
            var hours = dateDifference.Hours;
            hours += (days * 24);
            var mins = dateDifference.Minutes;
            var secs = dateDifference.Seconds;
            return string.Format("{0:00}:{1:00}:{2:00}", hours, mins, secs);
        }
#endregion
#region hooks
        private object OnDeathNotice(Dictionary<string, object> data, string message)  // this shouldn't be required ever
        {
            //PrintWarning(data["VictimEntity"].ToString());
            var entity = data["VictimEntity"] as ScientistNPC;
            if (entity == null) {
                return null;
            }
            if (paratrooperList.ContainsKey(entity)) {
                paratrooperList.Remove(entity);
                return false;
            }
            return null;
        }
        private object OnCustomLootNPC(uint ID) {
            foreach (var npc in paratrooperList.Keys) {
                if (npc?.net?.ID == ID) {
                    if (configData.npc.LootType.ToLower() == "default") {
                        return null;
                    }
                    return true;
                }
            }
            return null;
        }
        private object OnNpcResume(ScientistNPC npc) {
            if (npc == null) {
                return null;
            }
            NPCParatrooper paratrooper;
            if (!paratrooperList.TryGetValue(npc, out paratrooper) || paratrooper.hasLanded) {
                return null;
            }
            return true;
        }
        private void OnEntityKill(SupplyDrop drop) => drops.Remove(drop);
        private void OnEntityKill(HackableLockedCrate crate) => dropsCrate.Remove(crate);
        private void OnEntityKill(CargoPlane cp) {
            if (cp == null) {
                return;
            }
            ParatrooperPlane crashComponent;
            if (!planes.TryGetValue(cp, out crashComponent)) {
                return;
            }
            UnityEngine.Object.Destroy(crashComponent);
            planes.Remove(cp);
        }
        private void OnEntityKill(ScientistNPC victim) => OnPlayerDeath(victim, null);
        private void OnPlayerDeath(ScientistNPC victim, HitInfo hitInfo) {
            if (victim == null) {
                return;
            }
            NPCParatrooper paratrooper;
            if (!paratrooperList.TryGetValue(victim, out paratrooper)) {
                return;
            }
            victim.UpdateActiveItem(0);
            if (configData.npc.LootType.ToLower() == "inventory") {
                paratrooper.PrepareInventory();
            }
            if (hitInfo == null) {
                return;
            }
            var attacker = hitInfo.Initiator as BasePlayer;
            if (attacker == null) {
                return;
            }
            MapMarkerGenericRadius mapMarker;
            if (botMarkerList.TryGetValue(victim, out mapMarker)) {
                mapMarker.Kill();
                mapMarker.SendUpdate();
                botMarkerList.Remove(victim);
            }
            paratrooperCorpseIDs.Add(victim.userID);
            if (victim == attacker) {
                if (configData.Notifications.NPCSuicide) {
                    string key = hitInfo.damageTypes.Has(Rust.DamageType.Drowned) ? "ParatrooperDrowned" : "ParatrooperKilledSelf";
                    foreach (var target in BasePlayer.activePlayerList) {
                        target.SendConsoleCommand("chat.add", new object[] {
                            2, ChatIcon, string.Format(msg(key, target.UserIDString), victim.displayName)
                        }
                        );
                    }
                }
            }
            else if (configData.Notifications.NPCDeath) {
                foreach (var target in BasePlayer.activePlayerList) {
                    target.SendConsoleCommand("chat.add", new object[] {
                        2, ChatIcon, string.Format(msg("ParatrooperKilled", target.UserIDString), attacker.displayName, victim.displayName)
                    }
                    );
                }
            }
        }
        private void OnEntityDeath(BradleyAPC victim, HitInfo hitInfo) {
            if (victim == null || hitInfo == null || !dropBradley.Contains(victim)) {
                return;
            }
            dropBradley.Remove(victim);
            victim.GetOrAddComponent<APCController>();
            if (!configData.Notifications.APCDeath) {
                return;
            }
            var attacker = hitInfo.Initiator as BasePlayer;
            if (attacker == null) {
                return;
            }
            foreach (var target in BasePlayer.activePlayerList) {
                target.SendConsoleCommand("chat.add", new object[] {
                    2, ChatIcon, string.Format(msg("BradleyKilled", target.UserIDString), attacker.displayName)
                }
                );
            }
        }
        private object OnTurretTarget(NPCAutoTurret turret, ScientistNPC ScientistNPC) => HookHandler(ScientistNPC);
        private object CanHelicopterTarget(PatrolHelicopterAI heliAi, ScientistNPC ScientistNPC) => HookHandler(ScientistNPC);
        private object CanHelicopterStrafeTarget(PatrolHelicopterAI heliAi, ScientistNPC ScientistNPC) => HookHandler(ScientistNPC);
        private object OnNpcTarget(BaseNpc npc, ScientistNPC ScientistNPC) => HookHandler(ScientistNPC);
        private object HookHandler(ScientistNPC ScientistNPC) => ScientistNPC != null && paratrooperList.ContainsKey(ScientistNPC) ? true : (object)null;
        private object CanBradleyApcTarget(BradleyAPC apc, BasePlayer player) {
            if (player == null || apc == null || !dropBradley.Contains(apc)) {
                return null;
            }
            if (player is ScientistNPC) {
                return HookHandler(player as ScientistNPC);
            }
            return player.IsNearEnemyBase() || CanIgnoreSleeper(player) ? false : (object)null;
        }
        private bool EventTerritory(Vector3 target) {
            foreach (var drop in drops) {
                if ((drop.transform.position - target).magnitude <= configData.Distance) {
                    return true;
                }
            }
            foreach (var drop in dropsCrate) {
                if ((drop.transform.position - target).magnitude <= configData.Distance) {
                    return true;
                }
            }
            foreach (var drop in dropBradley) {
                if ((drop.transform.position - target).magnitude <= configData.Distance) {
                    return true;
                }
            }
            return false;
        }
        private object CanEntityTakeDamage(BasePlayer victim, HitInfo hitInfo) {
            if (hitInfo == null || !victim.IsValid() || victim.IsNpc) {
                return null;
            }
            var attacker = hitInfo.Initiator as BasePlayer;
            if (!attacker.IsValid()) {
                return null;
            }
            if (EventTerritory(victim.transform.position) && EventTerritory(attacker.transform.position)) {
                return true;
            }
            return null;
        }
        private void OnEntityTakeDamage(BradleyAPC apc, HitInfo hitInfo) {
            if (apc == null || !dropBradley.Contains(apc) || hitInfo == null || !(hitInfo.Initiator is BasePlayer)) {
                return;
            }
            var attacker = hitInfo.Initiator as BasePlayer;
            if (!attacker.IsNearEnemyBase()) {
                return;
            }
            hitInfo.damageTypes = new DamageTypeList();
        }
        private void OnEntityTakeDamage(ScientistNPC ScientistNPC, HitInfo hitInfo) {
            if (ScientistNPC == null || hitInfo == null || !(hitInfo.Initiator is BasePlayer)) {
                return;
            }
            NPCParatrooper paratrooper;
            if (!paratrooperList.TryGetValue(ScientistNPC, out paratrooper)) {
                return;
            }
            paratrooper.OnReceivedDamage(hitInfo.Initiator as BasePlayer, hitInfo);
        }
#region IgnoreSleeper
        private object OnNpcTarget(BaseEntity npc, BasePlayer player) => CanIgnoreSleeper(player) ? true : (object)null;
        private bool CanIgnoreSleeper(BasePlayer player) {
            if (player == null || player is TunnelDweller || !player.userID.IsSteamId() || !player.IsSleeping()) return false;
            return true;
        }
#endregion IgnoreSleeper
#region WeaponHandling
        private int GetRange(float distance) {
            if (distance < 2f) return 1;
            if (distance < 10f) return 2;
            if (distance < 40f) return 3;
            return 4;
        }
#endregion
        private object CanPopulateLoot(ScientistNPC ScientistNPC, NPCPlayerCorpse corpse) => HookHandler(ScientistNPC);
        private object OnCorpsePopulate(HumanNPC ScientistNPC, NPCPlayerCorpse corpse) {
            if (corpse != null && paratrooperCorpseIDs.Contains(corpse.playerSteamID)) {
                paratrooperCorpseIDs.Remove(corpse.playerSteamID);
                DeadNPCPlayerIds.Add(corpse.playerSteamID);
                if (corpse.containers != null) {
                    for (int i = 0; i < corpse.containers.Length; i++) {
                        ClearContainer(corpse.containers[i]);
                    }
                }
            }
            if (ScientistNPC == null) {
                return null;
            }
            NPCParatrooper paratrooper;
            if (!paratrooperList.TryGetValue(ScientistNPC as ScientistNPC, out paratrooper)) return null;
            paratrooperList.Remove(ScientistNPC as ScientistNPC);
            if (configData.npc.LootType.ToLower() == "inventory") {
                paratrooper.MoveInventoryTo(corpse);
                return corpse;
            }
            //if (configData.npc.RandomItems.Maximum > 0)
            //{
            //    PopulateLoot(corpse.containers[0], configData.npc.RandomItems);
            //}
            return corpse;
        }
        private object OnEntityDismounted(BaseMountable mount, BasePlayer player) {
            if (player.IsNpc && paratrooperList.ContainsKey(player.GetComponent<ScientistNPC>()) && mount.VehicleParent() is CH47Helicopter) {
                player.Invoke(() => {
                    if (player == null) {
                        return;
                    }
                    BaseNavigator BN = player.GetComponent<BaseNavigator>();
                    if (BN == null) {
                        return;
                    }
                    NavMeshHit hit;
                    if (NavMesh.SamplePosition(player.transform.position, out hit, 30, -1)) {
                        player.gameObject.layer = 17;
                        player.ServerPosition = hit.position;
                        BN.Agent.Warp(player.ServerPosition);
                        player.Invoke(() => BN.CanUseNavMesh = true, 2f);
                    }
                }
                , 1f);
            }
            return null;
        }
        private void Subscribe()  // removed all init checks
        {
            if (configData.Distance > 0 && configData.LootBoxes.LootEffects.dropBradley) {
                Subscribe(nameof(CanEntityTakeDamage));
            }
            Subscribe(nameof(OnEntityKill));
            Subscribe(nameof(OnPlayerDeath));
            Subscribe(nameof(OnEntityDeath));
            Subscribe(nameof(OnEntityTakeDamage));
            Subscribe(nameof(OnEntitySpawned));
            Subscribe(nameof(CanLootPlayer));
            Subscribe(nameof(OnPlayerAssist));
            if (configData.npc.LootType.ToLower() != "default") {
                Subscribe(nameof(OnCorpsePopulate));
                Subscribe(nameof(CanPopulateLoot));
            }
        }
        private void Unsubscribe() {
            Unsubscribe(nameof(CanEntityTakeDamage));
            Unsubscribe(nameof(OnEntityKill));
            Unsubscribe(nameof(OnPlayerDeath));
            Unsubscribe(nameof(OnEntityDeath));
            Unsubscribe(nameof(OnEntityTakeDamage));
            Unsubscribe(nameof(OnEntitySpawned));
            Unsubscribe(nameof(CanLootPlayer));
            Unsubscribe(nameof(OnPlayerAssist));
            Unsubscribe(nameof(OnCorpsePopulate));
            Unsubscribe(nameof(CanPopulateLoot));
            Unsubscribe(nameof(CanBradleyApcTarget));
        }
        private void OnEntitySpawned(DroppedItemContainer container) {
            NextTick(() => {
                if (container == null || !DeadNPCPlayerIds.Contains(container.playerSteamID)) return;
                DeadNPCPlayerIds.Remove(container.playerSteamID);
                if (!container.IsDestroyed) container.Kill();
            }
            );
        }
        private object CanLootPlayer(ScientistNPC ScientistNPC, BasePlayer player) {
            if (ScientistNPC != null && paratrooperList.ContainsKey(ScientistNPC) && ScientistNPC.IsWounded()) {
                return false;
            }
            return null;
        }
        private object OnPlayerAssist(ScientistNPC ScientistNPC, BasePlayer player) => HookHandler(ScientistNPC);
        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 string GetGridString(Vector3 position) {
            var adjPosition = new Vector2((World.Size / 2) + position.x, (World.Size / 2) - position.z);
            return $"{NumberToString((int)(adjPosition.x / 145))}{((int)(adjPosition.y / 145))}";
        }
        private static string NumberToString(int number) {
            var a = number > 26;
            var c = (System.Char)(65 + (a ? number - 26 : number));
            return a ? "A" + c : c.ToString();
        }
        private static void StripInventory(BasePlayer player) {
            ClearContainer(player.inventory.containerBelt);
            ClearContainer(player.inventory.containerMain);
            ClearContainer(player.inventory.containerWear);
        }
        private static void ClearContainer(ItemContainer container) {
            while (container.itemList.Count > 0) {
                Item item = container.itemList[0];
                item.RemoveFromContainer();
                item.Remove();
            }
        }
        private static void PopulateLoot(ItemContainer container, ConfigData.LootContainer loot) {
            ClearContainer(container);
            var amount = UnityEngine.Random.Range(loot.Minimum, loot.Maximum);
            var list = new List<ConfigData.LootItem>(loot.Items);
            for (int i = 0; i < amount; i++) {
                if (list.Count == 0) {
                    list = new List<ConfigData.LootItem>(loot.Items);
                }
                var lootItem = list[UnityEngine.Random.Range(0, list.Count())];
                list.Remove(lootItem);
                Item item = ItemManager.CreateByName(lootItem.Name, UnityEngine.Random.Range(lootItem.Minimum, lootItem.Maximum), lootItem.Skin);
                if (!item.MoveToContainer(container)) item.Remove();
            }
        }
        private static object FindPointOnNavmesh(Vector3 targetPosition) {
            targetPosition.y = TerrainMeta.HeightMap.GetHeight(targetPosition);
            for (int i = 0; i < 10; i++) {
                NavMeshHit navHit;
                if (NavMesh.SamplePosition(targetPosition, out navHit, 40, -1)) {
                    if (IsInOrOnRock(navHit.position)) {
                        continue;
                    }
                    return navHit.position;
                }
            }
            return null;
        }
        private static bool IsInOrOnRock(Vector3 position, string meshName = "rock_", float radius = 2f) {
            bool flag = false;
            int hits = Physics.OverlapSphereNonAlloc(position, radius, Vis.colBuffer, Layers.Mask.World, QueryTriggerInteraction.Ignore);
            for (int i = 0; i < hits; i++) {
                if (Vis.colBuffer[i].name.StartsWith(meshName) && IsRockTooLarge(Vis.colBuffer[i].bounds)) {
                    flag = true;
                }
                Vis.colBuffer[i] = null;
            }
            if (!flag) {
                float y = TerrainMeta.HighestPoint.y + 250f;
                RaycastHit hit;
                if (Physics.Raycast(position, Vector3.up, out hit, y, Layers.Mask.World, QueryTriggerInteraction.Ignore)) {
                    if (hit.collider.name.StartsWith(meshName) && IsRockTooLarge(hit.collider.bounds)) flag = true;
                }
                if (!flag && Physics.Raycast(position, Vector3.down, out hit, y, Layers.Mask.World, QueryTriggerInteraction.Ignore)) {
                    if (hit.collider.name.StartsWith(meshName) && IsRockTooLarge(hit.collider.bounds)) flag = true;
                }
                if (!flag && Physics.Raycast(position + new Vector3(0f, y, 0f), Vector3.down, out hit, y + 1f, Layers.Mask.World, QueryTriggerInteraction.Ignore)) {
                    if (hit.collider.name.StartsWith(meshName) && IsRockTooLarge(hit.collider.bounds)) flag = true;
                }
            }
            return flag;
        }
        private static bool IsRockTooLarge(Bounds bounds, float extents = 1.5f) {
            return bounds.extents.Max() > extents;
        }
        private bool IsKit(string kit) {
            //Call kit plugin to check if its valid kit
            var success = Kits?.Call("isKit", kit);
            if (success == null || !(success is bool)) {
                return false;
            }
            return (bool)success;
        }
        void GiveKit(NPCPlayer npc, string kit) {
            if (kit == "" || !IsKit(kit)) return;
            object success = Kits?.Call("GiveKit", npc, kit);
            if (success == null || !(success is bool)) {
                Puts("Failed to give NPC Kit");
                return;
            }
            //Trys to equip stuff
            Item projectileItem = null;
            //Find first gun
            foreach (var item in npc.inventory.containerBelt.itemList.ToList()) {
                if (item.GetHeldEntity() is BaseProjectile) {
                    projectileItem = item;
                    break;
                }
                //Move medial items out of hot bar
                if (item.GetHeldEntity() is MedicalTool) {
                    item.MoveToContainer(npc.inventory.containerMain);
                    continue;
                }
            }
            if (projectileItem == null) {
                //Find a melee weapon in the belt
                foreach (var item in npc.inventory.containerBelt.itemList.ToList()) {
                    if (item.GetHeldEntity() is BaseMelee) {
                        projectileItem = item;
                        break;
                    }
                }
            }
            if (projectileItem != null) {
                //pull out active item.npc.UpdateActiveItem(projectileItem.uid);
                npc.inventory.UpdatedVisibleHolsteredItems();
                timer.Once(1f, () => {
                    npc.AttemptReload();
                }
                );
            }
        }
#endregion
#region Map Markers
        private void CreateBotMarker(ScientistNPC npc) {
            if (npc == null || npc.IsDestroyed) {
                return;
            }
            MapMarkerGenericRadius mapMarker;
            if (!botMarkerList.TryGetValue(npc, out mapMarker)) {
                mapMarker = GameManager.server.CreateEntity(StringPool.Get(2849728229), npc.transform.position) as MapMarkerGenericRadius;
                mapMarker.alpha = configData.MapSettings.BotDropZoneAlpha;
                mapMarker.color1 = Color.yellow;
                mapMarker.radius = configData.MapSettings.BotDropZoneRadius;
                mapMarker.Spawn();
                botMarkerList[npc] = mapMarker;
            }
            mapMarker.SendUpdate();
        }
        private void CreateDropZoneMarker(Vector3 pos) {
            var mapMarker = GameManager.server.CreateEntity(StringPool.Get(2849728229), pos) as MapMarkerGenericRadius;
            mapMarker.alpha = configData.MapSettings.DropZoneAlpha;
            mapMarker.color1 = Color.red;
            mapMarker.radius = configData.MapSettings.DropZoneRadius;
            mapMarker.Spawn();
            mapMarker.SendUpdate();
            timer.Once(configData.npc.Lifetime + 90f, () => {
                try {
                    dropZoneMarkerList.Remove(mapMarker);
                    mapMarker.Kill();
                    mapMarker.SendUpdate();
                }
                catch {
                }
            }
            );
            // add time to account for drop time
            dropZoneMarkerList.Add(mapMarker);
        }
        private void RefreshBotMarkers() {
            foreach (var npcPlayer in paratrooperList.Keys) {
                CreateBotMarker(npcPlayer);
            }
            foreach (var jumperPlayer in jumperList) {
                CreateBotMarker(jumperPlayer);
            }
            foreach (var mapMarker in dropZoneMarkerList) {
                mapMarker?.SendUpdate();
            }
        }
        private List<string> GetParatrooperPositions() {
            var returnPositionList = new List<string>();
            foreach (var jumper in jumperList) {
                if (jumper == null || jumper.IsDestroyed) {
                    continue;
                }
                var gridPos = GetGridString(jumper.transform.position);
                if (!returnPositionList.Contains(gridPos)) {
                    returnPositionList.Add(gridPos);
                }
            }
            foreach (var ScientistNPC in paratrooperList.Keys) {
                if (ScientistNPC == null || ScientistNPC.IsDestroyed) {
                    continue;
                }
                var gridPos = GetGridString(ScientistNPC.transform.position);
                if (!returnPositionList.Contains(gridPos)) {
                    returnPositionList.Add(gridPos);
                }
            }
            return returnPositionList;
        }
        private string GetParatrooperGridLocations() {
            var troopPositionList = GetParatrooperPositions();
            if (troopPositionList.Count == 0) {
                return msg("NoParatroopers");
            }
            string returnValue = msg("ParatroopersFound");
            foreach (string gridLoc in troopPositionList) {
                returnValue = returnValue + " <color=orange>" + gridLoc + "</color>";
            }
            return returnValue;
        }
#endregion
#region Wipe Elements
        private void WipeMarkers(List<MapMarkerGenericRadius> markers) {
            foreach (var mapMarker in markers) {
                if (mapMarker == null || mapMarker.IsDestroyed) {
                    continue;
                }
                mapMarker.Kill();
                mapMarker.SendUpdate();
            }
            markers.Clear();
        }
        private void WipeTroopers() {
            foreach (var x in jumperList.ToList()) {
                if (x != null && !x.IsDestroyed) {
                    x.Kill();
                }
            }
            foreach (var entry in paratrooperList.ToList()) {
                var x = entry.Key;
                if (x != null && !x.IsDestroyed) {
                    x.Kill();
                }
            }
            jumperList.Clear();
            paratrooperList.Clear();
        }
        private void KillEvent() {
            if (paratrooperList.Count > 0 || jumperList.Count > 0) {
                WipeTroopers();
            }
            if (botMarkerList.Count > 0) {
                WipeMarkers(botMarkerList.Values.ToList());
            }
            if (dropZoneMarkerList.Count > 0) {
                WipeMarkers(dropZoneMarkerList);
            }
            foreach (var x in drops) {
                if (x != null && !x.IsDestroyed) {
                    x.Kill();
                }
            }
            foreach (var x in dropsCrate) {
                if (x != null && !x.IsDestroyed) {
                    x.Kill();
                }
            }
            foreach (var x in dropBradley) {
                if (x != null && !x.IsDestroyed) {
                    x.Kill();
                }
            }
            FltNum.Clear();
            ParatrooperPlane[] planes = UnityEngine.Object.FindObjectsOfType<ParatrooperPlane>();
            for (int i = 0; i < planes?.Length; i++) {
                UnityEngine.Object.Destroy(planes[i]);
            }
        }
#endregion
#region Misc Functions
        private Vector3 SpreadPosition(Vector3 origPosition, int amtToSpread) {
            int spreadX = Oxide.Core.Random.Range(amtToSpread * -1, amtToSpread);
            int spreadZ = Oxide.Core.Random.Range(amtToSpread * -1, amtToSpread);
            return new Vector3(origPosition.x + spreadX, origPosition.y, origPosition.z + spreadZ);
        }
        private void RepeatRandomJump() {
            // Call random jump
            if (BasePlayer.activePlayerList.Count >= configData.Automation.RequiredPlayers) {
                TriggerRandomJump();
            }
            else if (configData.Notifications.ConsoleOutput) {
                Puts("Not enough players for event.");
            }
            // Queue up the next one..float nextJump = UnityEngine.Random.Range(configData.Automation.RandomJumpIntervalMinSec, configData.Automation.RandomJumpIntervalMaxSec);
            timer.Once(nextJump, () => RepeatRandomJump());
            if (configData.Notifications.ConsoleOutput) {
                Puts("A random Paratroopers Event will occur in {0}s", nextJump);
            }
        }
        private SpawnFilter filter = new SpawnFilter();
        public Vector3 RandomDropPosition() {
            Vector3 vector;
            if (configData.Airfield) {
                vector = GetAirfieldPosition();
                if (vector != Vector3.zero) {
                    return vector;
                }
            }
            float num = 100f;
            float x = TerrainMeta.Size.x;
            do {
                vector = Vector3Ex.Range(0f - x / 3f, x / 3f);
            }
            while (filter.GetFactor(vector) == 0f && (num -= 1f) > 0f);
            vector.y = 0f;
            return vector;
        }
        private void TriggerRandomJump() {
            var jumpPosition = RandomDropPosition();
            if (configData.Notifications.ConsoleOutput) {
                Puts("A random Paratroopers Event will occur near {0}", GetGridString(jumpPosition));
            }
            CallParatroopers(jumpPosition, configData.npc.RandomJumperCount, null, 0, true);
        }
#endregion
#region Grid Teleport
        public class SpawnPosition {
            private const float aboveGoundPosition = 2.5f;
            public Vector3 Position;
            public Vector3 GroundPosition;
            public string GridReference;
            public SpawnPosition(Vector3 position) {
                Position = position;
                GroundPosition = GetGroundPosition(new Vector3(position.x, 25, position.z));
            }
            public bool isPositionAboveWater() {
                if ((TerrainMeta.HeightMap.GetHeight(Position) - TerrainMeta.WaterMap.GetHeight(Position)) >= 0) return false;
                return true;
            }
            public float WaterDepthAtPosition() {
                return (TerrainMeta.WaterMap.GetHeight(Position) - TerrainMeta.HeightMap.GetHeight(Position));
            }
            Vector3 GetGroundPosition(Vector3 sourcePos) {
                RaycastHit hitInfo;
                if (Physics.Raycast(sourcePos, Vector3.down, out hitInfo)) sourcePos.y = hitInfo.point.y;
                sourcePos.y = Mathf.Max(sourcePos.y, TerrainMeta.HeightMap.GetHeight(sourcePos)) + aboveGoundPosition;
                return sourcePos;
            }
        }
#endregion
#region Drop Chutes
        public class CrateDropChute : MonoBehaviour {
            private SupplyDrop crate;
            private Rigidbody rigidbody;
            private BaseEntity parachute;
            private void Awake() {
                rigidbody = crate.GetComponent<Rigidbody>();
            }
            private void Start() {
                AddParachute();
            }
            private void OnDestroy() {
                RemoveParachute();
            }
            private void AddParachute() {
                if (rigidbody != null) {
                    rigidbody.useGravity = true;
                }
                parachute = GameManager.server.CreateEntity(StringPool.Get(CHUTE_PREFABID));
                if (parachute != null) {
                    parachute.SetParent(crate, false);
                    parachute.Spawn();
                    parachute.SendNetworkUpdateImmediate(true);
                }
            }
            private void RemoveParachute() {
                if (parachute.IsValid()) {
                    if (rigidbody != null) {
                        rigidbody.useGravity = false;
                    }
                    if (!parachute.IsDestroyed) {
                        parachute.Kill();
                    }
                    parachute = null;
                }
            }
            private void OnCollisionEnter(Collision collision) {
                Effect.server.Run(StringPool.Get(SUPPLYDROP_EFFECTID), transform.position);
                Destroy(this);
            }
            private void FixedUpdate() {
                if (parachute.IsValid()) {
                    rigidbody.useGravity = true;
                    rigidbody.mass = configData.LootBoxes.LootEffects.lootMass;
                    rigidbody.drag = configData.LootBoxes.LootEffects.lootDrag * (rigidbody.mass / 5f);
                    crate.transform.position -= new Vector3(0, 10f * configData.LootBoxes.LootEffects.lootMass * Time.deltaTime, 0);
                    //crate.transform.position -= new Vector3(0, 10f * Time.deltaTime, 0);
                }
            }
        }
        private class HackCrateDropChute : MonoBehaviour {
            private BaseEntity crate;
            private BaseEntity parachute;
            private Rigidbody rigidbody;
            private void Awake() {
                crate = GetComponent<BaseEntity>();
                rigidbody = crate.GetComponent<Rigidbody>();
                rigidbody.useGravity = true;
                rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
                rigidbody.mass = 5.25f;
                rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
                rigidbody.angularVelocity = Vector3Ex.Range(-1.75f, 1.75f);
                rigidbody.drag = 2.0f * (rigidbody.mass / 5f);
                rigidbody.angularDrag = 0.2f * (rigidbody.mass / 5f);
            }
            private void Start() {
                AddParachute();
            }
            private void OnDestroy() {
                RemoveParachute();
            }
            private void AddParachute() {
                if (rigidbody != null) {
                    rigidbody.useGravity = false;
                }
                parachute = GameManager.server.CreateEntity(StringPool.Get(CHUTE_PREFABID));
                if (parachute != null) {
                    parachute.SetParent(crate, false);
                    parachute.Spawn();
                    parachute.SendNetworkUpdateImmediate(true);
                }
            }
            private void RemoveParachute() {
                if (parachute.IsValid()) {
                    if (rigidbody != null) {
                        rigidbody.useGravity = true;
                    }
                    if (!parachute.IsDestroyed) {
                        parachute.Kill();
                    }
                    parachute = null;
                }
            }
            private void OnCollisionEnter(Collision collision) {
                Destroy(this);
            }
            private void FixedUpdate() {
                if (parachute.IsValid()) {
                    crate.transform.position -= new Vector3(0, 10f * Time.deltaTime, 0);
                }
            }
        }
        private class DroppingVehicle : MonoBehaviour {
            private BaseEntity vehicle;
            private BaseEntity parachute;
            private Rigidbody rb;
            private void Awake() {
                vehicle = GetComponent<BaseEntity>();
                rb = vehicle.gameObject.GetComponent<Rigidbody>();
            }
            private void Start() {
                AddParachute();
            }
            private void OnDestroy() {
                RemoveParachute();
            }
            private void AddParachute() {
                if (rb != null) {
                    rb.useGravity = false;
                }
                parachute = GameManager.server.CreateEntity(StringPool.Get(CHUTE_PREFABID));
                if (parachute != null) {
                    parachute.SetParent(vehicle, "parachute_attach");
                    parachute.Spawn();
                    if (configData.LootBoxes.LootEffects.enableSmoke) {
                        Effect.server.Run(StringPool.Get(SMOKE_EFFECTID), parachute, 0, Vector3.zero, Vector3.zero, null, true);
                    }
                }
            }
            private void RemoveParachute() {
                if (vehicle.IsValid() && rb != null) {
                    rb.useGravity = true;
                }
                if (parachute.IsValid()) {
                    if (!parachute.IsDestroyed) {
                        parachute.Kill();
                    }
                    parachute = null;
                }
            }
            private void OnCollisionEnter(Collision collision) {
                Destroy(this);
            }
            private void FixedUpdate() {
                if (parachute.IsValid()) {
                    vehicle.transform.position -= new Vector3(0, 10f * Time.deltaTime, 0);
                }
            }
        }
#endregion
#region Jump Event Manager
        private class JumpEventManager {
            public Vector3 DropPosition = new Vector3();
            public int ParatrooperCount = 0;
            public int JumpedCount = 0;
            public string ParatrooperKit = "";
            public bool ParatrooperRandomKit;
            public int ParatrooperHealth = 0;
            private BaseEntity parachute;
            private bool EnableLootDrop;
            internal ParatrooperPlane paratrooperPlane {
                get;
                private set;
            }
            internal APCController APCBradley {
                get;
                private set;
            }
            private bool CreatedDropZoneMarker = false;
            private void a_PositionReached(object sender, EventArgs e) {
                Vector3 deployPos = paratrooperPlane.transform.position;
                string jumpMessage = string.Format(ins.GetInboundMessage(), ins.GetGridString(deployPos));
                foreach (int FlightNumber in ins.FltNum) {
                    if (configData.Notifications.Inbound) {
                        string key = configData.LootBoxes.LootEffects.dropBradley ? "InboundJumpPositionMessage2" : "InboundJumpPositionMessage";
                        SendChatMessage(key, FlightNumber, ParatrooperCount, ins.GetGridString(deployPos));
                    }
                }
                if (configData.Notifications.ConsoleOutput) {
                    ins.Puts(jumpMessage);
                }
                CreateJumpers();
            }
            private void CreateJumpers() {
                var jumpPosition = ins.SpreadPosition(paratrooperPlane.transform.position, ins.GetDefaultJumpSpread());
                ServerMgr.Instance.StartCoroutine(SpawnNPCs(jumpPosition, ParatrooperKit, ParatrooperHealth, ParatrooperRandomKit));
                string ent = configData.LootBoxes.typeOfBox.ToLower();
                if (++JumpedCount < ParatrooperCount) {
                    float nextJumperDelay = UnityEngine.Random.Range(0.01f, 0.5f);
                    ins.timer.Once(nextJumperDelay, () => CreateJumpers());
                }
                if (configData.MapSettings.CreateDropZoneMarkers && !CreatedDropZoneMarker && JumpedCount >= (ParatrooperCount / 2)) {
                    ins.CreateDropZoneMarker(jumpPosition);
                    CreatedDropZoneMarker = true;
                    if (configData.LootBoxes.enableLootBox) {
                        if (ent == "supplydrop") {
                            SpawnLoot();
                        }
                        else if (ent == "hackablecrate") {
                            SpawnLootCrate();
                        }
                    }
                    if (configData.LootBoxes.LootEffects.dropBradley) {
                        ins.timer.Once(0.05f, () => SpawnBradley());
                    }
                }
            }
            private static void CreateSirenLights(BaseEntity entity) {
                var SirenLight = GameManager.server.CreateEntity(StringPool.Get(SIRENLIGHT_EFFECTID), 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(StringPool.Get(SIRENALARM_EFFECTID), default(Vector3), default(Quaternion), true);
                SirenAlarm.gameObject.Identity();
                SirenAlarm.SetParent(entity as LootContainer, "parachute_attach");
                SirenAlarm.Spawn();
                SirenAlarm.SetFlag(BaseEntity.Flags.Reserved8, true);
            }
            private void CreateDropEffects(BaseEntity entity) {
                if (entity == null) {
                    return;
                }
                if (configData.LootBoxes.LootEffects.enableSmoke) {
                    Effect.server.Run(StringPool.Get(SMOKE_EFFECTID), entity, 0, Vector3.zero, Vector3.zero, null, true);
                }
                if (configData.LootBoxes.LootEffects.enableSirenAlarm && configData.LootBoxes.LootEffects.enableSirenAlarmNight && TOD_Sky.Instance.IsNight) {
                    CreateSirenAlarms(entity);
                }
                else if (configData.LootBoxes.LootEffects.enableSirenAlarmNight && TOD_Sky.Instance.IsNight) {
                    CreateSirenAlarms(entity);
                }
                else if (configData.LootBoxes.LootEffects.enableSirenAlarm) {
                    CreateSirenAlarms(entity);
                }
                else return;
                if (configData.LootBoxes.LootEffects.enableSirenLight && configData.LootBoxes.LootEffects.enableSirenLightNight && TOD_Sky.Instance.IsNight) {
                    CreateSirenLights(entity);
                }
                else if (configData.LootBoxes.LootEffects.enableSirenLightNight && TOD_Sky.Instance.IsNight) {
                    CreateSirenLights(entity);
                }
                else if (configData.LootBoxes.LootEffects.enableSirenLight) {
                    CreateSirenLights(entity);
                }
                else return;
            }
            private Vector3 GetRandomPoint(Vector3 position) {
                var vector = position + UnityEngine.Random.onUnitSphere * 40f;
                return vector;
            }
            private IEnumerator SpawnNPCs(Vector3 position, string jumperKit, int botHeal
// ... [Code preview truncated due to length. Full source in attached file] ...

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