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

FREE Convoy : 1.1.8 1.1.8

Нет прав для скачивания
C#:
using System.Collections.Generic;
using Newtonsoft.Json;
using CompanionServer.Handlers;
using System.Linq;
using UnityEngine;
using Oxide.Core.Plugins;
using Network;
using Rust;
using Rust.Modular;
using System.Collections;
using Newtonsoft.Json.Linq;
using Oxide.Game.Rust.Cui;
using Oxide.Core;
using System;
namespace Oxide.Plugins {
    [Info("Convoy", "WebGhost", "1.1.8")]
    class Convoy : RustPlugin {
        [PluginReference]
        Plugin NpcSpawn, GUIAnnouncements, DiscordMessages;
#region Variables
        const bool en = true;
        static Convoy ins;
        int pathCount = 0;
        bool active;
        bool round = true;
        int stopTime = 0;
        int destroyTime = 0;
        int eventTime = 0;
        bool destroying = false;
        bool failed = false;
        bool hackedCrate = false;
        List<Vector3> currentPath = new List<Vector3>();
        List<ConvoyVehicle> convoyVehicles = new List<ConvoyVehicle>();
        List<ScientistNPC> freeConvoyNpc = new List<ScientistNPC>();
        HashSet<BasePlayer> players = new HashSet<BasePlayer>();
        HashSet<BaseEntity> convoySummons = new HashSet<BaseEntity>();
        DoorCloser doorCloser;
        ConvoyModular convoyModular;
        ConvoyHeli convoyHeli;
        RootCar rootCar;
        HeliConfig heliConfig;
        BradleyConfig bradleyConfig;
        ModularConfig modularConfig;
        SupportModularConfig supportModularConfig;
        SedanConfig sedanConfig;
        Vector3 deathBradleyCoord = Vector3.zero;
        Vector3 deathHeliCoord = Vector3.zero;
        Coroutine stopCoroutine;
        Coroutine eventCoroutine;
        Coroutine destroyCoroutine;
#endregion Variables
#region API
        private bool IsConvoyVehicle(BaseEntity entity) {
            if (entity == null) return false;
            return convoyVehicles.Any(x => x.baseEntity.net.ID == entity.net.ID);
        }
        private bool IsConvoyCrate(HackableLockedCrate crate) {
            if (crate == null) return false;
            if (convoyModular != null && convoyModular.crate.net.ID == crate.net.ID) return true;
            return false;
        }
        private bool IsConvoyHeli(BaseHelicopter baseHelicopter) {
            if (baseHelicopter == null) return false;
            return convoyHeli != null && convoyHeli.baseHelicopter.net.ID == baseHelicopter.net.ID;
        }
#endregion API
#region Hooks
        void Init() {
            ins = this;
            Unsubscribes();
            LoadData();
            Unsubscribe("OnLootSpawn");
        }
        void OnServerInitialized() {
            Subscribe("OnLootSpawn");
            LoadDefaultMessages();
            int vehicleCount = 0;
            foreach (ConvoySetting convoySetting in _config.convoys) {
                int count = convoySetting.firstBradleyCount + convoySetting.firstModularCount + convoySetting.firstSedanCount + 1 + convoySetting.endSedanCount + convoySetting.endModularCount + convoySetting.endBradleyCount;
                if (count > vehicleCount) vehicleCount = count;
            }
            int rootCount = vehicleCount * _config.carDistance * 2 + vehicleCount + 20;
            int roadCount = _config.roadCount <= rootCount ? rootCount : _config.roadCount;
            if (_config.customRootName != "" && roots.ContainsKey(_config.customRootName)) {
                List<List<string>> rootsPrefab = roots[_config.customRootName];
                List<List<string>> goodRoads = rootsPrefab.Where(x => x.Count() > roadCount).ToList();
                if (goodRoads.Count > 0) {
                    List<string> currentpathString = goodRoads.GetRandom();
                    foreach (string vectorString in currentpathString) currentPath.Add(vectorString.ToVector3());
                }
            }
            if (_config.rounRoadPriority && currentPath.Count == 0) {
                PathList pathList = TerrainMeta.Path.Roads.Where(x => x.Path.Points.Count() > roadCount && Vector3.Distance(x.Path.Points[0], x.Path.Points[x.Path.Points.Count() - 1]) < 10f && Vector3.Distance(x.Path.Points[0], x.Path.Points[x.Path.Points.Count() / 2]) > 50f).FirstOrDefault();
                if (pathList != null && pathList.Path != null && pathList.Path.Points != null) currentPath = pathList.Path.Points.ToList();
            }
            if (currentPath.Count == 0) {
                List<PathList> goodRoads = TerrainMeta.Path.Roads.Where(x => !_config.blockRoads.Contains(TerrainMeta.Path.Roads.IndexOf(x)) && x.Path.Points.Count() > roadCount && Vector3.Distance(x.Path.Points[0], x.Path.Points[x.Path.Points.Count() - 1]) > 100 && UnityEngine.Physics.RaycastAll(new Ray(x.Path.Points[10] + new Vector3(0, 1, 0), Vector3.down), 4f).Any(y => y.collider.name.Contains("Road Mesh")) && UnityEngine.Physics.RaycastAll(new Ray(x.Path.Points[x.Path.Points.Length / 2] + new Vector3(0, 1, 0), Vector3.down), 4f).Any(y => y.collider.name.Contains("Road Mesh"))).ToList();
                if (goodRoads.Count > 0) {
                    PathList path = goodRoads.GetRandom();
                    currentPath = path.Path.Points.ToList();
                    pathCount = currentPath.Count();
                }
            }
            pathCount = currentPath.Count();
            if (pathCount == 0) {
                PrintError("No road detected");
                NextTick(() => Server.Command($"o.unload {Name}"));
                return;
            }
            if (_config.version != Version.ToString()) {
                if (_config.version == "1.1.6" || _config.version == "1.1.7") {
                    foreach (var a in _config.supportModularConfiguration) if (a.prefabName == null) a.prefabName = "assets/content/vehicles/modularcar/4module_car_spawned.entity.prefab";
                    foreach (var a in _config.modularConfiguration) if (a.prefabName == null) a.prefabName = "assets/content/vehicles/modularcar/4module_car_spawned.entity.prefab";
                    foreach (var a in _config.NPC) a.deleteCorpse = true;
                    _config.version = "1.1.8";
                    SaveConfig();
                }
                else {
                    PrintError("Delete the configuration file!");
                    NextTick(() => Server.Command($"o.unload {Name}"));
                    return;
                }
            }
            if (Vector3.Distance(currentPath[0], currentPath[currentPath.Count() - 1]) > 10f) round = false;
            timer.In(UnityEngine.Random.Range(_config.minStartTime, _config.minStartTime), () => {
                if (!active) CreateConvoy();
                else Puts("This event is active now");
            }
            );
        }
        void Unload() {
            if (active) DeleteConvoy(false);
            RootStop();
            if (rootCar != null) rootCar.basicCar.Kill();
            ins = null;
        }
        object OnEntityTakeDamage(BaseVehicleModule baseVehicleModule, HitInfo info) {
            if (baseVehicleModule == null || info == null) return null;
            BaseModularVehicle modularVehicle = baseVehicleModule.Vehicle;
            if (modularVehicle != null && convoyVehicles.Any(x => x.baseEntity != null && x.baseEntity == modularVehicle)) {
                if (info.InitiatorPlayer != null) {
                    float damageScale = convoyModular.baseEntity == modularVehicle ? modularConfig.damageMultiplier : supportModularConfig.damageMultiplier;
                    if (info.damageTypes.Has(DamageType.Explosion)) modularVehicle.health -= damageScale * info.damageTypes.Total() / 10;
                    else modularVehicle.health -= damageScale * info.damageTypes.Total() / 5;
                    if (!modularVehicle.IsDestroyed && modularVehicle.health <= 0) modularVehicle.Kill();
                    else ConvoyTakeDamage(modularVehicle, info);
                }
                return true;
            }
            return null;
        }
        object OnEntityTakeDamage(ModularCar entity, HitInfo info) {
            if (convoyModular != null && convoyVehicles.Any(x => x.baseEntity == entity)) {
                if (entity == convoyModular.baseEntity) info.damageTypes.ScaleAll(modularConfig.damageMultiplier);
                else info.damageTypes.ScaleAll(supportModularConfig.damageMultiplier);
            }
            return ConvoyTakeDamage(entity, info);
        }
        object OnEntityTakeDamage(BasicCar entity, HitInfo info) {
            if (info.InitiatorPlayer != null && convoySummons.Contains(entity)) {
                if (!info.damageTypes.Has(DamageType.Explosion) && info.damageTypes.GetMajorityDamageType() == DamageType.Bullet) info.damageTypes.ScaleAll(250f);
                else if (info.damageTypes.GetMajorityDamageType() == DamageType.Explosion && info.WeaponPrefab != null && info.WeaponPrefab.name == "rocket_hv") info.damageTypes.ScaleAll(10f);
                return ConvoyTakeDamage(entity, info);
            }
            return null;
        }
        object OnEntityTakeDamage(BradleyAPC entity, HitInfo info) {
            return ConvoyTakeDamage(entity, info);
        }
        object OnEntityTakeDamage(ScientistNPC entity, HitInfo info) {
            if (info == null || entity == null) return null;
            if ((info.InitiatorPlayer == null || !info.InitiatorPlayer.userID.IsSteamId()) && convoyVehicles.Count > 0 && convoyVehicles.Any(x => x.roamNpc.Contains(entity))) return true;
            ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x.scientists.Contains(entity)).FirstOrDefault();
            if (convoyVehicle != null) StopConvoy();
            if (convoyVehicles.Any(x => x.driver == entity)) return true;
            return null;
        }
        void OnEntityTakeDamage(BaseHelicopter entity, HitInfo info) {
            if (convoyHeli == null || info == null || entity == null || convoyHeli.baseHelicopter != entity) return;
            if (info.InitiatorPlayer != null) StopConvoy();
        }
        void OnEntityTakeDamage(BasePlayer player, HitInfo info) {
            if (player == null || info == null || info.Initiator == null) return;
            BradleyAPC bradleyAPC = info.Initiator as BradleyAPC;
            if (bradleyAPC != null && convoyVehicles.Any(x => x.baseEntity == bradleyAPC)) {
                if (!player.userID.IsSteamId()) info.damageTypes.ScaleAll(0);
                else info.damageTypes.ScaleAll(bradleyConfig.scaleDamage);
            }
        }
        void OnEntityKill(ModularCar entity) {
            if (entity != null && convoyVehicles.Any(x => x.baseEntity == entity)) {
                if (convoyModular != null && entity == convoyModular.baseEntity) {
                    failed = true;
                    if (convoyVehicles.Contains(convoyModular)) convoyVehicles.Remove(convoyModular);
                    StopConvoy();
                    if (!destroying && destroyCoroutine == null) {
                        destroying = true;
                        AlertToAllPlayers("Failed", _config.prefics);
                        AlertToAllPlayers("PreFinish", _config.prefics, GetTimeFromSecond(_config.preFinishTime));
                        destroyCoroutine = ServerMgr.Instance.StartCoroutine(DestroyCounter());
                    }
                }
                else ConvoyVehicleDie(entity);
            }
        }
        void OnEntityKill(BradleyAPC entity) => ConvoyVehicleDie(entity);
        void OnEntityKill(BasicCar entity) => ConvoyVehicleDie(entity);
        void OnEntityKill(BaseHelicopter entity) {
            if (entity == null || convoyHeli == null || convoyHeli.baseHelicopter != entity) return;
            deathHeliCoord = entity.transform.position;
            ConvoyVehicleDie(entity);
        }
        void OnEntityDeath(BasePlayer player, HitInfo info) {
            if (player == null) return;
            if (player.userID.IsSteamId() && players.Contains(player)) {
                players.Remove(player);
                if (_config.GUI.IsGUI) CuiHelper.DestroyUi(player, "TextMain");
            }
            else if (_config.blockSpawnDieNpc && info != null && info.Initiator != null && player is ScientistNPC) {
                ConvoyVehicle convoyVehicle = convoyVehicles.FirstOrDefault(x => x.roamNpc.Contains(player));
                if (convoyVehicle != null) convoyVehicle.NpcDie(player as ScientistNPC);
            }
        }
        object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
            if (crate == null || convoyModular == null || crate != convoyModular.crate) return null;
            else if ((!_config.needStopConvoy || stopTime > 0) && (!_config.needKillCars || (convoySummons.Count == 0 && !convoySummons.Any(x => x != null && !x.IsDestroyed))) && (!_config.needKillNpc || (!freeConvoyNpc.Any(x => x != null && !x.IsDestroyed) && !convoyVehicles.Any(x => x.roamNpc.Any(y => x != null && !y.IsDestroyed))))) {
                Unsubscribe("CanHackCrate");
                AlertToAllPlayers("StartHackCrate", _config.prefics, player.displayName);
                if (destroying) destroyTime += (int)modularConfig.crateUnlockTime + 30;
                hackedCrate = true;
                timer.In(modularConfig.crateUnlockTime, () => {
                    if (destroyCoroutine == null && !destroying) {
                        destroying = true;
                        destroyCoroutine = ServerMgr.Instance.StartCoroutine(DestroyCounter());
                        AlertToAllPlayers("PreFinish", _config.prefics, _config.preFinishTime);
                    }
                }
                );
                if (stopTime <= 0) StopConvoy();
                timer.In(0.5f, () => crate.hackSeconds = HackableLockedCrate.requiredHackSeconds - ins.modularConfig.crateUnlockTime);
                return null;
            }
            else {
                Alert(player, GetMessage("CantHackCrate", player.UserIDString, _config.prefics));
                return true;
            }
        }
        void OnEntitySpawned(HelicopterDebris entity) => NextTick(() => {
            if (entity != null && !entity.IsDestroyed && deathBradleyCoord != null && (Vector3.Distance(entity.transform.position, deathBradleyCoord) < 20f || Vector3.Distance(entity.transform.position, deathHeliCoord) < 20f)) entity.Kill();
        }
        );
        object CanMountEntity(BasePlayer player, BaseMountable entity) {
            BaseEntity parrent = entity.VehicleParent();
            if (parrent != null && player.userID.IsSteamId() && convoyVehicles.Any(x => x.baseEntity == parrent)) return true;
            return null;
        }
        object OnHelicopterRetire(PatrolHelicopterAI ai) {
            if (convoyHeli != null && convoyHeli.patrolHelicopterAI == ai) return true;
            return null;
        }
        object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer player) {
            if (convoyHeli != null && heli != null && heli == convoyHeli.patrolHelicopterAI && ((_config.blockFirstAttack && stopTime == 0 && !failed && !hackedCrate) || player == null || !player.userID.IsSteamId() || player.IsSleeping())) return false;
            return null;
        }
        object CanBradleyApcTarget(BradleyAPC apc, BaseEntity entity) {
            if (apc != null && convoySummons.Count > 0 && convoySummons.Contains(apc)) {
                if (_config.blockFirstAttack && stopTime == 0 && !failed && !hackedCrate) return false;
                BasePlayer player = entity as BasePlayer;
                if (player == null || !player.userID.IsSteamId() || player.IsSleeping()) return false;
            }
            return null;
        }
        object OnBotReSpawnCrateDropped(HackableLockedCrate crate) {
            if (active && convoyModular != null && convoyModular.crate != null && convoyModular.crate == crate) return true;
            return null;
        }
#endregion Hooks
#region Commands
        [ChatCommand("convoystart")]
        void StartCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            if (active) {
                Alert(player, GetMessage("EventActive", player.UserIDString, _config.prefics));
                return;
            }
            if (arg != null && arg.Length >= 1) CreateConvoy(arg[0]);
            else CreateConvoy();
        }
        [ChatCommand("convoystop")]
        void StopCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin) return;
            if (active) DeleteConvoy(true);
        }
        [ConsoleCommand("convoystart")]
        void ConsoleStartCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() != null) return;
            if (arg.Args != null && arg.Args.Count() > 0) CreateConvoy(arg.Args[0]);
            CreateConvoy();
        }
        [ConsoleCommand("convoystop")]
        void ConsoleStopCommand(ConsoleSystem.Arg arg) {
            if (arg.Player() == null && active) DeleteConvoy(true);
        }
        [ChatCommand("convoyrootstart")]
        void RootStartCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || player.isInAir) return;
            CreateRootCar(player);
        }
        [ChatCommand("convoyrootstop")]
        void RootStopCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || rootCar == null) return;
            RootStop();
        }
        [ChatCommand("convoyrootsave")]
        void RootSaveCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || rootCar == null) return;
            if (arg == null || arg.Count() == 0) {
                Alert(player, $"{_config.prefics} To save the route, use the command: <color=#738d43>convoyrootsave [rootpresetname]</color>");
                return;
            }
            if (rootCar.root.Count() < 50) Alert(player, $"{_config.prefics} The route is too short!");
            else {
                List<string> root = new List<string>();
                foreach (Vector3 vector in rootCar.root) root.Add(vector.ToString());
                if (!roots.ContainsKey(arg[0])) roots.Add(arg[0], new List<List<string>>());
                roots[arg[0]].Add(root);
                SaveData();
                RootStop();
                Alert(player, $"{_config.prefics} Route added to group <color=#738d43>{arg[0]}</color>");
            }
        }
        [ChatCommand("convoyroadblock")]
        void RoadBlockCommand(BasePlayer player, string command, string[] arg) {
            if (!player.IsAdmin || player.isInAir) return;
            PathList blockRoad = TerrainMeta.Path.Roads.FirstOrDefault(x => x.Path.Points.Any(y => Vector3.Distance(player.transform.position, y) < 10));
            if (blockRoad == null) Alert(player, $"{_config.prefics} Road not found <color=#ce3f27>not found</color>");
            int index = TerrainMeta.Path.Roads.IndexOf(blockRoad);
            if (_config.blockRoads.Contains(index)) Alert(player, $"{_config.prefics} The road is already <color=#ce3f27>blocked</color>");
            else if (blockRoad != null) {
                _config.blockRoads.Add(index);
                SaveConfig();
                Alert(player, $"{_config.prefics} The road with the index <color=#738d43>{index}</color> is <color=#ce3f27>blocked</color>");
            }
        }
#endregion Commands
#region Method
        void CreateConvoy(string presetName = "") {
            if (active) {
                Puts("This event is active now.To finish this event (convoystop), then to start the next one");
                return;
            }
            if (!plugins.Exists("NpcSpawn")) {
                PrintError("NpcSpawn plugin doesn`t exist! Please read the file ReadMe.txt");
                Server.Command($"o.unload {Name}");
                return;
            }
            destroyTime = ins._config.preFinishTime;
            ConvoySetting convoySetting = null;
            if (presetName != "") convoySetting = _config.convoys.Where(x => x.name == presetName).FirstOrDefault();
            else if (_config.convoys.Any(x => x.chance > 0)) {
                while (convoySetting == null) {
                    foreach (ConvoySetting setting in _config.convoys) {
                        if (UnityEngine.Random.Range(0.0f, 100.0f) <= setting.chance) convoySetting = setting;
                    }
                }
            }
            if (convoySetting == null) {
                PrintError("Event configuration not found!");
                Server.Command($"o.reload {Name}");
                return;
            }
            AlertToAllPlayers("PreStart", _config.prefics, GetTimeFromSecond(_config.preStartTime));
            active = true;
            timer.In(_config.preStartTime, () => {
                if (!active) return;
                Subscribes();
                bradleyConfig = _config.bradleyConfiguration.Where(x => x.presetName == convoySetting.bradleyConfigurationName).FirstOrDefault();
                sedanConfig = _config.sedanConfiguration.Where(x => x.presetName == convoySetting.sedanConfigurationName).FirstOrDefault();
                modularConfig = _config.modularConfiguration.Where(x => x.presetName == convoySetting.modularConfigurationName).FirstOrDefault();
                heliConfig = _config.heliesConfiguration.Where(x => x.presetName == convoySetting.heliConfigurationName).FirstOrDefault();
                supportModularConfig = _config.supportModularConfiguration.Where(x => x.presetName == convoySetting.supportodularConfigurationName).FirstOrDefault();
                int totalVehicleCount = convoySetting.firstBradleyCount + convoySetting.firstSedanCount + convoySetting.endSedanCount + convoySetting.endBradleyCount;
                int startPoint = round ? UnityEngine.Random.Range(0, pathCount / 2) : 1;
                //int startPoint = round ? (int)(pathCount * 0.98f) : 1;
                int count = 0;
                int totalCount = convoySetting.endBradleyCount;
                int delataPoint = _config.carDistance;
                int cycleCount = 0;
                while (cycleCount < 25 && Vector3.Distance(currentPath[0], currentPath[delataPoint]) < 10) {
                    delataPoint += 2;
                    cycleCount++;
                }
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateBradley(firstpoint, secondpoint);
                    startPoint += delataPoint;
                }
                totalCount += convoySetting.endModularCount;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateModular(firstpoint, secondpoint, false);
                    startPoint += delataPoint;
                }
                totalCount += convoySetting.endSedanCount;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateSedan(firstpoint, secondpoint);
                    startPoint += delataPoint;
                }
                totalCount++;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateModular(firstpoint, secondpoint);
                    startPoint += delataPoint;
                }
                totalCount += convoySetting.firstSedanCount;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateSedan(firstpoint, secondpoint);
                    startPoint += delataPoint;
                }
                totalCount += convoySetting.firstModularCount;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateModular(firstpoint, secondpoint, false);
                    startPoint += delataPoint;
                }
                totalCount += convoySetting.firstBradleyCount;
                for (; count < totalCount; count++) {
                    int firstpoint = 0, secondpoint = 0;
                    DefineNextPathPoint(startPoint, pathCount, out firstpoint, out secondpoint);
                    CreateBradley(firstpoint, secondpoint);
                    startPoint += delataPoint;
                }
                if (convoySetting.heliOn && convoyModular != null) CreateHelicopter();
                convoyVehicles.Reverse();
                AlertToAllPlayers("EventStart", _config.prefics);
                if (eventCoroutine != null) ServerMgr.Instance.StopCoroutine(eventCoroutine);
                eventCoroutine = ServerMgr.Instance.StartCoroutine(EventCounter());
                Puts("The event has begun");
                Interface.CallHook("OnConvoyStart");
            }
            );
        }
        void DefineNextPathPoint(int point, int pathCount, out int firstPoint, out int endPoint) {
            if (point > pathCount - 1) {
                if (round) firstPoint = point - pathCount;
                else {
                    PrintError("Insufficient route length!");
                    DeleteConvoy(true);
                    firstPoint = endPoint = 0;
                }
            }
            else firstPoint = point;
            int endpointClone = firstPoint++;
            if (endpointClone > pathCount - 1) {
                if (round) endPoint = endpointClone - pathCount;
                else {
                    PrintError("Insufficient route length!");
                    DeleteConvoy(true);
                    firstPoint = endPoint = 0;
                }
            }
            else endPoint = endpointClone;
        }
        void ReverseConvoy() {
            currentPath.Reverse();
            convoyVehicles.Reverse();
            foreach (ConvoyVehicle convoyVehicle in convoyVehicles) {
                if (convoyVehicle == null) continue;
                Transform transform = convoyVehicle.baseEntity.transform;
                transform.RotateAround(transform.position, transform.up, 180);
                convoyVehicle.Rotate();
                convoyVehicle.DefineFollowEntity();
            }
        }
        void DeleteConvoy(bool unload = false) {
            Unsubscribes();
            if (active) Interface.CallHook("OnConvoyStop");
            active = false;
            if (doorCloser != null && !doorCloser.IsDestroyed) doorCloser.Kill();
            foreach (BasePlayer player in ins.players) CuiHelper.DestroyUi(player, "TextMain");
            players.Clear();
            if (active) AlertToAllPlayers("Finish", _config.prefics);
            destroying = false;
            foreach (ScientistNPC scientist in freeConvoyNpc) {
                if (scientist != null && !scientist.IsDestroyed) scientist.Kill();
            }
            foreach (ConvoyVehicle convoyVehicle in convoyVehicles) {
                if (convoyVehicle != null && convoyVehicle.baseEntity != null && !convoyVehicle.baseEntity.IsDestroyed) {
                    convoyVehicle.destroyAll = true;
                    convoyVehicle.baseEntity.Kill();
                }
            }
            if (convoyHeli != null && convoyHeli.baseHelicopter != null && !convoyHeli.baseHelicopter.IsDestroyed) convoyHeli.baseHelicopter.Kill();
            convoyVehicles.Clear();
            convoySummons.Clear();
            Puts("The event is over");
            if (stopCoroutine != null) ServerMgr.Instance.StopCoroutine(stopCoroutine);
            if (eventCoroutine != null) ServerMgr.Instance.StopCoroutine(eventCoroutine);
            if (destroyCoroutine != null) ServerMgr.Instance.StopCoroutine(destroyCoroutine);
            if (convoyModular != null && convoyModular.baseEntity != null && !convoyModular.baseEntity.IsDestroyed) convoyModular.baseEntity.Kill();
            if (unload) Server.Command($"o.reload {Name}");
        }
        void ConvoyVehicleDie(BaseEntity entity) {
            if (entity == null) return;
            ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x.baseEntity == entity).FirstOrDefault();
            if (convoyVehicle != null) {
                if (convoyVehicle is ConvoyBradley) deathBradleyCoord = entity.transform.position;
                DefineFollow(entity);
            }
            if (convoySummons.Count > 0 && convoySummons.Contains(entity)) {
                convoySummons.Remove(entity);
                if (convoySummons.Count == 0 && convoyModular != null) {
                    StopConvoy();
                    convoyModular.StopMoving(false, true);
                    AlertToAllPlayers("SecurityKill", _config.prefics);
                }
            }
        }
        object ConvoyTakeDamage(BaseEntity entity, HitInfo info) {
            if (entity == null || info == null || info.InitiatorPlayer == null || !convoyVehicles.Any(x => x.baseEntity == entity)) return null;
            BasePlayer initiator = info.InitiatorPlayer;
            if (!initiator.userID.IsSteamId()) return true;
            if (info.ProjectileDistance <= 100f) StopConvoy(initiator);
            return null;
        }
        void StopConvoy(BasePlayer initiator = null, int time = 0) {
            stopTime = time > 0 ? time : _config.damamageStopTime;
            if (stopCoroutine != null && stopTime != 0) return;
            stopCoroutine = ServerMgr.Instance.StartCoroutine(StopCounter());
            foreach (ConvoyVehicle convoyVehicle in convoyVehicles) if (convoyVehicle != null) convoyVehicle.StopMoving(true, true);
            if (initiator != null && convoyHeli != null) convoyHeli.SetTarget(initiator);
            if (convoyModular != null) CreateEventZone(convoyModular.baseEntity.transform.position - new Vector3(0f, 0.5f, 0f));
            if (initiator != null) AlertToAllPlayers("ConvoyAttacked", _config.prefics, initiator.displayName);
        }
        void StartConvoy() {
            if (failed || convoyModular == null || convoyModular.crate == null || convoyModular.crate.IsFullyHacked() || convoyModular.crate.IsBeingHacked()) return;
            if (stopCoroutine != null) ServerMgr.Instance.StopCoroutine(stopCoroutine);
            foreach (ScientistNPC scientist in freeConvoyNpc) if (scientist != null && !scientist.IsDestroyed) scientist.Kill();
            freeConvoyNpc.Clear();
            stopCoroutine = null;
            stopTime = 0;
            foreach (ConvoyVehicle convoyVehicle in convoyVehicles) convoyVehicle.StartMoving();
            if (doorCloser != null && !doorCloser.IsDestroyed) doorCloser.Kill();
            players.Clear();
        }
        void CreateEventZone(Vector3 position) {
            if (doorCloser != null && !doorCloser.IsDestroyed) doorCloser.Kill();
            if (convoyModular == null || convoyModular.baseEntity.IsDestroyed) return;
            doorCloser = GameManager.server.CreateEntity("assets/prefabs/misc/doorcloser/doorcloser.prefab", position) as DoorCloser;
            doorCloser.gameObject.AddComponent<ZoneController>();
        }
        void CreateBradley(int firstPoint, int secondPoint) {
            Vector3 vector3 = currentPath[firstPoint];
            ChechTrash(vector3);
            BradleyAPC bradley = GameManager.server.CreateEntity("assets/prefabs/npc/m2bradley/bradleyapc.prefab", vector3, Quaternion.LookRotation(currentPath[firstPoint] - currentPath[secondPoint])) as BradleyAPC;
            bradley.OwnerID = 755446;
            bradley.skinID = 755446;
            bradley.Spawn();
            bradley.ClearPath();
            bradley.currentPath = currentPath;
            bradley.currentPathIndex = firstPoint;
            ConvoyBradley convoyBradley = bradley.gameObject.AddComponent<ConvoyBradley>();
            convoyVehicles.Add(convoyBradley);
            convoyBradley.InitBradley();
            convoySummons.Add(bradley);
        }
        void CreateSedan(int firstPoint, int secondPoint) {
            Vector3 vector3 = currentPath[firstPoint];
            ChechTrash(vector3);
            BasicCar car = GameManager.server.CreateEntity("assets/content/vehicles/sedan_a/sedantest.entity.prefab", vector3, Quaternion.LookRotation(currentPath[firstPoint] - currentPath[secondPoint])) as BasicCar;
            car.enableSaving = false;
            car.OwnerID = 755446;
            car.skinID = 755446;
            car.Spawn();
            ConvoyCar convoyCar = car.gameObject.AddComponent<ConvoyCar>();
            convoyCar.currentPoint = firstPoint;
            convoyCar.InitSedan();
            convoyVehicles.Add(convoyCar);
            convoySummons.Add(car);
        }
        void CreateModular(int firstPoint, int secondPoint, bool main = true) {
            Vector3 vector3 = currentPath[firstPoint];
            ChechTrash(vector3);
            ModularCar car = GameManager.server.CreateEntity(main ? modularConfig.prefabName : supportModularConfig.prefabName, vector3, Quaternion.LookRotation(currentPath[firstPoint] - currentPath[secondPoint])) as ModularCar;
            car.enableSaving = false;
            car.spawnSettings.useSpawnSettings = false;
            car.OwnerID = 755446;
            car.skinID = 755446;
            car.Spawn();
            ConvoyModular modular = car.gameObject.AddComponent<ConvoyModular>();
            modular.baseEntity = car;
            modular.currentPoint = firstPoint;
            convoyVehicles.Add(modular);
            modular.InitModular(main);
            if (main) convoyModular = modular;
            else convoySummons.Add(car);
        }
        void CreateHelicopter() {
            Vector3 position = convoyModular.baseEntity.transform.position + new Vector3(0, heliConfig.height, 0);
            Quaternion rotation = convoyModular.baseEntity.transform.rotation;
            BaseHelicopter heli = GameManager.server.CreateEntity("assets/prefabs/npc/patrol helicopter/patrolhelicopter.prefab", position, rotation) as BaseHelicopter;
            heli.enableSaving = false;
            heli.OwnerID = 755446;
            heli.skinID = 755446;
            heli.Spawn();
            heli.transform.position = position;
            convoyHeli = heli.gameObject.AddComponent<ConvoyHeli>();
            heli._maxHealth = heliConfig.hp;
            heli.startHealth = heliConfig.hp;
            convoyHeli.InitHelicopter(heliConfig.hp);
            convoySummons.Add(heli);
        }
        void DefineFollow(BaseEntity entity) {
            ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x.baseEntity.net.ID == entity.net.ID).FirstOrDefault();
            if (convoyVehicle == null) return;
            int index = convoyVehicles.IndexOf(convoyVehicle);
            index++;
            if (index >= convoyVehicles.Count()) return;
            ConvoyVehicle nextVehicle = convoyVehicles[index];
            if (nextVehicle == null) return;
            BaseEntity baseEntity = nextVehicle.baseEntity;
            if (baseEntity == null || baseEntity.IsDestroyed) return;
            convoyVehicles.Remove(convoyVehicle);
            nextVehicle.DefineFollowEntity();
        }
        void RootStop() {
            if (rootCar != null && !rootCar.basicCar.IsDestroyed) rootCar.basicCar.Kill();
        }
        void CreateRootCar(BasePlayer player) {
            if (rootCar != null) {
                Alert(player, $"{_config.prefics} The route is <color=#738d43>already</color> being recorded!");
                return;
            }
            Alert(player, $"{_config.prefics} To build a route, drive a car along it and write to the chat: <color=#738d43>convoyrootsave [rootgroupname]</color>\nTo reset the route, print to the chat: <color=#738d43>convoyrootstop</color>");
            BasicCar car = GameManager.server.CreateEntity("assets/content/vehicles/sedan_a/sedantest.entity.prefab", player.transform.position + new Vector3(0, 0.3f, 0), player.eyes.GetLookRotation()) as BasicCar;
            car.enableSaving = false;
            car.Spawn();
            rootCar = car.gameObject.AddComponent<RootCar>();
            rootCar.InitSedan(player);
            BaseVehicle.MountPointInfo mountPointInfo = car.mountPoints[0];
            player.MountObject(mountPointInfo.mountable);
            mountPointInfo.mountable.MountPlayer(player);
        }
        IEnumerator EventCounter() {
            while (eventTime < _config.eventTime && !destroying && active) {
                eventTime++;
                yield return CoroutineEx.waitForSeconds(1f);
            }
            if (!destroying && destroyCoroutine == null) {
                destroying = true;
                AlertToAllPlayers("PreFinish", _config.prefics, _config.preFinishTime);
                destroyCoroutine = ServerMgr.Instance.StartCoroutine(DestroyCounter());
            }
        }
        IEnumerator StopCounter() {
            while (stopTime > 0) {
                stopTime--;
                yield return CoroutineEx.waitForSeconds(1f);
            }
            stopTime = 0;
            if (active) StartConvoy();
        }
        IEnumerator DestroyCounter() {
            while (destroyTime > 0) {
                destroyTime--;
                yield return CoroutineEx.waitForSeconds(1f);
            }
            destroyTime = 0;
            if (active) DeleteConvoy(true);
        }
#endregion Method
#region Classes
        class ZoneController : FacepunchBehaviour {
            DoorCloser mainCloser;
            SphereCollider sphereCollider;
            HashSet<BaseEntity> spheres = new HashSet<BaseEntity>();
            void Awake() {
                gameObject.layer = (int)Layer.Reserved1;
                sphereCollider = gameObject.AddComponent<SphereCollider>();
                sphereCollider.isTrigger = true;
                sphereCollider.radius = ins._config.eventZone.radius;
                mainCloser = GetComponent<DoorCloser>();
                if (ins._config.GUI.IsGUI) InvokeRepeating(UpdateGui, 1f, 1f);
                if (ins._config.eventZone.isDome) CreateSphere();
            }
            void CreateSphere() {
                for (int i = 0; i < ins._config.eventZone.darkening; i++) {
                    BaseEntity sphere = GameManager.server.CreateEntity("assets/prefabs/visualization/sphere.prefab", mainCloser.transform.position);
                    SphereEntity entity = sphere.GetComponent<SphereEntity>();
                    entity.currentRadius = ins._config.eventZone.radius * 2;
                    entity.lerpSpeed = 0f;
                    sphere.enableSaving = false;
                    sphere.Spawn();
                    spheres.Add(sphere);
                }
            }
            void UpdateGui() {
                int time = ins._config.eventTime - ins.eventTime;
                if (ins.destroying) time = ins.destroyTime;
                foreach (BasePlayer player in ins.players) ins.MessageGUI(player, ins.GetMessage("GUI", player.UserIDString, ins.GetTimeFromSecond(time)));
            }
            void OnTriggerEnter(Collider other) {
                BasePlayer player = other.GetComponentInParent<BasePlayer>();
                if (player != null && player.userID.IsSteamId()) {
                    ins.players.Add(player);
                    if (ins._config.GUI.IsGUI) ins.MessageGUI(player, ins.GetMessage("GUI", player.UserIDString, ins.GetTimeFromSecond(ins._config.eventTime - ins.eventTime + ins.destroyTime)));
                    if (ins._config.eventZone.isCreateZonePVP) ins.Alert(player, ins.GetMessage("EnterPVP", player.UserIDString, ins._config.prefics));
                }
            }
            void OnTriggerExit(Collider other) {
                BasePlayer player = other.GetComponentInParent<BasePlayer>();
                if (player != null && player.userID.IsSteamId()) {
                    ins.players.Remove(player);
                    if (ins._config.GUI.IsGUI) CuiHelper.DestroyUi(player, "TextMain");
                    if (ins._config.eventZone.isCreateZonePVP) ins.Alert(player, ins.GetMessage("ExitPVP", player.UserIDString, ins._config.prefics));
                }
            }
            void OnDestroy() {
                foreach (BaseEntity sphere in spheres) if (sphere != null && !sphere.IsDestroyed) sphere.Kill();
                CancelInvoke(UpdateGui);
                foreach (BasePlayer player in BasePlayer.activePlayerList) CuiHelper.DestroyUi(player, "TextMain");
            }
        }
        class ConvoyVehicle : FacepunchBehaviour {
            List<CoordConfig> coordNPC = new List<CoordConfig>();
            List<BaseVehicle.MountPointInfo> baseMountables = new List<BaseVehicle.MountPointInfo>();
            internal ConvoyVehicle followVehicle;
            internal Rigidbody rigidbody;
            internal BaseEntity baseEntity;
            internal ScientistNPC driver;
            internal bool destroyAll = false;
            internal bool stop = true;
            internal bool allConvoyStop = true;
            int countDieNpc = 0;
            internal List<ScientistNPC> scientists = new List<ScientistNPC>();
            internal List<ScientistNPC> roamNpc = new List<ScientistNPC>();
            NpcConfig npcConfig;
            void Awake() {
                Invoke(InitVehicle, 0.5f);
            }
            void InitVehicle() {
                baseEntity = GetComponent<BaseEntity>();
                if (baseEntity is BradleyAPC) {
                    npcConfig = ins._config.NPC.FirstOrDefault(x => x.name == ins.bradleyConfig.npcName);
                    coordNPC = ins.bradleyConfig.coordinates;
                }
                else if (baseEntity is ModularCar) {
                    if (ins.convoyModular != null && ins.convoyModular.baseEntity != null && baseEntity.net.ID == ins.convoyModular.baseEntity.net.ID) {
                        npcConfig = ins._config.NPC.FirstOrDefault(x => x.name == ins.modularConfig.npcName);
                        coordNPC = ins.modularConfig.coordinates;
                    }
                    else {
                        npcConfig = ins._config.NPC.FirstOrDefault(x => x.name == ins.supportModularConfig.npcName);
                        coordNPC = ins.supportModularConfig.coordinates;
                    }
                }
                else if (baseEntity is BasicCar) {
                    npcConfig = ins._config.NPC.FirstOrDefault(x => x.name == ins.sedanConfig.npcName);
                    coordNPC = ins.sedanConfig.coordinates;
                }
                rigidbody = baseEntity.gameObject.GetComponent<Rigidbody>();
                rigidbody.mass = 3500;
                rigidbody.centerOfMass = new Vector3(0, -0.2f, 0);
                rigidbody.isKinematic = true;
                DefineMountPoints();
                StartMoving();
                DefineFollowEntity();
                if (!ins.round) InvokeRepeating(CheckRotate, 0.5f, 0.1f);
                if (ins._config.deleteBarriers) InvokeRepeating(CheckBarriers, 3f, 3f);
            }
            internal virtual void Rotate() {
            }
            internal virtual void CheckRotate() {
            }
            internal virtual int GetCurrentPointIndex() {
                return 0;
            }
            internal virtual void CheckBarriers() {
                if (followVehicle != null) return;
                foreach (Collider collider in UnityEngine.Physics.OverlapSphere(baseEntity.transform.position + baseEntity.transform.forward * 4f, 3f)) {
                    BaseEntity entity = collider.ToBaseEntity();
                    if (entity != null && !entity.IsDestroyed && ins._config.barriers.Contains(entity.ShortPrefabName) && !ins.convoyVehicles.Any(x => x.baseEntity == entity)) {
                        if (entity is BaseVehicle) {
                            BaseVehicle vehicle = entity as BaseVehicle;
                            if (!vehicle.mountPoints.Any(x => x.mountable.GetMounted() != null)) entity.Kill();
                        }
                        else entity.Kill();
                    }
                }
            }
            internal virtual void OnDestroy() {
                CancelInvoke(CheckRotate);
                CancelInvoke(CheckBarriers);
                KillScientists(!destroyAll);
            }
#region Moving
            internal void DefineFollowEntity() {
                int index = ins.convoyVehicles.IndexOf(this);
                if (index == 0) followVehicle = null;
                else followVehicle = ins.convoyVehicles[--index];
            }
            internal void StopMoving(bool NPC = true, bool allConvoyStop = false) {
                this.allConvoyStop = allConvoyStop;
                CancelInvoke(BreakOff);
                stop = true;
                BreakOn();
                if (NPC && ins.active) Invoke(CreateRoamNpc, 0.1f);
            }
            internal void StartMoving(bool delay = true) {
                foreach (ScientistNPC scientist in roamNpc) if (scientist != null && !scientist.IsDestroyed) scientist.Kill();
                roamNpc.Clear();
                if (allConvoyStop && ins.active) CreatePassengers();
                if (delay && ins.active) Invoke(BreakOff, 7f);
                else BreakOff();
            }
            internal void BreakOff() {
                allConvoyStop = false;
                rigidbody.isKinematic = false;
                stop = false;
            }
            void BreakOn() => rigidbody.isKinematic = true;
#endregion Moving
#region NPC
            internal void NpcDie(ScientistNPC scientistNPC) {
                if (!ins.active) return;
                roamNpc.Remove(scientistNPC);
                countDieNpc++;
            }
            void DefineMountPoints() {
                BaseVehicle baseVehicle = baseEntity.gameObject.GetComponent<BaseVehicle>();
                if (baseVehicle != null) baseMountables = baseVehicle.allMountPoints.ToList();
            }
            void CreatePassengers() {
                int count = baseMountables.Count();
                if (count == 0) return;
                count -= countDieNpc;
                if (count == 0) count = 1;
                driver = null;
                scientists.Clear();
                for (int i = 0; i < count; i++) {
                    BaseVehicle.MountPointInfo mountPointInfo = baseMountables[i];
                    BaseMountable baseMountable = mountPointInfo.mountable;
                    if (baseMountable == null) continue
// ... [Code preview truncated due to length. Full source in attached file] ...

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

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

Сверху