Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PersistentRaids v1.0.6
Cjayride.PersistentRaids.dll
Decompiled 10 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("Cjayride.PersistentRaids")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.6.0")] [assembly: AssemblyInformationalVersion("1.0.6")] [assembly: AssemblyProduct("Cjayride.PersistentRaids")] [assembly: AssemblyTitle("Cjayride.PersistentRaids")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Cjayride.PersistentRaids { internal static class CapService { internal static void OnCreatureSpawned() { if (ModConfig.EnableMonsterCap.Value) { EnforceCap(); } } internal static void EnforceCap() { if (!ModConfig.EnableMonsterCap.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } List<Character> allCharacters = Character.GetAllCharacters(); List<Character> list = new List<Character>(); for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if (CreatureRules.IsEnemy(val) && CreatureRules.PassesFilter(val)) { list.Add(val); } } int value = ModConfig.MaxActiveMonsters.Value; if (list.Count <= value) { return; } if (ModConfig.LogCapEvents.Value) { Plugin.Log.LogInfo((object)("Monster cap " + value + " hit, living=" + list.Count)); } int value2 = ModConfig.CapBehavior.Value; if (value2 == 0) { return; } int num = list.Count - value; if (value2 == 2) { list.Sort((Character a, Character b) => DistanceToNearestPlayer(b).CompareTo(DistanceToNearestPlayer(a))); } int num2 = 0; for (int num3 = 0; num3 < list.Count; num3++) { if (num2 >= num) { break; } Character val2 = list[num3]; if (!val2.IsBoss() || !ModConfig.NeverDespawnBosses.Value) { ZNetView component = ((Component)val2).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.Destroy(); num2++; } } } } internal static int Clear(bool eventOnly, bool includeBosses, string prefabFilter) { int num = 0; List<Character> list = new List<Character>(Character.GetAllCharacters()); for (int i = 0; i < list.Count; i++) { Character val = list[i]; if (!CreatureRules.IsEnemy(val) || (!includeBosses && val.IsBoss()) || (!string.IsNullOrEmpty(prefabFilter) && !((Object)((Component)val).gameObject).name.Replace("(Clone)", string.Empty).Equals(prefabFilter, StringComparison.OrdinalIgnoreCase))) { continue; } if (eventOnly) { MonsterAI component = ((Component)val).GetComponent<MonsterAI>(); if ((Object)(object)component == (Object)null || !component.IsEventCreature()) { continue; } } ZNetView component2 = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid()) { component2.Destroy(); num++; } } return num; } private static float DistanceToNearestPlayer(Character character) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null)) { float num2 = Vector3.Distance(((Component)character).transform.position, ((Component)allPlayer).transform.position); if (num2 < num) { num = num2; } } } return num; } } public class ConfigurationManagerAttributes { public bool? IsAdminOnly; } internal static class CreatureRules { internal sealed class RaidChaseApplied : MonoBehaviour { } internal static bool PlayersOnline() { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (ZNet.instance.IsServer()) { if (ZNet.instance.GetPeers().Count <= 0) { return (Object)(object)Player.m_localPlayer != (Object)null; } return true; } return (Object)(object)Player.m_localPlayer != (Object)null; } internal static bool RulesActive() { if (ModConfig.Enabled == null || !ModConfig.Enabled.Value) { return false; } if (ModConfig.OnlyApplyWhilePlayersOnline.Value && !PlayersOnline()) { return false; } return true; } internal static bool PassesFilter(Character character) { if ((Object)(object)character == (Object)null || character.IsPlayer()) { return false; } string text = ((Object)((Component)character).gameObject).name.Replace("(Clone)", string.Empty); string value = ModConfig.CreatureBlacklist.Value; string[] array; if (!string.IsNullOrWhiteSpace(value)) { array = value.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text.Equals(text2.Trim(), StringComparison.OrdinalIgnoreCase)) { return false; } } } string value2 = ModConfig.CreatureWhitelist.Value; if (string.IsNullOrWhiteSpace(value2)) { return true; } array = value2.Split(new char[1] { ',' }); foreach (string text3 in array) { if (text.Equals(text3.Trim(), StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal static bool IsEnemy(Character character) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 if ((Object)(object)character == (Object)null || character.IsPlayer()) { return false; } Faction faction = character.GetFaction(); if ((int)faction != 0) { return (int)faction != 10; } return false; } internal static bool ShouldPersist(Character character, MonsterAI monster) { if (!RulesActive() || !PassesFilter(character) || !IsEnemy(character)) { return false; } if (character.IsBoss()) { return ModConfig.NeverDespawnBosses.Value; } if (ModConfig.NeverDespawnMonsters.Value) { return IsRaidCreature(monster); } return false; } internal static void ApplyPersistence(MonsterAI monster) { if ((Object)(object)monster == (Object)null) { return; } Character character = ((BaseAI)monster).m_character; if ((Object)(object)character == (Object)null || !ShouldPersist(character, monster)) { return; } ZNetView nview = ((BaseAI)monster).m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO != null && !zDO.Persistent) { zDO.Persistent = true; } } } internal static bool IsRaidCreature(MonsterAI monster) { if ((Object)(object)monster != (Object)null) { return monster.IsEventCreature(); } return false; } internal static bool ShouldKeepHunt(BaseAI ai) { if (!RulesActive() || (Object)(object)ai == (Object)null || (Object)(object)ai.m_character == (Object)null || !PassesFilter(ai.m_character)) { return false; } if (!IsRaidCreature((MonsterAI)(object)((ai is MonsterAI) ? ai : null))) { return false; } if (!ModConfig.EnablePersistentChase.Value) { return ModConfig.EventMonstersSurviveRaidEnd.Value; } return true; } internal static void ApplyRaidChase(MonsterAI monster) { if ((Object)(object)monster == (Object)null || !RulesActive() || !IsRaidCreature(monster) || !PassesFilter(((BaseAI)monster).m_character) || (!ModConfig.EnablePersistentChase.Value && !ModConfig.EventMonstersSurviveRaidEnd.Value)) { return; } EnforceFightAi(monster); if (ModConfig.EnablePersistentChase.Value && (Object)(object)((Component)monster).GetComponent<RaidChaseApplied>() == (Object)null) { ((Component)monster).gameObject.AddComponent<RaidChaseApplied>(); float num = Mathf.Max(1f, ModConfig.ChaseRangeMultiplier.Value); monster.m_maxChaseDistance *= num; ((BaseAI)monster).m_viewRange = ((BaseAI)monster).m_viewRange * num; monster.m_alertRange *= num; float value = ModConfig.MaxChaseDistance.Value; if (value > 0f) { monster.m_maxChaseDistance = Mathf.Min(monster.m_maxChaseDistance, value); } } } internal static void EnforceFightAi(MonsterAI monster) { if (!((Object)(object)monster == (Object)null)) { monster.m_fleeIfNotAlerted = false; monster.m_fleeIfHurtWhenTargetCantBeReached = false; monster.m_fleeIfLowHealth = 0f; monster.m_enableHuntPlayer = true; if (!((BaseAI)monster).m_huntPlayer) { ((BaseAI)monster).SetHuntPlayer(true); } if (!((BaseAI)monster).IsAlerted()) { ((BaseAI)monster).SetAlerted(true); } } } internal static void DebugLog(string message) { if (ModConfig.EnableDebugLogging != null && ModConfig.EnableDebugLogging.Value) { Plugin.Log.LogInfo((object)message); } } } [HarmonyPatch(typeof(BaseAI), "MoveAwayAndDespawn", new Type[] { typeof(float), typeof(bool) })] internal static class PatchMoveAwayAndDespawn { private static bool Prefix(BaseAI __instance) { if ((Object)(object)__instance.m_character != (Object)null && CreatureRules.ShouldPersist(__instance.m_character, (MonsterAI)(object)((__instance is MonsterAI) ? __instance : null))) { CreatureRules.DebugLog("Blocked MoveAwayAndDespawn " + ((Object)__instance.m_character).name); return false; } return true; } } [HarmonyPatch(typeof(MonsterAI), "HuntPlayer")] internal static class PatchMonsterHuntPlayer { private static bool Prefix(MonsterAI __instance, ref bool __result) { if (!CreatureRules.ShouldKeepHunt((BaseAI)(object)__instance)) { return true; } if (__instance.DespawnInDay() && EnvMan.IsDay() && !ModConfig.NeverDespawnNightMonsters.Value) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(BaseAI), "SetAlerted")] internal static class PatchSetAlerted { private static bool Prefix(BaseAI __instance, bool alert) { if (!alert && CreatureRules.ShouldKeepHunt(__instance)) { return false; } return true; } } [HarmonyPatch(typeof(BaseAI), "SetHuntPlayer")] internal static class PatchSetHuntPlayer { private static bool Prefix(BaseAI __instance, bool hunt) { if (!hunt && CreatureRules.ShouldKeepHunt(__instance)) { return false; } return true; } } [HarmonyPatch(typeof(BaseAI), "Flee", new Type[] { typeof(float), typeof(Vector3) })] internal static class PatchFlee { private static bool Prefix(BaseAI __instance, ref bool __result) { if (CreatureRules.ShouldKeepHunt(__instance)) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(MonsterAI), "UpdateAI")] internal static class PatchMonsterUpdateAI { private static void Postfix(MonsterAI __instance) { if (CreatureRules.ShouldKeepHunt((BaseAI)(object)__instance)) { CreatureRules.EnforceFightAi(__instance); } } } [HarmonyPatch(typeof(MonsterAI), "Awake")] internal static class PatchMonsterAwake { private static void Postfix(MonsterAI __instance) { CreatureRules.ApplyRaidChase(__instance); CreatureRules.ApplyPersistence(__instance); } } [HarmonyPatch(typeof(MonsterAI), "SetEventCreature")] internal static class PatchSetEventCreature { private static void Postfix(MonsterAI __instance) { CreatureRules.ApplyRaidChase(__instance); CreatureRules.ApplyPersistence(__instance); } } [HarmonyPatch(typeof(MonsterAI), "SetDespawnInDay")] internal static class PatchSetDespawnInDay { private static bool Prefix(MonsterAI __instance, ref bool despawn) { if (despawn && CreatureRules.RulesActive() && ModConfig.NeverDespawnNightMonsters.Value && CreatureRules.IsRaidCreature(__instance) && CreatureRules.PassesFilter(((BaseAI)__instance).m_character)) { despawn = false; } return true; } } internal static class ModConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> EnablePersistentChase; internal static ConfigEntry<float> ChaseRangeMultiplier; internal static ConfigEntry<float> MaxChaseDistance; internal static ConfigEntry<bool> NeverDespawnMonsters; internal static ConfigEntry<bool> NeverDespawnBosses; internal static ConfigEntry<bool> EventMonstersSurviveRaidEnd; internal static ConfigEntry<bool> NeverDespawnNightMonsters; internal static ConfigEntry<bool> AllowMultipleRaids; internal static ConfigEntry<bool> ContinueSpawningWithoutPlayers; internal static ConfigEntry<float> SpawnWithoutPlayersDuration; internal static ConfigEntry<bool> OverrideRaidDurations; internal static ConfigEntry<float> OverrideDurationSeconds; internal static ConfigEntry<bool> EnableMonsterCap; internal static ConfigEntry<int> MaxActiveMonsters; internal static ConfigEntry<int> CapBehavior; internal static ConfigEntry<bool> OnlyApplyWhilePlayersOnline; internal static ConfigEntry<float> AutoCleanupInterval; internal static ConfigEntry<string> CreatureWhitelist; internal static ConfigEntry<string> CreatureBlacklist; internal static ConfigEntry<bool> EnableDebugLogging; internal static ConfigEntry<bool> LogCapEvents; private static ConfigDescription Admin(string desc) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { IsAdminOnly = true } }); } internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("General", "Enabled", true, Admin("Master switch.")); EnablePersistentChase = config.Bind<bool>("RaidChase", "EnablePersistentChase", true, Admin("ALL RandomEvent/raid creatures hunt and fight (no shy flee). Open-world mobs stay vanilla.")); ChaseRangeMultiplier = config.Bind<float>("RaidChase", "ChaseRangeMultiplier", 3f, Admin("Multiplies view/alert/chase range for raid creatures only. 1 = vanilla.")); MaxChaseDistance = config.Bind<float>("RaidChase", "MaxChaseDistance", 200f, Admin("Absolute chase cap in meters. 0 = multiplier only.")); NeverDespawnMonsters = config.Bind<bool>("Despawn", "NeverDespawnMonsters", true, Admin("Block far-despawn and mark ZDOs persistent for RAID/event creatures only. Open-world wildlife culls like vanilla so it does not pile up around bases.")); NeverDespawnBosses = config.Bind<bool>("Despawn", "NeverDespawnBosses", true, Admin("Bosses persist / skip far-despawn. Hunt range is still raid-only.")); EventMonstersSurviveRaidEnd = config.Bind<bool>("Despawn", "EventMonstersSurviveRaidEnd", true, Admin("Event creatures keep hunting after the raid timer ends.")); NeverDespawnNightMonsters = config.Bind<bool>("Despawn", "NeverDespawnNightMonsters", true, Admin("Ignore despawn-in-day on night-spawned event creatures.")); AllowMultipleRaids = config.Bind<bool>("MultipleRaids", "AllowMultipleRaids", false, Admin("OFF by default. Custom Raids will not start a new raid while any event is still current. Leave false.")); ContinueSpawningWithoutPlayers = config.Bind<bool>("MultipleRaids", "ContinueSpawningWithoutPlayers", false, Admin("OFF by default. When on, keeps the raid timer (and spawn checks) running with nobody in the circle. Leave off so each raid's PauseIfNoPlayerInArea and Duration work as configured.")); SpawnWithoutPlayersDuration = config.Bind<float>("MultipleRaids", "SpawnWithoutPlayersDuration", 600f, Admin("Unused (kept so old configs still load).")); OverrideRaidDurations = config.Bind<bool>("MultipleRaids", "OverrideRaidDurations", false, Admin("OFF by default. When on, replaces every random-event Duration with OverrideDurationSeconds. Leave off to use each Custom Raids Duration.")); OverrideDurationSeconds = config.Bind<float>("MultipleRaids", "OverrideDurationSeconds", 60f, Admin("Only used when OverrideRaidDurations is on. Seconds.")); EnableMonsterCap = config.Bind<bool>("Safety", "EnableMonsterCap", true, Admin("Hard cap on living non-player characters.")); MaxActiveMonsters = config.Bind<int>("Safety", "MaxActiveMonsters", 220, Admin("Global living monster cap.")); CapBehavior = config.Bind<int>("Safety", "CapBehavior", 1, Admin("0 = stop persisting new ones. 1 = despawn oldest. 2 = despawn furthest from any player.")); OnlyApplyWhilePlayersOnline = config.Bind<bool>("Safety", "OnlyApplyWhilePlayersOnline", true, Admin("When no players are online, never-despawn rules are off so the server can unload.")); AutoCleanupInterval = config.Bind<float>("Safety", "AutoCleanupInterval", 15f, Admin("Minutes between cap sweeps. 0 = only on spawn.")); CreatureWhitelist = config.Bind<string>("Filters", "CreatureWhitelist", "", Admin("Comma prefab names. Empty = all enemies.")); CreatureBlacklist = config.Bind<string>("Filters", "CreatureBlacklist", "", Admin("Comma prefab names to ignore.")); EnableDebugLogging = config.Bind<bool>("Logging", "EnableDebugLogging", false, "Log blocked despawns and extra raids."); LogCapEvents = config.Bind<bool>("Logging", "LogCapEvents", true, "Log when the monster cap is hit."); } } [BepInPlugin("cjayride.persistentraids", "PersistentRaids", "1.0.6")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__7_0; internal void <Awake>b__7_0(ConsoleEventArgs args) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { args.Context.AddString("PersistentRaids: server only"); return; } if (args.Length < 2) { args.Context.AddString("persistraid clear | event | stop | cap | boss <prefab>"); return; } switch (args[1].ToLowerInvariant()) { case "clear": { int num = CapService.Clear(eventOnly: false, includeBosses: false, null); args.Context.AddString("Cleared " + num + " non-boss monsters"); break; } case "event": { int num = CapService.Clear(eventOnly: true, includeBosses: false, null); args.Context.AddString("Cleared " + num + " event monsters"); break; } case "stop": ExtraRaids.StopAll(RandEventSystem.instance); args.Context.AddString("Cleared current/stashed random events"); break; case "cap": CapService.EnforceCap(); args.Context.AddString("Cap enforced"); break; case "boss": { if (args.Length < 3) { args.Context.AddString("persistraid boss <prefab>"); break; } int num = CapService.Clear(eventOnly: false, includeBosses: true, args[2]); args.Context.AddString("Cleared " + num + " matching bosses"); break; } default: args.Context.AddString("persistraid clear | event | stop | cap | boss <prefab>"); break; } } } public const string PluginGUID = "cjayride.persistentraids"; public const string PluginName = "PersistentRaids"; public const string PluginVersion = "1.0.6"; internal static Plugin Instance; internal static Harmony Harmony; internal static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown Instance = this; ModConfig.Bind(((BaseUnityPlugin)this).Config); Harmony = new Harmony("cjayride.persistentraids"); Harmony.PatchAll(Assembly.GetExecutingAssembly()); object obj = <>c.<>9__7_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { args.Context.AddString("PersistentRaids: server only"); } else if (args.Length < 2) { args.Context.AddString("persistraid clear | event | stop | cap | boss <prefab>"); } else { switch (args[1].ToLowerInvariant()) { case "clear": { int num = CapService.Clear(eventOnly: false, includeBosses: false, null); args.Context.AddString("Cleared " + num + " non-boss monsters"); break; } case "event": { int num = CapService.Clear(eventOnly: true, includeBosses: false, null); args.Context.AddString("Cleared " + num + " event monsters"); break; } case "stop": ExtraRaids.StopAll(RandEventSystem.instance); args.Context.AddString("Cleared current/stashed random events"); break; case "cap": CapService.EnforceCap(); args.Context.AddString("Cap enforced"); break; case "boss": if (args.Length < 3) { args.Context.AddString("persistraid boss <prefab>"); } else { int num = CapService.Clear(eventOnly: false, includeBosses: true, args[2]); args.Context.AddString("Cleared " + num + " matching bosses"); } break; default: args.Context.AddString("persistraid clear | event | stop | cap | boss <prefab>"); break; } } }; <>c.<>9__7_0 = val; obj = (object)val; } new ConsoleCommand("persistraid", "clear | event | stop | cap | boss <prefab> — PersistentRaids cleanup", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); if (ModConfig.AutoCleanupInterval.Value > 0f) { ((MonoBehaviour)this).InvokeRepeating("TickCap", 60f, ModConfig.AutoCleanupInterval.Value * 60f); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"PersistentRaids 1.0.6 loaded. Custom Raids owns raid start. This mod only persists raid creatures."); } private void TickCap() { CapService.EnforceCap(); } } internal static class ExtraRaids { internal static readonly List<RandomEvent> Stashed = new List<RandomEvent>(); internal static void StashCurrent(RandEventSystem system) { if (system.m_randomEvent != null) { Stashed.Add(system.m_randomEvent); CreatureRules.DebugLog("Stashed raid " + system.m_randomEvent.m_name + " extras=" + Stashed.Count); system.m_randomEvent = null; } } internal static void StopAll(RandEventSystem system) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) Stashed.Clear(); if ((Object)(object)system != (Object)null) { system.SetRandomEvent((RandomEvent)null, Vector3.zero); } } internal static void ApplyDurationOverride(RandomEvent ev) { if (ev != null && ModConfig.OverrideRaidDurations.Value) { float duration = Mathf.Max(1f, ModConfig.OverrideDurationSeconds.Value); CreatureRules.DebugLog("Duration override " + ev.m_name + " " + ev.m_duration + " -> " + duration); ev.m_duration = duration; } } internal static void Tick(RandEventSystem system, float dt) { bool flag = ModConfig.ContinueSpawningWithoutPlayers.Value && CreatureRules.RulesActive(); for (int num = Stashed.Count - 1; num >= 0; num--) { RandomEvent val = Stashed[num]; if (val == null) { Stashed.RemoveAt(num); } else { bool flag2 = system.IsAnyPlayerInEventArea(val) || flag; if (val.Update(true, true, flag2, dt)) { val.OnStop(); Stashed.RemoveAt(num); CreatureRules.DebugLog("Extra raid ended " + val.m_name); } } } } } [HarmonyPatch(typeof(RandEventSystem), "StartRandomEvent")] internal static class PatchStartRandomEvent { private static void Prefix(RandEventSystem __instance) { if (CreatureRules.RulesActive() && ModConfig.AllowMultipleRaids.Value && __instance.m_randomEvent != null) { ExtraRaids.StashCurrent(__instance); } } } [HarmonyPatch(typeof(RandEventSystem), "SetRandomEvent")] internal static class PatchSetRandomEvent { private static void Postfix(RandEventSystem __instance) { if (CreatureRules.RulesActive()) { ExtraRaids.ApplyDurationOverride(__instance.m_randomEvent); } } } [HarmonyPatch(typeof(RandEventSystem), "FixedUpdate")] internal static class PatchEventFixedUpdate { private static void Postfix(RandEventSystem __instance) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && ModConfig.AllowMultipleRaids.Value && ExtraRaids.Stashed.Count != 0) { ExtraRaids.Tick(__instance, Time.fixedDeltaTime); } } } [HarmonyPatch(typeof(RandomEvent), "Update", new Type[] { typeof(bool), typeof(bool), typeof(bool), typeof(float) })] internal static class PatchRandomEventUpdate { private static void Prefix(ref bool playerInArea) { if (CreatureRules.RulesActive() && ModConfig.ContinueSpawningWithoutPlayers.Value) { playerInArea = true; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }