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 RainDance v0.3.6
Pix.RainDance.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; 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 Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 Pix.RainDance { [BepInPlugin("Pix.RainDance", "RainDance", "0.3.6")] public sealed class RainDancePlugin : BaseUnityPlugin { private enum PendingMode { Weather, Sun } private struct PendingDestruct { public ZDOID Zdoid; public Vector3 Pos; public long StrikeAtMs; public long DestroyAtMs; public bool Struck; } private sealed class RainDanceTotem : MonoBehaviour, Hoverable, Interactable { private ZNetView _nview; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); } public string GetHoverName() { return "Rain Dance Totem"; } public string GetHoverText() { if (CfgEnabled == null || !CfgEnabled.Value) { return "Disabled"; } long num = NowMs(); long num2 = 0L; long val = 0L; if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { ZDO zDO = _nview.GetZDO(); num2 = zDO.GetLong("RD_RitualEndMs", 0L); val = zDO.GetLong("RD_CooldownEndMs", 0L); } if (num2 > num) { return "[E] Tempt the skies\n[F] Tempt the sun\n<color=#cfd7df>(ritual in progress)</color>"; } long num3 = Math.Max(GetGlobalCooldownEndMs(), val); string text = ((CfgSelfDestructAfterUse != null && CfgSelfDestructAfterUse.Value) ? "\n<color=#9fdcff>The wood smells of storm.</color>" : ""); if (num3 > num) { int num4 = Mathf.CeilToInt((float)(num3 - num) / 1000f); return $"[E] Tempt the skies\n[F] Tempt the sun\n<color=#cfd7df>(cooldown {num4}s)</color>{text}"; } return "[E] Tempt the skies\n[F] Tempt the sun" + text; } private bool ClientCanStartRitual() { long num = NowMs(); long num2 = 0L; long val = 0L; if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { ZDO zDO = _nview.GetZDO(); num2 = zDO.GetLong("RD_RitualEndMs", 0L); val = zDO.GetLong("RD_CooldownEndMs", 0L); } if (num2 > num) { return false; } long num3 = Math.Max(GetGlobalCooldownEndMs(), val); if (num3 > num) { return false; } return true; } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (hold) { return false; } if (CfgEnabled == null || !CfgEnabled.Value) { return true; } if (!ClientCanStartRitual()) { return true; } StartLocalRitualVibe(user); TryRegisterRpcs(force: false); ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return true; } if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ServerBeginRitual", new object[1] { _nview.GetZDO().m_uid }); } return true; } internal void TriggerSunRitual(Humanoid user) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (CfgEnabled != null && CfgEnabled.Value && ClientCanStartRitual()) { StartLocalRitualVibe(user); TryRegisterRpcs(force: false); ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null) { instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ServerBeginSunRitual", new object[1] { _nview.GetZDO().m_uid }); } } } private static void StartLocalRitualVibe(Humanoid user) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val != (Object)null) { try { val.StartEmote("dance", true); } catch { } if (CfgPlayDrumOnInteract != null && CfgPlayDrumOnInteract.Value) { float volume = ((CfgDrumVolume != null) ? Mathf.Clamp01(CfgDrumVolume.Value) : 0.75f); PlayOneShot(_drumClip, ((Component)val).transform.position, volume); } } } public bool UseItem(Humanoid user, ItemData item) { return false; } } private static class Patches { [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] private static void ZNetScene_Awake_Postfix(ZNetScene __instance) { EnsurePrefabLoaded(); RegisterPrefabInZNetScene(); ApplyPlacementAndBreakEffectsIfPossible(); TryRegisterRpcs(force: true); } [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] private static void ObjectDB_Awake_Postfix(ObjectDB __instance) { EnsurePrefabLoaded(); TryAddToHammer(__instance); ApplyBuildCostIfPossible(); ApplyPlacementAndBreakEffectsIfPossible(); } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPostfix] private static void ObjectDB_CopyOtherDB_Postfix(ObjectDB __instance) { EnsurePrefabLoaded(); TryAddToHammer(__instance); ApplyBuildCostIfPossible(); ApplyPlacementAndBreakEffectsIfPossible(); } [HarmonyPatch(typeof(EnvMan), "Update")] [HarmonyPostfix] private static void EnvMan_Update_Postfix(EnvMan __instance) { if (CfgEnabled == null || !CfgEnabled.Value) { return; } TryRegisterRpcs(force: false); LateInitOnce(); ApplyPlacementAndBreakEffectsIfPossible(); long num = NowMs(); if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ServerTick(); } else if (_clientForcedUntilMs > num) { ApplyEnvLocal(_clientForcedEnv); if (_clientForcedTimeEnabled) { ApplyDebugTimeLocal(enabled: true, _clientForcedTimeOfDay); } } else if (_clientForcedUntilMs != 0) { _clientForcedUntilMs = 0L; _clientForcedEnv = ""; ApplyEnvLocal(""); if (_clientForcedTimeEnabled) { _clientForcedTimeEnabled = false; ApplyDebugTimeLocal(enabled: false, 0.5f); } } } [HarmonyPatch(typeof(Player), "Update")] [HarmonyPostfix] private static void Player_Update_Postfix(Player __instance) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || CfgEnabled == null || !CfgEnabled.Value || CfgSunHotkey == null || IsTextInputOpen()) { return; } KeyboardShortcut value = CfgSunHotkey.Value; if (!((KeyboardShortcut)(ref value)).IsDown()) { return; } long num = NowMs(); long globalCooldownEndMs = GetGlobalCooldownEndMs(); if (globalCooldownEndMs > num) { return; } GameObject val = TryGetLocalHoverObject(__instance); if (!((Object)(object)val == (Object)null)) { RainDanceTotem rainDanceTotem = val.GetComponent<RainDanceTotem>() ?? val.GetComponentInParent<RainDanceTotem>() ?? val.GetComponentInChildren<RainDanceTotem>(true); if (!((Object)(object)rainDanceTotem == (Object)null)) { rainDanceTotem.TriggerSunRitual((Humanoid)(object)__instance); } } } catch { } } } [CompilerGenerated] private sealed class <LoadClipCoroutine>d__129 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Func<string> getFileName; public Action<AudioClip> assign; private string <pluginFolder>5__1; private string <fileName>5__2; private string <path>5__3; private string <url>5__4; private UnityWebRequest <req>5__5; private AudioClip <clip>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadClipCoroutine>d__129(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <pluginFolder>5__1 = null; <fileName>5__2 = null; <path>5__3 = null; <url>5__4 = null; <req>5__5 = null; <clip>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Invalid comparison between Unknown and I4 bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <pluginFolder>5__1 = Path.GetDirectoryName(typeof(RainDancePlugin).Assembly.Location) ?? Paths.PluginPath; <fileName>5__2 = ((getFileName != null) ? getFileName() : null) ?? ""; <fileName>5__2 = <fileName>5__2.Trim(); if (<fileName>5__2.Length == 0) { result = false; break; } <path>5__3 = Path.Combine(<pluginFolder>5__1, <fileName>5__2); if (!File.Exists(<path>5__3)) { result = false; break; } <url>5__4 = "file://" + <path>5__3.Replace("\\", "/"); <req>5__5 = UnityWebRequestMultimedia.GetAudioClip(<url>5__4, (AudioType)14); <>1__state = -3; <>2__current = <req>5__5.SendWebRequest(); <>1__state = 1; result = true; break; case 1: <>1__state = -3; if ((int)<req>5__5.result != 1) { result = false; <>m__Finally1(); break; } <clip>5__6 = null; try { <clip>5__6 = DownloadHandlerAudioClip.GetContent(<req>5__5); } catch { <clip>5__6 = null; } if ((Object)(object)<clip>5__6 != (Object)null) { assign?.Invoke(<clip>5__6); } <clip>5__6 = null; <>m__Finally1(); <req>5__5 = null; result = false; break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__5 != null) { ((IDisposable)<req>5__5).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "Pix.RainDance"; public const string PluginName = "RainDance"; public const string PluginVersion = "0.3.6"; internal static ManualLogSource Log; private static RainDancePlugin _instance; private static AssetBundle _bundle; private static GameObject _totemPrefab; private const string ZdoTotemCooldownEndMs = "RD_CooldownEndMs"; private const string ZdoTotemRitualEndMs = "RD_RitualEndMs"; private const string ZdoTotemRitualMode = "RD_RitualMode"; private const string ZdoTotemRitualNonce = "RD_RitualNonce"; private const string RpcServerBeginRitual = "RD_ServerBeginRitual"; private const string RpcServerBeginSunRitual = "RD_ServerBeginSunRitual"; private const string RpcClientSetEnv = "RD_ClientSetEnv"; private const string RpcClientVerdict = "RD_ClientVerdict"; private const string RpcClientSetGlobalCooldown = "RD_SetGlobalCooldown"; private const string RpcClientLightningVfx = "RD_ClientLightningVfx"; private const string RpcClientMythLine = "RD_ClientMythLine"; private const string RpcClientSetDebugTime = "RD_ClientSetDebugTime"; private static ConfigEntry<bool> CfgEnabled; private static ConfigEntry<string> CfgPreset; private static ConfigEntry<bool> CfgApplyMostlyClearNow; private static ConfigEntry<bool> CfgApplyChaosWeatherNow; private static ConfigEntry<float> CfgGlobalCooldownSeconds; private static ConfigEntry<float> CfgAnticipationSeconds; private static ConfigEntry<float> CfgForcedDurationSeconds; private static ConfigEntry<float> CfgChanceWeatherChange; private static ConfigEntry<float> CfgChanceGoodWhenChanging; private static ConfigEntry<string> CfgGoodEnvsCsv; private static ConfigEntry<string> CfgBadEnvsCsv; private static ConfigEntry<float> CfgClearWeatherBadBias; private static ConfigEntry<float> CfgClearWeatherChangeBoost; private static ConfigEntry<KeyboardShortcut> CfgSunHotkey; private static ConfigEntry<float> CfgSunChanceChange; private static ConfigEntry<float> CfgSunChanceGoodWhenChanging; private static ConfigEntry<string> CfgSunGoodEnvsCsv; private static ConfigEntry<string> CfgSunBadEnvsCsv; private static ConfigEntry<string> CfgSunGoodTimesCsv; private static ConfigEntry<string> CfgSunBadTimesCsv; private static ConfigEntry<bool> CfgPlayDrumOnInteract; private static ConfigEntry<float> CfgDrumVolume; private static ConfigEntry<string> CfgDrumFileName; private static ConfigEntry<bool> CfgPlayVerdictOnVerdict; private static ConfigEntry<float> CfgVerdictVolume; private static ConfigEntry<string> CfgVerdictFileName; private static ConfigEntry<bool> CfgEnableVerdictVfx; private static ConfigEntry<bool> CfgSelfDestructAfterUse; private static ConfigEntry<float> CfgSelfDestructDelaySeconds; private static ConfigEntry<bool> CfgSpawnLightningAoeServer; private static ConfigEntry<bool> CfgAlsoPlayClientLightningVfx; private static ConfigEntry<bool> CfgEnableMythLines; private static ConfigEntry<bool> CfgMythLinesRevealEnvInLogs; private static ConfigEntry<bool> CfgLogDebug; private static ConfigEntry<bool> CfgDebugForceWeatherChange; private static ConfigEntry<string> CfgBuildCostCsv; private static bool _rpcsRegistered; private static long _nextRpcRetryMs; private static bool _registeredInZNetScene; private static bool _addedToHammer; private static bool _costApplied; private static bool _effectsApplied; private static bool _iconApplied; private static string _serverForcedEnv = ""; private static long _serverForcedUntilMs = 0L; private static string _clientForcedEnv = ""; private static long _clientForcedUntilMs = 0L; private static bool _serverForcedTimeEnabled = false; private static float _serverForcedTimeOfDay = 0.5f; private static bool _clientForcedTimeEnabled = false; private static float _clientForcedTimeOfDay = 0.5f; private static long _serverGlobalCooldownEndMs = 0L; private static long _clientGlobalCooldownEndMs = 0L; private static bool _pending; private static PendingMode _pendingMode; private static ZDOID _pendingTotemZdoid; private static Vector3 _pendingTotemPos; private static long _pendingResolveAtMs; private static long _pendingNonce; private static AudioClip _drumClip; private static bool _drumClipRequested; private static AudioClip _verdictClip; private static bool _verdictClipRequested; private static long _nextForcedEnvBroadcastMs = 0L; private const string LightningAoePrefabName = "lightningAOE"; private static readonly List<PendingDestruct> _pendingDestructs = new List<PendingDestruct>(8); private static readonly FieldRef<Player, GameObject> PlayerHoveringRef = AccessTools.FieldRefAccess<Player, GameObject>("m_hovering"); private void Awake() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) _instance = this; Log = ((BaseUnityPlugin)this).Logger; _registeredInZNetScene = false; _addedToHammer = false; _costApplied = false; _effectsApplied = false; _iconApplied = false; _serverForcedTimeEnabled = false; _clientForcedTimeEnabled = false; CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable RainDance."); CfgPreset = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Preset", "MostlyClear", new ConfigDescription("Preset: Custom, MostlyClear, ChaosWeather", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "MostlyClear", "ChaosWeather" }), Array.Empty<object>())); CfgApplyMostlyClearNow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyMostlyClearNow", false, "Click to apply MostlyClear values now (auto-resets)."); CfgApplyChaosWeatherNow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyChaosWeatherNow", false, "Click to apply ChaosWeather values now (auto-resets)."); CfgGlobalCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "GlobalCooldownSeconds", 240f, "GLOBAL cooldown (seconds)."); CfgAnticipationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "AnticipationSeconds", 7f, "Dance time before verdict (seconds)."); CfgForcedDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ForcedDurationSeconds", 300f, "How long the chosen env is forced (seconds)."); CfgChanceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceWeatherChange", 0.75f, "WEATHER: Chance (0-1) the ritual changes weather (vs no change)."); CfgChanceGoodWhenChanging = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceGoodWhenChanging", 0.65f, "WEATHER: If changing weather, chance (0-1) it is Good vs Bad."); CfgGoodEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "GoodEnvsCsv", "Clear", "WEATHER: Good env pool."); CfgBadEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BadEnvsCsv", "Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm", "WEATHER: Bad env pool."); CfgClearWeatherBadBias = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherBadBias", 0.25f, "WEATHER: When weather is clear-ish, reduce Good chance by this amount."); CfgClearWeatherChangeBoost = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ClearWeatherChangeBoost", 0.1f, "WEATHER: When weather is clear-ish, boost ChanceWeatherChange by this amount."); CfgSunHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("SunRitual", "SunHotkey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Hotkey to Tempt the sun while hovering the totem."); CfgSunChanceChange = ((BaseUnityPlugin)this).Config.Bind<float>("SunRitual", "SunChanceChange", 0.8f, "SUN: Chance (0-1) to change to a sun/night outcome (vs no change). Default 0.80 (20% no change)."); CfgSunChanceGoodWhenChanging = ((BaseUnityPlugin)this).Config.Bind<float>("SunRitual", "SunChanceGoodWhenChanging", 0.75f, "SUN: If changing, chance (0-1) of 'good' (dawn/day/evening) vs 'bad' (night). Default 0.75."); CfgSunGoodEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunGoodEnvsCsv", "Clear,LightClouds,Twilight_Clear", "SUN: Good env pool (sun-ish)."); CfgSunBadEnvsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunBadEnvsCsv", "Darklands_dark,Misty", "SUN: Bad env pool (night-ish)."); CfgSunGoodTimesCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunGoodTimesCsv", "0.22,0.30,0.38,0.50,0.65,0.72", "SUN: Good time-of-day pool (0..1): dawn/morning/noon/evening."); CfgSunBadTimesCsv = ((BaseUnityPlugin)this).Config.Bind<string>("SunRitual", "SunBadTimesCsv", "0.00,0.05,0.90,0.95", "SUN: Bad time-of-day pool (0..1): midnight/late night."); CfgPlayDrumOnInteract = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayDrumOnInteract", true, "Play drum on ritual start (client-side)."); CfgDrumVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "DrumVolume", 0.75f, "Drum volume (0-1)."); CfgDrumFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "DrumFileName", "RD_Drums.ogg", "Drum filename."); CfgPlayVerdictOnVerdict = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "PlayVerdictOnVerdict", true, "Play verdict sting at verdict (client-side)."); CfgVerdictVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "VerdictVolume", 1f, "Verdict volume (0-1). Default 1.0 (100%)."); CfgVerdictFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "VerdictFileName", "RD_Verdict.ogg", "Verdict filename."); CfgEnableVerdictVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("VFX", "EnableVerdictVfx", true, "Spawn verdict VFX at verdict."); CfgSelfDestructAfterUse = ((BaseUnityPlugin)this).Config.Bind<bool>("Lore", "SelfDestructAfterUse", true, "After a ritual, the totem destroys itself."); CfgSelfDestructDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Lore", "SelfDestructDelaySeconds", 1.05f, "Delay between verdict and destruction (seconds)."); CfgSpawnLightningAoeServer = ((BaseUnityPlugin)this).Config.Bind<bool>("Lightning", "SpawnLightningAoeServer", true, "Spawn lightningAOE via ZNetScene.SpawnObject on the server (authoritative)."); CfgAlsoPlayClientLightningVfx = ((BaseUnityPlugin)this).Config.Bind<bool>("Lightning", "AlsoPlayClientLightningVfx", true, "Also tell every client to locally spawn lightningAOE for visuals (reliable)."); CfgEnableMythLines = ((BaseUnityPlugin)this).Config.Bind<bool>("Lore", "EnableMythLines", true, "Show cryptic myth lines instead of naming the env."); CfgMythLinesRevealEnvInLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "RevealEnvInLogs", false, "Debug only: print the chosen env/time to log."); CfgLogDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDebug", false, "Debug logs."); CfgDebugForceWeatherChange = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugForceWeatherChange", false, "WEATHER: Always change weather (testing)."); CfgBuildCostCsv = ((BaseUnityPlugin)this).Config.Bind<string>("BuildCost", "CostCsv", "Wood:10,Thunderstone:1", "Build cost as CSV: ItemName:Amount,ItemName:Amount ... Example: Wood:10,Thunderstone:1"); CfgBuildCostCsv.SettingChanged += delegate { _costApplied = false; }; CfgApplyMostlyClearNow.SettingChanged += delegate { if (CfgApplyMostlyClearNow.Value) { ApplyPresetValues("MostlyClear"); CfgPreset.Value = "MostlyClear"; CfgApplyMostlyClearNow.Value = false; } }; CfgApplyChaosWeatherNow.SettingChanged += delegate { if (CfgApplyChaosWeatherNow.Value) { ApplyPresetValues("ChaosWeather"); CfgPreset.Value = "ChaosWeather"; CfgApplyChaosWeatherNow.Value = false; } }; Harmony.CreateAndPatchAll(typeof(Patches), "Pix.RainDance"); EnsurePrefabLoaded(); TryRegisterRpcs(force: true); TryRequestDrumClipLoad(); TryRequestVerdictClipLoad(); } private static void ApplyPresetIfNeeded() { string text = ((CfgPreset != null) ? CfgPreset.Value : "MostlyClear") ?? "MostlyClear"; text = text.Trim(); if (!text.Equals("Custom", StringComparison.OrdinalIgnoreCase)) { ApplyPresetValues(text); } } private static void ApplyPresetValues(string preset) { if (!string.IsNullOrWhiteSpace(preset)) { preset = preset.Trim(); if (preset.Equals("MostlyClear", StringComparison.OrdinalIgnoreCase)) { CfgGlobalCooldownSeconds.Value = 240f; CfgAnticipationSeconds.Value = 7f; CfgForcedDurationSeconds.Value = 300f; CfgChanceWeatherChange.Value = 0.75f; CfgChanceGoodWhenChanging.Value = 0.68f; CfgGoodEnvsCsv.Value = "Clear"; CfgBadEnvsCsv.Value = "Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm"; CfgClearWeatherBadBias.Value = 0.25f; CfgClearWeatherChangeBoost.Value = 0.1f; } else if (preset.Equals("ChaosWeather", StringComparison.OrdinalIgnoreCase)) { CfgGlobalCooldownSeconds.Value = 120f; CfgAnticipationSeconds.Value = 7f; CfgForcedDurationSeconds.Value = 240f; CfgChanceWeatherChange.Value = 1f; CfgChanceGoodWhenChanging.Value = 0.5f; string value = "Clear,Rain,LightRain,ThunderStorm,Misty,Snow,SnowStorm"; CfgGoodEnvsCsv.Value = value; CfgBadEnvsCsv.Value = value; CfgClearWeatherBadBias.Value = 0.1f; CfgClearWeatherChangeBoost.Value = 0f; } } } private static void Dbg(string msg) { try { if (CfgLogDebug != null && CfgLogDebug.Value && Log != null) { Log.LogInfo((object)msg); } } catch { } } private static long NowMs() { try { if ((Object)(object)ZNet.instance != (Object)null) { return (long)(ZNet.instance.GetTimeSeconds() * 1000.0); } } catch { } return (long)((double)Time.realtimeSinceStartup * 1000.0); } private static void EnsurePrefabLoaded() { if ((Object)(object)_totemPrefab != (Object)null) { return; } try { string directoryName = Path.GetDirectoryName(typeof(RainDancePlugin).Assembly.Location); string text = Path.Combine(directoryName ?? Paths.PluginPath, "raindance"); if (!File.Exists(text)) { Log.LogError((object)("AssetBundle not found: " + text)); return; } if ((Object)(object)_bundle == (Object)null) { _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle == (Object)null) { Log.LogError((object)("Failed to load AssetBundle (null): " + text)); return; } } _totemPrefab = _bundle.LoadAsset<GameObject>("RD_Totem_Root"); if ((Object)(object)_totemPrefab == (Object)null) { Log.LogError((object)"Failed to load prefab 'RD_Totem_Root' from AssetBundle."); return; } Piece val = _totemPrefab.GetComponent<Piece>() ?? _totemPrefab.GetComponentInChildren<Piece>(true); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)(object)_totemPrefab) { _totemPrefab = ((Component)val).gameObject; } if ((Object)(object)_totemPrefab.GetComponent<RainDanceTotem>() == (Object)null) { _totemPrefab.AddComponent<RainDanceTotem>(); } } catch (Exception arg) { Log.LogError((object)$"Exception preparing prefab: {arg}"); } } private static void RegisterPrefabInZNetScene() { if (!_registeredInZNetScene && !((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)_totemPrefab == (Object)null)) { List<GameObject> prefabs = ZNetScene.instance.m_prefabs; if (prefabs != null && !prefabs.Contains(_totemPrefab)) { prefabs.Add(_totemPrefab); } _registeredInZNetScene = true; } } private static void TryAddToHammer(ObjectDB db) { if (_addedToHammer || (Object)(object)_totemPrefab == (Object)null || (Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0) { return; } GameObject itemPrefab = db.GetItemPrefab("Hammer"); if ((Object)(object)itemPrefab == (Object)null) { return; } PieceTable val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces; if (!((Object)(object)val == (Object)null)) { if (!val.m_pieces.Contains(_totemPrefab)) { val.m_pieces.Add(_totemPrefab); } _addedToHammer = true; } } private static List<(string item, int amount)> ParseCostCsv(string csv) { List<(string, int)> list = new List<(string, int)>(4); try { if (string.IsNullOrWhiteSpace(csv)) { return list; } string[] array = csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = (array[i] ?? "").Trim(); if (text.Length == 0) { continue; } int num = text.IndexOf(':'); if (num > 0) { string text2 = text.Substring(0, num).Trim(); string s = text.Substring(num + 1).Trim(); if (text2.Length != 0 && int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0) { list.Add((text2, result)); } } } } catch { } return list; } private static void ApplyBuildCostIfPossible() { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown if (_costApplied || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)_totemPrefab == (Object)null) { return; } try { Piece component = _totemPrefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } string csv = ((CfgBuildCostCsv != null) ? CfgBuildCostCsv.Value : "Wood:10,Thunderstone:1") ?? ""; List<(string, int)> list = ParseCostCsv(csv); if (list.Count == 0) { return; } List<Requirement> list2 = new List<Requirement>(list.Count); for (int i = 0; i < list.Count; i++) { (string, int) tuple = list[i]; string item = tuple.Item1; int item2 = tuple.Item2; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { Dbg("BuildCost item not found or not an ItemDrop: '" + item + "'"); continue; } list2.Add(new Requirement { m_resItem = val, m_amount = item2, m_recover = true }); } if (list2.Count > 0) { component.m_resources = list2.ToArray(); _costApplied = true; } } catch { } } private static Piece FindReferenceWoodPiece() { try { if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } string[] array = new string[7] { "wood_wall_1x1", "wood_wall_2x1", "wood_wall", "wood_floor_1x1", "wood_floor", "wood_pole", "wood_beam_2m" }; for (int i = 0; i < array.Length; i++) { GameObject prefab = ZNetScene.instance.GetPrefab(array[i]); if (!((Object)(object)prefab == (Object)null)) { Piece component = prefab.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null) && component.m_placeEffect.m_effectPrefabs != null && component.m_placeEffect.m_effectPrefabs.Length != 0) { return component; } } } } catch { } return null; } private static void ApplyPlacementAndBreakEffectsIfPossible() { if (_effectsApplied || (Object)(object)_totemPrefab == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } try { Piece component = _totemPrefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } Piece val = FindReferenceWoodPiece(); if ((Object)(object)val == (Object)null) { return; } if (val.m_placeEffect.m_effectPrefabs != null && val.m_placeEffect.m_effectPrefabs.Length != 0) { component.m_placeEffect = val.m_placeEffect; } WearNTear component2 = _totemPrefab.GetComponent<WearNTear>(); WearNTear component3 = ((Component)val).gameObject.GetComponent<WearNTear>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null) { if (component3.m_destroyedEffect.m_effectPrefabs != null && component3.m_destroyedEffect.m_effectPrefabs.Length != 0) { component2.m_destroyedEffect = component3.m_destroyedEffect; } if (component3.m_hitEffect.m_effectPrefabs != null && component3.m_hitEffect.m_effectPrefabs.Length != 0) { component2.m_hitEffect = component3.m_hitEffect; } } _effectsApplied = true; } catch { } } private static void TryRegisterRpcs(bool force) { if (_rpcsRegistered && !force) { return; } long num = NowMs(); if (!force && num < _nextRpcRetryMs) { return; } _nextRpcRetryMs = num + 500; ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null || _rpcsRegistered) { return; } try { instance.Register<ZDOID>("RD_ServerBeginRitual", (Action<long, ZDOID>)delegate(long sender, ZDOID totemZdoid) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ServerBeginRitual(totemZdoid, PendingMode.Weather); } }); instance.Register<ZDOID>("RD_ServerBeginSunRitual", (Action<long, ZDOID>)delegate(long sender, ZDOID totemZdoid) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { ServerBeginRitual(totemZdoid, PendingMode.Sun); } }); instance.Register<string, long>("RD_ClientSetEnv", (Action<long, string, long>)delegate(long sender, string env, long untilMs) { _clientForcedEnv = (env ?? "").Trim(); _clientForcedUntilMs = untilMs; ApplyEnvLocal(_clientForcedEnv); }); instance.Register<long>("RD_SetGlobalCooldown", (Action<long, long>)delegate(long sender, long untilMs) { _clientGlobalCooldownEndMs = untilMs; }); instance.Register<Vector3>("RD_ClientVerdict", (Action<long, Vector3>)delegate(long sender, Vector3 pos) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (CfgEnableVerdictVfx != null && CfgEnableVerdictVfx.Value) { SpawnVerdictVfx(pos); } if (CfgPlayVerdictOnVerdict != null && CfgPlayVerdictOnVerdict.Value) { float volume = ((CfgVerdictVolume != null) ? Mathf.Clamp01(CfgVerdictVolume.Value) : 1f); PlayOneShot(_verdictClip, pos, volume); } }); instance.Register<Vector3>("RD_ClientLightningVfx", (Action<long, Vector3>)delegate(long sender, Vector3 pos) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (CfgAlsoPlayClientLightningVfx == null || CfgAlsoPlayClientLightningVfx.Value) { SpawnLightningAoe_LocalVisual(pos); } }); instance.Register<string>("RD_ClientMythLine", (Action<long, string>)delegate(long sender, string line) { if ((CfgEnableMythLines == null || CfgEnableMythLines.Value) && (Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrWhiteSpace(line)) { MessageHud.instance.ShowMessage((MessageType)2, line, 0, (Sprite)null, false); } }); instance.Register<bool, float>("RD_ClientSetDebugTime", (Action<long, bool, float>)delegate(long sender, bool enabled, float tod) { _clientForcedTimeEnabled = enabled; _clientForcedTimeOfDay = Mathf.Repeat(tod, 1f); ApplyDebugTimeLocal(_clientForcedTimeEnabled, _clientForcedTimeOfDay); }); _rpcsRegistered = true; } catch (Exception arg) { _rpcsRegistered = false; try { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)$"[RainDance] RPC registration failed; will retry. {arg}"); } } catch { } } } private static long GetGlobalCooldownEndMs() { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return _serverGlobalCooldownEndMs; } return _clientGlobalCooldownEndMs; } private static void SetServerGlobalCooldownEndMs(long untilMs) { _serverGlobalCooldownEndMs = Math.Max(_serverGlobalCooldownEndMs, untilMs); try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_SetGlobalCooldown", new object[1] { _serverGlobalCooldownEndMs }); } } catch { } } private static void BroadcastEnvToClients(string env, long untilMs) { try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientSetEnv", new object[2] { (env ?? "").Trim(), untilMs }); } } catch { } } private static void BroadcastDebugTimeToClients(bool enabled, float tod) { try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientSetDebugTime", new object[2] { enabled, Mathf.Repeat(tod, 1f) }); } } catch { } } private static void BroadcastVerdict(Vector3 pos) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientVerdict", new object[1] { pos }); } } catch { } } private static void BroadcastLightningVfx(Vector3 pos) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientLightningVfx", new object[1] { pos }); } } catch { } } private static void BroadcastMythLine(string line) { try { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RD_ClientMythLine", new object[1] { line ?? "" }); } } catch { } } private static void ServerBeginRitual(ZDOID totemZdoid, PendingMode mode) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) long num = NowMs(); if (_pending) { return; } long globalCooldownEndMs = GetGlobalCooldownEndMs(); if (globalCooldownEndMs > num) { return; } ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(totemZdoid) : null); if (val == null) { return; } long @long = val.GetLong("RD_RitualEndMs", 0L); if (@long <= num) { long long2 = val.GetLong("RD_CooldownEndMs", 0L); if (long2 <= num) { long num2 = (long)(Mathf.Max(1f, CfgAnticipationSeconds.Value) * 1000f); long num3 = (long)(Mathf.Max(5f, CfgGlobalCooldownSeconds.Value) * 1000f); val.Set("RD_RitualEndMs", num + num2); val.Set("RD_RitualMode", (int)mode); val.Set("RD_RitualNonce", num); SetServerGlobalCooldownEndMs(num + num3); val.Set("RD_CooldownEndMs", num + num3); Vector3 position = val.GetPosition(); _pending = true; _pendingMode = mode; _pendingTotemZdoid = totemZdoid; _pendingTotemPos = position; _pendingResolveAtMs = num + num2; _pendingNonce = num; } } } private static void ServerTick() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } long num = NowMs(); if (_pending && num >= _pendingResolveAtMs) { ResolvePending(); } if (_serverForcedUntilMs > num) { ApplyEnvLocal(_serverForcedEnv); if (_serverForcedTimeEnabled) { ApplyDebugTimeLocal(enabled: true, _serverForcedTimeOfDay); } if (_nextForcedEnvBroadcastMs <= num) { _nextForcedEnvBroadcastMs = num + 10000; BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs); if (_serverForcedTimeEnabled) { BroadcastDebugTimeToClients(enabled: true, _serverForcedTimeOfDay); } } } else if (_serverForcedUntilMs != 0) { _serverForcedUntilMs = 0L; _serverForcedEnv = ""; ApplyEnvLocal(""); BroadcastEnvToClients("", 0L); if (_serverForcedTimeEnabled) { _serverForcedTimeEnabled = false; ApplyDebugTimeLocal(enabled: false, 0.5f); BroadcastDebugTimeToClients(enabled: false, 0.5f); } } TickPendingDestructs(num); } private static void ResolvePending() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) long now = NowMs(); _pending = false; ZDO val = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(_pendingTotemZdoid) : null); if (val == null) { BroadcastVerdict(_pendingTotemPos); MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos); SendMythLine(_pendingMode, "Interrupted"); return; } long @long = val.GetLong("RD_RitualNonce", 0L); if (@long == _pendingNonce) { val.Set("RD_RitualEndMs", 0L); if (_pendingMode == PendingMode.Sun) { ResolvePending_Sun(now); } else { ResolvePending_Weather(now); } } } private static void ResolvePending_Weather(long now) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(CfgChanceWeatherChange.Value); float num2 = Mathf.Clamp01(CfgChanceGoodWhenChanging.Value); string env = ""; try { if ((Object)(object)EnvMan.instance != (Object)null) { EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); if (currentEnvironment != null && !string.IsNullOrWhiteSpace(currentEnvironment.m_name)) { env = currentEnvironment.m_name.Trim(); } } } catch { env = ""; } if (IsClearish(env)) { num = Mathf.Clamp01(num + Mathf.Clamp01(CfgClearWeatherChangeBoost.Value)); num2 = Mathf.Clamp01(num2 - Mathf.Clamp01(CfgClearWeatherBadBias.Value)); } if (CfgDebugForceWeatherChange != null && CfgDebugForceWeatherChange.Value) { num = 1f; } if (!(Random.value <= num)) { BroadcastVerdict(_pendingTotemPos); MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos); SendMythLine(PendingMode.Weather, "NoChange"); return; } bool flag = Random.value <= num2; string text = PickEnvFromCsv(flag ? CfgGoodEnvsCsv.Value : CfgBadEnvsCsv.Value); if (string.IsNullOrWhiteSpace(text)) { text = (flag ? "Clear" : "Rain"); } long num3 = (long)(Mathf.Max(10f, CfgForcedDurationSeconds.Value) * 1000f); _serverForcedEnv = text.Trim(); _serverForcedUntilMs = Math.Max(_serverForcedUntilMs, now) + num3; _serverForcedTimeEnabled = false; ApplyEnvLocal(_serverForcedEnv); BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs); BroadcastVerdict(_pendingTotemPos); MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos); SendMythLine(PendingMode.Weather, _serverForcedEnv); } private static void ResolvePending_Sun(long now) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(CfgSunChanceChange.Value); float num2 = Mathf.Clamp01(CfgSunChanceGoodWhenChanging.Value); if (!(Random.value <= num)) { BroadcastVerdict(_pendingTotemPos); MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos); SendMythLine(PendingMode.Sun, "NoChange"); return; } bool flag = Random.value <= num2; string text = PickEnvFromCsv(flag ? CfgSunGoodEnvsCsv.Value : CfgSunBadEnvsCsv.Value); if (string.IsNullOrWhiteSpace(text)) { text = (flag ? "Clear" : "Darklands_dark"); } float num3 = PickTimeFromCsv(flag ? CfgSunGoodTimesCsv.Value : CfgSunBadTimesCsv.Value, flag ? 0.5f : 0f); long num4 = (long)(Mathf.Max(10f, CfgForcedDurationSeconds.Value) * 1000f); _serverForcedEnv = text.Trim(); _serverForcedUntilMs = Math.Max(_serverForcedUntilMs, now) + num4; _serverForcedTimeEnabled = true; _serverForcedTimeOfDay = Mathf.Repeat(num3, 1f); ApplyEnvLocal(_serverForcedEnv); ApplyDebugTimeLocal(enabled: true, _serverForcedTimeOfDay); BroadcastEnvToClients(_serverForcedEnv, _serverForcedUntilMs); BroadcastDebugTimeToClients(enabled: true, _serverForcedTimeOfDay); BroadcastVerdict(_pendingTotemPos); MaybeScheduleSelfDestruct(_pendingTotemZdoid, _pendingTotemPos); SendMythLine(PendingMode.Sun, flag ? "SunGood" : "SunBad"); } private static void SendMythLine(PendingMode mode, string key) { try { if (CfgEnableMythLines == null || CfgEnableMythLines.Value) { string mythLine = GetMythLine(mode, key ?? ""); if (!string.IsNullOrWhiteSpace(mythLine)) { BroadcastMythLine(mythLine); } } } catch { } } private static string PickRandom(string[] lines) { try { if (lines == null || lines.Length == 0) { return ""; } int num = Random.Range(0, lines.Length); if (num < 0 || num >= lines.Length) { num = 0; } return lines[num] ?? ""; } catch { return ""; } } private static string GetMythLine(PendingMode mode, string key) { string text = (key ?? "").Trim(); if (text.Equals("NoChange", StringComparison.OrdinalIgnoreCase)) { if (mode == PendingMode.Sun) { string[] lines = new string[3] { "Sól listens... and keeps her pace.", "Máni turns his face away.", "Heimdall hears you—yet the sky holds steady." }; return PickRandom(lines); } string[] lines2 = new string[4] { "Odin watches... and offers no omen.", "Heimdall keeps the gate closed.", "Freya turns away without a word.", "Thor does not lift Mjölnir today." }; return PickRandom(lines2); } if (text.Equals("Interrupted", StringComparison.OrdinalIgnoreCase)) { if (mode == PendingMode.Sun) { string[] lines3 = new string[3] { "Heimdall cuts the rite short.", "Odin snaps the thread—day and night refuse you.", "Máni blinks, and the moment is gone." }; return PickRandom(lines3); } string[] lines4 = new string[3] { "Odin cuts the thread. The skies refuse the tale.", "Heimdall scatters the rite before it takes root.", "Freya withdraws her hand—the omen breaks." }; return PickRandom(lines4); } if (mode == PendingMode.Sun) { if (text.Equals("SunGood", StringComparison.OrdinalIgnoreCase)) { string[] lines5 = new string[5] { "Sól smiles upon your steps.", "Freyr lifts the veil—warmth returns.", "Heimdall opens the gate of light.", "Odin's ravens circle, and the day stands tall.", "Baldr's calm drifts over the fields." }; return PickRandom(lines5); } if (text.Equals("SunBad", StringComparison.OrdinalIgnoreCase)) { string[] lines6 = new string[4] { "Máni draws the world into shadow.", "Skadi walks the long dark road.", "Odin closes one eye—and the night deepens.", "Hel's hush creeps into the grass." }; return PickRandom(lines6); } return "Heimdall shifts his gaze across the horizon."; } if (text.Equals("ThunderStorm", StringComparison.OrdinalIgnoreCase)) { string[] lines7 = new string[2] { "Thor answers your call.", "Thor raises Mjölnir in the clouds." }; return PickRandom(lines7); } if (text.Equals("Clear", StringComparison.OrdinalIgnoreCase) || text.Equals("LightClouds", StringComparison.OrdinalIgnoreCase) || text.Equals("Twilight_Clear", StringComparison.OrdinalIgnoreCase)) { string[] lines8 = new string[2] { "Freya swings her blade.", "Freya lays a calm hand on the sky." }; return PickRandom(lines8); } if (text.Equals("Rain", StringComparison.OrdinalIgnoreCase) || text.Equals("LightRain", StringComparison.OrdinalIgnoreCase)) { string[] lines9 = new string[2] { "Njord turns his gaze seaward.", "Njord sends his saltwind through the clouds." }; return PickRandom(lines9); } if (text.Equals("Misty", StringComparison.OrdinalIgnoreCase)) { string[] lines10 = new string[2] { "Odin veils the world with one eye.", "Odin's ravens vanish into the fog." }; return PickRandom(lines10); } if (text.Equals("Snow", StringComparison.OrdinalIgnoreCase) || text.Equals("SnowStorm", StringComparison.OrdinalIgnoreCase)) { string[] lines11 = new string[2] { "Skadi walks the white road.", "Skadi draws her cloak across the land." }; return PickRandom(lines11); } return "Odin stirs above."; } private static void MaybeScheduleSelfDestruct(ZDOID totemZdoid, Vector3 pos) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) try { if (CfgSelfDestructAfterUse != null && CfgSelfDestructAfterUse.Value) { float num = ((CfgSelfDestructDelaySeconds != null) ? Mathf.Max(0.05f, CfgSelfDestructDelaySeconds.Value) : 1.05f); long num2 = NowMs(); long strikeAtMs = num2 + Math.Max(0L, (long)(Mathf.Max(0f, num - 0.12f) * 1000f)); long destroyAtMs = num2 + (long)(num * 1000f); _pendingDestructs.Add(new PendingDestruct { Zdoid = totemZdoid, Pos = pos, StrikeAtMs = strikeAtMs, DestroyAtMs = destroyAtMs, Struck = false }); } } catch { } } private static void TickPendingDestructs(long now) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (_pendingDestructs.Count == 0) { return; } for (int num = _pendingDestructs.Count - 1; num >= 0; num--) { PendingDestruct value = _pendingDestructs[num]; if (!value.Struck && now >= value.StrikeAtMs) { value.Struck = true; _pendingDestructs[num] = value; if (CfgSpawnLightningAoeServer != null && CfgSpawnLightningAoeServer.Value) { SpawnLightningAoe_ServerAuthoritative(value.Pos); if (CfgAlsoPlayClientLightningVfx != null && CfgAlsoPlayClientLightningVfx.Value) { BroadcastLightningVfx(value.Pos); } } else { BroadcastLightningVfx(value.Pos); } } if (now >= value.DestroyAtMs) { _pendingDestructs.RemoveAt(num); DestroyTotemByZdoid(value.Zdoid); } } } private static void DestroyTotemByZdoid(ZDOID zdoid) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject val = null; try { val = ZNetScene.instance.FindInstance(zdoid); } catch { val = null; } if (!((Object)(object)val == (Object)null)) { ZNetView component = val.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.Destroy(); } else { Object.Destroy((Object)(object)val); } } } catch { } } private static void SpawnLightningAoe_ServerAuthoritative(Vector3 pos) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("lightningAOE"); if (!((Object)(object)prefab == (Object)null)) { ZNetScene.instance.SpawnObject(pos, Quaternion.identity, prefab); } } } catch { } } private static void SpawnLightningAoe_LocalVisual(Vector3 pos) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)ZNetScene.instance == (Object)null)) { GameObject prefab = ZNetScene.instance.GetPrefab("lightningAOE"); if (!((Object)(object)prefab == (Object)null)) { Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); } } } catch { } } private static bool IsClearish(string env) { if (string.IsNullOrWhiteSpace(env)) { return false; } string text = env.Trim(); if (text.Equals("Clear", StringComparison.OrdinalIgnoreCase)) { return true; } if (text.Equals("LightClouds", StringComparison.OrdinalIgnoreCase)) { return true; } if (text.Equals("Twilight_Clear", StringComparison.OrdinalIgnoreCase)) { return true; } if (text.IndexOf("clear", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } private static string PickEnvFromCsv(string csv) { try { if (string.IsNullOrWhiteSpace(csv)) { return ""; } string[] array = (from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select (s ?? "").Trim() into s where s.Length > 0 select s).ToArray(); if (array.Length == 0) { return ""; } return array[Random.Range(0, array.Length)]; } catch { return ""; } } private static float PickTimeFromCsv(string csv, float fallback) { try { if (string.IsNullOrWhiteSpace(csv)) { return Mathf.Repeat(fallback, 1f); } string[] array = (from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select (s ?? "").Trim() into s where s.Length > 0 select s).ToArray(); if (array.Length == 0) { return Mathf.Repeat(fallback, 1f); } List<float> list = new List<float>(array.Length); for (int i = 0; i < array.Length; i++) { if (float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && !float.IsNaN(result) && !float.IsInfinity(result)) { list.Add(Mathf.Repeat(result, 1f)); } } if (list.Count == 0) { return Mathf.Repeat(fallback, 1f); } return list[Random.Range(0, list.Count)]; } catch { return Mathf.Repeat(fallback, 1f); } } private static void ApplyEnvLocal(string env) { try { if (!((Object)(object)EnvMan.instance == (Object)null)) { EnvMan.instance.m_debugEnv = (env ?? "").Trim(); } } catch { } } private static void ApplyDebugTimeLocal(bool enabled, float tod) { try { if (!((Object)(object)EnvMan.instance == (Object)null)) { EnvMan.instance.m_debugTimeOfDay = enabled; if (enabled) { EnvMan.instance.m_debugTime = Mathf.Repeat(tod, 1f); } } } catch { } } private static void SpawnVerdictVfx(Vector3 pos) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } string[] array = new string[4] { "vfx_Potion_health_medium", "vfx_Potion_health_small", "vfx_Potion_health", "vfx_Healing" }; GameObject val = null; for (int i = 0; i < array.Length; i++) { val = ZNetScene.instance.GetPrefab(array[i]); if ((Object)(object)val != (Object)null) { break; } } if (!((Object)(object)val == (Object)null)) { Object.Instantiate<GameObject>(val, pos + Vector3.up * 1f, Quaternion.identity); } } catch { } } private static void TryRequestDrumClipLoad() { if (!_drumClipRequested && !((Object)(object)_instance == (Object)null) && CfgPlayDrumOnInteract != null && CfgPlayDrumOnInteract.Value) { _drumClipRequested = true; ((MonoBehaviour)_instance).StartCoroutine(LoadClipCoroutine(() => (CfgDrumFileName != null) ? CfgDrumFileName.Value : "RD_Drums.ogg", delegate(AudioClip clip) { _drumClip = clip; })); } } private static void TryRequestVerdictClipLoad() { if (!_verdictClipRequested && !((Object)(object)_instance == (Object)null) && CfgPlayVerdictOnVerdict != null && CfgPlayVerdictOnVerdict.Value) { _verdictClipRequested = true; ((MonoBehaviour)_instance).StartCoroutine(LoadClipCoroutine(() => (CfgVerdictFileName != null) ? CfgVerdictFileName.Value : "RD_Verdict.ogg", delegate(AudioClip clip) { _verdictClip = clip; })); } } [IteratorStateMachine(typeof(<LoadClipCoroutine>d__129))] private static IEnumerator LoadClipCoroutine(Func<string> getFileName, Action<AudioClip> assign) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadClipCoroutine>d__129(0) { getFileName = getFileName, assign = assign }; } private static void PlayOneShot(AudioClip clip, Vector3 pos, float volume) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)clip == (Object)null)) { float num = Mathf.Clamp01(volume); if (!(num <= 0f)) { AudioSource.PlayClipAtPoint(clip, pos, num); } } } catch { } } private static bool IsTextInputOpen() { try { if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return true; } } catch { } try { if (Console.IsVisible()) { return true; } } catch { } try { if (TextInput.IsVisible()) { return true; } } catch { } return false; } private static GameObject TryGetLocalHoverObject(Player p) { try { return ((Object)(object)p == (Object)null) ? null : PlayerHoveringRef.Invoke(p); } catch { return null; } } private static void LateInitOnce() { try { if (!_addedToHammer || !_costApplied) { EnsurePrefabLoaded(); if ((Object)(object)ZNetScene.instance != (Object)null) { RegisterPrefabInZNetScene(); } if ((Object)(object)ObjectDB.instance != (Object)null) { TryAddToHammer(ObjectDB.instance); ApplyBuildCostIfPossible(); } ApplyPlacementAndBreakEffectsIfPossible(); } } catch { } } } }