C#:
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.CaravanExtensionMethods;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Networking;
using static BaseAIBrain;
namespace Oxide.Plugins {
[Info("Caravan", "Adem", "1.3.4")]
public class Caravan : RustPlugin {
#region Variables
private const bool En = false;
private static Caravan _ins;
[PluginReference]
Plugin NpcSpawn, LootManager, PveMode, GUIAnnouncements, DiscordMessages, Notify, Economics, ServerRewards, IQEconomic, DynamicPVP, ArmoredTrain, Convoy;
private readonly HashSet<string> _subscribeMethods = new HashSet<string> {
"OnEntityTakeDamage", "OnPlayerDeath", "OnEntityDeath", "OnEntityKill", "OnCorpsePopulate", "CanMountEntity", "CanDismountEntity", "OnHorseLead", "CanLootEntity", "CanHackCrate", "OnLootEntity", "OnLootEntityEnd", "OnSamSiteTarget", "CanEntityBeTargeted", "CanEntityTakeDamage", "OnCustomNpcTarget", "CanPopulateLoot", "OnCustomLootContainer", "OnCustomLootNPC", "SetOwnerPveMode", "ClearOwnerPveMode", "OnPlayerViolation", "OnEntityEnter"
}
;
private EventController _eventController;
private ProtectionProperties _protection;
#endregion Variables
#region Hooks
private void Init() {
Unsubscribes();
}
private void OnServerInitialized() {
_ins = this;
if (!NpcSpawnManager.IsNpcSpawnReady() || !LootManagerBridge.IsLootManagerReady()) return;
_protection = ScriptableObject.CreateInstance<ProtectionProperties>();
_protection.Add(1);
UpdateConfig();
LoadDefaultMessages();
GuiManager.LoadImages();
PathManager.StartCachingRouts();
EventLauncher.AutoStartEvent();
LootManagerBridge.RegisterPresets();
NextTick(LootManagerBridge.CheckLootManagerTables);
}
private void Unload() {
EventLauncher.StopEvent(true);
PathManager.OnPluginUnloaded();
_ins = null;
}
private object OnEntityTakeDamage(RidableHorse horse, HitInfo info) {
if (!horse.IsExists() || info == null || horse.net == null || info.Initiator == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByHorseNetID(horse.net.ID.Value);
Horseman horseman = Horseman.GetHorsemanByNetID(horse.net.ID.Value);
if (horseCarriage != null || horseman != null) {
if (!info.InitiatorPlayer.IsRealPlayer()) return true;
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, horse, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) _eventController.OnEventAttacked(info.InitiatorPlayer);
else return true;
}
return null;
}
private object OnEntityTakeDamage(ModularCar modularCar, HitInfo info) {
if (!modularCar.IsExists() || info == null || modularCar.net == null || info.Initiator == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByModularCarNetID(modularCar.net.ID.Value);
if (horseCarriage != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, modularCar, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) {
_eventController.OnEventAttacked(info.InitiatorPlayer);
}
else return true;
}
else return true;
}
return null;
}
private object OnEntityTakeDamage(BaseVehicleModule baseVehicleModule, HitInfo info) {
if (!baseVehicleModule.IsExists() || info == null || baseVehicleModule.net == null || info.Initiator == null) return null;
BaseModularVehicle modularCar = baseVehicleModule.Vehicle;
if (modularCar == null || modularCar.net == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByModularCarNetID(modularCar.net.ID.Value);
if (horseCarriage != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, modularCar, shouldSendMessages : true)) {
_eventController.OnEventAttacked(info.InitiatorPlayer);
}
else return true;
}
else return true;
}
return null;
}
private object OnEntityTakeDamage(HotAirBalloon hotAirBalloon, HitInfo info) {
if (!hotAirBalloon.IsExists() || info == null || hotAirBalloon.net == null || info.Initiator == null) return null;
AirBalloon airBalloon = AirBalloon.GetAirBalloonByNetID(hotAirBalloon.net.ID.Value);
if (airBalloon != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, hotAirBalloon, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) {
_eventController.OnEventAttacked(info.InitiatorPlayer);
return null;
}
else return true;
}
SamSite samSite = info.Initiator as SamSite;
if (samSite != null) {
if (samSite.ShortPrefabName == "sam_static") return true;
if (_ins._config.DamageConfig.IsPlayerSamSiteCanAttackEvent) return null;
}
return true;
}
return null;
}
private object OnEntityTakeDamage(ScientistNPC scientistNpc, HitInfo info) {
if (!scientistNpc.IsExists() || info == null || scientistNpc.net == null || !info.InitiatorPlayer.IsRealPlayer()) return null;
if (!_eventController.IsEventNpc(scientistNpc.net.ID.Value)) return null;
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, scientistNpc, shouldSendMessages : true)) {
if (scientistNpc.isMounted) info.damageTypes.ScaleAll(10);
_eventController.OnEventAttacked(info.InitiatorPlayer);
}
else return true;
}
return null;
}
private void OnPlayerDeath(BasePlayer player, HitInfo info) {
if (player == null || info == null) return;
if (ZoneController.IsPlayerInZone(player.userID)) ZoneController.OnPlayerLeaveZone(player);
}
private void OnEntityDeath(ScientistNPC scientistNpc, HitInfo info) {
if (scientistNpc == null || info == null || scientistNpc.net == null) return;
if (info.InitiatorPlayer.IsRealPlayer() && NpcSpawnManager.IsEventNpc(scientistNpc)) {
Horseman horseman = Horseman.GetHorsemanByNpcNetId(scientistNpc.net.ID.Value);
if (horseman != null) EconomyManager.AddBalance(info.InitiatorPlayer.userID, _config.EconomicsConfig.HorsemanPoint);
else EconomyManager.AddBalance(info.InitiatorPlayer.userID, _config.EconomicsConfig.NpcPoint);
}
}
private void OnEntityDeath(RidableHorse horse, HitInfo info) {
if (horse == null || info == null || horse.net == null) return;
if (info.InitiatorPlayer.IsRealPlayer()) {
Horseman horseman = Horseman.GetHorsemanByHorseNetId(horse.net.ID.Value);
if (horseman != null) EconomyManager.AddBalance(info.InitiatorPlayer.userID, _config.EconomicsConfig.HorsemanPoint);
}
}
private void OnEntityKill(RidableHorse horse) {
if (!horse.IsExists() || horse.net == null) return;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByHorseNetID(horse.net.ID.Value);
if (horseCarriage != null) _ins.NextTick(() => _eventController.EventPassingCheck());
}
private void OnCorpsePopulate(ScientistNPC scientistNpc, NPCPlayerCorpse corpse) {
if (scientistNpc == null || corpse == null) return;
NpcConfig npcConfig = NpcSpawnManager.GetNpcConfigByDisplayName(scientistNpc.displayName);
if (npcConfig == null || !npcConfig.DeleteCorpse) return;
corpse.Invoke(() => {
if (corpse.IsExists()) corpse.Kill();
}
, 0.2f);
}
private object CanMountEntity(BasePlayer player, BaseMountable baseMountable) {
if (!player.IsRealPlayer() || baseMountable == null) return null;
BaseVehicle baseVehicle = baseMountable.VehicleParent();
if (!baseVehicle.IsExists() || baseVehicle.net == null) return null;
if (baseVehicle is RidableHorse) {
Horseman horseman = Horseman.GetHorsemanByNetID(baseVehicle.net.ID.Value);
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByHorseNetID(baseVehicle.net.ID.Value);
if (horseCarriage != null || horseman != null) return true;
}
return null;
}
private object CanDismountEntity(BasePlayer player, BaseMountable baseMountable) {
if (baseMountable == null || player == null || player.userID.IsSteamId()) return null;
BaseVehicle baseVehicle = baseMountable.VehicleParent();
if (!baseVehicle.IsExists() || baseVehicle.net == null) return null;
if (baseVehicle is RidableHorse) {
Horseman horseman = Horseman.GetHorsemanByNetID(baseVehicle.net.ID.Value);
if (horseman != null) return true;
}
return null;
}
private object OnHorseLead(RidableHorse horse, BasePlayer player) {
if (!horse.IsExists() || horse.net == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByHorseNetID(horse.net.ID.Value);
Horseman horseman = Horseman.GetHorsemanByNetID(horse.net.ID.Value);
if (horseCarriage != null || horseman != null) return true;
return null;
}
private object CanLootEntity(BasePlayer player, LootContainer lootContainer) {
return CanPlayerLootContainer(player, lootContainer);
}
private object CanLootEntity(BasePlayer player, StorageContainer storageContainer) {
return CanPlayerLootContainer(player, storageContainer);
}
private object CanLootEntity(BasePlayer player, Fridge fridge) {
return CanPlayerLootContainer(player, fridge);
}
private object CanPlayerLootContainer(BasePlayer player, BaseEntity container) {
if (player == null || container == null || container.net == null) return null;
if (_eventController.IsEventCrate(container.net.ID.Value)) {
_eventController.MakeCaravanAggressive();
if (!_ins._eventController.IsPlayerCanLootCaravan(player, true)) return true;
}
return null;
}
private object CanHackCrate(BasePlayer player, HackableLockedCrate crate) {
if (player == null || crate == null || crate.net == null) return null;
if (_eventController.IsEventCrate(crate.net.ID.Value)) {
_eventController.MakeCaravanAggressive();
if (!_ins._eventController.IsPlayerCanLootCaravan(player, true)) return true;
}
return null;
}
private void OnLootEntity(BasePlayer player, LootContainer lootContainer) {
if (player == null || lootContainer == null || lootContainer.net == null) return;
if (_eventController.IsEventCrate(lootContainer.net.ID.Value)) _eventController.OnEventCrateLooted(lootContainer, player.userID);
}
private void OnLootEntity(BasePlayer player, StorageContainer storageContainer) {
if (player == null || storageContainer == null || storageContainer.net == null) return;
if (_eventController.IsEventCrate(storageContainer.net.ID.Value)) _eventController.OnEventCrateLooted(storageContainer, player.userID);
}
private void OnLootEntity(BasePlayer player, Fridge fridge) {
if (player == null || fridge == null || fridge.net == null) return;
if (_eventController.IsEventCrate(fridge.net.ID.Value)) _eventController.OnEventCrateLooted(fridge, player.userID);
}
private void OnLootEntityEnd(BasePlayer player, StorageContainer storageContainer) {
if (storageContainer == null || storageContainer.net == null || !player.IsRealPlayer()) return;
if (storageContainer is not LootContainer && _eventController.IsEventCrate(storageContainer.net.ID.Value)) if (storageContainer.inventory.IsEmpty()) storageContainer.Kill();
}
private void OnLootEntityEnd(BasePlayer player, Fridge fridge) {
if (fridge == null || fridge.net == null || !player.IsRealPlayer()) return;
if (_eventController.IsEventCrate(fridge.net.ID.Value)) if (fridge.inventory.IsEmpty()) fridge.Kill();
}
private object OnSamSiteTarget(SamSite samSite, HotAirBalloon hotAirBalloon) {
if (samSite == null || hotAirBalloon == null || hotAirBalloon.net == null) return null;
AirBalloon airBalloon = AirBalloon.GetAirBalloonByNetID(hotAirBalloon.net.ID.Value);
if (airBalloon != null) {
if (samSite.ShortPrefabName == "sam_static") return true;
else if (!_ins._config.DamageConfig.IsPlayerSamSiteCanAttackEvent) return true;
}
return null;
}
private object OnPlayerViolation(BasePlayer player, AntiHackType type, float amount) {
if (player == null) return null;
if (type == AntiHackType.FlyHack && _eventController.IsCaravanLooted()) return true;
return null;
}
private object OnEntityEnter(TargetTrigger trigger, ScientistNPC scientistNpc) {
if (trigger == null || scientistNpc == null || scientistNpc.net == null) return null;
AutoTurret autoTurret = trigger.GetComponentInParent<AutoTurret>();
if (autoTurret == null || autoTurret.net == null) return null;
if (!_ins._eventController.IsEventNpc(scientistNpc.net.ID.Value)) return null;
if (scientistNpc.isMounted || !_config.BehaviorConfig.IsPlayerTurretEnable) return true;
return null;
}
#region OtherPlugins
private void OnLootManagerInitialized() {
LootManagerBridge.RegisterPresets();
}
private object CanEntityBeTargeted(HotAirBalloon hotAirBalloon, SamSite samSite) {
if (samSite == null || hotAirBalloon == null || hotAirBalloon.net == null) return null;
AirBalloon airBalloon = AirBalloon.GetAirBalloonByNetID(hotAirBalloon.net.ID.Value);
if (airBalloon != null) {
if (samSite.ShortPrefabName == "sam_static") return false;
else if (_ins._config.DamageConfig.IsPlayerSamSiteCanAttackEvent) return true;
else return false;
}
return null;
}
private object CanEntityTakeDamage(RidableHorse horse, HitInfo info) {
if (_eventController == null || info == null || !horse.IsExists() || horse.net == null || info.Initiator == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByHorseNetID(horse.net.ID.Value);
Horseman horseman = Horseman.GetHorsemanByNetID(horse.net.ID.Value);
if (horseCarriage != null || horseman != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, horse, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) return true;
else return false;
}
else return false;
}
return null;
}
private object CanEntityTakeDamage(ModularCar modularCar, HitInfo info) {
if (_eventController == null || info == null || !modularCar.IsExists() || modularCar.net == null || info.Initiator == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByModularCarNetID(modularCar.net.ID.Value);
if (horseCarriage != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, modularCar, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) return true;
else return false;
}
else return false;
}
return null;
}
private object CanEntityTakeDamage(BaseVehicleModule baseVehicleModule, HitInfo info) {
if (_eventController == null || info == null || !baseVehicleModule.IsExists() || baseVehicleModule.net == null || info.Initiator == null) return null;
BaseModularVehicle modularCar = baseVehicleModule.Vehicle;
if (modularCar == null || modularCar.net == null) return null;
HorseCarriage horseCarriage = HorseCarriage.GetCarriageByModularCarNetID(modularCar.net.ID.Value);
if (horseCarriage != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, modularCar, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) return true;
else return false;
}
else return false;
}
return null;
}
private object CanEntityTakeDamage(HotAirBalloon hotAirBalloon, HitInfo info) {
if (_eventController == null || info == null || !hotAirBalloon.IsExists() || hotAirBalloon.net == null || info.Initiator == null) return null;
AirBalloon airBalloon = AirBalloon.GetAirBalloonByNetID(hotAirBalloon.net.ID.Value);
if (airBalloon != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, hotAirBalloon, shouldSendMessages : true) && !PveModeManager.IsPveModeBlockAction(info.InitiatorPlayer)) return true;
else return false;
}
SamSite samSite = info.Initiator as SamSite;
if (samSite != null) {
if (samSite.ShortPrefabName == "sam_static") return false;
else if (_ins._config.DamageConfig.IsPlayerSamSiteCanAttackEvent) return true;
}
else return false;
}
return null;
}
private object CanEntityTakeDamage(ScientistNPC scientistNpc, HitInfo info) {
if (_eventController == null || info == null || !scientistNpc.IsExists() || scientistNpc.net == null || info.Initiator == null) return null;
NpcConfig npcConfig = NpcSpawnManager.GetNpcConfigByDisplayName(scientistNpc.displayName);
if (npcConfig != null) {
if (info.InitiatorPlayer.IsRealPlayer()) {
if (_eventController.IsPlayerCanDealDamage(info.InitiatorPlayer, scientistNpc, shouldSendMessages : true)) return null;
return false;
}
}
return null;
}
private object CanEntityTakeDamage(BasePlayer victim, HitInfo hitInfo) {
if (_eventController == null || hitInfo == null || !victim.IsRealPlayer()) return null;
if (_config.ZoneConfig.IsPvpZone && !_config.SupportedPluginsConfig.PveMode.Enable) {
if (hitInfo.InitiatorPlayer.IsRealPlayer() && ZoneController.IsPlayerInZone(hitInfo.InitiatorPlayer.userID) && ZoneController.IsPlayerInZone(victim.userID)) return true;
}
return null;
}
private object OnCustomNpcTarget(ScientistNPC scientistNpc, BasePlayer player) {
if (scientistNpc == null) return null;
if (_ins._config.BehaviorConfig.AggressiveTime < 0) return null;
NpcConfig npcConfig = NpcSpawnManager.GetNpcConfigByDisplayName(scientistNpc.displayName);
if (npcConfig != null) {
if (_eventController.IsCaravanAggressive()) return null;
return false;
}
return null;
}
private void SetOwnerPveMode(string shortname, BasePlayer player) {
if (_eventController == null || string.IsNullOrEmpty(shortname) || shortname != Name || !player.IsRealPlayer()) return;
if (shortname == Name) PveModeManager.OnNewOwnerSet(player);
}
private void ClearOwnerPveMode(string shortname) {
if (_eventController == null || string.IsNullOrEmpty(shortname)) return;
if (shortname == Name) PveModeManager.OnOwnerDeleted();
}
#endregion OtherPlugins
#endregion Hooks
#region Commands
[ChatCommand("caravanstart")]
private void ChatStartEventCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg == null || arg.Length == 0) EventLauncher.DelayStartEvent(false, player);
else {
string eventPresetName = arg[0];
EventLauncher.DelayStartEvent(false, player, eventPresetName);
}
}
[ConsoleCommand("caravanstart")]
private void ConsoleStartEventCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
if (arg == null || arg.Args == null || arg.Args.Length == 0) {
EventLauncher.DelayStartEvent();
}
else {
string eventPresetName = arg.Args[0];
EventLauncher.DelayStartEvent(presetName : eventPresetName);
}
}
[ChatCommand("caravanstop")]
private void ChatStopEventCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
EventLauncher.StopEvent();
}
[ConsoleCommand("caravanstop")]
private void ConsoleStopEventCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
EventLauncher.StopEvent();
}
[ChatCommand("caravanpathstart")]
private void ChatPathStartCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
PathRecorder.StartRecordingRoute(player);
}
[ChatCommand("caravanpathsave")]
private void ChatPathSaveCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
if (arg.Length == 0) {
NotifyManager.SendMessageToPlayer(player, "CustomRouteDescription", _ins._config.NotifyConfig.Prefix);
return;
}
string pathName = arg[0];
PathRecorder.TrySaveRoute(player.userID, pathName);
}
[ChatCommand("caravanpathcancel")]
private void ChatPathCancelCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
PathRecorder.TryCancelRoute(player.userID);
}
[ChatCommand("showroute")]
private void ChatShowRouteCommand(BasePlayer player, string command, string[] arg) {
PathManager.DrawPath(PathManager.CurrentPath, player);
}
[ConsoleCommand("savecaravancart")]
private void ConsoleSaveCustomWagonCommand(ConsoleSystem.Arg arg) {
if (arg.Player() != null) return;
string wagonShortPrefabName = arg.Args[0];
CarCustomizer.MapSaver.CreateOrAddNewWagonToData(wagonShortPrefabName);
}
[ChatCommand("caravanroadblock")]
private void ChatRoadBlockCommand(BasePlayer player, string command, string[] arg) {
if (!player.IsAdmin) return;
PathList blockRoad = TerrainMeta.Path.Roads.FirstOrDefault(x => x.Path.Points.Any(y => Vector3.Distance(player.transform.position, y) < 10));
if (blockRoad == null) {
NotifyManager.SendMessageToPlayer(player, $"{_config.NotifyConfig.Prefix} Road <color=#ce3f27>not found</color>. Step onto the required road and enter the command again.");
return;
}
int index = TerrainMeta.Path.Roads.IndexOf(blockRoad);
if (!_config.PathConfig.BlockRoads.Add(index)) {
NotifyManager.SendMessageToPlayer(player, $"{_config.NotifyConfig.Prefix} The road is already <color=#ce3f27>blocked</color>");
return;
}
SaveConfig();
NotifyManager.SendMessageToPlayer(player, $"{_config.NotifyConfig.Prefix} The road with the index <color=#738d43>{index}</color> is <color=#ce3f27>blocked</color>");
}
#endregion Commands
#region Methods
private void UpdateConfig() {
if (IsFrontierMap()) {
List<string> frontierMapRoutesNames = new List<string> {
"Frontier_1", "Frontier_2", "Frontier_3", "Frontier_4"
}
;
if (_config.PathConfig.PathType != 2) {
PrintError("There are no roads on this map! The plugin can only work with custom routes!\n1. Upload the data files that come with the map to the oxide/data/Caravan/Custom routes folder \n2. Change 'Type of caravan routes' to custom in config");
_ins.NextTick(() => _ins.Server.Command($"o.unload {_ins.Name}"));
}
else if (!_config.PathConfig.CustomPathConfig.CustomRoutesPresets.Any(x => x.Contains("Frontier"))) foreach (string name in frontierMapRoutesNames) if (!_config.PathConfig.CustomPathConfig.CustomRoutesPresets.Contains(name)) _config.PathConfig.CustomPathConfig.CustomRoutesPresets.Add(name);
}
if (_config.Version != Version) {
if (_config.Version.Minor == 2) {
if (_config.Version.Patch <= 6) _config.BehaviorConfig.IsPlayerTurretEnable = true;
if (_config.Version.Patch <= 9) {
NextTick(() => {
LootManagerBridge.SendAllLootTablesToLootManager();
SaveConfig();
}
);
}
_config.Version = new VersionNumber(1, 3, 0);
}
_config.Version = Version;
}
SaveConfig();
}
private static bool IsFrontierMap() {
return BaseNetworkable.serverEntities.OfType<RANDSwitch>().Any(x => x != null && x.transform != null && Mathf.Approximately(x.transform.position.x + x.transform.position.y + x.transform.position.z, 557));
}
private void Unsubscribes() {
foreach (string hook in _subscribeMethods) Unsubscribe(hook);
}
private void Subscribes() {
foreach (string hook in _subscribeMethods) Subscribe(hook);
}
private static void Debug(params object[] arg) {
string result = "";
foreach (object obj in arg) if (obj != null) result += obj.ToString() + " ";
_ins.Puts(result);
}
#endregion Methods
#region Classes
private static class LootManagerBridge {
public static bool IsLootManagerReady() {
if (!_ins.plugins.Exists("LootManager")) {
_ins.PrintError("LootManager plugin doesn`t exist! Please install it: https://codefling.com/adem");
_ins.NextTick(() => Interface.Oxide.UnloadPlugin(_ins.Name));
return false;
}
return true;
}
public static void SendAllLootTablesToLootManager() {
_ins.Puts("The transfer of loot tables to the LootManager plugin has started!");
if (_ins._config.NpcConfigs.Any(x => x.LootTableConfig == null) || _ins._config.CrateConfigs.Any(x => x.LootTableConfig == null)) {
_ins.PrintError("Failed to transfer loot tables. Configuration is corrupted!");
_ins.NextTick(() => Interface.Oxide.UnloadPlugin(_ins.Name));
return;
}
_ins.PrintWarning($"A backup of the config named '{_ins.Name}_Backup.json' has been created!");
_ins.Config.WriteObject(_ins._config, filename : _ins.Config.Filename.Replace(".json", "_Backup.json"));
foreach (NpcConfig npcConfig in _ins._config.NpcConfigs) {
string lootTableName = GetLootManagerPresetName(npcConfig.LootTableConfig, npcConfig.PresetName, false, npcConfig.PresetName);
npcConfig.LootManagerPreset = lootTableName;
npcConfig.LootTableConfig = null;
}
foreach (CrateConfig crateConfig in _ins._config.CrateConfigs) {
string lootTableName = GetLootManagerPresetName(crateConfig.LootTableConfig, crateConfig.PresetName, false, crateConfig.PresetName);
crateConfig.LootManagerPreset = lootTableName;
crateConfig.LootTableConfig = null;
}
_ins.Puts("The transfer of loot tables has been successfully completed.");
}
private static string GetLootManagerPresetName(BaseLootTableConfig baseLootTableConfig, string presetName, bool returnSame, string keyWord) {
if (IsDefaultLootTable(baseLootTableConfig)) return string.Empty;
HashSet<string> plugins = new HashSet<string> {
_ins.Name
}
;
JObject jObject = GetLootTableObject(baseLootTableConfig);
presetName = (string)_ins.LootManager.Call("TryAddLootTable", presetName, _ins.Name, jObject, returnSame, plugins, keyWord);
return presetName;
}
private static bool IsDefaultLootTable(BaseLootTableConfig baseLootTableConfig) {
if (baseLootTableConfig is LootTableConfig lootTableConfig) {
if (lootTableConfig.IsAlphaLoot || lootTableConfig.IsCustomLoot || lootTableConfig.ClearDefaultItemList) return false;
}
return !baseLootTableConfig.RandomItemsConfig.IsEnable && !baseLootTableConfig.PrefabConfigs.IsEnable;
}
private static JObject GetLootTableObject(BaseLootTableConfig baseLootTableConfig) {
bool clearDefaultItems = false;
bool isAlphaLoot = false;
string alphaLootPreset = string.Empty;
bool isCustomLoot = false;
string customLootPreset = string.Empty;
string lootTablePluginPreset = string.Empty;
if (baseLootTableConfig is LootTableConfig lootTableConfig) {
clearDefaultItems = lootTableConfig.ClearDefaultItemList;
isAlphaLoot = lootTableConfig.IsAlphaLoot;
isCustomLoot = lootTableConfig.IsCustomLoot;
}
return new JObject {
["Description"]
= _ins.Name, ["ClearDefaultItems"] = clearDefaultItems, ["IsAlphaLoot"] = isAlphaLoot, ["AlphaLootPreset"] = alphaLootPreset, ["IsCustomLoot"] = isCustomLoot, ["CustomLootPreset"] = customLootPreset, ["IsLootTablePlugin"] = false, ["LootTablePluginLootPreset"] = lootTablePluginPreset, ["UseItemList"] = baseLootTableConfig.RandomItemsConfig.IsEnable, ["UseMinMaxForItems"] = true, ["MinItemsAmount"] = baseLootTableConfig.RandomItemsConfig.MinItemsAmount, ["MaxItemsAmount"] = baseLootTableConfig.RandomItemsConfig.MaxItemsAmount, ["Items"] = !baseLootTableConfig.RandomItemsConfig.IsEnable ? new JArray() : new JArray {
baseLootTableConfig.RandomItemsConfig.Items.Select(x => new JObject {
["ShortName"]
= x.Shortname, ["ItemId"] = 0, ["CustomDisplayName"] = string.IsNullOrEmpty(x.Name) ? string.Empty : x.Name, ["DefaultDisplayName"] = string.Empty, ["OwnerDisplayName"] = string.Empty, ["Skin"] = x.Skin, ["IsBluePrint"] = x.IsBlueprint, ["Genomes"] = x.Genomes != null && x.Genomes.Count > 0 ? x.Genomes[0] : string.Empty, ["MinAmount"] = x.MinAmount, ["MaxAmount"] = x.MaxAmount, ["Chance"] = x.Chance
}
)
}
, ["UsePrefabList"] = baseLootTableConfig.PrefabConfigs.IsEnable, ["MinPrefabsAmount"] = 1, ["MaxPrefabsAmount"] = 1, ["Prefabs"] = !baseLootTableConfig.PrefabConfigs.IsEnable ? new JArray() : new JArray {
baseLootTableConfig.PrefabConfigs.Prefabs.Select(x => new JObject {
["PrefabName"]
= x.PrefabName, ["MinAmount"] = x.MinLootScale, ["MaxAmount"] = x.MaxLootScale, ["Chance"] = 10f,
}
)
}
}
;
}
public static void CheckLootManagerTables() {
if (!_ins.plugins.Exists("LootManager")) {
_ins.PrintError("LootManager plugin doesn`t exist! Please install it: https://codefling.com/adem");
_ins.NextTick(() => Interface.Oxide.UnloadPlugin(_ins.Name));
return;
}
HashSet<string> lootTableNames = new HashSet<string>();
foreach (NpcConfig npcConfig in _ins._config.NpcConfigs) if (!string.IsNullOrEmpty(npcConfig.LootManagerPreset)) lootTableNames.Add(npcConfig.LootManagerPreset);
foreach (CrateConfig crateConfig in _ins._config.CrateConfigs) if (!string.IsNullOrEmpty(crateConfig.LootManagerPreset)) lootTableNames.Add(crateConfig.LootManagerPreset);
HashSet<string> missingLootTables = (HashSet<string>)_ins.LootManager.Call("GetMissingLootTables", lootTableNames);
if (missingLootTables.Count > 0) {
foreach (string missingLootTable in missingLootTables) _ins.PrintWarning($"Loot table \"{missingLootTable}\" does not exist in LootManager. Use an existing table or leave the field empty!");
_ins.PrintError("If you have just installed the plugin, move the contents of the data folder from the file you downloaded from the website into the oxide/data folder on your server!");
}
}
public static void RegisterPresets() {
foreach (CrateConfig crateConfig in _ins._config.CrateConfigs) {
if (string.IsNullOrEmpty(crateConfig.LootManagerPreset)) continue;
HashSet<EventConfig> usages = new HashSet<EventConfig>();
foreach (EventConfig eventConfig in _ins._config.EventConfigs) {
foreach (CaravanVehicleConfig vehicleCfg in eventConfig.VehicleOrder) {
CarriageConfig carriageConfig = _ins._config.CarriageConfigs.FirstOrDefault(x => x.PresetName == vehicleCfg.PresetName);
if (carriageConfig == null) continue;
if (carriageConfig.CrateLocations.Any(x => x.PresetName == crateConfig.PresetName)) {
usages.Add(eventConfig);
break;
}
}
}
RegisterUsage(crateConfig.LootManagerPreset, usages);
}
foreach (NpcConfig npcConfig in _ins._config.NpcConfigs) {
if (string.IsNullOrEmpty(npcConfig.LootManagerPreset)) continue;
HashSet<EventConfig> usages = new HashSet<EventConfig>();
foreach (EventConfig eventConfig in _ins._config.EventConfigs) {
bool added = false;
foreach (CaravanVehicleConfig vehicleCfg in eventConfig.VehicleOrder) {
CarriageConfig carriageConfig = _ins._config.CarriageConfigs.FirstOrDefault(x => x.PresetName == vehicleCfg.PresetName);
if (carriageConfig != null && carriageConfig.Npcs.Any(x => x.PresetName == npcConfig.PresetName)) {
added = true;
break;
}
if (!string.IsNullOrEmpty(vehicleCfg.BalloonPresetName)) {
AirBalloonConfig balloonConfig = _ins._config.AirBalloonConfigs.FirstOrDefault(x => x.PresetName == vehicleCfg.BalloonPresetName);
if (balloonConfig != null && balloonConfig.NpcLocations.Any(x => x.PresetName == npcConfig.PresetName)) {
added = true;
break;
}
}
foreach (string guardPreset in vehicleCfg.GuardEntityPresets) {
if (guardPreset == npcConfig.PresetName) {
added = true;
break;
}
HorsemanConfig horsemanConfig = _ins._config.HorsemanConfigs.FirstOrDefault(x => x.PresetName == guardPreset);
if (horsemanConfig != null && horsemanConfig.FrontNpcPresetName == npcConfig.PresetName) {
added = true;
break;
}
}
if (added) break;
}
if (added) usages.Add(eventConfig);
}
RegisterUsage(npcConfig.LootManagerPreset, usages);
}
}
private static void RegisterUsage(string lootManagerPreset, HashSet<EventConfig> usages) {
if (string.IsNullOrEmpty(lootManagerPreset)) return;
if (usages != null && usages.Count > 0) {
foreach (EventConfig eventConfig in usages) _ins.LootManager.Call("RegisterPresetUsage", lootManagerPreset, _ins.Name, eventConfig.PresetName);
return;
}
_ins.LootManager.Call("RegisterPresetUsage", lootManagerPreset, _ins.Name, string.Empty);
}
internal static void AddNpc(ScientistNPC npc, string lootTablePreset) {
if (npc == null || npc.net == null) return;
_ins.LootManager.Call("AddNpc", npc.net.ID.Value, lootTablePreset);
}
internal static void AddCrate(BaseEntity entity, string lootTablePreset) {
if (entity == null || entity.net == null) return;
_ins.LootManager.Call("AddCrate", entity, lootTablePreset);
}
}
private static class EventLauncher {
private static Coroutine _autoEventCoroutine;
private static Coroutine _delayedEventStartCoroutine;
public static bool IsEventActive() {
return _ins != null && _ins._eventController != null;
}
public static void AutoStartEvent() {
if (!_ins._config.MainConfig.IsAutoEvent) return;
if (_autoEventCoroutine != null) ServerMgr.Instance.StopCoroutine(_autoEventCoroutine);
_autoEventCoroutine = ServerMgr.Instance.StartCoroutine(AutoEventCoroutine());
}
public static void DelayStartEvent(bool isAutoActivated = false, BasePlayer activator = null, string presetName = "") {
if (IsEventActive() || _delayedEventStartCoroutine != null) {
NotifyManager.PrintError(activator, "EventActive_Exeption");
return;
}
if (_autoEventCoroutine != null) ServerMgr.Instance.StopCoroutine(_autoEventCoroutine);
EventConfig eventConfig = DefineEventConfig(presetName);
if (eventConfig == null) {
NotifyManager.PrintError(activator, "ConfigurationNotFound_Exeption");
StopEvent();
return;
}
PathManager.GenerateNewPath();
if (PathManager.CurrentPath == null) return;
_delayedEventStartCoroutine = ServerMgr.Instance.StartCoroutine(DelayedStartEventCoroutine(eventConfig));
if (!isAutoActivated) NotifyManager.PrintInfoMessage(activator, "SuccessfullyLaunched");
}
private static IEnumerator AutoEventCoroutine() {
yield return CoroutineEx.waitForSeconds(UnityEngine.Random.Range(_ins._config.MainConfig.MinTimeBetweenEvents, _ins._config.MainConfig.MaxTimeBetweenEvents));
DelayStartEvent(true);
}
private static IEnumerator DelayedStartEventCoroutine(EventConfig eventConfig) {
if (_ins._config.MainConfig.PreStartTime > 0) NotifyManager.SendMessageToAll("PreStart", _ins._config.NotifyConfig.Prefix, _ins._config.MainConfig.PreStartTime);
yield return CoroutineEx.waitForSeconds(_ins._config.MainConfig.PreStartTime);
if (PathManager.CurrentPath != null) StartEvent(eventConfig);
else StopEvent();
}
private static void StartEvent(EventConfig eventConfig) {
GameObject gameObject = new GameObject();
_ins._eventController = gameObject.AddComponent<EventController>();
_ins._eventController.Init(eventConfig);
if (_ins._config.MainConfig.EnableStartStopLogs) NotifyManager.PrintLogMessage("EventStart_Log", eventConfig.PresetName);
Interface.CallHook("OnCaravanStart");
}
private static EventConfig DefineEventConfig(string eventPresetName = "") {
if (eventPresetName != "") return _ins._config.EventConfigs.FirstOrDefault(x => x.PresetName == eventPresetName);
HashSet<EventConfig> suitableEventConfigs = _ins._config.EventConfigs.Where(x => x.Chance > 0 && x.IsAutoStart && IsEventConfigSuitableByTime(x));
if (suitableEventConfigs == null || suitableEventConfigs.Count == 0) return null;
float sumChance = 0;
foreach (EventConfig eventConfig in suitableEventConfigs) sumChance += eventConfig.Chance;
float random = UnityEngine.Random.Range(0, sumChance);
foreach (EventConfig eventConfig in suitableEventConfigs) {
random -= eventConfig.Chance;
if (random <= 0) return eventConfig;
}
return null;
}
private static bool IsEventConfigSuitableByTime(EventConfig eventConfig) {
if (eventConfig.MinTimeAfterWipe <= 0 && eventConfig.MaxTimeAfterWipe <= 0) return true;
int timeScienceWipe = GetTimeScienceLastWipe();
if (timeScienceWipe < eventConfig.MinTimeAfterWipe) return false;
if (eventConfig.MaxTimeAfterWipe > 0 && timeScienceWipe > eventConfig.MaxTimeAfterWipe) return false;
return true;
}
private static int GetTimeScienceLastWipe() {
DateTime startTime = new DateTime(2019, 1, 1, 0, 0, 0);
double realTime = DateTime.UtcNow.Subtract(startTime).TotalSeconds;
double wipeTime = SaveRestore.SaveCreatedTime.Subtract(startTime).TotalSeconds;
return Convert.ToInt32(realTime - wipeTime);
}
public static void StopEvent(bool isPluginUnloading = false) {
if (IsEventActive()) {
_ins.Unsubscribes();
_ins._eventController.DeleteController();
Horseman.KillAllHorseman();
HorseCarriage.KillAllCarriages();
CaravanNpc.KillAllNpcs();
AirBalloon.KillAllBalloons();
HorseBrain.ClearData();
ZoneController.TryDeleteZone();
EventMapMarker.DeleteMapMarker();
PveModeManager.OnEventEnd();
GuiManager.DestroyAllGui();
EconomyManager.OnEventEnd();
NotifyManager.SendMessageToAll("Finish", _ins._config.NotifyConfig.Prefix);
Interface.CallHook("OnCaravanStop");
if (_ins._config.MainConfig.EnableStartStopLogs) NotifyManager.PrintLogMessage("EventStop_Log");
if (!isPluginUnloading) AutoStartEvent();
}
if (_delayedEventStartCoroutine != null) {
ServerMgr.Instance.StopCoroutine(_delayedEventStartCoroutine);
_delayedEventStartCoroutine = null;
}
}
}
private class EventController : FacepunchBehaviour {
public EventConfig EventConfig;
private Coroutine _spawnCoroutine;
private Coroutine _eventCoroutine;
public readonly List<CaravanHorse> CaravanHorses = new List<CaravanHorse>();
public readonly HashSet<ScientistNPC> Npcs = new HashSet<ScientistNPC>();
private int _eventTime;
private int _stopTime;
private int _aggressiveTime;
private bool _isEventLooted;
private readonly HashSet<ulong> _lootedContainersUids = new HashSet<ulong>();
private readonly HashSet<BaseEntity> _crates = new HashSet<BaseEntity>();
private int _countOfUnlootedCrates;
public int GetEventTime() {
return _eventTime;
}
public Vector3 GetEventPosition() {
int counter = 0;
Vector3 resultPositon = Vector3.zero;
foreach (CaravanHorse caravanHorse in CaravanHorses) {
if (caravanHorse != null && caravanHorse.customHorse.IsExists()) {
resultPositon += caravanHorse.transform.position;
counter++;
}
// ... [Code preview truncated due to length. Full source in attached file] ...