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

FREE XDChinookIvent : 2.2.0 2.2.0

Нет прав для скачивания
C#:
using Facepunch;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using VLB;
using static NPCPlayerApex;
namespace Oxide.Plugins {
    [Info("XDChinookIvent", "DezLife", "2.2.0")]
    [Description("Авто ивент особый груз")]
    public class XDChinookIvent : RustPlugin {
        private static XDChinookIvent _;
        [PluginReference]
        Plugin IQChat, IQEconomic, XDNotifications, RustMap;
#region Var
        static DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
        Vector3 vector;
        private const int LAND_LAYERS = 1 << 4 | 1 << 8 | 1 << 16 | 1 << 21 | 1 << 23;
        static double CurrentTime() => DateTime.UtcNow.Subtract(epoch).TotalSeconds;
        public int InitStart;
        public List<CH47Helicopter> ListHeli = new List<CH47Helicopter>();
        private void AddNotify(BasePlayer player, string title, string description, string command = "", string cmdyes = "", string cmdno = "") {
            var Setting = config.xDNotification;
            Interface.Oxide.CallHook("AddNotify", player, title, description, Setting.Color, Setting.AlertDelete, Setting.SoundEffect, command, cmdyes, cmdno);
        }
#endregion
#region Lang
        private new void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["ChinookBuild"]
                = "<color=#E66062>You cannot build in the event area</color>", ["ChinookStart"] = "<color=#608FE6>Chinook Special Cargo</color> already poured on the dumping site.\nReset square <color=#6ACB52>{0}</color>", ["ChinookIsDead"] = "<color=#608FE6>Chinook Special Cargo</color> crashed!!!", ["ChinookFinish"] = "<color=#608FE6>Chinook Special Cargo</color> dumping device (square <color=#6ACB52>{0}</color>),left to wait <color=#3DA9FF>{1}</color>  \nMap mark G", ["ChinookIsDrop"] = "<color=#608FE6>Chinook Special Cargo</color> dropped a very valuable load (square <color=#6ACB52>{0}</color>)\n Map mark G", ["ChinookIsDropHack"] = "<color=#FFAB3D>Особый someone started to crack the load!</color>\nYou have 15 minutes to open it\nSquare (<color=#6ACB52>{0}</color>) Map mark G", ["ChinookIsDropHackEnd"] = "<color=#FFAB3D>Special cargo hacked but not tarnished!</color>", ["ChinookIsDropHackEndLoot"] = "Special cargo tied up by player <color=#6ACB52>{0}</color>.",
            }
            , this);
            lang.RegisterMessages(new Dictionary<string, string> {
                ["ChinookBuild"]
                = "<color=#E66062>Вы не можете строить в зоне ивента</color>", ["ChinookStart"] = "<color=#608FE6>Чинук с особым грузом</color> уже вылител на место сброса.\nКвадрат сброса <color=#6ACB52>{0}</color>\nБудте осторожны! Его охраняет патруль", ["ChinookIsDead"] = "<color=#608FE6>Чинук с особым грузом</color> потерпел крушения!!!", ["ChinookFinish"] = "<color=#608FE6>Чинук с особым грузом</color> прилител на место сброса (квадрат <color=#6ACB52>{0}</color>), осталось подождать <color=#3DA9FF>{1}</color>  \n Метка на карте G", ["ChinookIsDrop"] = "<color=#608FE6>Чинук с особым грузом</color> сбросил очень ценный груз (квадрат <color=#6ACB52>{0}</color>)\n Метка на карте G", ["ChinookIsDropHack"] = "<color=#FFAB3D>Особый груз кто то начал взламывать!</color>\nУ тебя есть 15 минут до его открытие\nКвадрат (<color=#6ACB52>{0}</color>) Метка на карте G", ["ChinookIsDropHackEnd"] = "<color=#FFAB3D>Особый груз взломан но не залутан!</color>", ["ChinookIsDropHackEndLoot"] = "Особый груз залутан игроком <color=#6ACB52>{0}</color>.",
            }
            , this, "ru");
        }
#endregion
#region Configuration
        public static Configuration config = new Configuration();
        public class Configuration {
            public class ItemsDrop {
                [JsonProperty("Short name")]
                public string Shortname;
                [JsonProperty("Skin ID ")]
                public ulong SkinID;
                [JsonProperty("Имя предмета")]
                public string DisplayName;
                [JsonProperty("Чертеж?")]
                public bool BluePrint;
                [JsonProperty("Мин кол")]
                public int MinimalAmount;
                [JsonProperty("макс кол")]
                public int MaximumAmount;
                [JsonProperty("Шанс выпадения предмета")]
                public int DropChance;
            }
            public class ChinookSetings {
                [JsonProperty("Настройка плавности/скорости спуска ящика")]
                public float gravity;
                [JsonProperty("Радиус запрета построек во время ивента")]
                public int radius;
                [JsonProperty("Время ожидания сброса")]
                public int TimeStamp;
                [JsonProperty("Время до самоуничтожения (Если никто не начнет взламывать)")]
                public int CrateDestroy;
                [JsonProperty("Минимальное колличевство игроков для запуска ивента")]
                public int PlayersMin;
                [JsonProperty("Раз в сколько часов будет летать чинук")]
                public int TimeChinook;
                [JsonProperty("Максимум предметов в 1 ящике")]
                public int MaxItem;
                [JsonProperty("Использовать стандартный лут в ящике (Если false, то будет выпадать ваш лут)")]
                public bool customLoot;
                [JsonProperty("Использовать кастомные позиции ?")]
                public bool useCustomPos;
                [JsonProperty("Кастомные позиции (/chinook addspawnpoint)")]
                public List<Vector3> customPos = new List<Vector3>();
            }
            public class NpcChinook {
                [JsonProperty("Спавнить нпс возле ящика ?")]
                public bool npcUse;
                [JsonProperty("Количество нпс")]
                public int npcCount;
                [JsonProperty("Хп нпс")]
                public int healtNpc;
                [JsonProperty("Рандомные ники нпс")]
                public List<string> nickName = new List<string>();
            }
            public class MapMarker {
                [JsonProperty("Создавать маркер на G карте ?")]
                public bool markerUseG;
                [JsonProperty("Названия маркера")]
                public string nameMarkerG;
                [JsonProperty("Цвет маркера")]
                public string colorMarkerG;
                [JsonProperty("Прзрачность маркера")]
                public float alfaMarker;
                [JsonProperty("Метки на карте RustMap")]
                public bool rustMapUse;
                [JsonProperty("Картинка для метки карты RustMap")]
                public string imageForRustMap;
            }
            public class iqEconomic {
                [JsonProperty("Использовать выдачу баланса IQEconomic?")]
                public bool use;
                [JsonProperty("минимальное количество монет")]
                public int MinimalAmount;
                [JsonProperty("максимальное количество монет")]
                public int MaximumAmount;
                [JsonProperty("Шанс выпадения монеты")]
                public int chance;
            }
            public class XDNotification {
                [JsonProperty("Включить поддержку XDNotifications(UI уведомления будут заменены на уведомление с XDNotifications)")]
                public bool UseXDNotifications;
                [JsonProperty("Цвет заднего фона уведомления(HEX)")]
                public string Color;
                [JsonProperty("Через сколько удалиться уведомление")]
                public int AlertDelete;
                [JsonProperty("Звуковой эффект")]
                public string SoundEffect;
            }
            [JsonProperty("Настройки")]
            public ChinookSetings chinook = new ChinookSetings();
            [JsonProperty("Связка с IQEconomic")]
            public iqEconomic iqEconomics = new iqEconomic();
            [JsonProperty(PropertyName = "Настройка XDNotifications(Если есть)")]
            public XDNotification xDNotification = new XDNotification();
            [JsonProperty("Настройка отображения на картах")]
            public MapMarker mapMarker = new MapMarker();
            [JsonProperty("Настройка нпс")]
            public NpcChinook npcChinook = new NpcChinook();
            [JsonProperty("Выпадаемые предметы")]
            public List<ItemsDrop> itemsDrops = new List<ItemsDrop>();
            public static Configuration GetNewConfiguration() {
                return new Configuration {
                    chinook = new ChinookSetings {
                        gravity = 0.7f, radius = 65, TimeStamp = 60, CrateDestroy = 600, PlayersMin = 20, TimeChinook = 7200, MaxItem = 7, customLoot = true, useCustomPos = false, customPos = new List<Vector3>()
                    }
                    , npcChinook = new NpcChinook {
                        npcUse = true, npcCount = 6, healtNpc = 150, nickName = new List<string> {
                            "Патрульный", "Защитник особого груза", "Опасность"
                        }
                    }
                    , mapMarker = new MapMarker {
                        markerUseG = true, alfaMarker = 0.4f, colorMarkerG = "#54bbb4", nameMarkerG = "Особый груз", rustMapUse = false, imageForRustMap = "https://i.imgur.com/x6qoCaK.png"
                    }
                    , iqEconomics = new iqEconomic {
                        use = false, chance = 90, MinimalAmount = 3, MaximumAmount = 7
                    }
                    , xDNotification = new XDNotification {
                        UseXDNotifications = false, Color = "#5A54DDFF", AlertDelete = 5, SoundEffect = ""
                    }
                    , itemsDrops = new List<ItemsDrop> {
                        new ItemsDrop {
                            Shortname = "halloween.surgeonsuit", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 1, DropChance = 70
                        }
                        , new ItemsDrop {
                            Shortname = "metal.facemask", SkinID = 1886184322, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 1, DropChance = 20
                        }
                        , new ItemsDrop {
                            Shortname = "door.double.hinged.metal", SkinID = 191100000, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 2, DropChance = 60
                        }
                        , new ItemsDrop {
                            Shortname = "rifle.bolt", SkinID = 0, DisplayName = "", BluePrint = true, MinimalAmount = 1, MaximumAmount = 1, DropChance = 10
                        }
                        , new ItemsDrop {
                            Shortname = "rifle.lr300", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 1, DropChance = 15
                        }
                        , new ItemsDrop {
                            Shortname = "pistol.revolver", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 3, DropChance = 60
                        }
                        , new ItemsDrop {
                            Shortname = "supply.signal", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 3, DropChance = 20
                        }
                        , new ItemsDrop {
                            Shortname = "explosive.satchel", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 3, DropChance = 5
                        }
                        , new ItemsDrop {
                            Shortname = "grenade.smoke", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 1, MaximumAmount = 20, DropChance = 45
                        }
                        , new ItemsDrop {
                            Shortname = "ammo.rifle", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 50, MaximumAmount = 120, DropChance = 35
                        }
                        , new ItemsDrop {
                            Shortname = "scrap", SkinID = 0, DisplayName = "", BluePrint = false, MinimalAmount = 100, MaximumAmount = 500, DropChance = 20
                        }
                        , new ItemsDrop {
                            Shortname = "giantcandycanedecor", SkinID = 0, DisplayName = "Новый год", BluePrint = false, MinimalAmount = 1, MaximumAmount = 5, DropChance = 70
                        }
                        ,
                    }
                }
                ;
            }
        }
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                config = Config.ReadObject<Configuration>();
                if (config == null) LoadDefaultConfig();
            }
            catch {
                PrintWarning("Ошибка чтения конфигурации 'oxide/config/', создаём новую конфигурацию!!");
                LoadDefaultConfig();
            }
            NextTick(SaveConfig);
        }
        protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
        protected override void SaveConfig() => Config.WriteObject(config, true);
#endregion
#region Classes
#region Method By OxideBro
        Vector3 RandomCircle(Vector3 center, float radius = 2) {
            float ang = UnityEngine.Random.value * 360;
            Vector3 pos;
            pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
            pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
            pos.y = center.y;
            pos.y = GetGroundPosition(pos);
            return pos;
        }
        static float GetGroundPosition(Vector3 pos) {
            float y = TerrainMeta.HeightMap.GetHeight(pos);
            RaycastHit hit;
            if (Physics.Raycast(new Vector3(pos.x, pos.y + 200f, pos.z), Vector3.down, out hit, Mathf.Infinity, LayerMask.GetMask(new[] {
                "Terrain", "World", "Default", "Construction", "Deployed"
            }
            )) && !hit.collider.name.Contains("rock_cliff")) return Mathf.Max(hit.point.y, y);
            return y;
        }
        const string scientist = "assets/prefabs/npc/scientist/scientist.prefab";
        private NPCPlayerApex InstantiateEntity(string type, Vector3 position) {
            position.y = GetGroundPosition(position);
            var gameObject = Instantiate.GameObject(GameManager.server.FindPrefab(type), position, new Quaternion());
            gameObject.name = type;
            SceneManager.MoveGameObjectToScene(gameObject, Rust.Server.EntityScene);
            UnityEngine.Object.Destroy(gameObject.GetComponent<Spawnable>());
            if (!gameObject.activeSelf) gameObject.SetActive(true);
            NPCPlayerApex component = gameObject.GetComponent<NPCPlayerApex>();
            return component;
        }
        void SpawnBots(HackableLockedCrate hack) {
            for (int i = 0; i < config.npcChinook.npcCount; i++) {
                NPCPlayerApex entity = null;
                entity = InstantiateEntity(scientist, RandomCircle(hack.transform.position, 10));
                entity.enableSaving = false;
                entity.Spawn();
                entity.IsInvinsible = false;
                entity.startHealth = config.npcChinook.healtNpc;
                entity.InitializeHealth(entity.startHealth, entity.startHealth);
                entity.Stats.AggressionRange = entity.Stats.DeaggroRange = 150;
                entity.CommunicationRadius = 0;
                entity.displayName = config.npcChinook.nickName.GetRandom();
                entity.GetComponent<Scientist>().LootPanelName = entity.displayName;
                entity.CancelInvoke(entity.EquipTest);
                Equip(entity);
                entity.Stats.MaxRoamRange = 75f;
                entity.NeverMove = true;
                NPCMonitor npcMonitor = entity.gameObject.AddComponent<NPCMonitor>();
                npcMonitor.Initialize(hack);
            }
        }
        public HeldEntity GetFirstWeapon(BasePlayer player) {
            foreach (Item item in player.inventory.containerBelt.itemList) {
                if (item.CanBeHeld() && (item.info.category == ItemCategory.Weapon)) {
                    BaseProjectile projectile = item.GetHeldEntity() as BaseProjectile;
                    if (projectile != null) {
                        projectile.primaryMagazine.contents = projectile.primaryMagazine.capacity;
                        projectile.SendNetworkUpdateImmediate();
                        return item.GetHeldEntity() as HeldEntity;
                    }
                }
            }
            return null;
        }
        private void Equip(BasePlayer player) {
            HeldEntity weapon1 = GetFirstWeapon(player);
            if (weapon1 != null) {
                weapon1.SetHeld(true);
            }
        }
        public class NPCMonitor : FacepunchBehaviour {
            public NPCPlayerApex player {
                get;
                private set;
            }
            private List<Vector3> patrolPositions = new List<Vector3>();
            private HackableLockedCrate hacks;
            private Vector3 homePosition;
            private int lastPatrolIndex = 0;
            private void Awake() {
                player = GetComponent<NPCPlayerApex>();
                InvokeRepeating(UpdateDestination, 0f, 5.0f);
            }
            public void Initialize(HackableLockedCrate hack) {
                this.hacks = hack;
                homePosition = hacks.transform.position;
                GeneratePatrolPositions();
            }
            private void UpdateDestination() {
                if (player.AttackTarget == null) {
                    player.NeverMove = true;
                    float distance = (player.transform.position - homePosition).magnitude;
                    bool tooFar = distance > 20;
                    if (player.GetNavAgent == null || !player.GetNavAgent.isOnNavMesh) player.finalDestination = patrolPositions[lastPatrolIndex];
                    else {
                        if (Vector3.Distance(player.transform.position, patrolPositions[lastPatrolIndex]) < 5) lastPatrolIndex++;
                        if (lastPatrolIndex >= patrolPositions.Count) lastPatrolIndex = 0;
                        player.SetDestination(patrolPositions[lastPatrolIndex]);
                    }
                    player.SetDestination(patrolPositions[lastPatrolIndex]);
                    player.SetFact(NPCPlayerApex.Facts.Speed, tooFar ? (byte)NPCPlayerApex.SpeedEnum.Run : (byte)NPCPlayerApex.SpeedEnum.Walk, true, true);
                }
                else {
                    player.NeverMove = false;
                    player.IsStopped = false;
                    var attacker = player.AttackTarget as BasePlayer;
                    if (attacker == null) return;
                    if (attacker.IsDead()) Forget();
                }
            }
            private void Forget() {
                player.lastDealtDamageTime = Time.time - 21f;
                player.SetFact(Facts.HasEnemy, 0, true, true);
                player.SetFact(Facts.EnemyRange, 3, true, true);
                player.SetFact(Facts.AfraidRange, 1, true, true);
                player.AiContext.EnemyNpc = null;
                player.AiContext.EnemyPlayer = null;
                player.AttackTarget = null;
                player.lastAttacker = null;
                player.lastAttackedTime = Time.time - 31f;
                player.LastAttackedDir = Vector3.zero;
                player.SetDestination(patrolPositions[lastPatrolIndex]);
            }
            private void OnDestroy() {
                if(player != null) player.KillMessage();
                Destroy(gameObject);
            }
            private void GeneratePatrolPositions() {
                for (int i = 0; i < 6; i++) {
                    Vector3 position = hacks.transform.position + (UnityEngine.Random.onUnitSphere * 20f);
                    position.y = TerrainMeta.HeightMap.GetHeight(position);
                    patrolPositions.Add(position);
                }
                enabled = true;
            }
        }
#endregion
        private class ForceCrate : FacepunchBehaviour {
            public HackableLockedCrate crate;
            public bool isGrounded;
            public Vector3 groundPos;
            private BaseEntity chute;
            private float deathTime;
            private float speed = 1;
            private void Awake() {
                crate = GetComponent<HackableLockedCrate>();
                groundPos = new Vector3(crate.transform.position.x, TerrainMeta.HeightMap.GetHeight(crate.transform.position), crate.transform.position.z);
                deathTime = UnityEngine.Time.time + config.chinook.CrateDestroy;
                speed = config.chinook.gravity;
                isGrounded = false;
                InitChute();
            }
            private void Update() {
                if (!isGrounded) {
                    if (Physics.Raycast(new Ray(crate.transform.position, Vector3.down), 2f, LAND_LAYERS)) {
                        OnLanded();
                        return;
                    }
                    crate.transform.position = new Vector3(crate.transform.position.x, crate.transform.position.y - 0.015f * speed, crate.transform.position.z);
                }
                if (UnityEngine.Time.time >= deathTime) {
                    if (crate.HasFlag(BaseEntity.Flags.Reserved1)) {
                        deathTime += +320;
                        return;
                    }
                    _.DestroyAll<NPCMonitor>();
                    crate.Kill();
                    Destroy(this);
                    return;
                }
            }
            private void OnDestroy() {
                chute?.Kill();
                crate?.Kill();
                _.RemoveMarker();
            }
            private void OnLanded() {
                isGrounded = true;
                transform.position = groundPos;
                crate.GetComponent<Rigidbody>().useGravity = true;
                crate.GetComponent<Rigidbody>().drag = 1.5f;
                crate.GetComponent<Rigidbody>().isKinematic = false;
                chute?.Kill();
                if(config.npcChinook.npcUse) _.SpawnBots(crate);
            }
            private void InitChute() {
                chute = GameManager.server.CreateEntity("assets/prefabs/misc/parachute/parachute.prefab", crate.transform.position);
                chute.enableSaving = false;
                chute.Spawn();
                chute.SetParent(crate, false);
                chute.transform.localPosition = Vector3.up;
                Effect.server.Run("assets/bundled/prefabs/fx/smoke_signal_full.prefab", chute, 0, Vector3.zero, Vector3.zero, null, true);
            }
        }
#endregion
#region Commands
        [ChatCommand("chinook")]
        void ChinookCommands(BasePlayer player, string command, string[] args) {
            if (!player.IsAdmin) {
                PrintToChat(player, "У вас недостаточно прав!");
                return;
            }
            if (args.Length == 0) {
                PrintToChat(player, "/chinook addspawnpoint - Добавляет кастомную позицию для спавна чинука\n" + "/chinook call - Вызвать чинук преждевременно");
                return;
            }
            switch (args[0]) {
                case "addspawnpoint" : {
                    config.chinook.customPos.Add(player.transform.position);
                    PrintToChat(player, "Точка успешно добавлена");
                    SaveConfig();
                    break;
                }
                case "call" : {
                    if (ListHeli.Count >= 1) {
                        if (player != null) PrintToChat(player, "Ивент уже активен!");
                        return;
                    }
                    else {
                        ChinookHelicopterCall();
                        PrintToChat(player, "Вы вызвали чинук");
                    }
                    break;
                }
            }
        }
#endregion
#region MainMetods
        private void ChinookHelicopterCall() {
#region RandomSpawnPosition
            float x = TerrainMeta.Size.x;
            float y = 70f;
            Vector3 val = Vector3Ex.Range(-1f, 1f);
            val.y = 0f;
            val.Normalize();
            val *= x * 1f;
            val.y = y;
#endregion
            CH47Helicopter ChinookEnt = GameManager.server.CreateEntity("assets/prefabs/npc/ch47/ch47scientists.entity.prefab", val, new Quaternion(0f, 0f, 0f, 0f), true) as CH47Helicopter;
            //////////////////
            if (ChinookEnt == null) return;
            CH47HelicopterAIController ChinookAI = ChinookEnt.GetComponent<CH47HelicopterAIController>();
            ChinookAI.OwnerID = 112234;
            ChinookAI.Spawn();
            ChinookAI.SetMaxHealth(900000f);
            ChinookAI.health = 900000f;
            ChinookAI.Heal(900000f);
            ListHeli.Add(ChinookEnt);
            vector = config.chinook.useCustomPos ? config.chinook.customPos.GetRandom() : (Vector3)GetSpawnPoint();
            string Cvadrat = "";
            Cvadrat = GetGridString(vector);
            ChinookAI.SetMoveTarget(vector);
#region Метки на карте
            if (config.mapMarker.markerUseG) CreateMarker(vector, 5, config.mapMarker.nameMarkerG, config.mapMarker.nameMarkerG);
            if (config.mapMarker.rustMapUse) RustMap?.Call("ApiAddPointUrl", config.mapMarker.imageForRustMap, Name, vector, config.mapMarker.nameMarkerG);
#endregion
            SendChatAll(String.Format(lang.GetMessage("ChinookStart", this), Cvadrat));
            Subscribe(nameof(CanBuild));
            ChinookAI.SetLandingTarget(new Vector3(vector.x, TerrainMeta.HeightMap.GetHeight(vector) + 90f, vector.z));
            Timer timers = null;
            Vector3 CheckPos = Vector3.zero;
            bool PositionOutCrate = false;
            int i = 0;
            timers = timer.Every(10 , () => {
                if (ChinookAI.IsDead()) {
                    SendChatAll(lang.GetMessage("ChinookIsDead", this));
                    PrintWarning("Cninook is dead");
                    RemoveMarkers();
                    Unsubscribe(nameof(CanBuild));
                    ListHeli.Remove(ChinookAI);
                    timers.Destroy();
                    return;
                }
                if (Vector3.Distance(ChinookAI.transform.position.xz(), vector.xz()) < 10f) {
                    PositionOutCrate = true;
                    SendChatAll(String.Format(lang.GetMessage("ChinookFinish", this), Cvadrat, FormatTime(TimeSpan.FromSeconds(config.chinook.TimeStamp))));
                    timers.Destroy();
                    timer.Once(config.chinook.TimeStamp, () => {
                        SendChatAll(String.Format(lang.GetMessage("ChinookIsDrop", this), Cvadrat));
                        Vector3 pos = ChinookAI.transform.position + Vector3.down * 5f;
                        CreateCrate(pos);
                        ChinookAI.ClearLandingTarget();
                        ChinookAI.DestroyShared();
                    }
                    );
                }
#region Костыль века
                if(i > 5 && !PositionOutCrate && Vector3.Distance(CheckPos, ChinookAI.transform.position) < 7f) {
                    SendChatAll(lang.GetMessage("ChinookIsDead", this));
                    Unsubscribe(nameof(CanBuild));
                    RemoveMarkers();
                    ChinookAI.Kill();
                    ListHeli.Remove(ChinookAI);
                    timers.Destroy();
                    return;
                }
                if (i > 5) CheckPos = ChinookAI.transform.position;
                i++;
#endregion
            }
            );
        }
        private void CreateCrate(Vector3 position) {
            Quaternion rot = Quaternion.Euler(0f, UnityEngine.Random.Range(0f, 360f), 0f);
            HackableLockedCrate CrateEnt = GameManager.server.CreateEntity("assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab", position, rot, true) as HackableLockedCrate;
            CrateEnt.enableSaving = false;
            CrateEnt.GetComponent<Rigidbody>().useGravity = false;
            CrateEnt.Spawn();
            CrateEnt.OwnerID = 12436;
            ForceCrate crate = CrateEnt.gameObject.AddComponent<ForceCrate>();
            crate.crate = CrateEnt;
            if (!config.chinook.customLoot) {
                CrateEnt.inventory.itemList.Clear();
                for (int i = 0; i < config.itemsDrops.Count; i++) {
                    var cfg = config.itemsDrops[i];
                    bool goodChance = UnityEngine.Random.Range(0, 100) >= (100 - cfg.DropChance);
                    if (goodChance && CrateEnt.inventory.itemList.Count <= config.chinook.MaxItem) {
                        if (cfg.BluePrint) {
                            var bp = ItemManager.Create(ResearchTable.GetBlueprintTemplate());
                            bp.blueprintTarget = ItemManager.FindItemDefinition(cfg.Shortname).itemid;
                            bp.MoveToContainer(CrateEnt.inventory);
                        }
                        else {
                            Item GiveItem = ItemManager.CreateByName(cfg.Shortname, Oxide.Core.Random.Range(cfg.MinimalAmount, cfg.MaximumAmount), cfg.SkinID);
                            if (!string.IsNullOrEmpty(cfg.DisplayName)) {
                                GiveItem.name = cfg.DisplayName;
                            }
                            GiveItem.MoveToContainer(CrateEnt.inventory);
                        }
                    }
                }
                if (config.iqEconomics.use && IQEconomic) {
                    bool TypeMoney = (bool)IQEconomic?.Call("API_MONEY_TYPE");
                    if (TypeMoney) {
                        bool goodChance = UnityEngine.Random.Range(0, 100) >= (100 - config.iqEconomics.chance);
                        if (goodChance) {
                            Item money = (Item)IQEconomic?.Call("API_GET_ITEM", UnityEngine.Random.Range(config.iqEconomics.MinimalAmount, config.iqEconomics.MaximumAmount));
                            money.MoveToContainer(CrateEnt.inventory);
                        }
                    }
                }
            }
            CrateEnt.inventory.capacity = CrateEnt.inventory.itemList.Count;
            CrateEnt.inventory.MarkDirty();
            CrateEnt.SendNetworkUpdate();
        }
#endregion
#region Hooks
        private object CanBuild(Planner planner, Construction prefab, Construction.Target target) {
            if (Vector3.Distance(planner.transform.position, vector) < config.chinook.radius) {
                BasePlayer player = planner?.GetOwnerPlayer();
                if (player != null) SendChatPlayer(lang.GetMessage("ChinookBuild", this), player);
                return false;
            }
            return null;
        }
        void OnCrateHack(HackableLockedCrate crate) {
            if(crate.OwnerID == 12436) {
                SendChatAll(String.Format(lang.GetMessage("ChinookIsDropHack", this), GetGridString(crate.transform.position)));
            }
        }
        void OnCrateHackEnd(HackableLockedCrate crate) {
            if (crate.OwnerID == 12436) {
                SendChatAll(lang.GetMessage("ChinookIsDropHackEnd", this));
            }
        }
        void CanLootEntity(BasePlayer player, StorageContainer container) {
            if (container is HackableLockedCrate && container.OwnerID == 12436) {
                SendChatAll(String.Format(lang.GetMessage("ChinookIsDropHackEndLoot", this), player.displayName));
                RemoveMarker();
                timer.Once(30, () => Unsubscribe(nameof(CanBuild)));
                container.OwnerID = 32456345;
                Interface.Oxide.CallHook("LootHack", player);
            }
        }
        void OnEntityDestroy(CH47HelicopterAIController info) {
            CH47Helicopter ch47 = info.GetComponent<CH47Helicopter>();
            if (ListHeli.Contains(ch47)) ListHeli.Remove(ch47);
        }
        void Unload() {
            Unsubscribe(nameof(CanBuild));
            RemoveMarker();
            for (int i = 0; i < ListHeli.Count; i++) ListHeli[i].Kill();
            ListHeli.Clear();
            DestroyAll<ForceCrate>();
            DestroyAll<NPCMonitor>();
        }
        void Init() {
            Unsubscribe(nameof(CanBuild));
        }
        void OnServerInitialized() {
            _ = this;
            LoadDefaultMessages();
            if(!config.chinook.useCustomPos) GenerateSpawnpoints();
            InitStart = (int)CurrentTime();
            timer.Every(config.chinook.TimeChinook, () => {
                if (BasePlayer.activePlayerList.Count >= config.chinook.PlayersMin) {
                    ChinookHelicopterCall();
                }
                InitStart = (int)CurrentTime();
            }
            );
            PrintWarning($"Ивент будет запущен через {FormatTime(TimeSpan.FromSeconds(config.chinook.TimeChinook))}");
        }
#endregion
#region SpawnMetods
        private HashSet<Vector3> AnomaleisPoint = new HashSet<Vector3>();
        private int spawnCount;
        private object GetSpawnPoint() {
            Vector3 targetPos = AnomaleisPoint.ToList().GetRandom();
            if (targetPos == Vector3.zero) return null;
            List<BaseEntity> entities = Facepunch.Pool.GetList<BaseEntity>();
            Vis.Entities(targetPos, 50f, entities, LayerMask.GetMask("Construction", "Deployable", "Trigger"));
            int count = entities.Count;
            Facepunch.Pool.FreeList(ref entities);
            if (count > 0) {
                AnomaleisPoint.Remove(targetPos);
                --spawnCount;
                if (spawnCount < 10) {
                    PrintWarning("Все точки закончены!\n" + "Начинаем генерировать новые...");
                    AnomaleisPoint.Clear();
                    GenerateSpawnpoints();
                    return null;
                }
                return GetSpawnPoint();
            }
            AnomaleisPoint.Remove(targetPos);
            return targetPos;
        }
        private void GenerateSpawnpoints() {
            PrintWarning("Генерация точек для чинука...");
            for (int i = 0; i < 1500; i++) {
                float max = TerrainMeta.Size.x / 2;
                var success = FindNewPosition(new Vector3(0, 0, 0), max);
                if (success is Vector3) {
                    Vector3 spawnPoint = (Vector3)success;
                    float height = TerrainMeta.HeightMap.GetHeight(spawnPoint);
                    if (spawnPoint.y >= height && !(spawnPoint.y - height > 1)) {
                        AnomaleisPoint.Add(spawnPoint);
                    }
                }
            }
            spawnCount += AnomaleisPoint.Count;
            PrintWarning($"{spawnCount} точек сгенерированно!");
        }
        private object FindNewPosition(Vector3 position, float max, bool failed = false) {
            var targetPos = UnityEngine.Random.insideUnitCircle * max;
            var sourcePos = new Vector3(position.x + targetPos.x, 300, position.z + targetPos.y);
            var hitInfo = RayPosition(sourcePos);
            var success = ProcessRay(hitInfo);
            if (success == null) {
                if (failed) return null;
                else return FindNewPosition(position, max, true);
            }
            else if (success is Vector3) {
                if (failed) return null;
                else return FindNewPosition(new Vector3(sourcePos.x, ((Vector3)success).y, sourcePos.y), max, true);
            }
            else {
                sourcePos.y = Mathf.Max((float)success, TerrainMeta.HeightMap.GetHeight(sourcePos));
                return sourcePos;
            }
        }
        private object ProcessRay(RaycastHit hitInfo) {
            if (hitInfo.collider != null) {
                if (hitInfo.collider?.gameObject.layer == LayerMask.NameToLayer("Water")) return null;
                if (hitInfo.collider?.gameObject.layer == LayerMask.NameToLayer("Prevent Building")) return null;
                if (hitInfo.GetEntity() != null) {
                    return hitInfo.point.y;
                }
                if (hitInfo.collider?.name == "areaTrigger") return null;
                if (hitInfo.collider?.GetComponentInParent<SphereCollider>() || hitInfo.collider?.GetComponentInParent<BoxCollider>()) {
                    return hitInfo.collider.transform.position + new Vector3(0, -1, 0);
                }
            }
            return hitInfo.point.y;
        }
        private RaycastHit RayPosition(Vector3 sourcePos) {
            RaycastHit hitInfo;
            Physics.Raycast(sourcePos, Vector3.down, out hitInfo);
            return hitInfo;
        }
#endregion
#region HelpMetods
        private void RemoveMarker() {
            RemoveMarkers();
            RustMap?.Call("ApiRemovePointUrl", Name);
        }
#region Метка на g карте
        private void CreateMarker(Vector3 position, float refreshRate, string name, string displayName, float radius = 0.65f, string colorOutline = "00FFFFFF") {
            var marker = new GameObject().AddComponent<CustomMapMarker>();
            marker.name = name;
            marker.displayName = displayName;
            marker.radius = radius;
            marker.position = position;
            marker.refreshRate = refreshRate;
            ColorUtility.TryParseHtmlString($"{config.mapMarker.colorMarkerG}", out marker.color1);
            ColorUtility.TryParseHtmlString($"{colorOutline}", out marker.color2);
        }
        private void RemoveMarkers() {
            foreach (var marker in UnityEngine.Object.FindObjectsOfType<CustomMapMarker>()) {
                UnityEngine.Object.Destroy(marker);
            }
        }
        private const string genericPrefab = "assets/prefabs/tools/map/genericradiusmarker.prefab";
        private const string vendingPrefab = "assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab";
#region Scripts
        private class CustomMapMarker : MonoBehaviour {
            private VendingMachineMapMarker vending;
            private MapMarkerGenericRadius generic;
            public BaseEntity parent;
            private bool asChild;
            public float radius;
            public Color color1;
            public Color color2;
            public string displayName;
            public float refreshRate;
            public Vector3 position;
            public bool placedByPlayer;
            private void Start() {
                transform.position = position;
                asChild = parent != null;
                CreateMarkers();
            }
            private void CreateMarkers() {
                vending = GameManager.server.CreateEntity(vendingPrefab, position).GetComponent<VendingMachineMapMarker>();
                vending.markerShopName = displayName;
                vending.enableSaving = false;
                vending.Spawn();
                generic = GameManager.server.CreateEntity(genericPrefab).GetComponent<MapMarkerGenericRadius>();
                generic.color1 = color1;
                generic.color2 = color2;
                generic.radius = radius;
                generic.alpha = config.mapMarker.alfaMarker;
                generic.enableSaving = false;
                generic.SetParent(vending);
                generic.Spawn();
                UpdateMarkers();
                if (refreshRate > 0f) {
                    if (asChild) {
                        InvokeRepeating(nameof(UpdatePosition), refreshRate, refreshRate);
                    }
                    else {
                        InvokeRepeating(nameof(UpdateMarkers), refreshRate, refreshRate);
                    }
                }
            }
            private void UpdatePosition() {
                if (asChild == true) {
                    if (parent.IsValid() == false) {
                        Destroy(this);
                        return;
                    }
                    else {
                        var pos = parent.transform.position;
                        transform.position = pos;
                        vending.transform.position = pos;
                    }
                }
                UpdateMarkers();
            }
            private void UpdateMarkers() {
                vending.SendNetworkUpdate();
                generic.SendUpdate();
            }
            private void DestroyMakers() {
                if (vending.IsValid()) {
                    vending.Kill();
                }
                if (generic.IsValid()) {
                    generic.Kill();
                }
            }
            private void OnDestroy() {
                DestroyMakers();
            }
        }
#endregion
#endregion
#region Узнаем квадрат
        string GetGridString(Vector3 pos) {
            char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            pos.z = -pos.z;
            pos += new Vector3(TerrainMeta.Size.x, 0, TerrainMeta.Size.z) *.5f;
            var cubeSize = 146.14f;
            int xCube = (int)(pos.x / cubeSize);
            int zCube = (int)(pos.z / cubeSize);
            int firstLetterIndex = (int)(xCube / alpha.Length) - 1;
            string firstLetter = "";
            if (firstLetterIndex >= 0) firstLetter = $"{alpha[firstLetterIndex]}";
            var xStr = $"{firstLetter}{alpha[xCube % 26]}";
            var zStr = $"{zCube}";
            return $"{xStr}{zStr}";
        }
        private string NumberToString(int number) {
            bool a = number > 25;
            Char c = (Char)(65 + (a ? number - 26 : number));
            return a ? "A" + c : c.ToString();
        }
#endregion
        private void DestroyAll<T>() {
            UnityEngine.Object.FindObjectsOfType(typeof(T)).ToList().ForEach(UnityEngine.Object.Destroy);
        }
        public static string FormatTime(TimeSpan time, int maxSubstr = 5, string language = "ru") {
            string result = string.Empty;
            switch (language) {
                case "ru" : int i = 0;
                if (time.Days != 0 && i < maxSubstr) {
                    if (!string.IsNullOrEmpty(result)) result += " ";
                    result += $"{Format(time.Days, "дней", "дня", "день")}";
                    i++;
                }
                if (time.Hours != 0 && i < maxSubstr) {
                    if (!string.IsNullOrEmpty(result)) result += " ";
                    result += $"{Format(time.Hours, "часов", "часа", "час")}";
                    i++;
                }
                if (time.Minutes != 0 && i < maxSubstr) {
                    if (!string.IsNullOrEmpty(result)) result += " ";
                    result += $"{Format(time.Minutes, "минут", "минуты", "минута")}";
                    i++;
                }
                if (time.Seconds != 0 && i < maxSubstr) {
                    if (!string.IsNullOrEmpty(result)) result += " ";
                    result += $"{Format(time.Seconds, "секунд", "секунды", "секунд")}";
                    i++;
                }
                break;
                case "en" : result = string.Format("{0}{1}{2}{3}", time.Duration().Days > 0 ? $"{time.Days:0} day{(time.Days == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Hours > 0 ? $"{time.Hours:0} hour{(time.Hours == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Minutes > 0 ? $"{time.Minutes:0} minute{(time.Minutes == 1 ? String.Empty : "s")}, " : string.Empty, time.Duration().Seconds > 0 ? $"{time.Seconds:0} second{(time.Seconds == 1 ? String.Empty : "s")}" : string.Empty);
                if (result.EndsWith(", ")) result = result.Substring(0, result.Length - 2);
                if (string.IsNullOrEmpty(result)) result = "0 seconds";
                break;
            }
            return result;
        }
        int API_GetTimeStartIvent() {
            int RealTimeSecond = (int)CurrentTime();
            int LastTime = config.chinook.TimeChinook - (RealTimeSecond - InitStart);
            return LastTime;
        }
        public void SendChatAll(string Message, ConVar.Chat.ChatChannel channel = ConVar.Chat.ChatChannel.Global) {
            if (config.xDNotification.UseXDNotifications && XDNotifications) {
                foreach (BasePlayer player in BasePlayer.activePlayerList) AddNotify(player, "ОСОБЫЙ ГРУЗ", Message.Replace("\n", " "));
                return;
            }
            if (IQChat) IQChat?.Call("API_ALERT", Message);
            else BasePlayer.activePlayerList.ToList().ForEach(p => p.SendConsoleCommand("chat.add", channel, 0, Message));
        }
        public void SendChatPlayer(string Message, BasePlayer player, ConVar.Chat.ChatChannel channel = ConVar.Chat.ChatChannel.Global) {
            if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, Message);
            else player.SendConsoleCommand("chat.add", channel, 0, Message);
        }
        private static string Format(int units, string form1, string form2, string form3) {
            var tmp = units % 10;
            if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units} {form1}";
            if (tmp >= 2 && tmp <= 4) return $"{units} {form2}";
            return $"{units} {form3}";
        }
#endregion
    }
}

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