Decompiled source of TolerableFog v1.0.2

BepInEx/plugins/TolerableFog/bobabulkerENTERPRISE.TolerableFog.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSync.Extensions;
using CSync.Lib;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;
using WeatherRegistry;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("bobabulkerENTERPRISE.TolerableFog")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("TolerableFog")]
[assembly: AssemblyTitle("bobabulkerENTERPRISE.TolerableFog")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 TolerableFog
{
	[BepInPlugin("bobabulkerENTERPRISE.TolerableFog", "TolerableFog", "1.0.2")]
	[BepInDependency("com.sigurd.csync", "5.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static Harmony? Harmony { get; set; }

		internal static FogConfig Settings { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Settings = new FogConfig(((BaseUnityPlugin)this).Config);
			ModdedWeatherStrengths.Init(((BaseUnityPlugin)this).Config);
			Patch();
			FixCameraResolutionsCompat.EnsurePatched("plugin startup");
			RegisterLethalConfig();
			foreach (SyncedEntry<float> allEntry in Settings.AllEntries)
			{
				allEntry.Changed += delegate
				{
					FogController.RefreshIfSettingsChanged();
				};
			}
			Settings.ModdedWeatherStrengths.Changed += delegate
			{
				FogController.RefreshIfSettingsChanged();
			};
			Logger.LogInfo((object)"bobabulkerENTERPRISE.TolerableFog v1.0.2 has loaded!");
		}

		private void RegisterLethalConfig()
		{
			if (!LethalConfigCompat.IsLoaded)
			{
				return;
			}
			try
			{
				LethalConfigCompat.Register(((BaseUnityPlugin)this).Config);
				Logger.LogDebug((object)"Registered with LethalConfig.");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("LethalConfig integration failed, falling back to its auto-generated entries: " + ex.Message));
			}
		}

		internal static void Patch()
		{
			//IL_000c: 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)
			//IL_0017: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("bobabulkerENTERPRISE.TolerableFog");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll();
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}
	}
	internal static class FixCameraResolutionsCompat
	{
		private const string PatchesTypeName = "Rumi.FixCameraResolutions.Fogs.FCRHDRPPatches";

		private static bool _patched;

		private static readonly string[] VolumetricsOffByDesign = new string[1] { "MapCamera" };

		private const string StartupReason = "plugin startup";

		private static bool IsOffByDesign(string cameraName)
		{
			return Array.IndexOf(VolumetricsOffByDesign, cameraName) >= 0;
		}

		internal static void EnsurePatched(string reason)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			if (_patched || Plugin.Harmony == null)
			{
				return;
			}
			Type type = AccessTools.TypeByName("Rumi.FixCameraResolutions.Fogs.FCRHDRPPatches");
			if (type == null)
			{
				return;
			}
			_patched = true;
			try
			{
				MethodInfo methodInfo = AccessTools.Method(type, "UpdateVolume", new Type[1] { typeof(Volume) }, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "UpdateHDCameraData", new Type[1] { typeof(HDAdditionalCameraData) }, (Type[])null);
				if (methodInfo == null || methodInfo2 == null)
				{
					Plugin.Logger.LogWarning((object)"Fix Camera Resolutions is installed but its fog methods were not found (different version?); its fog option may override TolerableFog.");
					return;
				}
				string text = AccessTools.Property(type, "fogMode")?.GetValue(null)?.ToString() ?? "unknown";
				Plugin.Harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(FixCameraResolutionsCompat), "SkipUpdateVolume", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(FixCameraResolutionsCompat), "RestoreVolumetrics", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				AccessTools.Method(type, "UpdateAllHDCameraData", (Type[])null, (Type[])null)?.Invoke(null, null);
				Plugin.Logger.LogInfo((object)("Fix Camera Resolutions detected (fog mode: " + text + "); patched during " + reason + ". TolerableFog's fog settings take precedence over its fog option."));
				if (reason != "plugin startup" && (text == "Disable" || text == "ForceDisable"))
				{
					Plugin.Logger.LogWarning((object)("Patched after startup while Fix Camera Resolutions' fog mode is " + text + ": fog volumes that were enabled before this point may have been deactivated by it and stay off. This happens only if it loaded after TolerableFog."));
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogWarning((object)$"Could not neutralise Fix Camera Resolutions' fog option: {arg}");
			}
		}

		private static bool SkipUpdateVolume()
		{
			return false;
		}

		private static void RestoreVolumetrics(HDAdditionalCameraData cameraData)
		{
			bool flag = !IsOffByDesign(((Object)cameraData).name);
			((BitArray128)(ref cameraData.renderingPathCustomFrameSettingsOverrideMask.mask))[28u] = !flag;
			((FrameSettings)(ref cameraData.renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)28, flag);
		}

		internal static void VerifyVolumetrics()
		{
			try
			{
				Camera[] allCameras = Camera.allCameras;
				int num = 0;
				StringBuilder stringBuilder = new StringBuilder();
				Camera[] array = allCameras;
				foreach (Camera val in array)
				{
					HDAdditionalCameraData component = ((Component)val).GetComponent<HDAdditionalCameraData>();
					if (!((Object)(object)component == (Object)null) && !IsOffByDesign(((Object)val).name))
					{
						bool flag = ((BitArray128)(ref component.renderingPathCustomFrameSettingsOverrideMask.mask))[28u];
						bool flag2 = ((FrameSettings)(ref component.renderingPathCustomFrameSettings)).IsEnabled((FrameSettingsField)28);
						if (flag && !flag2)
						{
							num++;
							stringBuilder.Append(" '" + ((Object)val).name + "'");
						}
					}
				}
				if (num == 0)
				{
					Plugin.Logger.LogDebug((object)$"Volumetric fog check: OK ({allCameras.Length} camera(s), none has volumetric fog switched off).");
				}
				else
				{
					Plugin.Logger.LogWarning((object)($"Volumetric fog check: volumetric fog is switched OFF on {num} camera(s):{stringBuilder}. " + "Something other than TolerableFog is overriding it."));
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Volumetric fog check failed: " + ex.Message));
			}
		}
	}
	public class FogConfig : SyncedConfig2<FogConfig>
	{
		internal const float StrengthMin = 0f;

		internal const float StrengthMax = 1f;

		internal const float MovingStrengthMin = 0f;

		internal const float MovingStrengthMax = 1f;

		internal const float ReflectionMin = 0f;

		internal const float ReflectionMax = 1f;

		internal const float SteamStrengthMin = 0f;

		internal const float SteamStrengthMax = 1f;

		internal const float SteamSizeMin = 0f;

		internal const float SteamSizeMax = 1f;

		internal static readonly ConfigDefinition MovingStrengthDefinition = new ConfigDefinition("MovingFog", "Strength");

		internal static readonly ConfigDefinition ReflectionDefinition = new ConfigDefinition("Flashlight", "Reflection");

		internal static readonly ConfigDefinition SteamStrengthDefinition = new ConfigDefinition("SteamLeak", "Strength");

		internal static readonly ConfigDefinition SteamSizeDefinition = new ConfigDefinition("SteamLeak", "Size");

		internal static readonly ConfigDefinition ModdedStrengthsDefinition = new ConfigDefinition("Internal", "ModdedWeatherStrengths");

		internal static readonly ConfigDefinition NoneStrengthDefinition = new ConfigDefinition("Strength", "None");

		internal static readonly ConfigDefinition RainyStrengthDefinition = new ConfigDefinition("Strength", "Rainy");

		internal static readonly ConfigDefinition StormyStrengthDefinition = new ConfigDefinition("Strength", "Stormy");

		internal static readonly ConfigDefinition FoggyStrengthDefinition = new ConfigDefinition("Strength", "Foggy");

		internal static readonly ConfigDefinition FloodedStrengthDefinition = new ConfigDefinition("Strength", "Flooded");

		internal static readonly ConfigDefinition EclipsedStrengthDefinition = new ConfigDefinition("Strength", "Eclipsed");

		internal static readonly ConfigDefinition DustCloudsStrengthDefinition = new ConfigDefinition("Strength", "DustClouds");

		internal static readonly ConfigDefinition[] WeatherStrengthDefinitions = (ConfigDefinition[])(object)new ConfigDefinition[7] { NoneStrengthDefinition, RainyStrengthDefinition, StormyStrengthDefinition, FoggyStrengthDefinition, FloodedStrengthDefinition, EclipsedStrengthDefinition, DustCloudsStrengthDefinition };

		[field: SyncedEntryField]
		public SyncedEntry<float> NoneStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> RainyStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> StormyStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> FoggyStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> FloodedStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> EclipsedStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> DustCloudsStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> MovingFogStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> FlashlightReflection { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> SteamLeakStrength { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<float> SteamLeakSize { get; private set; }

		[field: SyncedEntryField]
		public SyncedEntry<string> ModdedWeatherStrengths { get; private set; }

		internal IEnumerable<SyncedEntry<float>> AllEntries => new SyncedEntry<float>[11]
		{
			NoneStrength, RainyStrength, StormyStrength, FoggyStrength, FloodedStrength, EclipsedStrength, DustCloudsStrength, MovingFogStrength, FlashlightReflection, SteamLeakStrength,
			SteamLeakSize
		};

		public FogConfig(ConfigFile cfg)
			: base("bobabulkerENTERPRISE.TolerableFog")
		{
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			NoneStrength = Bind(cfg, NoneStrengthDefinition, 0.2f, "Fog density on clear days (weather None). 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			RainyStrength = Bind(cfg, RainyStrengthDefinition, 0.2f, "Fog density while it is Rainy. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			StormyStrength = Bind(cfg, StormyStrengthDefinition, 0.2f, "Fog density while it is Stormy. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			FoggyStrength = Bind(cfg, FoggyStrengthDefinition, 0.2f, "Fog density while it is Foggy. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			FloodedStrength = Bind(cfg, FloodedStrengthDefinition, 0.2f, "Fog density while it is Flooded. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			EclipsedStrength = Bind(cfg, EclipsedStrengthDefinition, 0.2f, "Fog density while it is Eclipsed. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			DustCloudsStrength = Bind(cfg, DustCloudsStrengthDefinition, 0.2f, "Fog density while there are DustClouds. 1 = vanilla, 0 = no fog, above 1 = denser.", 0f, 1f);
			MovingFogStrength = Bind(cfg, MovingStrengthDefinition, 0.5f, "Strength of the drifting fog that moves around a moon (e.g. dust storms), in every weather. Independent of the weather strengths. 1 = vanilla, 0 = removed, above 1 = denser.", 0f, 1f);
			FlashlightReflection = Bind(cfg, ReflectionDefinition, 0.1f, "How strongly flashlight and helmet-light beams glow in fog. 1 = vanilla, 0 = invisible beams.", 0f, 1f);
			SteamLeakStrength = Bind(cfg, SteamStrengthDefinition, 0.4f, "How dense the fog from burst steam valves is. 1 = vanilla, 0 = no steam fog.", 0f, 1f);
			SteamLeakSize = Bind(cfg, SteamSizeDefinition, 0.6f, "How large burst steam fog can grow. 1 = vanilla (full size), 0 = it never grows.", 0f, 1f);
			ModdedWeatherStrengths = SyncedBindingExtensions.BindSyncedEntry<string>(CreateInMemoryConfig(), ModdedStrengthsDefinition, "", new ConfigDescription("Managed automatically from the [Strength (Modded)] settings.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigManager.Register<FogConfig>((SyncedConfig2<FogConfig>)(object)this);
		}

		public SyncedEntry<float> StrengthFor(LevelWeatherType weather)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			return (SyncedEntry<float>)((int)weather switch
			{
				1 => RainyStrength, 
				2 => StormyStrength, 
				3 => FoggyStrength, 
				4 => FloodedStrength, 
				5 => EclipsedStrength, 
				0 => DustCloudsStrength, 
				_ => NoneStrength, 
			});
		}

		private static ConfigFile CreateInMemoryConfig()
		{
			//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_0033: Expected O, but got Unknown
			string text = Path.Combine(Path.GetTempPath(), string.Format("{0}.{1:N}.cfg", "bobabulkerENTERPRISE.TolerableFog", Guid.NewGuid()));
			return new ConfigFile(text, false)
			{
				SaveOnConfigSet = false
			};
		}

		private static SyncedEntry<float> Bind(ConfigFile cfg, ConfigDefinition definition, float defaultValue, string description, float min, float max)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			return SyncedBindingExtensions.BindSyncedEntry<float>(cfg, definition, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}
	}
	internal static class FogController
	{
		private struct FogBaseline
		{
			public LocalVolumetricFog Fog;

			public float MeanFreePath;
		}

		private sealed class ManagedFogEntry
		{
			public LocalVolumetricFog Fog;

			public float BaseMeanFreePath;

			public bool IsMoving;
		}

		private sealed class GlobalFogEntry
		{
			public Fog Component;

			public float BaseMeanFreePath;
		}

		private sealed class FollowedFog
		{
			public LocalVolumetricFog Fog;

			public float Base;

			public float LastWritten;
		}

		private const float FogOffDistance = 1000000f;

		private static FollowedFog? _foggy;

		private static FogBaseline? _indoorFog;

		private static readonly List<ManagedFogEntry> ManagedFogs = new List<ManagedFogEntry>();

		private static readonly List<GlobalFogEntry> GlobalFogs = new List<GlobalFogEntry>();

		private static readonly HashSet<LocalVolumetricFog> SteamFogs = new HashSet<LocalVolumetricFog>();

		private static readonly ConditionalWeakTable<HDAdditionalLightData, StrongBox<float>> LightBaselines = new ConditionalWeakTable<HDAdditionalLightData, StrongBox<float>>();

		private static float _lastStrength = float.NaN;

		private static float _strengthCache;

		private static int _strengthFrame = -1;

		private static float _nextTick;

		private static float _lastMovingStrength = float.NaN;

		private static float _lastReflection = float.NaN;

		private static float _lastSteamStrength = float.NaN;

		private static float _lastSteamSize = float.NaN;

		internal static LevelWeatherType CurrentWeather
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				TimeOfDay instance = TimeOfDay.Instance;
				if (!((Object)(object)instance != (Object)null))
				{
					return (LevelWeatherType)(-1);
				}
				return instance.currentLevelWeather;
			}
		}

		internal static float CurrentStrength
		{
			get
			{
				if (_strengthFrame != Time.frameCount)
				{
					_strengthCache = ComputeCurrentStrength();
					_strengthFrame = Time.frameCount;
				}
				return _strengthCache;
			}
		}

		internal static float MovingStrength => Mathf.Clamp(Plugin.Settings.MovingFogStrength.Value, 0f, 1f);

		internal static float Reflection => Mathf.Clamp(Plugin.Settings.FlashlightReflection.Value, 0f, 1f);

		internal static float SteamStrength => Mathf.Clamp(Plugin.Settings.SteamLeakStrength.Value, 0f, 1f);

		internal static float SteamSize => Mathf.Clamp(Plugin.Settings.SteamLeakSize.Value, 0f, 1f);

		internal static float WeatherStrength(LevelWeatherType weather)
		{
			//IL_000a: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.IsDefined(typeof(LevelWeatherType), weather) && ModdedWeatherStrengths.TryGetStrength(weather, out var strength))
			{
				return Mathf.Clamp(strength, 0f, 1f);
			}
			return Mathf.Clamp(Plugin.Settings.StrengthFor(weather).Value, 0f, 1f);
		}

		private static float ComputeCurrentStrength()
		{
			//IL_0071: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			List<LevelWeatherType> list = WeatherRegistryCompat.ActiveEffects();
			if (list != null && list.Count > 0)
			{
				float num = 1f;
				int num2 = 0;
				foreach (LevelWeatherType item in list)
				{
					if ((int)item != -1 || list.Count <= 1)
					{
						num *= WeatherStrength(item);
						num2++;
					}
				}
				if (num2 > 0)
				{
					return Mathf.Min(num, 1f);
				}
			}
			return WeatherStrength(CurrentWeather);
		}

		private unsafe static string WeatherLabel(LevelWeatherType type)
		{
			//IL_000a: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected I4, but got Unknown
			if (Enum.IsDefined(typeof(LevelWeatherType), type))
			{
				return ((object)(*(LevelWeatherType*)(&type))/*cast due to .constrained prefix*/).ToString();
			}
			return WeatherRegistryCompat.NameOf(type) ?? $"Modded({(int)type})";
		}

		internal static string DescribeCurrentWeather()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			List<LevelWeatherType> list = WeatherRegistryCompat.ActiveEffects();
			if (list != null && list.Count > 0)
			{
				List<string> list2 = new List<string>();
				foreach (LevelWeatherType item in list)
				{
					list2.Add(WeatherLabel(item));
				}
				return string.Join("+", list2);
			}
			return WeatherLabel(CurrentWeather);
		}

		internal static float ScaleByStrength(float vanilla, float strength)
		{
			if (Mathf.Approximately(strength, 1f))
			{
				return vanilla;
			}
			float num = ((strength <= 0.0001f) ? 1000000f : (vanilla / strength));
			return Mathf.Max(1f, num);
		}

		internal static float ScaleMeanFreePath(float vanilla)
		{
			return ScaleByStrength(vanilla, CurrentStrength);
		}

		private static float ScaleMovingMeanFreePath(float vanilla)
		{
			return ScaleByStrength(vanilla, MovingStrength);
		}

		private static float ScaleManaged(ManagedFogEntry entry)
		{
			if (!entry.IsMoving)
			{
				return ScaleMeanFreePath(entry.BaseMeanFreePath);
			}
			return ScaleMovingMeanFreePath(entry.BaseMeanFreePath);
		}

		private static void SetMeanFreePath(LocalVolumetricFog fog, float value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//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)
			LocalVolumetricFogArtistParameters parameters = fog.parameters;
			if (!Mathf.Approximately(parameters.meanFreePath, value))
			{
				parameters.meanFreePath = value;
				fog.parameters = parameters;
			}
		}

		private static void SetGlobalMeanFreePath(Fog fog, float value)
		{
			if (!Mathf.Approximately(((VolumeParameter<float>)(object)fog.meanFreePath).value, value))
			{
				((VolumeParameter<float>)(object)fog.meanFreePath).value = value;
			}
		}

		private static void Apply(in FogBaseline baseline)
		{
			SetMeanFreePath(baseline.Fog, ScaleMeanFreePath(baseline.MeanFreePath));
		}

		private static string PathOf(Transform t)
		{
			string text = ((Object)t).name;
			Transform parent = t.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		internal static void OnFoggyWeatherSet(TimeOfDay timeOfDay)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)timeOfDay.currentLevelWeather == 3 && !((Object)(object)timeOfDay.foggyWeather == (Object)null))
			{
				LocalVolumetricFog foggyWeather = timeOfDay.foggyWeather;
				float meanFreePath = foggyWeather.parameters.meanFreePath;
				float num = ScaleMeanFreePath(meanFreePath);
				SetMeanFreePath(foggyWeather, num);
				_foggy = new FollowedFog
				{
					Fog = foggyWeather,
					Base = meanFreePath,
					LastWritten = num
				};
				Plugin.Logger.LogDebug((object)$"Foggy weather (game set it): {meanFreePath} -> {foggyWeather.parameters.meanFreePath}");
			}
		}

		internal static void OnPlayerEffectsSet(PlayerControllerB player)
		{
			PlayerControllerB spectatedPlayerScript = player.spectatedPlayerScript;
			AudioReverbTrigger val = (((Object)(object)spectatedPlayerScript != (Object)null) ? spectatedPlayerScript.currentAudioTrigger : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.localFog == (Object)null) && val.toggleLocalFog)
			{
				SetMeanFreePath(val.localFog, ScaleMeanFreePath(val.fogEnabledAmount));
			}
		}

		internal static bool ApplyLight(Light? light)
		{
			if ((Object)(object)light == (Object)null)
			{
				return false;
			}
			HDAdditionalLightData component = ((Component)light).GetComponent<HDAdditionalLightData>();
			if ((Object)(object)component == (Object)null || !component.affectsVolumetric)
			{
				return false;
			}
			StrongBox<float> value = LightBaselines.GetValue(component, (HDAdditionalLightData h) => new StrongBox<float>(h.volumetricDimmer));
			component.volumetricDimmer = Mathf.Clamp(value.Value * Reflection, 0f, 16f);
			return true;
		}

		internal static void Refresh()
		{
			_strengthFrame = -1;
			float num = (_lastStrength = CurrentStrength);
			_lastMovingStrength = MovingStrength;
			_lastReflection = Reflection;
			_lastSteamStrength = SteamStrength;
			_lastSteamSize = SteamSize;
			bool flag = RefreshFoggyWeather();
			bool flag2 = RefreshIndoorFog();
			int num2 = RefreshManagedFogs();
			int num3 = RefreshGlobalFogs();
			int num4 = RefreshLights();
			RefreshAreaFog();
			int num5 = CountSteamValves();
			RoundManager instance = RoundManager.Instance;
			bool flag3 = (Object)(object)instance != (Object)null && (Object)(object)instance.indoorFog != (Object)null && ((Component)instance.indoorFog).gameObject.activeSelf;
			string text = "";
			if (flag && _foggy != null)
			{
				text = $" [attenuation {_foggy.Base} -> {_foggy.Fog.parameters.meanFreePath}]";
			}
			Plugin.Logger.LogDebug((object)($"Refresh | weather={DescribeCurrentWeather()} strength={num} | movingFog={_lastMovingStrength}, " + $"reflection={_lastReflection}, steamStrength={_lastSteamStrength}, steamSize={_lastSteamSize} | " + string.Format("foggy weather fog={0}{1}, indoor fog applied={2} (active={3}), ", flag ? "found" : "missing", text, flag2, flag3) + $"scene fogs={num2}, global fog volumes={num3}, lights={num4}, steam valves={num5}"));
		}

		internal static void Tick()
		{
			if (!(Time.unscaledTime < _nextTick))
			{
				_nextTick = Time.unscaledTime + 0.25f;
				ModdedWeatherStrengths.Poll();
				RefreshIfSettingsChanged();
				if (FoggyFogWasRewritten())
				{
					RefreshFoggyWeather();
				}
			}
		}

		internal static void RefreshIfSettingsChanged()
		{
			if (Plugin.Settings != null)
			{
				_strengthFrame = -1;
				if (CurrentStrength != _lastStrength || MovingStrength != _lastMovingStrength || Reflection != _lastReflection || SteamStrength != _lastSteamStrength || SteamSize != _lastSteamSize)
				{
					Refresh();
				}
			}
		}

		private static bool RefreshFoggyWeather()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			LocalVolumetricFog val = (((Object)(object)instance != (Object)null) ? instance.foggyWeather : null);
			if ((Object)(object)val == (Object)null)
			{
				_foggy = null;
				return false;
			}
			float meanFreePath = val.parameters.meanFreePath;
			if (_foggy == null || (Object)(object)_foggy.Fog != (Object)(object)val)
			{
				_foggy = new FollowedFog
				{
					Fog = val,
					Base = meanFreePath,
					LastWritten = meanFreePath
				};
				Plugin.Logger.LogDebug((object)$"Foggy weather fog found (vanilla attenuation {meanFreePath}).");
			}
			else if (!Mathf.Approximately(meanFreePath, _foggy.LastWritten))
			{
				_foggy.Base = meanFreePath;
				Plugin.Logger.LogDebug((object)$"Foggy weather fog was rewritten by the game (now {meanFreePath}); following it.");
			}
			float num = ScaleMeanFreePath(_foggy.Base);
			SetMeanFreePath(val, num);
			_foggy.LastWritten = num;
			return true;
		}

		private static bool FoggyFogWasRewritten()
		{
			if (_foggy != null && (Object)(object)_foggy.Fog != (Object)null)
			{
				return !Mathf.Approximately(_foggy.Fog.parameters.meanFreePath, _foggy.LastWritten);
			}
			return false;
		}

		private static bool RefreshIndoorFog()
		{
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.indoorFog == (Object)null)
			{
				return false;
			}
			LocalVolumetricFog indoorFog = instance.indoorFog;
			if (!_indoorFog.HasValue || (Object)(object)_indoorFog.Value.Fog != (Object)(object)indoorFog)
			{
				_indoorFog = new FogBaseline
				{
					Fog = indoorFog,
					MeanFreePath = indoorFog.parameters.meanFreePath
				};
			}
			Apply(_indoorFog.Value);
			return true;
		}

		private static int RefreshManagedFogs()
		{
			ManagedFogs.RemoveAll((ManagedFogEntry e) => (Object)(object)e.Fog == (Object)null);
			HashSet<LocalVolumetricFog> hashSet = new HashSet<LocalVolumetricFog>();
			TimeOfDay instance = TimeOfDay.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.foggyWeather != (Object)null)
			{
				hashSet.Add(instance.foggyWeather);
			}
			RoundManager instance2 = RoundManager.Instance;
			if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.indoorFog != (Object)null)
			{
				hashSet.Add(instance2.indoorFog);
			}
			AudioReverbTrigger[] array = Object.FindObjectsByType<AudioReverbTrigger>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (AudioReverbTrigger val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.localFog != (Object)null)
				{
					hashSet.Add(val.localFog);
				}
			}
			LocalVolumetricFog[] array2 = Object.FindObjectsByType<LocalVolumetricFog>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (LocalVolumetricFog fog in array2)
			{
				if (!((Object)(object)fog == (Object)null) && !hashSet.Contains(fog) && !IsExcludedByRole(fog) && !ManagedFogs.Exists((ManagedFogEntry e) => (Object)(object)e.Fog == (Object)(object)fog))
				{
					float meanFreePath = fog.parameters.meanFreePath;
					bool flag = IsMovingFog(fog);
					ManagedFogs.Add(new ManagedFogEntry
					{
						Fog = fog,
						BaseMeanFreePath = meanFreePath,
						IsMoving = flag
					});
					Plugin.Logger.LogDebug((object)string.Format("{0}: '{1}' (vanilla attenuation {2})", flag ? "Moving fog" : "Scene fog", PathOf(((Component)fog).transform), meanFreePath));
				}
			}
			foreach (ManagedFogEntry managedFog in ManagedFogs)
			{
				SetMeanFreePath(managedFog.Fog, ScaleManaged(managedFog));
			}
			return ManagedFogs.Count;
		}

		private static bool IsMovingFog(LocalVolumetricFog fog)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			LocalVolumetricFogArtistParameters parameters = fog.parameters;
			if ((Object)(object)parameters.volumeMask != (Object)null)
			{
				return ((Vector3)(ref parameters.textureScrollingSpeed)).sqrMagnitude > 0f;
			}
			return false;
		}

		private static bool IsExcludedByRole(LocalVolumetricFog fog)
		{
			if (SteamFogs.Contains(fog) || (Object)(object)((Component)fog).GetComponentInParent<SteamValveHazard>(true) != (Object)null)
			{
				return true;
			}
			return ((Object)fog).name.IndexOf("exclusion", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static int RefreshGlobalFogs()
		{
			GlobalFogs.RemoveAll((GlobalFogEntry e) => (Object)(object)e.Component == (Object)null);
			Volume[] array = Object.FindObjectsByType<Volume>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			Fog fog = default(Fog);
			foreach (Volume val in array)
			{
				VolumeProfile sharedProfile = val.sharedProfile;
				if (!((Object)(object)sharedProfile == (Object)null) && sharedProfile.TryGet<Fog>(ref fog) && ((VolumeComponent)fog).active && ((VolumeParameter)fog.meanFreePath).overrideState && !GlobalFogs.Exists((GlobalFogEntry e) => (Object)(object)e.Component == (Object)(object)fog))
				{
					float value = ((VolumeParameter<float>)(object)fog.meanFreePath).value;
					GlobalFogs.Add(new GlobalFogEntry
					{
						Component = fog,
						BaseMeanFreePath = value
					});
					Plugin.Logger.LogDebug((object)$"Global fog: volume '{((Object)val).name}' (vanilla attenuation {value})");
				}
			}
			foreach (GlobalFogEntry globalFog in GlobalFogs)
			{
				SetGlobalMeanFreePath(globalFog.Component, ScaleMeanFreePath(globalFog.BaseMeanFreePath));
			}
			return GlobalFogs.Count;
		}

		private static void RefreshAreaFog()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.localPlayerController != (Object)null)
			{
				OnPlayerEffectsSet(instance.localPlayerController);
			}
		}

		private static int RefreshLights()
		{
			int num = 0;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && instance.allPlayerScripts != null)
			{
				PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
				foreach (PlayerControllerB val in allPlayerScripts)
				{
					if ((Object)(object)val == (Object)null || val.allHelmetLights == null)
					{
						continue;
					}
					Light[] allHelmetLights = val.allHelmetLights;
					foreach (Light light in allHelmetLights)
					{
						if (ApplyLight(light))
						{
							num++;
						}
					}
				}
			}
			FlashlightItem[] array = Object.FindObjectsByType<FlashlightItem>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			foreach (FlashlightItem val2 in array)
			{
				if (ApplyLight(val2.flashlightBulb))
				{
					num++;
				}
			}
			return num;
		}

		internal static void OnSteamValveUpdated(SteamValveHazard valve)
		{
			float steamSize = SteamSize;
			if (!(steamSize >= 1f) && !((Object)(object)valve.fogAnimator == (Object)null) && !(valve.currentFogSize <= 0f))
			{
				valve.fogAnimator.SetFloat("time", valve.currentFogSize * steamSize);
			}
		}

		private static void AddFogs(List<LocalVolumetricFog> into, LocalVolumetricFog[] found)
		{
			foreach (LocalVolumetricFog val in found)
			{
				if ((Object)(object)val != (Object)null && !into.Contains(val))
				{
					into.Add(val);
				}
			}
		}

		internal static void OnSteamValveStart(SteamValveHazard valve)
		{
			List<LocalVolumetricFog> list = new List<LocalVolumetricFog>();
			AddFogs(list, ((Component)valve).GetComponentsInChildren<LocalVolumetricFog>(true));
			if ((Object)(object)valve.fogAnimator != (Object)null)
			{
				AddFogs(list, ((Component)valve.fogAnimator).GetComponentsInChildren<LocalVolumetricFog>(true));
			}
			if (list.Count == 0)
			{
				Plugin.Logger.LogWarning((object)("Steam valve '" + ((Object)valve).name + "': no LocalVolumetricFog found under the valve or its fog animator, so SteamLeak/Strength can't affect it (SteamLeak/Size still works)."));
				return;
			}
			foreach (LocalVolumetricFog fog in list)
			{
				SteamFogs.Add(fog);
				ManagedFogEntry managedFogEntry = ManagedFogs.Find((ManagedFogEntry e) => (Object)(object)e.Fog == (Object)(object)fog);
				if (managedFogEntry != null)
				{
					SetMeanFreePath(fog, managedFogEntry.BaseMeanFreePath);
					ManagedFogs.Remove(managedFogEntry);
				}
			}
			SteamFogScaler steamFogScaler = ((Component)valve).GetComponent<SteamFogScaler>();
			if ((Object)(object)steamFogScaler == (Object)null)
			{
				steamFogScaler = ((Component)valve).gameObject.AddComponent<SteamFogScaler>();
			}
			steamFogScaler.Init(list.ToArray());
			Plugin.Logger.LogDebug((object)($"Steam valve '{((Object)valve).name}': tracking {list.Count} fog volume(s) " + "[" + string.Join(", ", list.ConvertAll((LocalVolumetricFog f) => $"{((Object)f).name} (attenuation {f.parameters.meanFreePath})")) + "]"));
		}

		private static int CountSteamValves()
		{
			return Object.FindObjectsByType<SteamValveHazard>((FindObjectsInactive)1, (FindObjectsSortMode)0).Length;
		}
	}
	internal static class FogDiagnostics
	{
		private const int MaxNamedObjects = 200;

		internal static void LogFogObjects()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				StringBuilder stringBuilder = new StringBuilder("Fog object dump:");
				FieldInfo[] fields = typeof(LocalVolumetricFogArtistParameters).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				LocalVolumetricFog[] array = Object.FindObjectsByType<LocalVolumetricFog>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				Scene scene;
				foreach (LocalVolumetricFog val in array)
				{
					string[] obj = new string[6]
					{
						"\n  LocalVolumetricFog '",
						PathOf(((Component)val).transform),
						"' scene='",
						null,
						null,
						null
					};
					scene = ((Component)val).gameObject.scene;
					obj[3] = ((Scene)(ref scene)).name;
					obj[4] = "' ";
					obj[5] = $"activeInHierarchy={((Component)val).gameObject.activeInHierarchy} enabled={((Behaviour)val).enabled}";
					stringBuilder.Append(string.Concat(obj));
					object boxed = val.parameters;
					stringBuilder.Append("\n      ");
					stringBuilder.Append(string.Join("; ", fields.Select((FieldInfo f) => f.Name + "=" + Format(f.GetValue(boxed)))));
				}
				string[] source = new string[7] { "fog", "mist", "haze", "cloud", "smoke", "vapor", "steam" };
				int num = 0;
				stringBuilder.Append("\n  Objects with fog-like names:");
				Transform[] array2 = Object.FindObjectsByType<Transform>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				foreach (Transform val2 in array2)
				{
					string lower = ((Object)val2).name.ToLowerInvariant();
					if (source.Any((string k) => lower.Contains(k)))
					{
						if (++num > 200)
						{
							stringBuilder.Append("\n    ... (truncated)");
							break;
						}
						string arg = string.Join(", ", from c in ((Component)val2).GetComponents<Component>()
							where (Object)(object)c != (Object)null && !(c is Transform)
							select ((object)c).GetType().Name);
						string[] obj2 = new string[6]
						{
							"\n    '",
							PathOf(val2),
							"' scene='",
							null,
							null,
							null
						};
						scene = ((Component)val2).gameObject.scene;
						obj2[3] = ((Scene)(ref scene)).name;
						obj2[4] = "' ";
						obj2[5] = $"active={((Component)val2).gameObject.activeInHierarchy} [{arg}]";
						stringBuilder.Append(string.Concat(obj2));
					}
				}
				Plugin.Logger.LogDebug((object)stringBuilder.ToString());
			}
			catch (Exception arg2)
			{
				Plugin.Logger.LogWarning((object)$"Fog object dump failed: {arg2}");
			}
		}

		private static string Format(object? value)
		{
			if (value != null)
			{
				Object val = (Object)((value is Object) ? value : null);
				if (val != null)
				{
					return (val != (Object)null) ? (((object)val).GetType().Name + ":" + val.name) : "null";
				}
				return value.ToString();
			}
			return "null";
		}

		private static string PathOf(Transform t)
		{
			StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
			Transform parent = t.parent;
			while ((Object)(object)parent != (Object)null)
			{
				stringBuilder.Insert(0, ((Object)parent).name + "/");
				parent = parent.parent;
			}
			return stringBuilder.ToString();
		}
	}
	internal static class LethalConfigBridge
	{
		internal static void RegisterSlider(ConfigEntry<float> entry)
		{
			if (!LethalConfigCompat.IsLoaded)
			{
				return;
			}
			try
			{
				LethalConfigCompat.RegisterModdedSlider(entry);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogDebug((object)("Could not add '" + ((ConfigEntryBase)entry).Definition.Key + "' to LethalConfig: " + ex.Message));
			}
		}
	}
	internal static class LethalConfigCompat
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static CanModifyDelegate <0>__CanModify;
		}

		internal const string PluginGuid = "ainavt.lc.lethalconfig";

		internal static bool IsLoaded => Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Register(ConfigFile cfg)
		{
			ConfigDefinition[] weatherStrengthDefinitions = FogConfig.WeatherStrengthDefinitions;
			foreach (ConfigDefinition definition in weatherStrengthDefinitions)
			{
				AddSlider(cfg, definition, 0f, 1f);
			}
			AddSlider(cfg, FogConfig.MovingStrengthDefinition, 0f, 1f);
			AddSlider(cfg, FogConfig.ReflectionDefinition, 0f, 1f);
			AddSlider(cfg, FogConfig.SteamStrengthDefinition, 0f, 1f);
			AddSlider(cfg, FogConfig.SteamSizeDefinition, 0f, 1f);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void RegisterModdedSlider(ConfigEntry<float> entry)
		{
			AddSlider(entry, 0f, 1f);
		}

		private static void AddSlider(ConfigFile cfg, ConfigDefinition definition, float min, float max)
		{
			AddSlider((ConfigEntry<float>)(object)cfg[definition], min, max);
		}

		private static void AddSlider(ConfigEntry<float> entry, float min, float max)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//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_0038: Expected O, but got Unknown
			FloatSliderOptions val = new FloatSliderOptions();
			((BaseRangeOptions<float>)(object)val).Min = min;
			((BaseRangeOptions<float>)(object)val).Max = max;
			((BaseOptions)val).RequiresRestart = false;
			object obj = <>O.<0>__CanModify;
			if (obj == null)
			{
				CanModifyDelegate val2 = CanModify;
				<>O.<0>__CanModify = val2;
				obj = (object)val2;
			}
			((BaseOptions)val).CanModifyCallback = (CanModifyDelegate)obj;
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(entry, val));
		}

		private static CanModifyResult CanModify()
		{
			//IL_0032: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton != (Object)null) || !singleton.IsClient || singleton.IsHost)
			{
				return CanModifyResult.True();
			}
			return CanModifyResult.False("Controlled by the host while you are in their lobby.");
		}
	}
	internal static class ModdedWeatherStrengths
	{
		internal const string Section = "Strength (Modded)";

		private static ConfigFile? _cfg;

		private static readonly Dictionary<string, ConfigEntry<float>> Entries = new Dictionary<string, ConfigEntry<float>>();

		private static readonly Dictionary<LevelWeatherType, string> KeyByType = new Dictionary<LevelWeatherType, string>();

		private static bool _needsRebuild = true;

		private static int _lastCount = -1;

		private static string _parsedFrom = "";

		private static Dictionary<string, float> _parsed = new Dictionary<string, float>();

		internal static void Init(ConfigFile cfg)
		{
			_cfg = cfg;
		}

		internal static void Poll()
		{
			if (_cfg == null || !WeatherRegistryCompat.TryGetSetupState(out var finished, out var count))
			{
				return;
			}
			if (!finished)
			{
				_needsRebuild = true;
			}
			else if (_needsRebuild || count != _lastCount)
			{
				List<KeyValuePair<LevelWeatherType, string>> list = WeatherRegistryCompat.ModdedWeathers();
				if (list != null)
				{
					_needsRebuild = false;
					_lastCount = count;
					Rebuild(list);
				}
			}
		}

		private static void Rebuild(List<KeyValuePair<LevelWeatherType, string>> weathers)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected I4, but got Unknown
			KeyByType.Clear();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			List<string> list = new List<string>();
			foreach (KeyValuePair<LevelWeatherType, string> weather in weathers)
			{
				string text = Sanitize(weather.Value, weather.Key);
				string text2 = text;
				int num = 2;
				while (!hashSet.Add(text2))
				{
					text2 = $"{text} ({num})";
					num++;
				}
				KeyByType[weather.Key] = text2;
				Bind(text2, weather.Value);
				list.Add($"'{text2}' = {(int)weather.Key}");
			}
			Plugin.Logger.LogDebug((object)((weathers.Count == 0) ? "WeatherRegistry is set up; no modded weathers registered." : ("Modded weathers found: " + string.Join(", ", list))));
			Pack();
		}

		private static void Bind(string key, string displayName)
		{
			//IL_0019: 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_0051: Expected O, but got Unknown
			//IL_0051: Expected O, but got Unknown
			if (!Entries.ContainsKey(key))
			{
				ConfigEntry<float> val = _cfg.Bind<float>(new ConfigDefinition("Strength (Modded)", key), 1f, new ConfigDescription("Fog density while the modded weather '" + displayName + "' is active. 1 = vanilla, 0 = no fog, above 1 = denser.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
				Entries[key] = val;
				val.SettingChanged += delegate
				{
					Pack();
				};
				LethalConfigBridge.RegisterSlider(val);
			}
		}

		internal static void Pack()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (Plugin.Settings == null || ((Object)(object)singleton != (Object)null && singleton.IsClient && !singleton.IsHost))
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string value2 in KeyByType.Values)
			{
				if (Entries.TryGetValue(value2, out ConfigEntry<float> value))
				{
					stringBuilder.Append(value2).Append('=').Append(value.Value.ToString("0.####", CultureInfo.InvariantCulture))
						.Append(';');
				}
			}
			string text = stringBuilder.ToString();
			if (Plugin.Settings.ModdedWeatherStrengths.LocalValue != text)
			{
				Plugin.Settings.ModdedWeatherStrengths.LocalValue = text;
			}
		}

		internal static bool TryGetStrength(LevelWeatherType type, out float strength)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			strength = 1f;
			if (!KeyByType.TryGetValue(type, out string value))
			{
				return false;
			}
			strength = (Parsed().TryGetValue(value, out var value2) ? value2 : 1f);
			return true;
		}

		private static Dictionary<string, float> Parsed()
		{
			string text = Plugin.Settings.ModdedWeatherStrengths.Value ?? "";
			if (text == _parsedFrom)
			{
				return _parsed;
			}
			Dictionary<string, float> dictionary = new Dictionary<string, float>(StringComparer.Ordinal);
			string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				int num = text2.LastIndexOf('=');
				if (num > 0 && float.TryParse(text2.Substring(num + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					dictionary[text2.Substring(0, num)] = Mathf.Clamp(result, 0f, 1f);
				}
			}
			_parsedFrom = text;
			_parsed = dictionary;
			return dictionary;
		}

		private static string Sanitize(string name, LevelWeatherType type)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected I4, but got Unknown
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in name)
			{
				if (c != '=' && c != ';' && c != '\n' && c != '\r' && c != '\t' && c != '"' && c != '\'' && c != '[' && c != ']')
				{
					stringBuilder.Append(c);
				}
			}
			string text = stringBuilder.ToString().Trim();
			if (text.Length <= 0)
			{
				return $"Weather{(int)type}";
			}
			return text;
		}
	}
	internal sealed class SteamFogScaler : MonoBehaviour
	{
		private LocalVolumetricFog[] _fogs = Array.Empty<LocalVolumetricFog>();

		private float[] _baseline = Array.Empty<float>();

		private float[] _lastWritten = Array.Empty<float>();

		private bool _reportedAnimated;

		internal void Init(LocalVolumetricFog[] fogs)
		{
			_fogs = fogs;
			_baseline = new float[fogs.Length];
			_lastWritten = new float[fogs.Length];
			for (int i = 0; i < fogs.Length; i++)
			{
				float meanFreePath = fogs[i].parameters.meanFreePath;
				_baseline[i] = meanFreePath;
				_lastWritten[i] = meanFreePath;
			}
		}

		private void LateUpdate()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			float steamStrength = FogController.SteamStrength;
			for (int i = 0; i < _fogs.Length; i++)
			{
				LocalVolumetricFog val = _fogs[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				LocalVolumetricFogArtistParameters parameters = val.parameters;
				float meanFreePath = parameters.meanFreePath;
				if (!Mathf.Approximately(meanFreePath, _lastWritten[i]))
				{
					if (!_reportedAnimated)
					{
						_reportedAnimated = true;
						Plugin.Logger.LogDebug((object)$"Steam fog '{((Object)val).name}': attenuation is changed by the game (now {meanFreePath}); scaling it each frame.");
					}
					_baseline[i] = meanFreePath;
				}
				float num = FogController.ScaleByStrength(_baseline[i], steamStrength);
				if (!Mathf.Approximately(num, meanFreePath))
				{
					parameters.meanFreePath = num;
					val.parameters = parameters;
				}
				_lastWritten[i] = num;
			}
		}
	}
	internal static class WeatherRegistryCompat
	{
		private const string ManagerTypeName = "WeatherRegistry.WeatherManager";

		private static bool? _available;

		private static bool _reportedError;

		internal static bool IsAvailable
		{
			get
			{
				bool valueOrDefault = _available == true;
				if (!_available.HasValue)
				{
					valueOrDefault = AccessTools.TypeByName("WeatherRegistry.WeatherManager") != null;
					_available = valueOrDefault;
					return valueOrDefault;
				}
				return valueOrDefault;
			}
		}

		internal static List<LevelWeatherType>? ActiveEffects()
		{
			if (!IsAvailable)
			{
				return null;
			}
			try
			{
				return ReadActiveEffects();
			}
			catch (Exception e)
			{
				ReportOnce(e);
				return null;
			}
		}

		internal static string? NameOf(LevelWeatherType type)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!IsAvailable)
			{
				return null;
			}
			try
			{
				return ReadName(type);
			}
			catch (Exception e)
			{
				ReportOnce(e);
				return null;
			}
		}

		internal static bool TryGetSetupState(out bool finished, out int count)
		{
			finished = false;
			count = 0;
			if (!IsAvailable)
			{
				return false;
			}
			try
			{
				finished = ReadSetupState(out count);
				return true;
			}
			catch (Exception e)
			{
				ReportOnce(e);
				return false;
			}
		}

		internal static List<KeyValuePair<LevelWeatherType, string>>? ModdedWeathers()
		{
			if (!IsAvailable)
			{
				return null;
			}
			try
			{
				return ReadModdedWeathers();
			}
			catch (Exception e)
			{
				ReportOnce(e);
				return null;
			}
		}

		private static void ReportOnce(Exception e)
		{
			if (!_reportedError)
			{
				_reportedError = true;
				Plugin.Logger.LogWarning((object)("WeatherRegistry integration failed (different version?); modded weathers fall back to the None strength. " + e.Message));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static List<LevelWeatherType>? ReadActiveEffects()
		{
			if (!WeatherManager.IsSetupFinished)
			{
				return null;
			}
			return WeatherManager.CurrentEffectTypes;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string? ReadName(LevelWeatherType type)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!WeatherManager.WeathersDictionary.TryGetValue(type, out var value))
			{
				return null;
			}
			return value.Name;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool ReadSetupState(out int count)
		{
			count = WeatherManager.WeathersDictionary.Count;
			return WeatherManager.IsSetupFinished;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static List<KeyValuePair<LevelWeatherType, string>>? ReadModdedWeathers()
		{
			//IL_0030: 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)
			if (!WeatherManager.IsSetupFinished)
			{
				return null;
			}
			List<KeyValuePair<LevelWeatherType, string>> list = new List<KeyValuePair<LevelWeatherType, string>>();
			foreach (KeyValuePair<LevelWeatherType, Weather> item in WeatherManager.WeathersDictionary)
			{
				if (!Enum.IsDefined(typeof(LevelWeatherType), item.Key) && item.Value != null)
				{
					list.Add(new KeyValuePair<LevelWeatherType, string>(item.Key, item.Value.Name ?? string.Empty));
				}
			}
			list.Sort((KeyValuePair<LevelWeatherType, string> a, KeyValuePair<LevelWeatherType, string> b) => ((int)a.Key).CompareTo((int)b.Key));
			return list;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "bobabulkerENTERPRISE.TolerableFog";

		public const string PLUGIN_NAME = "TolerableFog";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}
namespace TolerableFog.Patches
{
	[HarmonyPatch(typeof(TimeOfDay))]
	internal static class TimeOfDayPatches
	{
		[HarmonyPatch("SetWeatherBasedOnVariables")]
		[HarmonyPostfix]
		private static void SetWeatherBasedOnVariablesPostfix(TimeOfDay __instance)
		{
			FogController.OnFoggyWeatherSet(__instance);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix()
		{
			FogController.Tick();
		}
	}
	[HarmonyPatch(typeof(RoundManager), "FinishGeneratingLevel")]
	internal static class RoundManagerPatches
	{
		[HarmonyPostfix]
		private static void FinishGeneratingLevelPostfix()
		{
			FixCameraResolutionsCompat.EnsurePatched("level load");
			FixCameraResolutionsCompat.VerifyVolumetrics();
			FogController.Refresh();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatches
	{
		[HarmonyPatch("SetSpectatedPlayerEffects")]
		[HarmonyPostfix]
		private static void SetSpectatedPlayerEffectsPostfix(PlayerControllerB __instance)
		{
			FogController.OnPlayerEffectsSet(__instance);
		}
	}
	[HarmonyPatch(typeof(FlashlightItem))]
	internal static class FlashlightItemPatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix(FlashlightItem __instance)
		{
			FogController.ApplyLight(__instance.flashlightBulb);
		}
	}
	[HarmonyPatch(typeof(SteamValveHazard))]
	internal static class SteamValveHazardPatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix(SteamValveHazard __instance)
		{
			FogController.OnSteamValveStart(__instance);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(SteamValveHazard __instance)
		{
			FogController.OnSteamValveUpdated(__instance);
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "Awake")]
	internal static class StartOfRoundPatches
	{
		[HarmonyPostfix]
		private static void AwakePostfix()
		{
			FixCameraResolutionsCompat.EnsurePatched("StartOfRound.Awake");
		}
	}
}