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", "Sempai#3239", "2.1.5")]
class Convoy : RustPlugin {
[PluginReference]
Plugin NpcSpawn, GUIAnnouncements, DiscordMessages, PveMode, Economics, ServerRewards, IQEconomic;
#region Variables
const bool en = false;
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;
ConvoySetting convoySetting = null;
HashSet<string> subscribeMetods = new HashSet<string> {
"OnEntityKill", "OnEntityTakeDamage", "OnVehicleModulesAssign", "CanHackCrate", "OnEntitySpawned", "OnHelicopterRetire", "CanHelicopterTarget", "CanBradleyApcTarget"
}
;
List<Vector3> currentPath = new List<Vector3>();
List<ConvoyVehicle> convoyVehicles = new List<ConvoyVehicle>();
HashSet<uint> convoyVehicleNetIds = new HashSet<uint>();
List<ScientistNPC> freeConvoyNpc = new List<ScientistNPC>();
HashSet<BasePlayer> players = new HashSet<BasePlayer>();
HashSet<ulong> owners = new HashSet<ulong>();
HashSet<BaseEntity> convoySummons = new HashSet<BaseEntity>();
HashSet<uint> heliContainers = new HashSet<uint>();
HashSet<uint> bradleyContainers = new HashSet<uint>();
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;
Vector3 deathModularCoord = Vector3.zero;
Coroutine stopCoroutine;
Coroutine eventCoroutine;
Coroutine destroyCoroutine;
#endregion Variables
#region API
private bool IsConvoyVehicle(BaseEntity entity) {
if (entity == null) return false;
return convoyVehicleNetIds.Any(x => x == entity.net.ID);
}
private bool IsConvoyCrate(HackableLockedCrate crate) {
if (crate == null) return false;
if (convoyModular != null && convoyModular.crate != 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;
UpdateConfig();
Unsubscribes();
Unsubscribe("OnLootSpawn");
if (!_config.blockFirstAttack) Unsubscribe("OnExplosiveThrown");
if (_config.betterNpcConfig.bradleyNpc) Unsubscribe("CanBradleySpawnNpc");
if (_config.betterNpcConfig.heliNpc) Unsubscribe("CanHelicopterSpawnNpc");
LoadData();
}
void OnServerInitialized() {
PrintWarning("\n-----------------------------\n" + " Author - Sempai#3239\n" + " VK - https://vk.com/rustnastroika/n" + " Forum - https://darkplugins.ru/n" + " Discord - https://discord.gg/5DPTsRmd3G/n" + "-----------------------------");
LoadDefaultMessages();
CheckZeroCoord();
int vehicleCount = 0;
Subscribe("OnLootSpawn");
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");
return;
}
if (Vector3.Distance(currentPath[0], currentPath[currentPath.Count() - 1]) > 10f) round = false;
if (_config.autoEvent && _config.convoys.Any(x => x.on && x.chance > 0)) {
timer.In(UnityEngine.Random.Range(_config.minStartTime, _config.maxStartTime), () => {
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;
}
void OnEntitySpawned(LockedByEntCrate crate) {
if (crate == null) return;
timer.In(0.35f, () => {
if (crate == null) return;
if (crate.ShortPrefabName == "bradley_crate" && Vector3.Distance(deathBradleyCoord, crate.transform.position) < 15f) {
if (bradleyConfig.offDelay) {
crate.CancelInvoke(crate.Think);
crate.SetLocked(false);
crate.lockingEnt = null;
}
if (bradleyConfig.typeLootTable == 1) {
for (int i = crate.inventory.itemList.Count - 1; i >= 0; i--) {
Item item = crate.inventory.itemList[i];
item.RemoveFromContainer();
item.Remove();
}
AddToContainer(crate.inventory, bradleyConfig.lootTable.Items, UnityEngine.Random.Range(bradleyConfig.lootTable.Min, bradleyConfig.lootTable.Max + 1));
}
}
else if (crate.ShortPrefabName == "heli_crate" && Vector3.Distance(deathHeliCoord, crate.transform.position) < 15f) {
if (heliConfig.offDelay) {
crate.CancelInvoke(crate.Think);
crate.SetLocked(false);
crate.lockingEnt = null;
}
if (heliConfig.typeLootTable == 1) {
for (int i = crate.inventory.itemList.Count - 1; i >= 0; i--) {
Item item = crate.inventory.itemList[i];
item.RemoveFromContainer();
item.Remove();
}
AddToContainer(crate.inventory, heliConfig.lootTable.Items, UnityEngine.Random.Range(heliConfig.lootTable.Min, heliConfig.lootTable.Max + 1));
}
}
}
);
}
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 OnEntityTakeDamage(BaseVehicleModule baseVehicleModule, HitInfo info) {
if (baseVehicleModule == null || info == null) return null;
BaseModularVehicle modularVehicle = baseVehicleModule.Vehicle;
if (modularVehicle != null && convoyVehicles.Any(x => x != null && x.baseEntity != null && x.baseEntity == modularVehicle)) {
if (info.InitiatorPlayer != null) {
if (!PveModeAllowAction(info.InitiatorPlayer)) return true;
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 {
for (int i = 0; i <= modularVehicle.moduleSockets.Count; i++) {
BaseVehicleModule module;
if (modularVehicle.TryGetModuleAt(i, out module)) module.SetHealth(module._maxHealth * modularVehicle.health / modularVehicle._maxHealth);
}
ConvoyTakeDamage(modularVehicle, info);
}
}
return true;
}
return null;
}
object OnEntityTakeDamage(ModularCar entity, HitInfo info) {
if (convoyModular != null && convoyVehicles.Any(x => x.baseEntity == entity)) {
if (info.InitiatorPlayer != null) {
if (!PveModeAllowAction(info.InitiatorPlayer)) return true;
}
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)) 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 != null && x.scientists.Contains(entity)).FirstOrDefault();
if (convoyVehicle != null) StopConvoy();
if (convoyVehicles.Any(x => x != null && 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 != null && x.baseEntity == entity)) {
deathModularCoord = entity.transform.position;
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;
if (_config.pveMode.pve && plugins.Exists("PveMode")) timer.In(1f, () => {
PveMode.Call("EventAddCrates", Name, bradleyContainers);
heliContainers.Clear();
}
);
ConvoyVehicleDie(entity);
}
void OnEntityKill(BasePlayer player) {
if (player == null) return;
if (player.userID.IsSteamId() && players.Contains(player)) {
players.Remove(player);
if (_config.GUI.IsGUI) CuiHelper.DestroyUi(player, "TextMain");
}
}
void OnEntityDeath(ModularCar entity, HitInfo info) {
if (entity == null || info == null || info.InitiatorPlayer == null) return;
ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x != null && x.baseEntity != null && x.baseEntity.net.ID == entity.net.ID).FirstOrDefault();
if (convoyVehicle == null) return;
EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Modular");
}
void OnEntityDeath(BradleyAPC entity, HitInfo info) {
if (entity == null || info == null || info.InitiatorPlayer == null) return;
ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x != null && x.baseEntity != null && x.baseEntity.net.ID == entity.net.ID).FirstOrDefault();
if (convoyVehicle == null) return;
EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Bradley");
}
void OnEntityDeath(BasicCar entity, HitInfo info) {
if (entity == null || info == null || info.InitiatorPlayer == null) return;
ConvoyVehicle convoyVehicle = convoyVehicles.Where(x => x != null && x.baseEntity != null && x.baseEntity.net.ID == entity.net.ID).FirstOrDefault();
if (convoyVehicle == null) return;
EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Sedan");
}
void OnEntityDeath(BaseHelicopter entity, HitInfo info) {
if (entity == null || info == null || info.InitiatorPlayer == null) return;
if (convoySummons.Count > 0 && convoySummons.Contains(entity)) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Heli");
}
void OnEntityDeath(BasePlayer player, HitInfo info) {
if (player != null && info != null && info.InitiatorPlayer != null && player is ScientistNPC) {
ConvoyVehicle convoyVehicle = convoyVehicles.FirstOrDefault(x => x != null && x.roamNpc.Contains(player));
if (convoyVehicle != null) {
if (_config.blockSpawnDieNpc) convoyVehicle.NpcDie(player as ScientistNPC);
EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Npc");
}
else if (freeConvoyNpc.Contains(player as ScientistNPC)) EconomyManager.ActionEconomy(info.InitiatorPlayer.userID, "Npc");
}
}
object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
if (crate == null || player == null || convoyModular == null || convoyModular.crate == null || crate.net.ID != convoyModular.crate.net.ID) return null;
else if (!player.InSafeZone() && (!_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 != null && x.roamNpc.Any(y => y != null && !y.IsDestroyed))))) {
if (_config.pveMode.pve && plugins.Exists("PveMode") && !_config.pveMode.hackCrate && PveMode.Call("CanActionEvent", Name, player) != null) return true;
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, GetTimeFromSecond(_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;
}
}
object CanMountEntity(BasePlayer player, BaseMountable entity) {
BaseEntity parrent = entity.VehicleParent();
if (parrent != null && player.userID.IsSteamId() && convoyVehicles.Any(x => x != null && 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;
}
void OnEntitySpawned(DroppedItemContainer entity) {
if (entity == null) return;
if (deathModularCoord != Vector3.zero && Vector3.Distance(deathModularCoord, entity.transform.position) < 5) NextTick(() => entity.Kill());
}
object OnTurretTarget(AutoTurret turret, ScientistNPC scientistNPC) {
if (turret == null || scientistNPC == null) return null;
NpcConfig npcConfig = _config.NPC.FirstOrDefault(x => x.name == scientistNPC.displayName);
if (npcConfig != null && scientistNPC.isMounted) return true;
return null;
}
void OnExplosiveThrown(BasePlayer player, BaseEntity entity, ThrownWeapon item) {
if (player != null && player.userID.IsSteamId() && stopTime <= 0 && convoyVehicles.Any(x => x != null && x.baseEntity != null && Vector3.Distance(player.transform.position, x.baseEntity.transform.position) < 17.5f)) StopConvoy(player);
}
object CanBradleySpawnNpc(BradleyAPC bradley) {
if (bradley != null && convoySummons.Any(x => x != null && x.net.ID == bradley.net.ID)) return true;
return null;
}
object CanHelicopterSpawnNpc(BaseHelicopter helicopter) {
if (helicopter != null && convoyHeli != null && convoyHeli.baseHelicopter != null && convoyHeli.baseHelicopter.net.ID == helicopter.net.ID) return true;
return null;
}
#region OtherPLugins
void OnCorpsePopulate(BasePlayer entity, NPCPlayerCorpse corpse) {
if (entity == null || corpse == null) return;
if (entity is ScientistNPC) {
NpcConfig npcConfig = _config.NPC.FirstOrDefault(x => x.name == entity.displayName);
if (npcConfig == null) return;
NextTick(() => {
if (corpse == null) return;
ItemContainer container = corpse.containers[0];
if (npcConfig.typeLootTable == 0) {
for (int i = container.itemList.Count - 1; i >= 0; i--) {
Item item = container.itemList[i];
if (npcConfig.wearItems.Any(x => x.shortName == item.info.shortname)) {
item.RemoveFromContainer();
item.Remove();
}
}
if (npcConfig.deleteCorpse && corpse != null && !corpse.IsDestroyed) corpse.Kill();
return;
}
if (npcConfig.typeLootTable == 2 || npcConfig.typeLootTable == 3) {
if (npcConfig.deleteCorpse && !corpse.IsDestroyed) corpse.Kill();
return;
}
for (int i = container.itemList.Count - 1; i >= 0; i--) {
Item item = corpse.containers[0].itemList[i];
item.RemoveFromContainer();
item.Remove();
}
if (npcConfig.typeLootTable == 1 && npcConfig.lootTable.Min > 0) AddToContainer(container, npcConfig.lootTable.Items, UnityEngine.Random.Range(npcConfig.lootTable.Min, npcConfig.lootTable.Max + 1));
if (npcConfig.deleteCorpse && corpse != null && !corpse.IsDestroyed) corpse.Kill();
}
);
}
}
object CanPopulateLoot(LootContainer container) {
if (container == null) return null;
else if (container is HackableLockedCrate && convoyModular != null && convoyModular.crate != null && convoyModular.crate == container) {
if (modularConfig.typeLootTable == 2) return null;
else return true;
}
else if (container.ShortPrefabName == "bradley_crate" && Vector3.Distance(deathBradleyCoord, container.transform.position) < 15f) {
bradleyContainers.Add(container.net.ID);
if (bradleyConfig.typeLootTable == 2) return null;
else return true;
}
else if (container.ShortPrefabName == "heli_crate" && Vector3.Distance(deathHeliCoord, container.transform.position) < 25f) {
heliContainers.Add(container.net.ID);
if (heliConfig.typeLootTable == 2) return null;
else return true;
}
else return null;
}
object CanPopulateLoot(BasePlayer entity, NPCPlayerCorpse corpse) {
if (entity == null || corpse == null || convoyVehicles.Count == 0) return null;
if (entity is ScientistNPC && convoyVehicles.Any(x => x != null && x.scientists.Contains(entity))) {
NpcConfig npcConfig = _config.NPC.FirstOrDefault(x => x.name == entity.name);
if (npcConfig == null) return null;
if (npcConfig.typeLootTable == 2) return null;
else return true;
}
return null;
}
private object OnCustomLootContainer(uint netID) {
if (!active) return null;
if (convoyModular != null && convoyModular.baseEntity != null && !convoyModular.baseEntity.IsDestroyed && convoyModular.crate != null && convoyModular.crate.net.ID == netID) {
if (modularConfig.typeLootTable == 3) return null;
else return true;
}
return null;
}
object CanEntityTakeDamage(BasePlayer victim, HitInfo hitinfo) {
if (victim == null || hitinfo == null || !_config.eventZone.isCreateZonePVP || victim == null || !victim.userID.IsSteamId() || hitinfo == null || !active || doorCloser == null || doorCloser.IsDestroyed) return null;
BasePlayer attacker = hitinfo.InitiatorPlayer;
if (players.Contains(victim) && (attacker == null || (attacker != null && players.Contains(attacker)))) return true;
else return null;
}
object CanEntityTakeDamage(BasicCar victim, HitInfo hitinfo) {
if (victim == null || hitinfo == null || active == false || hitinfo.InitiatorPlayer == null || !hitinfo.InitiatorPlayer.userID.IsSteamId()) return null;
if (convoySummons.Contains(victim)) return true;
else return null;
}
object CanEntityTakeDamage(ModularCar victim, HitInfo hitinfo) {
if (victim == null || hitinfo == null || active == false || hitinfo.InitiatorPlayer == null || !hitinfo.InitiatorPlayer.userID.IsSteamId()) return null;
if (!PveModeAllowAction(hitinfo.InitiatorPlayer)) return false;
if (convoyVehicles.Count > 0 && convoyVehicles.Any(x => x != null && x.baseEntity != null && x.baseEntity.net.ID == victim.net.ID)) return true;
else return null;
}
object CanEntityTakeDamage(BaseVehicleModule baseVehicleModule, HitInfo hitinfo) {
if (baseVehicleModule == null || hitinfo == null || active == false || hitinfo.InitiatorPlayer == null || !hitinfo.InitiatorPlayer.userID.IsSteamId() || baseVehicleModule.Vehicle == null || baseVehicleModule.Vehicle.IsDestroyed) return null;
if (!PveModeAllowAction(hitinfo.InitiatorPlayer)) return false;
if (convoyVehicles.Any(x => x != null && x.baseEntity != null && !x.baseEntity.IsDestroyed && x.baseEntity.net.ID == baseVehicleModule.Vehicle.net.ID)) return true;
else return null;
}
#endregion OtherPLugins
#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("convoystartpersonal")]
void ConsoleStartPersonalCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
if (owners != null) owners.Clear();
foreach (var a in arg.Args) {
ulong id = Convert.ToUInt64(a);
if (id != 0 && id.IsSteamId()) owners.Add(id);
}
if (arg.Args != null && arg.Args.Count() > 0 && _config.convoys.Any(x => x.name == arg.Args[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 Unsubscribes() {
foreach (string hook in subscribeMetods) Unsubscribe(hook);
}
void Subscribes() {
foreach (string hook in subscribeMetods) Subscribe(hook);
}
void CheckZeroCoord() {
foreach (Collider collider in UnityEngine.Physics.OverlapSphere(Vector3.zero, 3f)) {
BaseEntity entity = collider.ToBaseEntity();
if (entity == null) continue;
if (entity.PrefabName.Contains("modular") || entity.PrefabName.Contains("locked")) entity.Kill();
}
}
void UpdateConfig() {
if (_config.version != Version.ToString()) {
if (_config.version == "2.0.0") {
foreach (ConvoySetting convoySetting in _config.convoys) convoySetting.displayName = "Convoy";
}
if (_config.version == "2.0.0" || _config.version == "2.0.1" || _config.version == "2.0.2" || _config.version == "2.0.3" || _config.version == "2.0.4" || _config.version == "2.0.5" || _config.version == "2.0.6" || _config.version == "2.0.7") {
foreach (NpcConfig npcConfig in _config.NPC) npcConfig.kit = "";
}
if (_config.version == "2.0.0" || _config.version == "2.0.1" || _config.version == "2.0.2" || _config.version == "2.0.3" || _config.version == "2.0.4" || _config.version == "2.0.5" || _config.version == "2.0.6" || _config.version == "2.0.7" || _config.version == "2.0.8" || _config.version == "2.0.9") {
_config.autoEvent = true;
foreach (string name in trains) if (!_config.barriers.Contains(name)) _config.barriers.Add(name);
}
_config.version = Version.ToString();
SaveConfig();
}
}
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;
}
if (pathCount == 0) {
PrintError("No road detected");
NextTick(() => Server.Command($"o.unload {Name}"));
return;
}
destroyTime = ins._config.preFinishTime;
if (presetName != "") convoySetting = _config.convoys.Where(x => x.name == presetName).FirstOrDefault();
else if (_config.convoys.Any(x => x.chance > 0 && x.on)) {
while (convoySetting == null) {
foreach (ConvoySetting setting in _config.convoys) {
if (setting.on && 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 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 || convoyVehicle.baseEntity == null || convoyVehicle.baseEntity.IsDestroyed) continue;
Transform transform = convoyVehicle.baseEntity.transform;
convoyVehicle.rigidbody.velocity = Vector3.zero;
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 (_config.pveMode.pve && plugins.Exists("PveMode")) PveMode.Call("EventRemovePveMode", Name, true);
EconomyManager.SendBalance();
if (owners != null) owners.Clear();
if (unload) Server.Command($"o.reload {Name}");
}
void ConvoyVehicleDie(BaseEntity entity) {
if (entity == null) return;
ConvoyVehicle convoyVehicle = convoyVehicles.FirstOrDefault(x => x != null && x.baseEntity != null && !x.baseEntity.IsDestroyed && x.baseEntity.net.ID == entity.net.ID);
if (convoyVehicle != null) {
if (convoyVehicle is ConvoyBradley) {
deathBradleyCoord = entity.transform.position;
if (_config.pveMode.pve && plugins.Exists("PveMode")) timer.In(1f, () => {
PveMode.Call("EventAddCrates", Name, bradleyContainers);
bradleyContainers.Clear();
}
);
}
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 || !convoyVehicles.Any(x => x != null && x.baseEntity == entity)) return null;
if (info == null || info.InitiatorPlayer == null) return true;
BasePlayer initiator = info.InitiatorPlayer;
if (!initiator.userID.IsSteamId()) return true;
if (info.ProjectileDistance >= _config.maxDamageDistance) {
Alert(initiator, GetMessage("Distance", initiator.UserIDString, _config.prefics));
return true;
}
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 (initiator != null) AlertToAllPlayers("ConvoyAttacked", _config.prefics, initiator.displayName);
if (convoyModular != null) timer.In(2f, () => CreateEventZone(convoyModular.baseEntity.transform.position - new Vector3(0f, 0.5f, 0f)));
}
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.C
// ... [Code preview truncated due to length. Full source in attached file] ...