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 NightTerrors v1.0.3
plugins/NightTerrors.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("NightTerrors")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d5123f41927d720c0452d1c2014ee6686a47d44b")] [assembly: AssemblyProduct("NightTerrors")] [assembly: AssemblyTitle("NightTerrors")] [assembly: AssemblyVersion("1.0.0.0")] namespace NightTerrors; public static class NightTerrorsEvent { public static bool IsActive; public static Scenario CurrentScenario; public static Vector3 ChosenDestination; public static HashSet<long> AlivePeers = new HashSet<long>(); public static void Begin() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (IsActive) { return; } CurrentScenario = ScenarioSelector.Choose(NightTerrorsPlugin.CfgScenarioWeights.Value); ChosenDestination = FindRandomPosition(); if (ChosenDestination == Vector3.zero) { NightTerrorsPlugin.Log.LogWarning((object)"NightTerrors: could not find a valid teleport position — aborting."); return; } AlivePeers.Clear(); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_uid != 0L) { AlivePeers.Add(peer.m_uid); } } if (AlivePeers.Count == 0) { NightTerrorsPlugin.Log.LogWarning((object)"NightTerrors: no valid peers — aborting."); return; } IsActive = true; NightTerrorsPlugin.Log.LogInfo((object)$"NightTerrors: event starting — scenario={CurrentScenario}, peers={AlivePeers.Count}, dest={ChosenDestination}"); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_SaveInventory", Array.Empty<object>()); ((MonoBehaviour)NightTerrorsPlugin.Instance).StartCoroutine(EventSequence()); } private static IEnumerator EventSequence() { yield return (object)new WaitForSeconds(1.5f); string[] array = ((CurrentScenario == Scenario.DifferentEquipment) ? ScenarioSelector.PickKit() : new string[0]); ZPackage val = new ZPackage(); val.Write((int)CurrentScenario); val.Write(NightTerrorsPlugin.CfgFriendlyFire.Value); val.Write(NightTerrorsPlugin.CfgMonsterCount.Value); val.Write(array.Length); string[] array2 = array; foreach (string text in array2) { val.Write(text); } Announce("YOU HAVE BEEN TAKEN", (MessageType)2); ApplyRandomWeather(); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_EventStart", new object[1] { val }); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.m_uid != 0L) { TeleportPeer(peer, ChosenDestination); } } if (NightTerrorsPlugin.CfgSpawnMonsters.Value) { SpawnMonsters(ChosenDestination, NightTerrorsPlugin.CfgMonsterCount.Value); } yield return (object)new WaitForSeconds((float)NightTerrorsPlugin.CfgEventDuration.Value); if (IsActive) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: time limit reached — ending event."); End(); } } public static void OnPlayerDied(long peerUID) { if (IsActive) { AlivePeers.Remove(peerUID); NightTerrorsPlugin.Log.LogInfo((object)$"NightTerrors: {AlivePeers.Count} players still alive."); HashSet<long> connected = new HashSet<long>(from p in ZNet.instance.GetPeers() select p.m_uid); AlivePeers.RemoveWhere((long uid) => !connected.Contains(uid)); if (AlivePeers.Count == 0) { End(); } } } public static void End() { if (!IsActive) { return; } IsActive = false; NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: ending event."); Announce("The darkness claims you.", (MessageType)2); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_SetWeather", new object[1] { "" }); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_RestoreInventory", Array.Empty<object>()); foreach (long alivePeer in AlivePeers) { NightTerrorsPlugin.Log.LogInfo((object)$"NightTerrors: killing survivor {alivePeer}."); ZRoutedRpc.instance.InvokeRoutedRPC(alivePeer, "NightTerrors_KillSurvivor", Array.Empty<object>()); } ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_EventEnd", Array.Empty<object>()); AlivePeers.Clear(); } private static void TeleportPeer(ZNetPeer peer, Vector3 pos) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "RPC_TeleportPlayer", new object[3] { pos, Quaternion.identity, true }); } private static Vector3 FindRandomPosition() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) float waterLevel = ZoneSystem.instance.m_waterLevel; for (int i = 0; i < 100; i++) { float num = Random.Range(-10000f, 10000f); float num2 = Random.Range(-10000f, 10000f); float height = WorldGenerator.instance.GetHeight(num, num2); if (height > waterLevel - 20f) { return new Vector3(num, Mathf.Max(height, waterLevel) + 1f, num2); } } NightTerrorsPlugin.Log.LogError((object)"NightTerrors: FindRandomPosition failed after 100 attempts."); return Vector3.zero; } private static void SpawnMonsters(Vector3 pos, int count) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) string[] monstersForBiome = GetMonstersForBiome(pos); for (int i = 0; i < count; i++) { int stableHashCode = StringExtensionMethods.GetStableHashCode(monstersForBiome[Random.Range(0, monstersForBiome.Length)]); Vector3 val = pos + new Vector3(Random.Range(-8f, 8f), 0f, Random.Range(-8f, 8f)); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SpawnObject", new object[3] { val, Quaternion.identity, stableHashCode }); } } private static string[] GetMonstersForBiome(Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Invalid comparison between Unknown and I4 //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Invalid comparison between Unknown and I4 //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Invalid comparison between Unknown and I4 //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Invalid comparison between Unknown and I4 //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Invalid comparison between Unknown and I4 //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Invalid comparison between Unknown and I4 Biome biome = WorldGenerator.instance.GetBiome(pos.x, pos.z, 0.02f, false); if (!(WorldGenerator.instance.GetHeight(pos.x, pos.z) < ZoneSystem.instance.m_waterLevel)) { if ((int)biome != 1) { if ((int)biome != 8) { if ((int)biome != 2) { if ((int)biome != 4) { if ((int)biome != 16) { if ((int)biome != 512) { if ((int)biome != 32) { return new string[2] { "Greydwarf", "Troll" }; } return new string[2] { "Charred_Warrior", "Morgen" }; } return new string[2] { "Seeker", "Tick" }; } return new string[2] { "Fuling", "Deathsquito" }; } return new string[2] { "Drake", "Fenring" }; } return new string[3] { "Draugr", "Blob", "Wraith" }; } return new string[2] { "Troll", "Greydwarf_Elite" }; } return new string[2] { "Greydwarf", "Neck" }; } return new string[1] { "Serpent" }; } private static void ApplyRandomWeather() { string value = NightTerrorsPlugin.CfgWeatherPool.Value; if (!string.IsNullOrWhiteSpace(value)) { string[] array = value.Split(','); string text = array[Random.Range(0, array.Length)].Trim(); NightTerrorsPlugin.Log.LogInfo((object)("NightTerrors: forcing weather '" + text + "'.")); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NightTerrors_SetWeather", new object[1] { text }); } } private static void Announce(string text, MessageType type) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected I4, but got Unknown if (!string.IsNullOrWhiteSpace(text) && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ShowMessage", new object[2] { (int)type, text }); } } } [HarmonyPatch(typeof(EnvMan), "SkipToMorning")] internal static class Patch_SkipToMorning { private static void Prefix() { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !NightTerrorsEvent.IsActive) { int value = NightTerrorsPlugin.CfgTriggerChance.Value; if (value > 0 && Random.Range(0, value) == 0) { NightTerrorsEvent.Begin(); } } } } [HarmonyPatch(typeof(Player), "OnDeath")] internal static class Patch_Player_OnDeath { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && NightTerrorsClient.IsEventActive) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: local player died during event."); ZRoutedRpc.instance.InvokeRoutedRPC("NightTerrors_PlayerDied", Array.Empty<object>()); } } } [HarmonyPatch(typeof(Skills), "OnDeath")] internal static class Patch_Skills_OnDeath { private static bool Prefix() { if (NightTerrorsClient.IsEventActive) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: skill loss suppressed."); return false; } return true; } } [HarmonyPatch(typeof(Player), "CreateTombStone")] internal static class Patch_CreateTombStone { private static bool Prefix() { if (NightTerrorsClient.IsEventActive) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: tombstone suppressed."); return false; } return true; } } [HarmonyPatch(typeof(EnvMan), "OnMorning")] internal static class Patch_EnvMan_OnMorning { private static bool Prefix() { return !NightTerrorsClient.SuppressMorning; } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class Patch_Player_OnSpawned { private static void Postfix(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (NightTerrorsClient.PendingRestore) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: applying deferred inventory restore on spawn."); NightTerrorsClient.ApplyRestore(); } if (NightTerrorsClient.SuppressMorning) { NightTerrorsClient.SuppressMorning = false; if ((Object)(object)EnvMan.instance != (Object)null) { ((Character)__instance).Message((MessageType)2, $"Day {EnvMan.instance.GetDay()}", 0, (Sprite)null); } } } } [HarmonyPatch(typeof(Player), "Message")] internal static class Patch_Player_Message { private static bool Prefix(string msg) { if (!NightTerrorsClient.IsEventStarting && !NightTerrorsClient.IsEventActive) { return true; } if (msg == "$msg_goodmorning") { return false; } return true; } } [HarmonyPatch(typeof(SleepText), "ShowDreamText")] internal static class Patch_SleepText_ShowDreamText { private static bool Prefix() { if (NightTerrorsClient.IsEventStarting || NightTerrorsClient.IsEventActive) { return false; } return true; } } [HarmonyPatch(typeof(Player), "AddKnownItem")] internal static class Patch_AddKnownItem { private static bool Prefix() { if (NightTerrorsClient.IsEventActive || NightTerrorsClient.IsEventStarting) { return false; } return true; } } [HarmonyPatch(typeof(Player), "AddKnownBiome")] internal static class Patch_AddKnownBiome { private static bool Prefix() { if (NightTerrorsClient.IsEventActive || NightTerrorsClient.IsEventStarting) { return false; } return true; } } [HarmonyPatch(typeof(Character), "Damage")] internal static class Patch_FriendlyFire { private static void Prefix(HitData hit, Character __instance) { if (NightTerrorsClient.IsEventActive && NightTerrorsPlugin.CfgFriendlyFire.Value && __instance.IsPlayer()) { Character attacker = hit.GetAttacker(); if (!((Object)(object)attacker == (Object)null) && attacker.IsPlayer()) { hit.m_ignorePVP = true; } } } } [BepInPlugin("nightterrors", "NightTerrors", "1.0.3")] public class NightTerrorsPlugin : BaseUnityPlugin { public const string PluginGUID = "nightterrors"; public const string PluginName = "NightTerrors"; public const string PluginVersion = "1.0.3"; internal static ManualLogSource Log; internal static NightTerrorsPlugin Instance; private Harmony _harmony; internal static ConfigEntry<int> CfgTriggerChance; internal static ConfigEntry<bool> CfgFriendlyFire; internal static ConfigEntry<bool> CfgSpawnMonsters; internal static ConfigEntry<int> CfgMonsterCount; internal static ConfigEntry<string> CfgScenarioWeights; internal static ConfigEntry<string> CfgWeatherPool; internal static ConfigEntry<int> CfgEventDuration; private void Awake() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Instance = this; CfgTriggerChance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "TriggerChance", 20, "1-in-N chance of the event triggering each time everyone sleeps."); CfgFriendlyFire = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FriendlyFire", false, "Allow players to damage each other during the event."); CfgSpawnMonsters = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SpawnMonsters", true, "Spawn monsters at the teleport location."); CfgMonsterCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MonsterCount", 3, "Number of monsters to spawn."); CfgScenarioWeights = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ScenarioWeights", "1,1,1", "Comma-separated weights for: KeepGear, GoNaked, DifferentEquipment."); CfgEventDuration = ((BaseUnityPlugin)this).Config.Bind<int>("General", "EventDuration", 120, "Maximum event duration in seconds. Survivors have their inventory restored and the event ends."); CfgWeatherPool = ((BaseUnityPlugin)this).Config.Bind<string>("Weather", "WeatherPool", "ThunderStorm,Ashrain,Snow,Twilight_Snow,DeepForest_Mist,SwampRain,Mistlands_darkening", "Comma-separated list of environment names to pick from randomly. Set to empty string to disable weather effects."); _harmony = new Harmony("nightterrors"); _harmony.PatchAll(); Log.LogInfo((object)"NightTerrors v1.0.3 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class NightTerrorsClient { public static bool IsEventActive; public static bool IsEventStarting; public static bool SuppressMorning; public static byte[] SavedInventory; public static bool PendingRestore; public static Scenario CurrentScenario; public static void ApplyRestore() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && SavedInventory != null) { ((Humanoid)localPlayer).UnequipAllItems(); ((Humanoid)localPlayer).GetInventory().Load(new ZPackage(SavedInventory)); SavedInventory = null; PendingRestore = false; NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: inventory restored."); } } } internal static class RpcHandler { [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static class Patch_ZRoutedRpc_Awake { private static void Postfix() { ZRoutedRpc.instance.Register("NightTerrors_SaveInventory", (Action<long>)SaveInventory); ZRoutedRpc.instance.Register<ZPackage>("NightTerrors_EventStart", (Action<long, ZPackage>)EventStart); ZRoutedRpc.instance.Register("NightTerrors_RestoreInventory", (Action<long>)RestoreInventory); ZRoutedRpc.instance.Register("NightTerrors_EventEnd", (Action<long>)EventEnd); ZRoutedRpc.instance.Register("NightTerrors_PlayerDied", (Action<long>)PlayerDied); ZRoutedRpc.instance.Register("NightTerrors_KillSurvivor", (Action<long>)KillSurvivor); ZRoutedRpc.instance.Register<string>("NightTerrors_SetWeather", (Action<long, string>)SetWeather); } } private static void SaveInventory(long sender) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { NightTerrorsClient.IsEventStarting = true; NightTerrorsClient.SuppressMorning = true; ZPackage val = new ZPackage(); ((Humanoid)localPlayer).GetInventory().Save(val); NightTerrorsClient.SavedInventory = val.GetArray(); NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: inventory saved."); } } private static void EventStart(long sender, ZPackage pkg) { int currentScenario = pkg.ReadInt(); pkg.ReadBool(); pkg.ReadInt(); int num = pkg.ReadInt(); string[] array = new string[num]; for (int i = 0; i < num; i++) { array[i] = pkg.ReadString(); } NightTerrorsClient.IsEventActive = true; NightTerrorsClient.CurrentScenario = (Scenario)currentScenario; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } switch (NightTerrorsClient.CurrentScenario) { case Scenario.GoNaked: ((Humanoid)localPlayer).UnequipAllItems(); ((Humanoid)localPlayer).GetInventory().RemoveAll(); NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: stripped for GoNaked."); break; case Scenario.DifferentEquipment: { ((Humanoid)localPlayer).UnequipAllItems(); ((Humanoid)localPlayer).GetInventory().RemoveAll(); string[] array2 = array; foreach (string text in array2) { ItemData val = ((Humanoid)localPlayer).GetInventory().AddItem(text, 1, 1, 0, 0L, "", false); if (val != null) { ((Humanoid)localPlayer).EquipItem(val, false); } else { NightTerrorsPlugin.Log.LogWarning((object)("NightTerrors: unknown kit item '" + text + "'")); } } NightTerrorsPlugin.Log.LogInfo((object)("NightTerrors: equipped kit [" + string.Join(", ", array) + "].")); break; } } } private static void RestoreInventory(long sender) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead()) { NightTerrorsClient.PendingRestore = true; NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: restore deferred (player dead/null)."); } else { NightTerrorsClient.ApplyRestore(); } } private static void EventEnd(long sender) { NightTerrorsClient.IsEventActive = false; NightTerrorsClient.IsEventStarting = false; NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: event ended on client."); } private static void SetWeather(long sender, string envName) { if (!((Object)(object)EnvMan.instance == (Object)null)) { EnvMan.instance.SetForceEnvironment(envName); NightTerrorsPlugin.Log.LogInfo((object)("NightTerrors: weather set to '" + envName + "'.")); } } private static void PlayerDied(long sender) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { NightTerrorsPlugin.Log.LogInfo((object)$"NightTerrors: peer {sender} died."); NightTerrorsEvent.OnPlayerDied(sender); } } private static void KillSurvivor(long sender) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && NightTerrorsClient.IsEventActive) { NightTerrorsPlugin.Log.LogInfo((object)"NightTerrors: time limit — killing survivor."); HitData val = new HitData(); val.m_damage.m_blunt = 99999f; val.m_point = ((Component)localPlayer).transform.position; ((Character)localPlayer).Damage(val); } } } public enum Scenario { KeepGear, GoNaked, DifferentEquipment } public static class ScenarioSelector { public static readonly string[][] Kits = new string[5][] { new string[2] { "Club", "ShieldWood" }, new string[1] { "Torch" }, new string[1] { "FishingRod" }, new string[1] { "Hammer" }, new string[2] { "SwordBlackmetal", "ShieldBlackmetal" } }; public static Scenario Choose(string weightsConfig) { string[] array = weightsConfig.Split(','); int[] array2 = new int[4]; for (int i = 0; i < array2.Length; i++) { if (i < array.Length && int.TryParse(array[i].Trim(), out var result)) { array2[i] = Mathf.Max(0, result); } else { array2[i] = 1; } } int num = 0; int[] array3 = array2; foreach (int num2 in array3) { num += num2; } if (num <= 0) { return Scenario.KeepGear; } int num3 = Random.Range(0, num); int num4 = 0; for (int k = 0; k < array2.Length; k++) { num4 += array2[k]; if (num3 < num4) { return (Scenario)k; } } return Scenario.KeepGear; } public static string[] PickKit() { return Kits[Random.Range(0, Kits.Length)]; } }