Decompiled source of BetterStorm v1.0.8
BepInEx/plugins/BetterStorm/BetterStorm.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("BetterStorm.Tests")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("BetterStorm")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8")] [assembly: AssemblyProduct("BetterStorm")] [assembly: AssemblyTitle("BetterStorm")] [assembly: AssemblyVersion("1.0.8.0")] [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 BetterStorm { [BepInPlugin("DogEggz.BetterStorm", "Better Storm", "1.0.8")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class BetterStormPlugin : BaseUnityPlugin { public const string PluginGuid = "DogEggz.BetterStorm"; public const string PluginName = "Better Storm"; public const string PluginVersion = "1.0.8"; public const string ChaoticWindGuid = "com.pete.sailwind.windconfigurator"; public const string ClimateGuid = "com.raddude.climate"; public const string BorderExpanderGuid = "com.nandbrew.borderexpander"; private Harmony harmony; private ConfigEntry<string> debugStormButtons; private readonly Dictionary<CustomStormId, ConfigEntry<bool>> stormEnabledEntries = new Dictionary<CustomStormId, ConfigEntry<bool>>(); internal static BetterStormPlugin Instance { get; private set; } internal ConfigEntry<bool> DisableSeasonLimits { get; private set; } internal ConfigEntry<float> FallbackBonusCap { get; private set; } internal ConfigEntry<int> RelocationDistance { get; private set; } private void Awake() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown Instance = this; if (!StormCatalog.TryValidate(out var error)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Better Storm cannot start: " + error)); Instance = null; ((Behaviour)this).enabled = false; return; } BindConfiguration(); if (ChaoticWindCompatibility.HasLegacyStormOwner()) { ((BaseUnityPlugin)this).Logger.LogError((object)"Better Storm cannot start while the legacy storm-owning Chaotic Wind 1.3.4 build is loaded. Install the reduced Chaotic Wind companion separately, or remove Chaotic Wind."); Instance = null; ((Behaviour)this).enabled = false; return; } Subscribe(); harmony = new Harmony("DogEggz.BetterStorm"); harmony.PatchAll(Assembly.GetExecutingAssembly()); ClimateCompatibility.Install(harmony); ApplyRuntimeSettings(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Better Storm 1.0.8 loaded."); } private void Update() { WindOverrideState.Tick(); SandstormVisuals.Tick(); SandstormDirt.Tick(); } private void OnDestroy() { Unsubscribe(); WindOverrideState.RestoreImmediately(); MediEastStormSetting.Apply(enabled: false); SandstormVisuals.Shutdown(); SandstormDirt.Reset(); GlobalLightningSettings.RestoreSnapshots(); ThunderPoolRegistry.Shutdown(); ModStormFactory.Shutdown(); StormPositionPersistence.ResetAll(); if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void BindConfiguration() { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown for (int i = 0; i < StormCatalog.Custom.Length; i++) { StormDefinition stormDefinition = StormCatalog.Custom[i]; stormEnabledEntries.Add(stormDefinition.Id, ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Storms", "Enable " + stormDefinition.Name, true, stormDefinition.EnableDescription)); } DisableSeasonLimits = ((BaseUnityPlugin)this).Config.Bind<bool>("Climate Compatibility", "Disable Seasonal Storm Limits", false, "Allow Hurricane, Sandstorm, and Dry Thunderstorm year-round, even while Climate Custom Winds is enabled."); FallbackBonusCap = BindSteppedSlider("Wind", "Storm + Ocean Bonus Cap", 40f, 0f, 100f, 1f, "Used when Chaotic Wind is not installed. Chaotic Wind's setting has priority when both mods are installed.", 10); RelocationDistance = ((BaseUnityPlugin)this).Config.Bind<int>("Storms", "Storm Relocation Distance", 44000, new ConfigDescription("Distance at which a custom storm is recycled across the player. Increasing this reduces the chance of encountering a storm.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(18000, 90000), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = false, Order = 10 } })); debugStormButtons = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "Custom Storm Controls", string.Empty, new ConfigDescription("Always-available storm controls. Expand the compact panel to summon or push a custom storm to its outer weather edge.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = DebugStormControls.DrawButtons, HideDefaultButton = true, HideSettingName = true, Order = -10 } })); } private ConfigEntry<float> BindSteppedSlider(string section, string key, float defaultValue, float minimum, float maximum, float step, string description, int order) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new SteppedAcceptableValueRange(minimum, maximum, step), new object[1] { new ConfigurationManagerAttributes { ShowRangeAsPercent = false, Order = order } })); } private void Subscribe() { foreach (ConfigEntry<bool> value in stormEnabledEntries.Values) { value.SettingChanged += OnStormToggleChanged; } DisableSeasonLimits.SettingChanged += OnStormToggleChanged; } private void Unsubscribe() { foreach (ConfigEntry<bool> value in stormEnabledEntries.Values) { value.SettingChanged -= OnStormToggleChanged; } if (DisableSeasonLimits != null) { DisableSeasonLimits.SettingChanged -= OnStormToggleChanged; } } private void OnStormToggleChanged(object sender, EventArgs e) { ModStormFactory.ApplyEnabledState(); MediEastStormSetting.Apply(ModStormFactory.AnyMediStormEnabled); if (!IsEnabled(CustomStormId.Sandstorm)) { SandstormVisuals.Deactivate(); SandstormDirt.Reset(); } RefreshCurrentStorm(); WindOverrideState.Tick(); } private void ApplyRuntimeSettings() { ModStormFactory.ApplyEnabledState(); MediEastStormSetting.Apply(ModStormFactory.AnyMediStormEnabled); ModStormFactory.RefreshSandstormCloudVisuals(); GlobalLightningSettings.ApplyToLiveStorms(); } internal bool IsEnabled(CustomStormId id) { if (stormEnabledEntries.TryGetValue(id, out var value)) { return value.Value; } return false; } internal void LogFeatureInfo(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } internal void LogFeatureWarning(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); } internal void LogFeatureError(string message) { ((BaseUnityPlugin)this).Logger.LogError((object)message); } internal static void RefreshCurrentStorm() { WeatherStorms instance = WeatherStorms.instance; if (GameState.playing && !((Object)(object)instance == (Object)null)) { instance.FindClosestStorm(); if ((Object)(object)instance.GetCurrentStorm() != (Object)null) { instance.ApplyStorm(); } } } } internal static class ChaoticWindCompatibility { internal static bool IsLoaded => Chainloader.PluginInfos.ContainsKey("com.pete.sailwind.windconfigurator"); internal static bool HasLegacyStormOwner() { if (!Chainloader.PluginInfos.TryGetValue("com.pete.sailwind.windconfigurator", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { return false; } return ((object)value.Instance).GetType().Assembly.GetType("ChaoticWind.StormInfluenceService", throwOnError: false) != null; } internal static bool TryGetFloat(string section, string key, out float value) { value = 0f; if (!TryGetPlugin(out var info)) { return false; } ConfigEntry<float> val = default(ConfigEntry<float>); if (!info.Instance.Config.TryGetEntry<float>(section, key, ref val)) { return false; } value = val.Value; return true; } internal static bool TryGetBool(string section, string key, out bool value) { value = false; if (!TryGetPlugin(out var info)) { return false; } ConfigEntry<bool> val = default(ConfigEntry<bool>); if (!info.Instance.Config.TryGetEntry<bool>(section, key, ref val)) { return false; } value = val.Value; return true; } private static bool TryGetPlugin(out PluginInfo info) { if (Chainloader.PluginInfos.TryGetValue("com.pete.sailwind.windconfigurator", out info) && info != null) { return (Object)(object)info.Instance != (Object)null; } return false; } } [Flags] internal enum ClimateSeasonMask { None = 0, Winter = 1, Spring = 2, Summer = 4, Autumn = 8, All = 0xF } internal static class ClimateSeasonCompatibility { private const int DefaultYearLength = 92; internal static bool Allows(StormDefinition definition) { if (definition == null || definition.AllowedClimateSeasons == ClimateSeasonMask.All) { return true; } BetterStormPlugin instance = BetterStormPlugin.Instance; if ((Object)(object)instance == (Object)null || instance.DisableSeasonLimits.Value || !TryGetActiveClimateYear(out var yearLength)) { return true; } ClimateSeasonMask season = GetSeason(GameState.day, yearLength); return (definition.AllowedClimateSeasons & season) != 0; } internal static ClimateSeasonMask GetSeason(int day, int yearLength) { int num = Math.Max(4, yearLength); int num2 = day % num; if (num2 < 0) { num2 += num; } int num3 = num / 4; if (num2 < num3) { return ClimateSeasonMask.Winter; } if (num2 < num3 * 2) { return ClimateSeasonMask.Spring; } if (num2 < num3 * 3) { return ClimateSeasonMask.Summer; } return ClimateSeasonMask.Autumn; } private static bool TryGetActiveClimateYear(out int yearLength) { yearLength = 92; ConfigEntry<bool> val = default(ConfigEntry<bool>); if (!Chainloader.PluginInfos.TryGetValue("com.raddude.climate", out var value) || value == null || (Object)(object)value.Instance == (Object)null || !value.Instance.Config.TryGetEntry<bool>("Settings", "Enable Custom Winds", ref val) || !val.Value) { return false; } ConfigEntry<int> val2 = default(ConfigEntry<int>); if (value.Instance.Config.TryGetEntry<int>("Settings", "Days In A Year", ref val2)) { yearLength = val2.Value; } return yearLength >= 4; } } internal sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public bool? HideDefaultButton; public bool? HideSettingName; public string DispName; public int? Order; } internal sealed class SteppedAcceptableValueRange : AcceptableValueRange<float> { private readonly float step; internal SteppedAcceptableValueRange(float minimum, float maximum, float step) : base(minimum, maximum) { this.step = step; } public override object Clamp(object value) { float num = (float)base.Clamp(value); return Mathf.Clamp(((AcceptableValueRange<float>)this).MinValue + Mathf.Floor((num - ((AcceptableValueRange<float>)this).MinValue) / step + 0.5f) * step, ((AcceptableValueRange<float>)this).MinValue, ((AcceptableValueRange<float>)this).MaxValue); } public override bool IsValid(object value) { if (!(value is float num)) { return false; } return Mathf.Approximately(num, (float)((AcceptableValueBase)this).Clamp((object)num)); } } internal static class DebugStormControls { private const float DrawerWidth = 230f; private static bool expanded; internal static void DrawButtons(ConfigEntryBase unused) { if (GUILayout.Button(expanded ? "[-] Storm Debug Controls" : "[+] Storm Debug Controls", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) })) { expanded = !expanded; } if (expanded) { GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); for (int i = 0; i < StormCatalog.Custom.Length; i++) { StormDefinition stormDefinition = StormCatalog.Custom[i]; DrawControls(stormDefinition.Name, stormDefinition.Id); } GUILayout.EndVertical(); } } internal static bool Summon(CustomStormId id) { //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!TryGetContext(id, out var controller, out var weatherStorms, out var player)) { return false; } ThunderPoolRegistry.Reset(controller); Vector3 position = player.position; position.y = ((Component)controller).transform.position.y; ((Component)controller).transform.position = position; controller.PrepareDebugMove(resetLightningCooldown: true); WindOverrideState.NotifyDebugSummon(controller.Definition.Kind); Refresh(weatherStorms); BetterStormPlugin.Instance.LogFeatureInfo("Debug summoned " + controller.Definition.Name + "."); return true; } internal static bool PushToOuterEdge(CustomStormId id) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!TryGetContext(id, out var controller, out var weatherStorms, out var player)) { return false; } float weatherRange = StormInfluenceService.GetWeatherRange(weatherStorms, controller); float num = controller.Definition.Radius + weatherRange; Vector3 val = ((Component)controller).transform.position - player.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = player.forward; val.y = 0f; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } else { ((Vector3)(ref val)).Normalize(); } ThunderPoolRegistry.Reset(controller); Vector3 position = player.position + val * num; position.y = ((Component)controller).transform.position.y; ((Component)controller).transform.position = position; controller.PrepareDebugMove(resetLightningCooldown: false); Refresh(weatherStorms); BetterStormPlugin.Instance.LogFeatureInfo("Debug pushed " + controller.Definition.Name + " to outer edge " + num.ToString("0.0") + "."); return true; } private static void DrawControls(string label, CustomStormId id) { bool enabled = GUI.enabled; GUI.enabled = enabled && CanOperate(id); GUILayout.Space(4f); GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) }); if (GUILayout.Button("Summon", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) })) { Summon(id); } if (GUILayout.Button("Push to outer edge", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) })) { PushToOuterEdge(id); } GUI.enabled = enabled; } private static bool CanOperate(CustomStormId id) { BetterStormPlugin instance = BetterStormPlugin.Instance; ModStormController modStormController = ModStormFactory.Find(id); if ((Object)(object)instance != (Object)null && instance.IsEnabled(id) && GameState.playing && (Object)(object)modStormController != (Object)null && modStormController.ShouldBeActive() && (Object)(object)WeatherStorms.instance != (Object)null) { return (Object)(object)Camera.main != (Object)null; } return false; } private static bool TryGetContext(CustomStormId id, out ModStormController controller, out WeatherStorms weatherStorms, out Transform player) { controller = ModStormFactory.Find(id); weatherStorms = WeatherStorms.instance; player = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : null); if (!CanOperate(id) || (Object)(object)controller == (Object)null || (Object)(object)weatherStorms == (Object)null || (Object)(object)player == (Object)null) { BetterStormPlugin.Instance?.LogFeatureWarning("Debug storm action is unavailable for " + id.ToString() + "."); return false; } return true; } private static void Refresh(WeatherStorms weatherStorms) { weatherStorms.FindClosestStorm(); if ((Object)(object)weatherStorms.GetCurrentStorm() != (Object)null) { weatherStorms.ApplyStorm(); } WindOverrideState.Tick(); } } [HarmonyPatch(typeof(WanderingStormLightning), "LightningStrike")] internal static class UniversalLightningPatch { [HarmonyPrefix] private static bool Prefix(WanderingStormLightning __instance) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) BetterStormPlugin instance = BetterStormPlugin.Instance; if ((Object)(object)instance == (Object)null) { return true; } ModStormController componentInParent = ((Component)__instance).GetComponentInParent<ModStormController>(); if ((Object)(object)componentInParent != (Object)null && (!instance.IsEnabled(componentInParent.Definition.Id) || !componentInParent.Definition.SupportsLightning)) { return false; } LightningProfile lightningProfile = (((Object)(object)componentInParent != (Object)null) ? componentInParent.Definition.Lightning : StormCatalog.VanillaLightning); float num = Mathf.Max(0.01f, lightningProfile.Interval); StormAccess.LightningCooldown.Invoke(__instance) = Random.Range(num, num * 3f); Vector2 val = Random.insideUnitCircle * lightningProfile.SpawnRadius; ((Component)__instance).transform.localPosition = new Vector3(val.x, lightningProfile.StrikeHeight, val.y); Vector3 position = ((Component)__instance).transform.position; if ((Object)(object)Refs.observerMirror == (Object)null) { return false; } float num2 = Vector3.Distance(position, ((Component)Refs.observerMirror).transform.position); float delay = Mathf.Max(0f, num2 / 340f - 1.47f); if (num2 <= lightningProfile.SchedulingDistance) { AudioClip[] array = ((num2 > 1600f) ? __instance.farThunders : __instance.closeThunders); if (array != null && array.Length != 0) { AudioClip clip = array[Random.Range(0, array.Length)]; ThunderPoolRegistry.Play(__instance, position, clip, delay, lightningProfile.AudioSourceMaxDistance); } } Light val2 = StormAccess.LightningLight.Invoke(__instance); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)__instance).GetComponent<Light>(); } ParticleSystem val3 = StormAccess.LightningParticles.Invoke(__instance); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)__instance).GetComponent<ParticleSystem>(); } if ((Object)(object)val2 != (Object)null) { val2.range = lightningProfile.LightRange; StormAccess.LightningIntensity.Invoke(__instance) = lightningProfile.LightIntensity; GlobalLightningSettings.ApplyToLight(val2); } if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && num2 <= lightningProfile.VisualMaximum) { ((Behaviour)val2).enabled = true; val2.intensity = lightningProfile.LightIntensity; StormAccess.LightningLightTimer.Invoke(__instance) = 0f; val3.Play(); } return false; } } internal static class ThunderPoolRegistry { private static readonly Dictionary<WanderingStormLightning, ThunderEmitterPool> Pools = new Dictionary<WanderingStormLightning, ThunderEmitterPool>(); internal static void Play(WanderingStormLightning owner, Vector3 fixedWorldPosition, AudioClip clip, float delay, float maximumDistance) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)owner == (Object)null || (Object)(object)clip == (Object)null) { return; } if (!Pools.TryGetValue(owner, out var value) || value == null) { AudioSource val = StormAccess.LightningAudio1.Invoke(owner); if ((Object)(object)val == (Object)null) { val = StormAccess.LightningAudio2.Invoke(owner); } if ((Object)(object)val == (Object)null) { AudioSource[] components = ((Component)owner).GetComponents<AudioSource>(); if (components.Length != 0) { val = components[0]; } } if ((Object)(object)val == (Object)null) { return; } value = new ThunderEmitterPool(owner, val); Pools[owner] = value; } value.Play(fixedWorldPosition, clip, delay, maximumDistance); } internal static void Reset(ModStormController controller) { if ((Object)(object)controller == (Object)null) { return; } WanderingStormLightning[] componentsInChildren = ((Component)controller).GetComponentsInChildren<WanderingStormLightning>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (Pools.TryGetValue(componentsInChildren[i], out var value)) { value.StopAll(); } } } internal static void ResetAll() { foreach (ThunderEmitterPool value in Pools.Values) { value?.StopAll(); } } internal static void Shutdown() { foreach (ThunderEmitterPool value in Pools.Values) { value?.Dispose(); } Pools.Clear(); } } internal sealed class ThunderEmitterPool { private sealed class Slot { internal GameObject Object; internal AudioSource Source; internal double BusyUntilDsp; } private const int MaximumEmitters = 30; private readonly WanderingStormLightning owner; private readonly AudioSource template; private readonly GameObject root; private readonly List<Slot> slots = new List<Slot>(); private double nextExhaustionWarningDsp; internal ThunderEmitterPool(WanderingStormLightning owner, AudioSource template) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown this.owner = owner; this.template = template; root = new GameObject("Better Storm fixed thunder pool"); if ((Object)(object)Refs.shiftingWorld != (Object)null) { root.transform.SetParent(Refs.shiftingWorld, true); } else { Object.DontDestroyOnLoad((Object)(object)root); } AddSlot(); AddSlot(); } internal void Play(Vector3 worldPosition, AudioClip clip, float delay, float maximumDistance) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) double dspTime = AudioSettings.dspTime; Slot slot = null; for (int i = 0; i < slots.Count; i++) { if (slots[i].BusyUntilDsp <= dspTime) { slot = slots[i]; break; } } if (slot == null && slots.Count < 30) { slot = AddSlot(); } if (slot == null) { if (dspTime >= nextExhaustionWarningDsp) { nextExhaustionWarningDsp = dspTime + 10.0; BetterStormPlugin.Instance?.LogFeatureWarning("Thunder emitter pool exhausted for " + ((Object)owner).name + "."); } } else { slot.Object.transform.position = worldPosition; slot.Source.minDistance = 250f; slot.Source.maxDistance = maximumDistance; slot.Source.clip = clip; double num = dspTime + (double)Mathf.Max(0f, delay); slot.BusyUntilDsp = num + (double)clip.length + 0.1; slot.Source.PlayScheduled(num); } } internal void StopAll() { for (int i = 0; i < slots.Count; i++) { if ((Object)(object)slots[i].Source != (Object)null) { slots[i].Source.Stop(); slots[i].Source.clip = null; } slots[i].BusyUntilDsp = 0.0; } } internal void Dispose() { StopAll(); if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } } private Slot AddSlot() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown GameObject val = new GameObject("Fixed thunder emitter"); val.transform.SetParent(root.transform, false); AudioSource val2 = val.AddComponent<AudioSource>(); CopySettings(template, val2); val2.playOnAwake = false; val2.loop = false; val2.minDistance = 250f; Slot slot = new Slot { Object = val, Source = val2, BusyUntilDsp = 0.0 }; slots.Add(slot); return slot; } private static void CopySettings(AudioSource from, AudioSource to) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown to.outputAudioMixerGroup = from.outputAudioMixerGroup; to.mute = from.mute; to.bypassEffects = from.bypassEffects; to.bypassListenerEffects = from.bypassListenerEffects; to.bypassReverbZones = from.bypassReverbZones; to.priority = from.priority; to.volume = from.volume; to.pitch = from.pitch; to.panStereo = from.panStereo; to.spatialBlend = from.spatialBlend; to.reverbZoneMix = from.reverbZoneMix; to.dopplerLevel = from.dopplerLevel; to.spread = from.spread; to.rolloffMode = from.rolloffMode; to.maxDistance = from.maxDistance; AudioSourceCurveType[] array = new AudioSourceCurveType[4]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); AudioSourceCurveType[] array2 = (AudioSourceCurveType[])(object)array; for (int i = 0; i < array2.Length; i++) { AnimationCurve customCurve = from.GetCustomCurve(array2[i]); if (customCurve != null) { to.SetCustomCurve(array2[i], new AnimationCurve(customCurve.keys)); } } } } internal static class GlobalLightningSettings { private static readonly Dictionary<Light, LightShadows> OriginalShadows = new Dictionary<Light, LightShadows>(); internal static void ApplyToLiveStorms() { WanderingStormLightning[] array = Resources.FindObjectsOfTypeAll<WanderingStormLightning>(); for (int i = 0; i < array.Length; i++) { Light val = StormAccess.LightningLight.Invoke(array[i]); if ((Object)(object)val == (Object)null) { val = ((Component)array[i]).GetComponent<Light>(); } ApplyToLight(val); } } internal static void ApplyToLight(Light light) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)light == (Object)null)) { if (!OriginalShadows.ContainsKey(light)) { OriginalShadows.Add(light, light.shadows); } light.shadows = (LightShadows)1; } } internal static void RestoreSnapshots() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<Light, LightShadows> originalShadow in OriginalShadows) { if ((Object)(object)originalShadow.Key != (Object)null) { originalShadow.Key.shadows = originalShadow.Value; } } OriginalShadows.Clear(); } } internal static class StormPositionCoordinates { internal static Vector3 ToSaveCoordinates(Vector3 runtimePosition) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) FloatingOriginManager instance = FloatingOriginManager.instance; if (!((Object)(object)instance != (Object)null)) { return runtimePosition; } return instance.ShiftingPosToRealPos(runtimePosition); } internal static Vector3 ToRuntimeCoordinates(Vector3 savedPosition) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) FloatingOriginManager instance = FloatingOriginManager.instance; if (!((Object)(object)instance != (Object)null)) { return savedPosition; } return instance.RealPosToShiftingPos(savedPosition); } } internal static class StormPositionPersistence { internal sealed class PositionOwner { private readonly CustomStormId stormId; private readonly string displayName; private readonly string betterStormV2Key; private bool loadCompleted; private bool hasLoadedPosition; private Vector3 loadedPosition; internal CustomStormId StormId => stormId; internal PositionOwner(CustomStormId stormId, string displayName, string betterStormV2Key) { this.stormId = stormId; this.displayName = displayName; this.betterStormV2Key = betterStormV2Key; } internal void BeginLoad() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) loadCompleted = false; hasLoadedPosition = false; loadedPosition = default(Vector3); } internal void Save() { //IL_002d: 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) //IL_0037: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) ModStormController modStormController = ModStormFactory.Find(stormId); if (!((Object)(object)modStormController == (Object)null)) { if (GameState.modData == null) { GameState.modData = new Dictionary<string, string>(); } Vector3 val = StormPositionCoordinates.ToSaveCoordinates(((Component)modStormController).transform.position); SaveData saveData = new SaveData { version = 2, x = val.x, y = val.y, z = val.z }; GameState.modData[betterStormV2Key] = JsonUtility.ToJson((object)saveData); } } internal void Load() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) loadCompleted = true; hasLoadedPosition = false; if (TryLoadKey(betterStormV2Key, out var position)) { loadedPosition = position; hasLoadedPosition = true; } ApplyLoadedPosition(ModStormFactory.Find(stormId)); } internal void ApplyLoadedPosition(ModStormController controller) { //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) if (loadCompleted && hasLoadedPosition && !((Object)(object)controller == (Object)null)) { ((Component)controller).transform.position = StormPositionCoordinates.ToRuntimeCoordinates(loadedPosition); } } internal void Reset() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) loadCompleted = false; hasLoadedPosition = false; loadedPosition = default(Vector3); } private bool TryLoadKey(string key, out Vector3 position) { //IL_0001: 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_00be: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (GameState.modData == null || !GameState.modData.TryGetValue(key, out var value) || string.IsNullOrEmpty(value)) { return false; } try { SaveData saveData = JsonUtility.FromJson<SaveData>(value); if (saveData == null || saveData.version != 2 || !IsFinite(saveData.x) || !IsFinite(saveData.y) || !IsFinite(saveData.z)) { BetterStormPlugin.Instance?.LogFeatureWarning("Ignoring invalid " + displayName + " save data in key " + key + "."); return false; } position = new Vector3(saveData.x, saveData.y, saveData.z); return true; } catch (Exception ex) { BetterStormPlugin.Instance?.LogFeatureWarning("Ignoring invalid " + displayName + " save data in key " + key + ": " + ex.Message); return false; } } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } [Serializable] private sealed class SaveData { public int version; public float x; public float y; public float z; } private static readonly PositionOwner[] Owners = BuildOwners(); private static PositionOwner[] BuildOwners() { PositionOwner[] array = new PositionOwner[StormCatalog.Custom.Length]; for (int i = 0; i < StormCatalog.Custom.Length; i++) { StormDefinition stormDefinition = StormCatalog.Custom[i]; array[i] = new PositionOwner(stormDefinition.Id, stormDefinition.Name, stormDefinition.SaveKey); } return array; } internal static void BeginLoadAll() { for (int i = 0; i < Owners.Length; i++) { Owners[i].BeginLoad(); } } internal static void LoadAll() { for (int i = 0; i < Owners.Length; i++) { Owners[i].Load(); } } internal static void SaveAll() { for (int i = 0; i < Owners.Length; i++) { Owners[i].Save(); } } internal static void ResetAll() { for (int i = 0; i < Owners.Length; i++) { Owners[i].Reset(); } } internal static void ApplyLoadedPosition(CustomStormId id, ModStormController controller) { for (int i = 0; i < Owners.Length; i++) { if (Owners[i].StormId == id) { Owners[i].ApplyLoadedPosition(controller); break; } } } } [HarmonyPatch(typeof(SaveLoadManager), "LoadGame")] internal static class CustomStormBeginLoadPatch { [HarmonyPrefix] private static void Prefix() { WindOverrideState.RestoreImmediately(); ThunderPoolRegistry.Shutdown(); SandstormVisuals.Shutdown(); SandstormDirt.Reset(); StormPositionPersistence.BeginLoadAll(); } } [HarmonyPatch(typeof(SaveLoadManager), "SaveModData")] internal static class CustomStormSavePatch { [HarmonyPostfix] private static void Postfix() { StormPositionPersistence.SaveAll(); } } [HarmonyPatch(typeof(SaveLoadManager), "LoadModData")] internal static class CustomStormLoadPatch { [HarmonyPostfix] private static void Postfix() { StormPositionPersistence.LoadAll(); } } internal enum CustomStormId { Squall1, Squall2, Squall3, Hurricane, DryThunderstorm, Sandstorm } internal enum StormKind { Vanilla, Squall, Hurricane, DryThunderstorm, Sandstorm } internal readonly struct LightningProfile { internal readonly float Interval; internal readonly float SpawnRadius; internal readonly float SchedulingDistance; internal readonly float AudioSourceMaxDistance; internal readonly float LightRange; internal readonly float StrikeHeight; internal readonly float LightIntensity; internal float VisualMaximum => LightRange + 500f; internal LightningProfile(float interval, float spawnRadius, float schedulingDistance, float lightRange, float strikeHeight, float lightIntensity) : this(interval, spawnRadius, schedulingDistance, schedulingDistance, lightRange, strikeHeight, lightIntensity) { } internal LightningProfile(float interval, float spawnRadius, float schedulingDistance, float audioSourceMaxDistance, float lightRange, float strikeHeight, float lightIntensity) { Interval = interval; SpawnRadius = spawnRadius; SchedulingDistance = schedulingDistance; AudioSourceMaxDistance = audioSourceMaxDistance; LightRange = lightRange; StrikeHeight = strikeHeight; LightIntensity = lightIntensity; } } internal sealed class StormDefinition { internal string Name; internal string EnableDescription; internal string SaveKey; internal CustomStormId Id; internal StormKind Kind; internal Vector3 InitialOffset; internal int Priority; internal float Radius; internal float ParticleDistance; internal float MoveSpeed; internal bool UsesFixedWeatherRange; internal float FixedWeatherRange; internal float WindCoefficient; internal float? RainTarget; internal bool SuppressRainParticles; internal bool SuppressFog; internal bool SupportsLightning; internal HashSet<string> AllowedRegions; internal ClimateSeasonMask AllowedClimateSeasons = ClimateSeasonMask.All; internal LightningProfile Lightning; internal bool AllowsRegion(string regionName) { if (AllowedRegions != null) { return AllowedRegions.Contains(regionName); } return true; } } internal static class StormCatalog { internal const float CloseThunderDistance = 1600f; internal const float AudioMinimumDistance = 250f; internal const float VisualPadding = 500f; internal static readonly LightningProfile VanillaLightning = new LightningProfile(16f, 1500f, 5500f, 4980f, 500f, 3f); internal static readonly StormDefinition[] Custom = new StormDefinition[6] { Squall("Squall 1", CustomStormId.Squall1, "DogEggz.BetterStorm.squall-1-position.v2", new Vector3(18000f, 0f, 0f), 1, 13f), Squall("Squall 2", CustomStormId.Squall2, "DogEggz.BetterStorm.squall-2-position.v2", new Vector3(-18000f, 0f, 0f), 2, 26f), Squall("Squall 3", CustomStormId.Squall3, "DogEggz.BetterStorm.squall-3-position.v2", new Vector3(0f, 0f, 18000f), 3, 19f), new StormDefinition { Name = "Hurricane", EnableDescription = "Enable the priority-3 Hurricane.", SaveKey = "DogEggz.BetterStorm.hurricane-position.v2", Id = CustomStormId.Hurricane, Kind = StormKind.Hurricane, InitialOffset = new Vector3(0f, 0f, -24000f), Priority = 3, Radius = 6000f, ParticleDistance = 9960f, MoveSpeed = 5.5f, UsesFixedWeatherRange = false, WindCoefficient = 34f, RainTarget = 13f, AllowedClimateSeasons = (ClimateSeasonMask.Summer | ClimateSeasonMask.Autumn), SupportsLightning = true, Lightning = new LightningProfile(12f, 3000f, 12500f, 7980f, 500f, 4f) }, new StormDefinition { Name = "Dry Thunderstorm", EnableDescription = "Enable the priority-2 Dry Thunderstorm in Medi and Medi East only.", SaveKey = "DogEggz.BetterStorm.dry-thunderstorm-position.v2", Id = CustomStormId.DryThunderstorm, Kind = StormKind.DryThunderstorm, InitialOffset = new Vector3(-24000f, 0f, 24000f), Priority = 2, Radius = 1800f, ParticleDistance = 2700f, MoveSpeed = 9f, UsesFixedWeatherRange = true, FixedWeatherRange = 900f, WindCoefficient = 30f, RainTarget = null, SuppressRainParticles = true, SuppressFog = true, AllowedClimateSeasons = (ClimateSeasonMask.Winter | ClimateSeasonMask.Autumn), SupportsLightning = true, AllowedRegions = new HashSet<string>(StringComparer.Ordinal) { "Region Medi", "Region Medi East" }, Lightning = new LightningProfile(1f, 1800f, 3200f, 6400f, 2250f, 500f, 4.5f) }, new StormDefinition { Name = "Sandstorm", EnableDescription = "Enable the priority-1 dry Sandstorm in Al'Ankh only.", SaveKey = "DogEggz.BetterStorm.sandstorm-position.v2", Id = CustomStormId.Sandstorm, Kind = StormKind.Sandstorm, InitialOffset = new Vector3(24000f, 0f, 24000f), Priority = 1, Radius = 2250f, ParticleDistance = 3600f, MoveSpeed = 12f, UsesFixedWeatherRange = true, FixedWeatherRange = 1350f, WindCoefficient = 26f, RainTarget = null, SuppressRainParticles = true, AllowedClimateSeasons = (ClimateSeasonMask.Spring | ClimateSeasonMask.Summer), SupportsLightning = false, AllowedRegions = new HashSet<string>(StringComparer.Ordinal) { "Region Al'ankh" } } }; private static StormDefinition Squall(string name, CustomStormId id, string saveKey, Vector3 initialOffset, int priority, float windCoefficient) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) return new StormDefinition { Name = name, EnableDescription = "Enable the priority-" + priority + " Squall.", SaveKey = saveKey, Id = id, Kind = StormKind.Squall, InitialOffset = initialOffset, Priority = priority, Radius = 1350f, ParticleDistance = 1350f, MoveSpeed = 24f, UsesFixedWeatherRange = true, FixedWeatherRange = 450f, WindCoefficient = windCoefficient, RainTarget = 25f, SupportsLightning = true, Lightning = new LightningProfile(8f, 1350f, 2000f, 1500f, 500f, 3f) }; } internal static StormDefinition Find(CustomStormId id) { for (int i = 0; i < Custom.Length; i++) { if (Custom[i].Id == id) { return Custom[i]; } } return null; } internal static bool TryValidate(out string error) { error = null; if (Custom.Length != Enum.GetValues(typeof(CustomStormId)).Length) { error = "The custom-storm catalog does not cover every storm ID."; return false; } HashSet<CustomStormId> hashSet = new HashSet<CustomStormId>(); HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); HashSet<string> hashSet3 = new HashSet<string>(StringComparer.Ordinal); for (int i = 0; i < Custom.Length; i++) { StormDefinition stormDefinition = Custom[i]; if (stormDefinition == null || string.IsNullOrEmpty(stormDefinition.Name) || string.IsNullOrEmpty(stormDefinition.EnableDescription) || string.IsNullOrEmpty(stormDefinition.SaveKey) || !hashSet.Add(stormDefinition.Id) || !hashSet2.Add(stormDefinition.Name) || !hashSet3.Add(stormDefinition.SaveKey)) { error = "The custom-storm catalog contains missing or duplicate identity metadata at index " + i + "."; return false; } if (stormDefinition.SupportsLightning && (stormDefinition.Lightning.SchedulingDistance <= 0f || stormDefinition.Lightning.AudioSourceMaxDistance < stormDefinition.Lightning.SchedulingDistance)) { error = stormDefinition.Name + " has invalid lightning audio distances."; return false; } } return true; } } internal static class StormAccess { internal static readonly FieldRef<WeatherStorms, WanderingStorm[]> Storms = AccessTools.FieldRefAccess<WeatherStorms, WanderingStorm[]>("storms"); internal static readonly FieldRef<WeatherStorms, float> CurrentStormRange = AccessTools.FieldRefAccess<WeatherStorms, float>("currentStormRange"); internal static readonly FieldRef<WeatherStorms, float> RainBorder = AccessTools.FieldRefAccess<WeatherStorms, float>("rainBorder"); internal static readonly FieldRef<Wind, float> WindTimer = AccessTools.FieldRefAccess<Wind, float>("timer"); internal static readonly FieldRef<Wind, float> GustTimer = AccessTools.FieldRefAccess<Wind, float>("gustTimer"); internal static readonly FieldRef<WanderingStorm, int> Priority = AccessTools.FieldRefAccess<WanderingStorm, int>("stormPriority"); internal static readonly FieldRef<WanderingStorm, float> ParticleDistance = AccessTools.FieldRefAccess<WanderingStorm, float>("particlesDistance"); internal static readonly FieldRef<WanderingStorm, float> Radius = AccessTools.FieldRefAccess<WanderingStorm, float>("stormRadius"); internal static readonly FieldRef<WanderingStorm, ParticleSystem> TopParticles = AccessTools.FieldRefAccess<WanderingStorm, ParticleSystem>("topParticles"); internal static readonly FieldRef<WanderingStorm, ParticleSystem> BottomParticles = AccessTools.FieldRefAccess<WanderingStorm, ParticleSystem>("bottomParticles"); internal static readonly FieldRef<WanderingStormLightning, float> LightningInterval = AccessTools.FieldRefAccess<WanderingStormLightning, float>("lightningInterval"); internal static readonly FieldRef<WanderingStormLightning, float> LightningIntensity = AccessTools.FieldRefAccess<WanderingStormLightning, float>("lightIntensity"); internal static readonly FieldRef<WanderingStormLightning, Light> LightningLight = AccessTools.FieldRefAccess<WanderingStormLightning, Light>("light"); internal static readonly FieldRef<WanderingStormLightning, ParticleSystem> LightningParticles = AccessTools.FieldRefAccess<WanderingStormLightning, ParticleSystem>("particles"); internal static readonly FieldRef<WanderingStormLightning, AudioSource> LightningAudio1 = AccessTools.FieldRefAccess<WanderingStormLightning, AudioSource>("audio1"); internal static readonly FieldRef<WanderingStormLightning, AudioSource> LightningAudio2 = AccessTools.FieldRefAccess<WanderingStormLightning, AudioSource>("audio2"); internal static readonly FieldRef<WanderingStormLightning, float> LightningCooldown = AccessTools.FieldRefAccess<WanderingStormLightning, float>("lightningCooldown"); internal static readonly FieldRef<WanderingStormLightning, float> LightningLightTimer = AccessTools.FieldRefAccess<WanderingStormLightning, float>("lightTimer"); internal static readonly FieldRef<CleanableObject, Texture2D> DirtCoat = AccessTools.FieldRefAccess<CleanableObject, Texture2D>("dirtCoat"); internal static readonly FieldInfo RegionBlenderTargetRegion = AccessTools.Field(typeof(RegionBlender), "currentTargetRegion"); } internal static class GameplayRegionResolver { internal static Region GetCurrentRegion() { if ((Object)(object)RegionBlender.instance != (Object)null && StormAccess.RegionBlenderTargetRegion != null) { object? value = StormAccess.RegionBlenderTargetRegion.GetValue(RegionBlender.instance); Region val = (Region)((value is Region) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } if (!((Object)(object)Weather.instance != (Object)null)) { return null; } return Weather.instance.currentRegion; } } internal readonly struct StormInfluence { internal readonly ModStormController Controller; internal readonly StormDefinition Definition; internal readonly float CenterDistance; internal readonly float Radius; internal readonly float WeatherRange; internal readonly float OuterEdge; internal readonly float WeatherLerp; internal bool Inside => CenterDistance < OuterEdge; internal float WindLerp => Mathf.InverseLerp(OuterEdge, Radius * 0.5f, CenterDistance); internal bool IsSquall { get { if (Definition != null) { return Definition.Kind == StormKind.Squall; } return false; } } internal bool IsSandstorm { get { if (Definition != null) { return Definition.Kind == StormKind.Sandstorm; } return false; } } internal StormInfluence(ModStormController controller, float centerDistance, float radius, float weatherRange) { Controller = controller; Definition = (((Object)(object)controller != (Object)null) ? controller.Definition : null); CenterDistance = centerDistance; Radius = radius; WeatherRange = weatherRange; OuterEdge = radius + weatherRange; WeatherLerp = Mathf.InverseLerp(OuterEdge, radius, centerDistance); } } internal static class StormInfluenceService { internal static StormInfluence Evaluate(WeatherStorms weatherStorms, WanderingStorm storm, float distance) { ModStormController controller = (((Object)(object)storm != (Object)null) ? ((Component)storm).GetComponent<ModStormController>() : null); float radius = (((Object)(object)storm != (Object)null) ? storm.GetRadius() : 0f); float weatherRange = GetWeatherRange(weatherStorms, controller); return new StormInfluence(controller, distance, radius, weatherRange); } internal static float GetWeatherRange(WeatherStorms weatherStorms, ModStormController controller) { if ((Object)(object)controller != (Object)null && controller.Definition.UsesFixedWeatherRange) { return controller.Definition.FixedWeatherRange; } if (!((Object)(object)weatherStorms != (Object)null)) { return 0f; } return Mathf.Max(0f, StormAccess.CurrentStormRange.Invoke(weatherStorms)); } internal static bool TryGetCurrent(out StormInfluence influence) { return TryGetCurrent(WeatherStorms.currentStormDistance, out influence); } internal static bool TryGetCurrent(float distance, out StormInfluence influence) { influence = default(StormInfluence); WeatherStorms instance = WeatherStorms.instance; WanderingStorm val = (((Object)(object)instance != (Object)null) ? instance.GetCurrentStorm() : null); if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null || !val.active) { return false; } influence = Evaluate(instance, val, distance); return influence.Inside; } internal static float NormalizeForSelection(WeatherStorms weatherStorms, WanderingStorm storm, float distance) { StormInfluence stormInfluence = Evaluate(weatherStorms, storm, distance); return Mathf.Clamp01((distance - stormInfluence.Radius) / Mathf.Max(0.0001f, stormInfluence.WeatherRange)); } internal static float GetStormContribution(StormInfluence influence) { if (!influence.Inside) { return 0f; } return ((influence.Definition != null) ? influence.Definition.WindCoefficient : 26f) * influence.WindLerp; } internal static float GetEffectiveWindLerp(float originalStart, float originalEnd, float distance) { if ((Object)(object)BetterStormPlugin.Instance == (Object)null) { return Mathf.InverseLerp(originalStart, originalEnd, distance); } if (!TryGetCurrent(distance, out var influence)) { return 0f; } float num = ((influence.Definition != null) ? influence.Definition.WindCoefficient : 26f); return influence.WindLerp * num / 26f; } } internal sealed class ModStormController : MonoBehaviour { private Transform player; private ParticleSystem topParticles; private ParticleSystem bottomParticles; private float oneSecondTimer; internal WanderingStorm Storm { get; private set; } internal StormDefinition Definition { get; private set; } internal void Configure(StormDefinition definition, Transform playerTransform) { Definition = definition; Storm = ((Component)this).GetComponent<WanderingStorm>(); player = playerTransform; if ((Object)(object)Storm == (Object)null) { throw new InvalidOperationException("Custom storm clone has no WanderingStorm component."); } StormAccess.Priority.Invoke(Storm) = definition.Priority; StormAccess.Radius.Invoke(Storm) = definition.Radius; StormAccess.ParticleDistance.Invoke(Storm) = definition.ParticleDistance; topParticles = StormAccess.TopParticles.Invoke(Storm); bottomParticles = StormAccess.BottomParticles.Invoke(Storm); if (definition.SupportsLightning) { ConfigureLightning(definition.Lightning); } else { DisableInheritedLightning(); } if (definition.Kind == StormKind.Sandstorm) { SandstormVisuals.ApplyStormCloudColors(topParticles, bottomParticles); } oneSecondTimer = 0f; } internal bool ShouldBeActive() { BetterStormPlugin instance = BetterStormPlugin.Instance; Region currentRegion = GameplayRegionResolver.GetCurrentRegion(); if ((Object)(object)instance != (Object)null && instance.IsEnabled(Definition.Id) && (Object)(object)currentRegion != (Object)null && Definition.AllowsRegion(((Object)((Component)currentRegion).gameObject).name) && ClimateSeasonCompatibility.Allows(Definition)) { return currentRegion.stormCount >= Definition.Priority; } return false; } internal void CustomUpdate() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) if (!GameState.playing || (Object)(object)Storm == (Object)null) { return; } if ((Object)(object)player == (Object)null && (Object)(object)Camera.main != (Object)null) { player = ((Component)Camera.main).transform; } if ((Object)(object)player == (Object)null) { return; } ((Component)this).transform.Translate(((Vector3)(ref Wind.currentWind)).normalized * Time.deltaTime * Definition.MoveSpeed, (Space)0); Vector3 val = ((Component)this).transform.position - player.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { ((Component)this).transform.Translate(((Vector3)(ref val)).normalized * Time.deltaTime * WeatherStorms.totemAttraction * Storm.totemMult, (Space)0); } oneSecondTimer -= Time.deltaTime; if (!(oneSecondTimer > 0f)) { oneSecondTimer = 1f; Storm.active = ShouldBeActive(); Vector3 val2 = ((Component)this).transform.position - player.position; val2.y = 0f; float magnitude = ((Vector3)(ref val2)).magnitude; BetterStormPlugin instance = BetterStormPlugin.Instance; if (Storm.active && (Object)(object)instance != (Object)null && magnitude > (float)instance.RelocationDistance.Value) { ((Component)this).transform.Translate(-val2 * 1.75f, (Space)0); val2 = ((Component)this).transform.position - player.position; val2.y = 0f; magnitude = ((Vector3)(ref val2)).magnitude; } SetParticleEmission(Storm.active && magnitude <= Definition.ParticleDistance); } } internal void SetModEnabled(bool enabled) { SetParticleEmission(enabled: false); if (!enabled) { ThunderPoolRegistry.Reset(this); Storm.active = false; ((Component)this).gameObject.SetActive(false); oneSecondTimer = 0f; } else { ((Component)this).gameObject.SetActive(true); Storm.active = ShouldBeActive(); oneSecondTimer = 0f; } } internal void RefreshSandstormCloudVisuals() { if (Definition.Kind == StormKind.Sandstorm) { SandstormVisuals.ApplyStormCloudColors(topParticles, bottomParticles); } } internal void PrepareDebugMove(bool resetLightningCooldown) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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) ((Component)this).gameObject.SetActive(true); Storm.active = ShouldBeActive(); oneSecondTimer = 0f; if (resetLightningCooldown && Definition.SupportsLightning) { WanderingStormLightning[] componentsInChildren = ((Component)this).GetComponentsInChildren<WanderingStormLightning>(true); for (int i = 0; i < componentsInChildren.Length; i++) { StormAccess.LightningCooldown.Invoke(componentsInChildren[i]) = 0f; } } if ((Object)(object)player != (Object)null) { Vector3 val = ((Component)this).transform.position - player.position; val.y = 0f; SetParticleEmission(Storm.active && ((Vector3)(ref val)).magnitude <= Definition.ParticleDistance); } } private void ConfigureLightning(LightningProfile profile) { WanderingStormLightning[] componentsInChildren = ((Component)this).GetComponentsInChildren<WanderingStormLightning>(true); foreach (WanderingStormLightning val in componentsInChildren) { StormAccess.LightningInterval.Invoke(val) = profile.Interval; StormAccess.LightningCooldown.Invoke(val) = profile.Interval; StormAccess.LightningIntensity.Invoke(val) = profile.LightIntensity; Light component = ((Component)val).GetComponent<Light>(); if ((Object)(object)component != (Object)null) { component.range = profile.LightRange; } AudioSource[] components = ((Component)val).GetComponents<AudioSource>(); for (int j = 0; j < components.Length; j++) { components[j].minDistance = 250f; components[j].maxDistance = profile.AudioSourceMaxDistance; } } } private void DisableInheritedLightning() { WanderingStormLightning[] componentsInChildren = ((Component)this).GetComponentsInChildren<WanderingStormLightning>(true); foreach (WanderingStormLightning obj in componentsInChildren) { ((Behaviour)obj).enabled = false; Light component = ((Component)obj).GetComponent<Light>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; } ParticleSystem component2 = ((Component)obj).GetComponent<ParticleSystem>(); if ((Object)(object)component2 != (Object)null) { component2.Stop(true, (ParticleSystemStopBehavior)0); } AudioSource[] components = ((Component)obj).GetComponents<AudioSource>(); for (int j = 0; j < components.Length; j++) { components[j].Stop(); ((Behaviour)components[j]).enabled = false; } } } private void SetParticleEmission(bool enabled) { SetEmission(topParticles, enabled); SetEmission(bottomParticles, enabled); } private static void SetEmission(ParticleSystem particles, bool enabled) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)particles == (Object)null)) { EmissionModule emission = particles.emission; ((EmissionModule)(ref emission)).enabled = enabled; } } } internal static class ModStormFactory { private static readonly List<ModStormController> CustomStorms = new List<ModStormController>(); private static WeatherStorms owner; private static WanderingStorm[] originalStorms; private static bool initialized; internal static ModStormController Hurricane { get; private set; } internal static ModStormController Sandstorm { get; private set; } internal static bool AnyMediStormEnabled { get { BetterStormPlugin instance = BetterStormPlugin.Instance; if ((Object)(object)instance == (Object)null) { return false; } for (int i = 0; i < StormCatalog.Custom.Length; i++) { StormDefinition stormDefinition = StormCatalog.Custom[i]; if (stormDefinition.AllowsRegion("Region Medi East") && instance.IsEnabled(stormDefinition.Id)) { return true; } } return false; } } internal static void Initialize(WeatherStorms weatherStorms) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)weatherStorms == (Object)null || (initialized && (Object)(object)owner == (Object)(object)weatherStorms)) { return; } if (initialized) { Shutdown(); } WanderingStorm[] array = StormAccess.Storms.Invoke(weatherStorms); WanderingStorm val = FindTemplate(array); Camera main = Camera.main; if (array == null || (Object)(object)val == (Object)null || (Object)(object)main == (Object)null) { BetterStormPlugin.Instance?.LogFeatureError("Custom storms could not initialize because the vanilla storm template or player camera was unavailable."); return; } owner = weatherStorms; originalStorms = array; bool activeSelf = ((Component)val).gameObject.activeSelf; ((Component)val).gameObject.SetActive(false); try { for (int i = 0; i < StormCatalog.Custom.Length; i++) { StormDefinition stormDefinition = StormCatalog.Custom[i]; GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)main).transform.position + stormDefinition.InitialOffset, ((Component)val).transform.rotation, ((Component)val).transform.parent); ((Object)val2).name = "Better Storm " + stormDefinition.Name; SaveableObject[] componentsInChildren = val2.GetComponentsInChildren<SaveableObject>(true); for (int j = 0; j < componentsInChildren.Length; j++) { Object.DestroyImmediate((Object)(object)componentsInChildren[j]); } ModStormController modStormController = val2.AddComponent<ModStormController>(); modStormController.Configure(stormDefinition, ((Component)main).transform); CustomStorms.Add(modStormController); StormPositionPersistence.ApplyLoadedPosition(stormDefinition.Id, modStormController); if (stormDefinition.Id == CustomStormId.Hurricane) { Hurricane = modStormController; } else if (stormDefinition.Id == CustomStormId.Sandstorm) { Sandstorm = modStormController; } } WanderingStorm[] array2 = (WanderingStorm[])(object)new WanderingStorm[array.Length + CustomStorms.Count]; Array.Copy(array, array2, array.Length); for (int k = 0; k < CustomStorms.Count; k++) { array2[array.Length + k] = CustomStorms[k].Storm; } StormAccess.Storms.Invoke(weatherStorms) = array2; initialized = true; ApplyEnabledState(); MediEastStormSetting.Apply(AnyMediStormEnabled); RefreshSandstormCloudVisuals(); GlobalLightningSettings.ApplyToLiveStorms(); BetterStormPlugin.Instance?.LogFeatureInfo("Initialized three Squalls, one Hurricane, one Dry Thunderstorm, and one Sandstorm."); } catch (Exception ex) { BetterStormPlugin.Instance?.LogFeatureError("Custom storm initialization failed: " + ex); Shutdown(); } finally { if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(activeSelf); } } } internal static void ApplyEnabledState() { BetterStormPlugin instance = BetterStormPlugin.Instance; if ((Object)(object)instance == (Object)null) { return; } for (int i = 0; i < CustomStorms.Count; i++) { ModStormController modStormController = CustomStorms[i]; if ((Object)(object)modStormController != (Object)null) { modStormController.SetModEnabled(instance.IsEnabled(modStormController.Definition.Id)); } } } internal static ModStormController Find(CustomStormId id) { for (int i = 0; i < CustomStorms.Count; i++) { ModStormController modStormController = CustomStorms[i]; if ((Object)(object)modStormController != (Object)null && modStormController.Definition.Id == id) { return modStormController; } } return null; } internal static void RefreshSandstormCloudVisuals() { Sandstorm?.RefreshSandstormCloudVisuals(); } internal static void Shutdown() { if ((Object)(object)owner != (Object)null && originalStorms != null) { StormAccess.Storms.Invoke(owner) = originalStorms; } for (int i = 0; i < CustomStorms.Count; i++) { ModStormController modStormController = CustomStorms[i]; if ((Object)(object)modStormController != (Object)null) { Object.Destroy((Object)(object)((Component)modStormController).gameObject); } } CustomStorms.Clear(); Hurricane = null; Sandstorm = null; originalStorms = null; owner = null; initialized = false; } private static WanderingStorm FindTemplate(WanderingStorm[] storms) { if (storms == null) { return null; } for (int i = 0; i < storms.Length; i++) { if ((Object)(object)storms[i] != (Object)null && (Object)(object)((Component)storms[i]).GetComponent<ModStormController>() == (Object)null) { return storms[i]; } } return null; } } internal static class MediEastStormSetting { private static Region mediEast; private static int originalStormCount; internal static void Apply(bool enabled) { if ((Object)(object)mediEast == (Object)null) { Region[] array = Object.FindObjectsOfType<Region>(); for (int i = 0; i < array.Length; i++) { if (((Object)((Component)array[i]).gameObject).name == "Region Medi East") { mediEast = array[i]; originalStormCount = array[i].stormCount; break; } } } if ((Object)(object)mediEast != (Object)null) { mediEast.stormCount = (enabled ? 3 : originalStormCount); } } } [HarmonyPatch(typeof(WeatherStorms), "Start")] internal static class WeatherStormsStartPatch { [HarmonyPostfix] private static void Postfix(WeatherStorms __instance) { ThunderPoolRegistry.Shutdown(); SandstormVisuals.Shutdown(); SandstormDirt.Reset(); GlobalLightningSettings.RestoreSnapshots(); ModStormFactory.Initialize(__instance); } } [HarmonyPatch(typeof(WeatherStorms), "FindClosestStorm")] internal static class StrongestStormPatch { [HarmonyPrefix] private static bool Prefix(WeatherStorms __instance, WanderingStorm[] ___storms, Transform ___player, ref WanderingStorm ___currentStorm) { //IL_0039: 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) if (___storms == null || (Object)(object)___player == (Object)null) { return true; } WanderingStorm val = null; float num = float.MaxValue; float num2 = float.MaxValue; foreach (WanderingStorm val2 in ___storms) { if (!((Object)(object)val2 == (Object)null) && val2.active) { float num3 = Vector3.Distance(___player.position, ((Component)val2).transform.position); float num4 = StormInfluenceService.NormalizeForSelection(__instance, val2, num3); if (num4 < num || (Mathf.Approximately(num4, num) && num3 < num2)) { val = val2; num = num4; num2 = num3; } } } ___currentStorm = val; WeatherStorms.currentStormDistance = (((Object)(object)val != (Object)null) ? num2 : 100000000f); return false; } } [HarmonyPatch(typeof(WeatherStorms), "GetNormalizedDistance")] internal static class CustomStormRangePatch { [HarmonyPrefix] private static bool Prefix(WanderingStorm ___currentStorm, ref float __result) { if ((Object)(object)___currentStorm == (Object)null) { return true; } ModStormController component = ((Component)___currentStorm).GetComponent<ModStormController>(); if ((Object)(object)component == (Object)null || !component.Definition.UsesFixedWeatherRange) { return true; } __result = Mathf.Clamp01((WeatherStorms.currentStormDistance - component.Definition.Radius) / Mathf.Max(0.0001f, component.Definition.FixedWeatherRange)); return false; } } [HarmonyPatch(typeof(WanderingStorm), "Update")] internal static class CustomStormMovementPatch { [HarmonyPrefix] private static bool Prefix(WanderingStorm __instance) { ModStormController component = ((Component)__instance).GetComponent<ModStormController>(); if ((Object)(object)component == (Object)null) { return true; } component.CustomUpdate(); return false; } } [HarmonyPatch(typeof(RegionBlender), "Start")] internal static class RegionBlenderStartPatch { [HarmonyPostfix] [HarmonyAfter(new string[] { "com.nandbrew.borderexpander" })] private static void Postfix() { MediEastStormSetting.Apply(ModStormFactory.AnyMediStormEnabled); ModStormFactory.ApplyEnabledState(); } } internal static class DryStormGameplay { internal static bool ShouldSuppressRain() { if (StormInfluenceService.TryGetCurrent(out var influence) && influence.Definition != null) { return influence.Definition.SuppressRainParticles; } return false; } internal static bool ShouldSuppressFog() { if (StormInfluenceService.TryGetCurrent(out var influence) && influence.Definition != null) { return influence.Definition.SuppressFog; } return false; } internal static void SuppressRainGameplay() { if (ShouldSuppressRain()) { GameState.rainIntensity = 0f; } } } internal static class SandstormVisuals { private const float VerticalVelocity = -4f; private const float StartLifetime = 2f; private const float SandParticleIntensity = 50f; private const float SandParticleSize = 0.015f; private const float SandParticleSpawnRadius = 60f; private const float SandstormFogDensity = 0.03f; private const float NoiseStrength = 1.2f; private const float WindInfluence = 0.3f; private const float HorizontalVelocityMultiplier = 2f; private const int MaximumParticles = 30000; private const float EmissionRateMultiplier = 200f; private const float DistantStormAlpha = 1f; private const float OverheadStormAlpha = 0.6f; private const string StormCloudTintShaderName = "Particles/Priority Alpha Blended"; private static readonly Color SandParticleColor = new Color(0.4352941f, 0.2588235f, 0.1215686f, 0.5f); private static readonly Color SandFogColor = new Color(0.7647059f, 0.6f, 0.2823529f, 1f); private static readonly Color DistantStormColor = SandFogColor; private static ParticleSystem sourceRain; private static ParticleSystem sourceOuterRain; private static ParticleSystem sandRain; private static bool active; private static bool rainStageActive; internal static void ApplyWeather(StormInfluence influence, ParticleSystem rain, ParticleSystem outerRain, ParticleSystem rainSplash) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) if (!influence.IsSandstorm) { Deactivate(); return; } EnsureInitialized(rain, outerRain); if (!active) { ClearParticles(rain); ClearParticles(outerRain); ClearParticles(rainSplash); } active = true; SuppressVanillaRain(rain, outerRain, rainSplash); GameState.rainIntensity = 0f; if (!TryGetRainStageLerp(influence, out var stageLerp)) { if (rainStageActive) { SetEmissionRate(sandRain, 0f); ClearParticles(sandRain); } rainStageActive = false; } else { rainStageActive = true; SetEmissionRate(sandRain, 50f * stageLerp * 200f); RenderSettings.fogDensity = Mathf.Lerp(RenderSettings.fogDensity, 0.03f, stageLerp); RenderSettings.fogColor = Color.Lerp(RenderSettings.fogColor, SandFogColor, stageLerp); } } internal static void Tick() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (active && rainStageActive && TryGetActiveInfluence(out var _)) { UpdateParticleMotion(sandRain, Wind.currentWind * 0.3f); } } internal static void ApplyFogParticleColor(FogEffectController fog) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0067: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)fog == (Object)null) && !((Object)(object)fog.fogParticles == (Object)null) && TryGetActiveInfluence(out var influence) && TryGetRainStageLerp(influence, out var stageLerp)) { MainModule main = fog.fogParticles.main; MinMaxGradient startColor = ((MainModule)(ref main)).startColor; Color color = ((MinMaxGradient)(ref startColor)).color; Color sandFogColor = SandFogColor; sandFogColor.a = color.a; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(Color.Lerp(color, sandFogColor, stageLerp)); } } internal static void ApplyStormCloudColors(ParticleSystem topParticles, ParticleSystem bottomParticles) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) ApplyStormCloudColor(topParticles, DistantStormColor, 1f); ApplyStormCloudColor(bottomParticles, DistantStormColor, 0.6f); } internal static void Deactivate() { rainStageActive = false; if (active) { SetEmissionRate(sandRain, 0f); ClearParticles(sandRain); active = false; } } internal static void Shutdown() { Deactivate(); if ((Object)(object)sandRain != (Object)null) { Object.Destroy((Object)(object)((Component)sandRain).gameObject); } sourceRain = null; sourceOuterRain = null; sandRain = null; } private static bool TryGetActiveInfluence(out StormInfluence influence) { influence = default(StormInfluence); if (StormInfluenceService.TryGetCurrent(out influence) && influence.IsSandstorm && (Object)(object)BetterStormPlugin.Instance != (Object)null && BetterStormPlugin.Instance.IsEnabled(CustomStormId.Sandstorm) && (Object)(object)GameplayRegionResolver.GetCurrentRegion() != (Object)null) { return ((Object)((Component)GameplayRegionResolver.GetCurrentRegion()).gameObject).name == "Region Al'ankh"; } return false; } private static bool TryGetRainStageLerp(StormInfluence influence, out float stageLerp) { WeatherStorms instance = WeatherStorms.instance; if ((Object)(object)instance == (Object)null) { stageLerp = 0f; return false; } float num = StormAccess.RainBorder.Invoke(instance); float num2 = 1f - influence.WeatherLerp; if (num <= 0f || num2 >= num) { stageLerp = 0f; return false; } stageLerp = Mathf.InverseLerp(num, 0f, num2); return stageLerp > 0f; } private static void EnsureInitialized(ParticleSystem rain, ParticleSystem outerRain) { if (!((Object)(object)rain == (Object)null) && !((Object)(object)outerRain == (Object)null) && (!((Object)(object)sandRain != (Object)null) || !((Object)(object)sourceRain == (Object)(object)rain) || !((Object)(object)sourceOuterRain == (Object)(object)outerRain))) { Shutdown(); sourceRain = rain; sourceOuterRain = outerRain; sandRain = CloneAndConfigure(outerRain, "Better Storm Sand Particles"); } } private static ParticleSystem CloneAndConfigure(ParticleSystem source, string name) { //IL_000c: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)source).transform.position, ((Component)source).transform.rotation, ((Component)source).transform.parent); ((Object)val).name = name; val.transform.localScale = ((Component)source).transform.localScale; Rain[] componentsInChildren = val.GetComponentsInChildren<Rain>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } LitParticles[] componentsInChildren2 = val.GetComponentsInChildren<LitParticles>(true); for (int j = 0; j < componentsInChildren2.Length; j++) { ((Behaviour)componentsInChildren2[j]).enabled = false; } AudioSource[] componentsInChildren3 = val.GetComponentsInChildren<AudioSource>(true); for (int k = 0; k < componentsInChildren3.Length; k++) { componentsInChildren3[k].Stop(); ((Behaviour)componentsInChildren3[k]).enabled = false; } ParticleSystem component = val.GetComponent<ParticleSystem>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return null; } MainModule main = component.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2f); ((MainModule)(ref main)).startSize3D = false; ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.015f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).maxParticles = 30000; ((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(SandParticleColor); ShapeModule shape = component.shape; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)8; ((ShapeModule)(ref shape)).angle = 0f; ((ShapeModule)(ref shape)).length = 29f; ((ShapeModule)(ref shape)).radius = 60f; ((ShapeModule)(ref shape)).radiusThickness = 1f; ((ShapeModule)(ref shape)).arc = 360f; ((ShapeModule)(ref shape)).rotation = Vector3.zero; ((ShapeModule)(ref shape)).position = Vector3.zero; NoiseModule noise = component.noise; ((NoiseModule)(ref noise)).enabled = true; ((NoiseModule)(ref noise)).separateAxes = false; ((NoiseModule)(ref noise)).strength = MinMaxCurve.op_Implicit(1.2f); ParticleSystemRenderer component2 = val.GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component2 != (Object)null) { component2.renderMode = (ParticleSystemRenderMode)0; } SetEmissionRate(component, 0f); EmissionModule emission = component.emission; ((EmissionModule)(ref emission)).enabled = true; component.Clear(true); component.Play(true); return component; } private static void UpdateParticleMotion(ParticleSystem particles, Vector3 windVelocity) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) if (!((Object)(object)particles == (Object)null)) { VelocityOverLifetimeModule velocityOverLifetime = particles.velocityOverLifetime; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = MinMaxCurve.op_Implicit(windVelocity.x * 2f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = MinMaxCurve.op_Implicit(-4f); ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = MinMaxCurve.op_Implicit(windVelocity.z * 2f); Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 position = ((Component)main).transform.position - windVelocity; position.y = 1f; ((Component)particles).transform.position = position; } } } private static void ApplyStormCloudColor(ParticleSystem particles, Color baseColor, float alpha) { //IL_000a: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)particles == (Object)null) { return; } Color val = baseColor; val.a = Mathf.Clamp01(alpha); ParticleSystemRenderer component = ((Component)particles).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component == (Object)null) { MainModule main = particles.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(val); return; } Material sharedMaterial = ((Renderer)component).sharedMaterial; Shader val2 = Shader.Find("Particles/Priority Alpha Blended"); SandstormCloudMaterialOwner sandstormCloudMaterialOwner = ((Component)particles).GetComponent<SandstormCloudMaterialOwner>(); if ((Object)(object)sandstormCloudMaterialOwner != (Object)null && (Object)(object)sandstormCloudMaterialOwner.OwnedMaterial != (Object)null && (Object)(object)sandstormCloudMaterialOwner.OwnedMaterial.shader == (Object)(object)val2) { DisableParticleLighting(particles); ApplyTintAndAlpha(particles, sandstormCloudMaterialOwner.OwnedMaterial, baseColor, val.a); return; } if ((Object)(object)sharedMaterial == (Object)null || (Object)(object)val2 == (Object)null) { MainModule main2 = particles.main; ((MainModule)(ref main2)).startColor = MinMaxGradient.op_Implicit(val); return; } Texture val3 = (sharedMaterial.HasProperty("_MainTex") ? sharedMaterial.GetTexture("_MainTex") : null); Vector2 val4 = (sharedMaterial.HasProperty("_MainTex") ? sharedMaterial.GetTextureScale("_MainTex") : Vector2.one); Vector2 val5 = (sharedMaterial.HasProperty("_MainTex") ? sharedMaterial.GetTextureOffset("_MainTex") : Vector2.zero); float num = (sharedMaterial.HasProperty("_InvFade") ? sharedMaterial.GetFloat("_InvFade") : 1f); Material val6 = new Material(val2) { name = "Better Storm Sandstorm Cloud Tint", hideFlags = (HideFlags)52, renderQueue = sharedMaterial.renderQueue }; val6.SetTexture("_MainTex", val3); val6.SetTextureScale("_MainTex", val4); val6.SetTextureOffset("_MainTex", val5); val6.SetFloat("_InvFade", num); DisableParticleLighting(particles); ApplyTintAndAlpha(particles, val6, baseColor, val.a); ((Renderer)component).sharedMaterial = val6; if ((Object)(object)sandstormCloudMaterialOwner == (Object)null) { sandstormCloudMaterialOwner = ((Component)particles).gameObject.AddComponent<SandstormCloudMaterialOwner>(); } sandstormCloudMaterialOwner.Own(val6); } private static void ApplyTintAndAlpha(ParticleSystem particles, Material material, Color baseColor, float alpha) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0053: 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) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) //IL_0076: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(alpha); Color val = baseColor; val.r *= 0.5f; val.g *= 0.5f; val.b *= 0.5f; val.a = num * 0.5f; material.SetColor("_TintColor", val); Color white = Color.white; white.a = num; MainModule main = particles.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(white); ApplyColorToExistingParticles(particles, white); } private static void ApplyColorToExistingParticles(ParticleSystem particles, Color color) { //IL_001b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) int particleCount = particles.particleCount; if (particleCount > 0) { Particle[] array = (Particle[])(object)new Particle[particleCount]; int particles2 = particles.GetParticles(array); Color32 startColor = Color32.op_Implicit(color); for (int i = 0; i < particles2; i++) { ((Particle)(ref array[i])).startColor = startColor; } particles.SetParticles(array, particles2); } } private static void DisableParticleLighting(ParticleSystem particles) { LitParticles[] components = ((Component)particles).GetComponents<LitParticles>(); for (int i = 0; i < components.Length; i++) { ((Behaviour)components[i]).enabled = false; } } private static void SuppressVanillaRain(ParticleSystem rain, ParticleSystem outerRain, ParticleSystem rainSplash) { SetEmissionRate(rain, 0f); SetEmissionRate(outerRain, 0f); SetEmissionRate(rainSplash, 0f); } internal static void SetEmissionRate(ParticleSystem particles, float rate) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)particles == (Object)null)) { EmissionModule emission = particles.emission; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(rate); } } private static void ClearParticles(ParticleSystem particles) { if ((Object)(object)particles != (Object)null) { particles.Clear(true); } } } internal sealed class SandstormCloudMaterialOwner : MonoBehaviour { private Material ownedMaterial; internal Material OwnedMaterial => ownedMaterial; internal void Own(Material material) { if ((Object)(object)ownedMaterial != (Object)null && (Object)(object)ownedMaterial != (Object)(object)material) { Object.Destroy((Object)(object)ownedMaterial); } ownedMaterial = material; } private void OnDestroy() { if ((Object)(object)ownedMaterial != (Object)null) { Object.Destroy((Object)(object)ownedMaterial); ownedMaterial = null; } } } internal static class SandstormDirt { private const float ApplicationInterval = 20f; private const float DirtStrength = 0.02f; private static Transform cachedBoat; private static CleanableObject cachedCleanable; private static float exposureTimer; internal static void Tick() { if (!TryGetExposedCleanable(out var cleanable)) { Reset(); return; } exposureTimer += Time.deltaTime; if (!(exposureTimer < 20f) && ApplyVanillaDirt(cleanable)) { exposureTimer -= 20f; } } internal static void Reset() { cachedBoat = null; cachedCleanable = null; exposureTimer = 0f; } private static bool TryGetExposedCleanable(out CleanableObject cleanable) { //IL_0078: 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_0088: 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) cleanable = null; BetterStormPlugin instance = BetterStormPlugin.Instance; ModStormController sandstorm = ModStormFactory.Sandstorm; Transform lastBoat = GameState.lastBoat; if (!GameState.playing || (Object)(object)instance == (Object)null || !instance.IsEnabled(CustomStormId.Sandstorm) || (Object)(object)sandstorm == (Object)null || (Object)(object)sandstorm.Storm == (Object)null || !sandstorm.Storm.active || !((Component)sandstorm).gameObject.activeInHierarchy || (Object)(object)lastBoat == (Object)null || (Object)(object)MasterPainter.instance == (Object)null) { return false; } Vector3 val = lastBoat.position - ((Component)sandstorm).transform.position; val.y = 0f; float num = sandstorm.Definition.Radius + sandstorm.Definition.FixedWeatherRange; if (((Vector3)(ref val)).sqrMagnitude >= num * num) { return false; } if ((Object)(object)cachedBoat != (Object)(object)lastBoat || (Object)(object)cachedCleanable == (Object)null) { cachedBoat = lastBoat; SaveableObject component = ((Component)lastBoat).GetComponent<SaveableObject>(); cachedCleanable = (((Object)(object)component != (Object)null) ? component.GetCleanable() : null); exposureTimer = 0f; } cleanable = cachedCleanable; if ((Object)(object)cleanable != (Object)null) { return ((Behaviour)cleanable).isActiveAndEnabled; } return false; } private static bool ApplyVanillaDirt(CleanableObject cleanable) { MasterPainter instance = MasterPainter.instance; if ((Object)(object)instance == (Object)null || (Object)(object)cleanable == (Object)null) { return false; } Texture2D val = StormAccess.DirtCoat.Invoke(cleanable); if ((Object)(object)val == (Object)null) { return false; } instance.ApplyCoat(cleanable, (Texture)(object)val, 0.02f); return true; } } [HarmonyPatch(typeof(Weather), "ApplyWeather")] [HarmonyAfter(new string[] { "com.raddude.climate" })] internal static class CustomStormWeatherPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(ParticleSystem ___rain, ParticleSystem ___outerRain, ParticleSystem ___rainSplash) { if ((Object)(object)BetterStormPlugin.Instance == (Object)null) { return; } if (!StormInfluenceService.TryGetCurrent(out var influence) || influence.Definition == null) { SandstormVisuals.Deactivate(); return; } if (influence.Definition.Kind == StormKind.Sandstorm) { SandstormVisuals.ApplyWeather(influence, ___rain, ___outerRain, ___rainSplash); return; } SandstormVisuals.Deactivate(); if (influence.Definition.SuppressFog) { RenderSettings.fogDensity = 0f; } if (influence.Definition.SuppressRainParticles) { SandstormVisuals.SetEmissionRate(___rain, 0f); SandstormVisuals.SetEmissionRate(___outerRain, 0f); SandstormVisuals.SetEmissionRate(___rainSplash, 0f); GameState.rainIntensity = 0f; } else if (influence.Definition.RainTarget.HasValue) { ApplyRainTarget(influence, influence.Definition.RainTarget.Value, ___rain, ___outerRain, ___rainSplash); } } private static void ApplyRainTarget(StormInfluence influence, float rainTarget, ParticleSystem rain, ParticleSystem outerRain, ParticleSystem rainSplash) { WeatherStorms instance = WeatherStorms.instance; Weather instance2 = Weather.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && !((Object)(object)instance2.currentRegion == (Object)null) && !((Object)(object)instance2.currentRegion.rainWeather == (Object)null) && instance2.currentRegion.rainWeather.particles != null && !((Object)(object)rain == (Object)null) && !((Object)(object)outerRain == (Object)null) && !((Object)(object)rainSplash == (Object)null)) { float num = StormAccess.RainBorder.Invoke(instance); float num2 = 1f - influence.WeatherLerp; if (!(num2 > num)) { float num3 = Mathf.InverseLerp(num, 0f, num2); float num4 = Mathf.Lerp(instance2.currentRegion.rainWeather.particles.rainDensity, rainTarget, num3); SandstormVisuals.SetEmissionRate(rain, num4 * 75f); SandstormVisuals.SetEmissionRate(outerRain, num4 * 125f); SandstormVisuals.SetEmissionRate(rainSplash, num4 * 250f); GameState.rainIntensity = num4; } } } } [HarmonyPatch(typeof(Rain), "Update")] internal static class DryStormRainAudioPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix() { DryStormGameplay.SuppressRainGameplay(); } } [HarmonyPatch(typeof(BoatDamage), "Update")] internal static class DryStormShipWaterPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix() { DryStormGameplay.SuppressRainGameplay(); } } [HarmonyPatch(typeof(FogEffectController), "Update")] internal static class CustomStormFogPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(FogEffectController __instance) { //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_002d: 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) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (DryStormGameplay.ShouldSuppressFog())