Decompiled source of Enigmas Realistic Smoke Rework v0.5.0

RealisticSmokeRework.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace RealisticSmokeRework
{
	[BepInPlugin("EnigmaPrime.RealisticSmokeRework", "Enigma's Realistic Smoke Rework", "0.5.0")]
	[BepInIncompatibility("smoke_collision")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "EnigmaPrime.RealisticSmokeRework";

		public const string PluginName = "Enigma's Realistic Smoke Rework";

		public const string PluginVersion = "0.5.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("EnigmaPrime.RealisticSmokeRework");
			_harmony.PatchAll();
			foreach (MethodBase patchedMethod in _harmony.GetPatchedMethods())
			{
				Log.LogInfo((object)("Patched: " + patchedMethod.DeclaringType?.Name + "." + patchedMethod.Name));
			}
			Log.LogInfo((object)"Enigma's Realistic Smoke Rework 0.5.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class ModConfig
	{
		internal sealed class ConfigurationManagerAttributes
		{
			public int? Order;

			public bool? IsAdvanced;
		}

		internal static readonly string[] DefaultIgnoredObjectIds = new string[8] { "darkwood_decowall", "iron_floor_1x1", "iron_floor_2x2", "iron_grate", "iron_wall_1x1", "iron_wall_2x2", "wood_stair", "wood_stepladder" };

		internal static ConfigEntry<string> ExtraIgnoredObjectIds;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> FlameEffects;

		internal static ConfigEntry<float> LifetimeMultiplier;

		internal static ConfigEntry<float> RecheckInterval;

		internal static ConfigEntry<int> MaxAmount;

		internal static ConfigEntry<float> SmokeSizeMultiplier;

		internal static ConfigEntry<float> ColliderSizeMultiplier;

		internal static ConfigEntry<float> RequiredSpace;

		internal static ConfigEntry<float> FreezingCapHeight;

		internal static ConfigEntry<float> ColdCapHeight;

		internal static ConfigEntry<float> RainDecayBoost;

		internal static ConfigEntry<float> RiseSpeed;

		internal static ConfigEntry<float> WindTurbulence;

		internal static ConfigEntry<float> SpawnTimingVariance;

		internal static ConfigEntry<float> FireSizeEffect;

		internal static ConfigEntry<float> SmokeExpansion;

		internal static ConfigEntry<float> FluePuffSize;

		internal static ConfigEntry<float> EmergeStartSize;

		internal static ConfigEntry<float> EmergeTime;

		internal static ConfigEntry<float> WeakFirePuffSize;

		internal static ConfigEntry<float> WeakFireSpawnBoost;

		internal static ConfigEntry<float> WeakFireRiseSpeed;

		internal static ConfigEntry<bool> MenuFire;

		internal static ConfigEntry<float> DetailedRange;

		internal static ConfigEntry<float> PuffSizeVariance;

		internal static ConfigEntry<float> WindDriftSpeed;

		internal static ConfigEntry<float> EarlyWindEffect;

		internal static ConfigEntry<float> RiseSpeedVariance;

		internal static ConfigEntry<float> ChimneyPull;

		internal static ConfigEntry<float> AccelerationMultiplier;

		internal static ConfigEntry<float> SpawnRateMultiplier;

		internal static ConfigEntry<bool> FuelAddedParticles;

		internal static ConfigEntry<float> FlameEffect;

		internal static ConfigEntry<float> DwindleStart;

		internal static ConfigEntry<float> DwindleEnd;

		internal static ConfigEntry<float> DwindleCurve;

		internal static ConfigEntry<float> WeakFlameSize;

		internal static ConfigEntry<float> FullFlameBoost;

		internal static ConfigEntry<float> WeakFlameLight;

		internal static ConfigEntry<float> FullFlameLight;

		internal static ConfigEntry<string> BlowoutMode;

		internal static ConfigEntry<float> RefuelFlare;

		internal static ConfigEntry<float> RefuelFlareHold;

		internal static ConfigEntry<float> RefuelFlareFade;

		internal static ConfigEntry<float> WeakFireBlowoutWind;

		internal static ConfigEntry<float> WindFlameShrink;

		internal static ConfigEntry<bool> WindFlameShrinkOn;

		internal static ConfigEntry<bool> RainFlameShrink;

		internal static ConfigEntry<float> RainDwindleTime;

		internal static ConfigEntry<float> LowFuelFlicker;

		internal static ConfigEntry<float> WindFlameStart;

		private static int _order = 1000;

		private const string SGeneral = "1 General";

		private const string SGlobal = "2 Global";

		private const string SFlames = "3 Flames";

		private const string SFlameWind = "4 Flames wind and rain";

		private const string SSmoke = "5 Smoke";

		private const string SVisuals = "6 Smoke visuals";

		private const string SWeather = "7 Smoke wind and weather";

		private const string SPerf = "8 Performance";

		private static Dictionary<string, string> _old;

		private static int _carried;

		private static readonly string[] OldSections = new string[10] { "General", "Fireplaces", "Flames", "Smoke", "Wind", "Weather", "Visuals", "Main Menu", "Performance", "Debug" };

		internal static bool FlamesActive
		{
			get
			{
				if (Enabled.Value)
				{
					return FlameEffects.Value;
				}
				return false;
			}
		}

		private static ConfigEntry<T> Add<T>(ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase range = null, bool advanced = false, string oldSection = null, string oldKey = null)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Order = _order--,
				IsAdvanced = (advanced ? new bool?(true) : ((bool?)null))
			};
			ConfigEntry<T> val = config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, range, new object[1] { configurationManagerAttributes }));
			if (TryOld(oldSection, oldKey, out var value))
			{
				try
				{
					((ConfigEntryBase)val).SetSerializedValue(value);
					_carried++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Could not carry over '" + oldKey + "' (" + value + "): " + ex.Message));
				}
			}
			return val;
		}

		private static AcceptableValueRange<float> F(float min, float max)
		{
			return new AcceptableValueRange<float>(min, max);
		}

		private static void PrepareMigration(ConfigFile config)
		{
			try
			{
				string configFilePath = config.ConfigFilePath;
				if (string.IsNullOrEmpty(configFilePath) || !File.Exists(configFilePath))
				{
					return;
				}
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				bool flag = false;
				string text = "";
				string[] array = File.ReadAllLines(configFilePath);
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i].Trim();
					if (text2.Length == 0 || text2.StartsWith("#"))
					{
						continue;
					}
					if (text2.StartsWith("[") && text2.EndsWith("]"))
					{
						text = text2.Substring(1, text2.Length - 2);
						if (Array.IndexOf(OldSections, text) >= 0)
						{
							flag = true;
						}
					}
					else
					{
						int num = text2.IndexOf('=');
						if (num > 0)
						{
							dictionary[text + "\n" + text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim();
						}
					}
				}
				if (flag)
				{
					string text3 = configFilePath + ".pre-0.4.bak";
					if (!File.Exists(text3))
					{
						File.Copy(configFilePath, text3);
					}
					_old = dictionary;
					Plugin.Log.LogInfo((object)("Old config layout found. Backed it up to '" + Path.GetFileName(text3) + "' and carrying your settings over."));
				}
			}
			catch (Exception ex)
			{
				_old = null;
				Plugin.Log.LogWarning((object)("Could not back up or read the old config, using defaults: " + ex.Message));
			}
		}

		private static bool TryOld(string section, string key, out string value)
		{
			value = null;
			if (_old != null && section != null && key != null)
			{
				return _old.TryGetValue(section + "\n" + key, out value);
			}
			return false;
		}

		internal static void Bind(ConfigFile config)
		{
			PrepareMigration(config);
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			Enabled = Add(config, "1 General", "Enabled", defaultValue: true, "Master switch for the whole mod. When off, smoke and flames behave exactly like the unmodded game (including the main menu fire).", null, advanced: false, "General", "Enabled");
			FlameEffects = Add(config, "1 General", "Flame effects", defaultValue: true, "Master switch for every flame change: fuel size and light, refuel flare, wind and rain. Off = the game's own flames, smoke only. Visual only.");
			MenuFire = Add(config, "1 General", "Affect main menu fire", defaultValue: true, "Also applies the mod to the fire on the main menu screen: spawn rate, lifetime, wind (never toward the camera), rise speed variance and uneven puffs. Takes effect when the menu loads.", null, advanced: false, "Main Menu", "Affect main menu fire");
			ExtraIgnoredObjectIds = Add(config, "1 General", "Extra ignored object ids", "", "Extra prefab names (separated by comma) that smoke passes straight through, added to the built-in list (grates, ladders, stairs and similar). Example: wood_gate,wood_door", null, advanced: true, "General", "Extra ignored object ids");
			FlameEffect = Add(config, "2 Global", "Fuel flame strength (Global)", 1f, "How strongly a fire's fuel level changes its flames: size, light and particles. 0 = every fire looks like the game's, 1 = full strength. To turn all flame changes off, use Flame effects in General. Visual only.", (AcceptableValueBase)(object)F(0f, 1f), advanced: false, "Flames", "Flame fuel effect");
			FireSizeEffect = Add(config, "2 Global", "Fuel smoke strength (Global)", 1f, "How much a fire's fuel level changes its smoke: puff size, rise speed and puff rate (the three Low fuel smoke settings). 0 = every fire's smoke looks the same, 1 = full strength.", (AcceptableValueBase)(object)F(0f, 1f), advanced: false, "Fireplaces", "Fire size effect");
			SmokeSizeMultiplier = Add(config, "2 Global", "Smoke size multiplier (Global)", 1f, "How big every puff of smoke looks.", (AcceptableValueBase)(object)F(0.1f, 4f), advanced: false, "Visuals", "Smoke size multiplier");
			LifetimeMultiplier = Add(config, "2 Global", "Lifetime multiplier (Global)", 2.5f, "How long all smoke lasts before it fades, relative to the game. Longer smoke travels farther and needs a higher Max amount.", (AcceptableValueBase)(object)F(0.1f, 5f), advanced: false, "Smoke", "Lifetime multiplier");
			SpawnRateMultiplier = Add(config, "2 Global", "Spawn rate multiplier (Global)", 2f, "How often all fires and chimneys release smoke, relative to the game. 2 = twice as often. More smoke costs performance.", (AcceptableValueBase)(object)F(0.1f, 10f), advanced: false, "Smoke", "Spawn rate multiplier");
			AccelerationMultiplier = Add(config, "2 Global", "Acceleration multiplier (Global)", 1.5f, "How quickly all smoke reaches its target speed, relative to the game. 2 = twice as snappy. Applies to new puffs.", (AcceptableValueBase)(object)F(0.1f, 10f), advanced: true, "Smoke", "Acceleration multiplier");
			ColliderSizeMultiplier = Add(config, "2 Global", "Collider size multiplier (Global)", 1f, "Scales how much room every puff needs to move, without changing how it looks. Lower it if smoke gets squeezed in tight flues. Applies to new puffs.", (AcceptableValueBase)(object)F(0.1f, 2f), advanced: false, "Smoke", "Collider size multiplier");
			FullFlameBoost = Add(config, "3 Flames", "Full fuel flame height", 1.75f, "How big flames get on a full fire, as a multiple of the game's. 1 = same as the game, higher makes full fires rage. Visual only.", (AcceptableValueBase)(object)F(1f, 2f), advanced: false, "Flames", "Full fire flame size");
			WeakFlameSize = Add(config, "3 Flames", "Low fuel flame height", 0.4f, "How small flames get on a nearly empty fire, as a fraction of the game's. Visual only.", (AcceptableValueBase)(object)F(0.1f, 1f), advanced: false, "Flames", "Weak flame size");
			DwindleStart = Add(config, "3 Flames", "Full flame fuel level", 1f, "Fuel level (0 to 1, as a fraction of the fire's maximum) where flames are at full height. 1 = only a completely full fire is at full height, and flames shrink steadily from there. Visual only.", (AcceptableValueBase)(object)F(0.05f, 1f), advanced: false, "Flames", "Dwindle starts at");
			DwindleEnd = Add(config, "3 Flames", "Low flame fuel level", 0.2f, "Fuel level where flames and light reach their lowest. Below it they stay there until the fuel runs out and the game puts the fire out. 0.2 = two logs on a campfire. Visual only.", (AcceptableValueBase)(object)F(0f, 0.9f), advanced: false, "Flames", "Dwindle ends at");
			DwindleCurve = Add(config, "3 Flames", "Flame height curve", 1f, "Shape of the shrink between the two fuel levels above. 1 = steady, the same amount per log. Higher keeps flames bigger for longer and drops them faster near the end. Lower does the opposite. Visual only.", (AcceptableValueBase)(object)F(0.3f, 3f), advanced: false, "Flames", "Dwindle curve");
			FullFlameLight = Add(config, "3 Flames", "Full fuel light", 1f, "How bright the light from a full fire is, as a multiple of the game's. 1 = same as the game. Visual only.", (AcceptableValueBase)(object)F(1f, 2f), advanced: false, "Flames", "Full fire light");
			WeakFlameLight = Add(config, "3 Flames", "Low fuel light", 0.45f, "How bright the light is on a nearly empty fire, as a fraction of the game's. Light dims smoothly with the flames down to this. Visual only.", (AcceptableValueBase)(object)F(0.05f, 1f), advanced: false, "Flames", "Weak flame light");
			RefuelFlare = Add(config, "3 Flames", "Refuel flare", 0.4f, "When logs are added, flames and light briefly get this much bigger and brighter on top of what the fuel level gives (0.4 = 40% more), then settle back. 0 = off. Visual only.", (AcceptableValueBase)(object)F(0f, 1f), advanced: false, "Flames", "Refuel flare");
			RefuelFlareHold = Add(config, "3 Flames", "Refuel flare hold", 2.5f, "Seconds the refuel flare stays at full strength. Visual only.", (AcceptableValueBase)(object)F(0f, 10f), advanced: false, "Flames", "Refuel flare hold");
			RefuelFlareFade = Add(config, "3 Flames", "Refuel flare fade", 1.5f, "Seconds the refuel flare takes to fade back to normal after the hold. Visual only.", (AcceptableValueBase)(object)F(0.1f, 5f), advanced: false, "Flames", "Refuel flare fade");
			LowFuelFlicker = Add(config, "3 Flames", "Low fuel flicker", 3f, "How unsteady the light is on a nearly empty fire, as a multiple of the game's flicker. 1 = same as the game. It builds up as the fuel drops, and also while a fire is blown down or soaked by rain. Does nothing if Reduce Flashing Lights is on in the game's settings. Visual only.", (AcceptableValueBase)(object)F(1f, 5f));
			FuelAddedParticles = Add(config, "3 Flames", "Fuel puff particles", defaultValue: false, "The extra puff of particles the game shows when you add fuel. Off = no puff (any sound is kept). On = the game's normal puff. Applies to fires that load after the change, so reload the area or restart. Visual only.", null, advanced: false, "Flames", "Fuel added particles");
			BlowoutMode = Add(config, "4 Flames wind and rain", "Enhanced wind blowout", "Visual only", "How exposed fires react to strong wind. Low fuel gives in sooner, shelter protects. Off = game default. On (Visual only) = flames shrink or go dark but the fire stays lit, and nothing changes for other players or the server. Sealed lanterns ignore wind.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Off", "Visual only" }), advanced: false, "Flames", "Wind blowout");
			WeakFireBlowoutWind = Add(config, "4 Flames wind and rain", "Low fuel wind blowout", 0.35f, "Wind strength (0 to 1) that blows out an exposed fire at its Low flame fuel level or less. A full fire holds until the game's own 0.8. Fires in between follow the same curve as their flame height.", (AcceptableValueBase)(object)F(0.1f, 0.8f), advanced: false, "Flames", "Weak fire blowout wind");
			WindFlameShrinkOn = Add(config, "4 Flames wind and rain", "Wind flame shrink", defaultValue: true, "Flames of an exposed fire shrink steadily as the wind rises, before any blowout. Off = flames ignore wind until the blowout. Sheltered fires are never affected. Visual only.");
			WindFlameShrink = Add(config, "4 Flames wind and rain", "Wind flame shrink amount", 0.6f, "How far wind shrinks exposed flames before the blowout. 0 = not at all, 1 = all the way down to the blown-down size just before it. Visual only.", (AcceptableValueBase)(object)F(0f, 1f), advanced: false, "Flames", "Wind flame shrink");
			WindFlameStart = Add(config, "4 Flames wind and rain", "Wind flame start", 0.2f, "Wind strength (0 to 1) where exposed flames start to shrink. Fires with less fuel reach their blowout wind sooner, so they shrink faster. Visual only.", (AcceptableValueBase)(object)F(0f, 0.7f), advanced: false, "Flames", "Wind flame start");
			if (TryOld("Flames", "Wind flame shrink", out var value) && float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result <= 0f)
			{
				WindFlameShrinkOn.Value = false;
			}
			RainFlameShrink = Add(config, "4 Flames wind and rain", "Rain flame shrink", defaultValue: true, "Exposed fires dwindle in rain until they look out, with thin smoke wisps. Cover brings them back. Sheltered fires and sealed lanterns are unaffected. Visual only: the fire still warms and cooks.");
			RainDwindleTime = Add(config, "4 Flames wind and rain", "Rain dwindle time", 180f, "Seconds of steady rain it takes an exposed full fire to dwindle until it looks out. Wind and low fuel make it faster, so a weak fire in a storm goes much sooner. 180 = three minutes. Visual only.", (AcceptableValueBase)(object)F(20f, 1200f));
			RequiredSpace = Add(config, "5 Smoke", "Required space", 0.5f, "Clear space needed above a fireplace, in meters, before it will release smoke (the game uses about 0.75). 0 turns the check off. GAMEPLAY: this is the same check smelters, kilns and similar stations use to decide they are blocked, so on a server every player should use the same value.", (AcceptableValueBase)(object)F(0f, 2f), advanced: false, "Fireplaces", "Required space");
			WeakFirePuffSize = Add(config, "5 Smoke", "Low fuel smoke size", 0.42f, "How big the puffs of a nearly empty fire (one log or less) look, as a fraction of normal. A full fire is normal size, fires in between scale smoothly. Visual only. 1 = no change.", (AcceptableValueBase)(object)F(0.03f, 1f), advanced: false, "Fireplaces", "Weak fire puff size");
			WeakFireRiseSpeed = Add(config, "5 Smoke", "Low fuel smoke speed", 0.38f, "How fast the smoke of a nearly empty fire (one log or less) rises, as a fraction of normal. A full fire rises a little faster than normal. 1 = no change.", (AcceptableValueBase)(object)F(0.1f, 1f), advanced: false, "Fireplaces", "Weak fire rise speed");
			WeakFireSpawnBoost = Add(config, "5 Smoke", "Low fuel puff rate", 6f, "How many times more often a nearly empty fire (one log or less) releases puffs than a full fire, so its small slow puffs make a steady stream. 1 = no change. High values mean more smoke objects, so raise Max amount with it.", (AcceptableValueBase)(object)F(1f, 6f), advanced: false, "Fireplaces", "Weak fire spawn boost");
			SpawnTimingVariance = Add(config, "5 Smoke", "Spawn timing variance", 0.3f, "Random variation in the time between puffs (0.3 = plus or minus 30%) so smoke comes out in uneven pulses. The average rate stays the same. 0 = perfectly even.", (AcceptableValueBase)(object)F(0f, 0.9f), advanced: false, "Smoke", "Spawn timing variance");
			RiseSpeed = Add(config, "5 Smoke", "Rise speed", 1.5f, "Starting upward speed of fresh smoke in meters per second. It still slows as the smoke ages. The game uses 1.", (AcceptableValueBase)(object)F(0f, 10f), advanced: false, "Smoke", "Rise speed");
			RiseSpeedVariance = Add(config, "5 Smoke", "Rise speed variance", 0.2f, "Each new puff rises this fraction faster or slower (0.2 = plus or minus 20%), so some smoke overtakes other smoke. 0 = all the same.", (AcceptableValueBase)(object)F(0f, 0.5f), advanced: false, "Smoke", "Rise speed variance");
			ChimneyPull = Add(config, "5 Smoke", "Chimney pull", 0.5f, "Extra upward speed (meters per second) for smoke inside narrow spaces like flues, so it is drawn out of the tube. A little stronger in wind. 0 = off.", (AcceptableValueBase)(object)F(0f, 5f), advanced: false, "Smoke", "Chimney pull");
			SmokeExpansion = Add(config, "6 Smoke visuals", "Smoke expansion", 1.6f, "How many times bigger the smoke looks by the end of its life. Growth starts after a quarter of its life, and after leaving any flue. It grows fastest at first and slows down as the smoke ages. 1 = no growth.", (AcceptableValueBase)(object)F(1f, 4f), advanced: false, "Visuals", "Smoke expansion");
			PuffSizeVariance = Add(config, "6 Smoke visuals", "Puff size variance", 0.2f, "Each new puff looks bigger or smaller by up to this fraction (0.2 = plus or minus 20%). 0 = all the same.", (AcceptableValueBase)(object)F(0f, 0.6f), advanced: false, "Visuals", "Puff size variance");
			FluePuffSize = Add(config, "6 Smoke visuals", "Flue puff size", 0.5f, "Smallest size a puff shrinks to (look and hitbox, as a fraction of normal) when it is stuck in a flue or other cramped space. It gets a little smaller each check until it escapes, then grows back to full size over a few seconds. 1 = no shrinking.", (AcceptableValueBase)(object)F(0.2f, 1f), advanced: false, "Visuals", "Flue puff size");
			EmergeStartSize = Add(config, "6 Smoke visuals", "Emerge start size", 0.35f, "How big a new puff looks the moment it leaves the fire, as a fraction of normal. It widens to full size over Emerge time, so smoke starts narrow and fans out as it rises. Weaker fires start closer to full size. Visual only. 1 = no emerging.", (AcceptableValueBase)(object)F(0.1f, 1f));
			EmergeTime = Add(config, "6 Smoke visuals", "Emerge time", 1.5f, "Seconds a new puff takes to widen from its start size to full size. It grows fastest at first, then eases off. Visual only.", (AcceptableValueBase)(object)F(0.2f, 5f));
			WindDriftSpeed = Add(config, "7 Smoke wind and weather", "Wind drift speed", 2.5f, "Sideways speed (meters per second) of cooled smoke in full wind. Higher bends the smoke more. 0 = wind has no effect (also on the main menu).", (AcceptableValueBase)(object)F(0f, 5f), advanced: false, "Wind", "Wind drift speed");
			EarlyWindEffect = Add(config, "7 Smoke wind and weather", "Early wind effect", 0.5f, "How much of the wind fresh, hot smoke feels (0 to 1). Higher makes the smoke bend sooner instead of rising as a straight column.", (AcceptableValueBase)(object)F(0f, 1f), advanced: true, "Wind", "Early wind effect");
			WindTurbulence = Add(config, "7 Smoke wind and weather", "Wind turbulence", 0.3f, "Gusts and swirls: smoke wavers around the wind direction and strength instead of following it smoothly. 0 = off, 1 = strong.", (AcceptableValueBase)(object)F(0f, 1f), advanced: false, "Wind", "Wind turbulence");
			FreezingCapHeight = Add(config, "7 Smoke wind and weather", "Freezing cap height", 20f, "In freezing weather smoke stops rising about this many meters above its source and spreads out sideways. 0 = no cap.", (AcceptableValueBase)(object)F(0f, 200f), advanced: false, "Weather", "Freezing cap height");
			ColdCapHeight = Add(config, "7 Smoke wind and weather", "Cold cap height", 30f, "Same as the freezing cap, for cold weather. 0 = no cap.", (AcceptableValueBase)(object)F(0f, 200f), advanced: false, "Weather", "Cold cap height");
			RainDecayBoost = Add(config, "7 Smoke wind and weather", "Rain decay boost", 0.25f, "While it is wet, smoke fades this much faster (0.25 = 25% faster). 0 = rain has no effect.", (AcceptableValueBase)(object)F(0f, 2f), advanced: false, "Weather", "Rain decay boost");
			MaxAmount = Add(config, "8 Performance", "Max amount", 200, "Maximum number of smoke objects in the world at once (the game uses 100). When it is reached the oldest smoke fades early. Raise it with Spawn rate multiplier, Lifetime multiplier or Low fuel puff rate.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 1000), advanced: false, "Performance", "Max amount");
			DetailedRange = Add(config, "8 Performance", "Detailed range", 40f, "Smoke farther than this many meters from you skips the wall and path checks and just rises and drifts in the wind. This is the biggest saver in bases with many fires. 0 = detailed checks everywhere.", (AcceptableValueBase)(object)F(0f, 64f), advanced: false, "Performance", "Detailed range");
			RecheckInterval = Add(config, "8 Performance", "Recheck interval", 1.5f, "Seconds between environment checks for each nearby puff. Higher is cheaper but makes smoke slower to react to walls and openings.", (AcceptableValueBase)(object)F(0.5f, 5f), advanced: true, "Performance", "Recheck interval");
			config.SaveOnConfigSet = saveOnConfigSet;
			config.Save();
			if (_carried > 0)
			{
				Plugin.Log.LogInfo((object)("Carried over " + _carried + " saved settings from the old config. Please check them in the new layout."));
			}
			_old = null;
		}

		internal static HashSet<string> BuildIgnoredSet()
		{
			HashSet<string> hashSet = new HashSet<string>(DefaultIgnoredObjectIds, StringComparer.OrdinalIgnoreCase);
			foreach (string item in from s in ExtraIgnoredObjectIds.Value.Split(new char[1] { ',' })
				select s.Trim() into s
				where s.Length > 0
				select s)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}
	}
	internal static class SmokeBrain
	{
		private class State
		{
			public float NextCheck;

			public int ClearCount;

			public bool Free;

			public float Gate = 1f;

			public Vector2 Spread;

			public Vector2 PathDir;

			public int Chosen = -1;

			public int Bad = -1;

			public int BadChecks;

			public Vector3 LastPos;

			public bool HasLastPos;

			public bool Cramped;

			public bool Released;

			public float ReleaseAge;

			public float ReleaseLife;

			public float Pull;

			public bool UpClear;

			public Vector2 HoldDir;

			public float HoldUntil;

			public Collider Own;

			public SphereCollider OwnSphere;

			public float BaseRadius;

			public float Size = 1f;

			public float SizeTarget = 1f;

			public float LastSizeAge;

			public Vector3 SqueezeLastPos;

			public bool HasSqueezeLastPos;

			public bool Init;

			public float SpawnY;

			public float SpeedMul = 1f;

			public float SizeMul = 1f;

			public float FireSize = 1f;

			public float Phase1;

			public float Phase2;

			public float Age;

			public float Ttl = 60f;

			public float BaseY = 1f;
		}

		private struct WindInfo
		{
			public bool Has;

			public Vector3 Dir;

			public Vector3 Force;

			public float Intensity;
		}

		private const float UpRayLength = 15f;

		private const float TightAngle = 45f;

		private const int TightCount = 6;

		private const float WideAngle = 90f;

		private const int WideCount = 8;

		private const float RingLength = 8f;

		private const float CrampedDistance = 1f;

		private const float GateStartDistance = 2f;

		private const float HoldSeconds = 2f;

		private const float GateFullDistance = 6f;

		private const int FreeAfterClearChecks = 3;

		private const float UpTightCutoff = 0.5f;

		private const float WideFreezeCutoff = 0.75f;

		private const float RoomDriftFactor = 0.1f;

		private const float CrampedPathFactor = 0.3f;

		private const float PathSpeed = 0.5f;

		private const float CoolStart = 0f;

		private const float CoolEnd = 0.45f;

		private const float SpreadSpeed = 0.2f;

		private const float SpreadWanderDegrees = 45f;

		private const float CapSoftStart = 0.7f;

		private const float CapBillowBoost = 1.5f;

		private const float StuckDistance = 0.3f;

		private const float IgnoreScanRadius = 2.5f;

		private static readonly ConditionalWeakTable<Smoke, State> States;

		private static readonly RaycastHit[] Hits;

		private static readonly Collider[] Overlaps;

		private const int RayCount = 14;

		private static readonly Vector3[] RayDir;

		private static readonly Vector2[] RayHoriz;

		private static readonly float[] RayDist;

		private static int _mask;

		private static HashSet<string> _ignored;

		private static string _ignoredSource;

		internal static float PendingStrength;

		private const float SqueezeSteps = 3f;

		private const float SqueezeRegrowSeconds = 4f;

		private static int _capFrame;

		private static float _capValue;

		private static int Mask
		{
			get
			{
				if (_mask == -2)
				{
					_mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
				}
				return _mask;
			}
		}

		private static HashSet<string> Ignored
		{
			get
			{
				string value = ModConfig.ExtraIgnoredObjectIds.Value;
				if (_ignored == null || value != _ignoredSource)
				{
					_ignored = ModConfig.BuildIgnoredSet();
					_ignoredSource = value;
				}
				return _ignored;
			}
		}

		static SmokeBrain()
		{
			//IL_0074: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			States = new ConditionalWeakTable<Smoke, State>();
			Hits = (RaycastHit[])(object)new RaycastHit[16];
			Overlaps = (Collider[])(object)new Collider[32];
			RayDir = (Vector3[])(object)new Vector3[14];
			RayHoriz = (Vector2[])(object)new Vector2[14];
			RayDist = new float[14];
			_mask = -2;
			PendingStrength = -1f;
			_capFrame = -1;
			for (int i = 0; i < 6; i++)
			{
				RayDir[i] = Dir(45f, 60f * (float)i);
			}
			for (int j = 0; j < 8; j++)
			{
				RayDir[6 + j] = Dir(90f, 45f * (float)j);
			}
			for (int k = 0; k < 14; k++)
			{
				Vector2[] rayHoriz = RayHoriz;
				int num = k;
				Vector2 val = new Vector2(RayDir[k].x, RayDir[k].z);
				rayHoriz[num] = ((Vector2)(ref val)).normalized;
			}
		}

		private static string BaseName(Transform t)
		{
			string name = ((Object)t.root).name;
			int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
			return ((num >= 0) ? name.Substring(0, num) : name).Trim();
		}

		private static float Cast(Vector3 origin, Vector3 dir, float maxDist)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.RaycastNonAlloc(origin, dir, Hits, maxDist, Mask, (QueryTriggerInteraction)1);
			float num2 = maxDist;
			for (int i = 0; i < num; i++)
			{
				RaycastHit val = Hits[i];
				if (!(((RaycastHit)(ref val)).distance >= num2) && !Ignored.Contains(BaseName(((Component)((RaycastHit)(ref val)).collider).transform)))
				{
					num2 = ((RaycastHit)(ref val)).distance;
				}
			}
			return num2;
		}

		private static Vector3 Dir(float tiltDeg, float azimuthDeg)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			float num = tiltDeg * ((float)Math.PI / 180f);
			float num2 = azimuthDeg * ((float)Math.PI / 180f);
			return new Vector3(Mathf.Sin(num) * Mathf.Sin(num2), Mathf.Cos(num), Mathf.Sin(num) * Mathf.Cos(num2));
		}

		private static float Gate(float dist)
		{
			return Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(2f, 6f, dist));
		}

		private static WindInfo ReadWind()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return default(WindInfo);
			}
			return new WindInfo
			{
				Has = true,
				Dir = instance.GetWindDir(),
				Force = instance.GetWindForce(),
				Intensity = instance.GetWindIntensity()
			};
		}

		internal static float SpawnFactor(float strength)
		{
			float num = Mathf.Clamp01(ModConfig.FireSizeEffect.Value);
			return Mathf.Lerp(Mathf.Lerp(1f, Mathf.Max(1f, ModConfig.WeakFireSpawnBoost.Value), num), 1f, FireLevel(strength)) * (1f + 0.25f * num);
		}

		private static float FireLevel(float strength)
		{
			float num = Mathf.Clamp01((strength - 0.1f) / 0.9f);
			return num * Mathf.Sqrt(num);
		}

		internal static float FireSizeScale(float strength)
		{
			if (strength < 0f)
			{
				return 1f;
			}
			float num = Mathf.Clamp01(ModConfig.FireSizeEffect.Value);
			return Mathf.Lerp(Mathf.Lerp(1f, Mathf.Clamp(ModConfig.WeakFirePuffSize.Value, 0.03f, 1f), num), 1f, FireLevel(strength));
		}

		internal static float RiseFactor(float strength)
		{
			if (strength < 0f)
			{
				return 1f;
			}
			float num = Mathf.Clamp01(ModConfig.FireSizeEffect.Value);
			return Mathf.Lerp(Mathf.Lerp(1f, Mathf.Clamp(ModConfig.WeakFireRiseSpeed.Value, 0.1f, 1f), num), 1f + 0.25f * num, FireLevel(strength));
		}

		public static float VisualSize(float baseSize, Smoke s)
		{
			if (!ModConfig.Enabled.Value)
			{
				return baseSize;
			}
			if (!States.TryGetValue(s, out var value))
			{
				return baseSize;
			}
			float num = Mathf.Clamp01(value.Age / Mathf.Max(0.01f, value.Ttl));
			float num2 = 0f;
			if (value.Released)
			{
				float num3 = Mathf.Clamp01(Mathf.InverseLerp(Mathf.Max(0.25f, value.ReleaseLife), 1f, num));
				num2 = 1f - (1f - num3) * (1f - num3);
			}
			float num4 = Mathf.Lerp(1f, Mathf.Max(1f, ModConfig.SmokeExpansion.Value), num2);
			float num5 = 1f;
			float num6 = Mathf.Clamp(ModConfig.EmergeStartSize.Value, 0.1f, 1f);
			if (num6 < 1f)
			{
				num6 = Mathf.Lerp(1f, num6, Mathf.Clamp01(value.FireSize));
				float num7 = Mathf.Clamp01(value.Age / Mathf.Max(0.2f, ModConfig.EmergeTime.Value));
				num5 = Mathf.Lerp(num6, 1f, 1f - (1f - num7) * (1f - num7));
			}
			return baseSize * value.SizeMul * num4 * num5 * value.Size * value.FireSize * Mathf.Max(0.1f, ModConfig.SmokeSizeMultiplier.Value);
		}

		private static float SqueezeFloor()
		{
			return Mathf.Clamp(ModConfig.FluePuffSize.Value, 0.2f, 1f);
		}

		private static void SqueezeCheck(State st, bool squeezing)
		{
			float num = SqueezeFloor();
			if (squeezing && num < 1f)
			{
				st.SizeTarget = Mathf.Max(num, st.SizeTarget - (1f - num) / 3f);
			}
			else
			{
				st.SizeTarget = 1f;
			}
		}

		private static void UpdateSqueeze(State st, float age)
		{
			float num = Mathf.Clamp(age - st.LastSizeAge, 0f, 0.5f);
			st.LastSizeAge = age;
			float num2 = SqueezeFloor();
			float num3 = Mathf.Clamp(st.SizeTarget, num2, 1f);
			float num4 = 1f - num2;
			float num5 = ((num3 < st.Size) ? (num4 / 3f) : (num4 / 4f)) * num;
			st.Size = Mathf.Clamp(Mathf.MoveTowards(st.Size, num3, num5), num2, 1f);
			if ((Object)(object)st.OwnSphere != (Object)null && st.BaseRadius > 0f)
			{
				float num6 = st.BaseRadius * st.Size;
				if (Mathf.Abs(st.OwnSphere.radius - num6) > 0.0005f)
				{
					st.OwnSphere.radius = num6;
				}
			}
		}

		private static State NewState()
		{
			float num = Mathf.Clamp(ModConfig.RiseSpeedVariance.Value, 0f, 0.5f);
			float num2 = Mathf.Clamp(ModConfig.PuffSizeVariance.Value, 0f, 0.6f);
			return new State
			{
				NextCheck = Random.Range(0f, ModConfig.RecheckInterval.Value),
				SpeedMul = (1f + Random.Range(0f - num, num)) * RiseFactor(PendingStrength),
				SizeMul = 1f + Random.Range(0f - num2, num2),
				FireSize = FireSizeScale(PendingStrength),
				Phase1 = Random.Range(0f, 6.2832f),
				Phase2 = Random.Range(0f, 6.2832f)
			};
		}

		public static float InitialRise(Smoke s)
		{
			State value = States.GetValue(s, (Smoke _) => NewState());
			return Mathf.Max(0f, ModConfig.RiseSpeed.Value) * value.SpeedMul;
		}

		public static void Tick(Smoke s, float age)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			State value = States.GetValue(s, (Smoke _) => NewState());
			if (!value.Init)
			{
				value.Init = true;
				value.Own = ((Component)s).GetComponent<Collider>();
				ref SphereCollider ownSphere = ref value.OwnSphere;
				Collider own = value.Own;
				ownSphere = (SphereCollider)(object)((own is SphereCollider) ? own : null);
				if ((Object)(object)value.OwnSphere != (Object)null)
				{
					value.BaseRadius = value.OwnSphere.radius;
				}
				value.LastSizeAge = age;
				value.SpawnY = ((Component)s).transform.position.y;
				value.BaseY = Mathf.Max(0f, ModConfig.RiseSpeed.Value) * value.SpeedMul;
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				value.Spread = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(0.5f, 1f);
			}
			value.Age = age;
			value.Ttl = Mathf.Max(0.01f, s.m_ttl);
			float num = CapHeight();
			if (num > 0f)
			{
				Vector3 vel = s.m_vel;
				vel.y = value.BaseY * CapRise(((Component)s).transform.position.y - value.SpawnY, num);
				s.m_vel = vel;
			}
			UpdateSqueeze(value, age);
			if (age < value.NextCheck)
			{
				return;
			}
			value.NextCheck = age + Mathf.Max(0.2f, ModConfig.RecheckInterval.Value);
			float num2 = Random.Range(-45f, 45f) * ((float)Math.PI / 180f);
			float num3 = Mathf.Cos(num2);
			float num4 = Mathf.Sin(num2);
			Vector2 normalized = ((Vector2)(ref value.Spread)).normalized;
			float num5 = Mathf.Clamp(((Vector2)(ref value.Spread)).magnitude + Random.Range(-0.2f, 0.2f), 0.3f, 1f);
			value.Spread = new Vector2(normalized.x * num3 - normalized.y * num4, normalized.x * num4 + normalized.y * num3) * num5;
			float ttl = value.Ttl;
			float num6 = age / ttl;
			Vector3 position = ((Component)s).transform.position;
			bool num7 = IsFar(position);
			bool flag = !num7 && !value.Free && num6 < 0.5f;
			bool flag2 = !num7 && !value.Free && num6 < 0.75f;
			WindInfo wi = ReadWind();
			if (!num7 && !value.Free)
			{
				IgnoreNearbyPassThroughs(value, position);
			}
			if (num7)
			{
				value.UpClear = true;
				value.Cramped = false;
			}
			if (flag)
			{
				float num8 = Cast(position, Vector3.up, 15f);
				value.UpClear = num8 >= 14.999f;
				value.ClearCount = (value.UpClear ? (value.ClearCount + 1) : 0);
				int num9 = 0;
				for (int num10 = 0; num10 < 6; num10++)
				{
					float num11 = Cast(position, RayDir[num10], 8f);
					RayDist[num10] = num11;
					if (num11 < 1f)
					{
						num9++;
					}
				}
				int num12 = MeasureWide(position);
				value.Cramped = num9 + num12 > 7;
				if (value.ClearCount >= 3 && !value.Cramped)
				{
					value.Free = true;
				}
				if (!value.Released && !value.Cramped)
				{
					value.Released = true;
					value.ReleaseLife = num6;
					value.ReleaseAge = age;
				}
				int num13;
				if (value.HasSqueezeLastPos && !value.UpClear && !value.Free)
				{
					Vector3 val = position - value.SqueezeLastPos;
					num13 = ((((Vector3)(ref val)).magnitude < 0.3f) ? 1 : 0);
				}
				else
				{
					num13 = 0;
				}
				bool flag3 = (byte)num13 != 0;
				value.SqueezeLastPos = position;
				value.HasSqueezeLastPos = true;
				SqueezeCheck(value, value.Cramped || flag3);
				if (!value.UpClear)
				{
					PickPath(value, position, wi);
					if (((Vector2)(ref value.PathDir)).sqrMagnitude > 1E-06f)
					{
						value.HoldDir = value.PathDir;
						value.HoldUntil = Time.time + 2f;
					}
				}
				else
				{
					value.PathDir = Vector2.zero;
					value.Chosen = -1;
				}
			}
			else if (flag2)
			{
				MeasureWide(position);
			}
			if (!value.Released && !flag)
			{
				value.Released = true;
				value.ReleaseLife = num6;
				value.ReleaseAge = age;
			}
			if (!flag)
			{
				value.SizeTarget = 1f;
			}
			if (flag2)
			{
				value.Gate = WindGate(wi);
			}
			ApplyVelocity(s, value, num6, wi);
		}

		private static bool IsFar(Vector3 pos)
		{
			//IL_0024: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			float value = ModConfig.DetailedRange.Value;
			if (value <= 0f)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Vector3 val = pos - ((Component)localPlayer).transform.position;
				return ((Vector3)(ref val)).sqrMagnitude > value * value;
			}
			return false;
		}

		private static int MeasureWide(Vector3 pos)
		{
			//IL_0006: 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)
			int num = 0;
			for (int i = 0; i < 8; i++)
			{
				float num2 = Cast(pos, RayDir[6 + i], 8f);
				RayDist[6 + i] = num2;
				if (num2 < 1f)
				{
					num++;
				}
			}
			return num;
		}

		private static float WindGate(WindInfo wi)
		{
			//IL_000f: 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)
			//IL_0015: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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 (!wi.Has)
			{
				return 1f;
			}
			Vector3 dir = wi.Dir;
			Vector2 val = new Vector2(dir.x, dir.z);
			if (((Vector2)(ref val)).sqrMagnitude < 1E-06f)
			{
				return 1f;
			}
			float num = Mathf.Atan2(dir.x, dir.z) * 57.29578f;
			if (num < 0f)
			{
				num += 360f;
			}
			float num2 = num / 45f;
			int num3 = Mathf.FloorToInt(num2) % 8;
			int num4 = (num3 + 1) % 8;
			float num5 = num2 - Mathf.Floor(num2);
			return Mathf.Lerp(Gate(RayDist[6 + num3]), Gate(RayDist[6 + num4]), num5);
		}

		private static void PickPath(State st, Vector3 pos, WindInfo wi)
		{
			//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)
			//IL_0074: 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_0011: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_01c4: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			if (st.HasLastPos && st.Chosen >= 0)
			{
				Vector3 val = pos - st.LastPos;
				if (((Vector3)(ref val)).magnitude < 0.3f)
				{
					st.Bad = st.Chosen;
					st.BadChecks = 2;
				}
			}
			st.LastPos = pos;
			st.HasLastPos = true;
			if (st.BadChecks > 0)
			{
				st.BadChecks--;
				if (st.BadChecks == 0)
				{
					st.Bad = -1;
				}
			}
			Vector2 zero = Vector2.zero;
			float num = 0f;
			if (wi.Has)
			{
				((Vector2)(ref zero))..ctor(wi.Dir.x, wi.Dir.z);
				if (((Vector2)(ref zero)).sqrMagnitude > 1E-06f)
				{
					((Vector2)(ref zero)).Normalize();
				}
				num = Mathf.Clamp01(wi.Intensity);
			}
			float num2 = Mathf.Clamp01(num / 0.3f);
			int num3 = -1;
			float num4 = float.NegativeInfinity;
			for (int i = 0; i < 14; i++)
			{
				float num5 = RayDist[i];
				if (!(num5 < 1f) && i != st.Bad)
				{
					float num6 = num5 / 8f;
					float num7 = Vector2.Dot(RayHoriz[i], zero);
					num6 += 1f * num2 * Mathf.Max(0f, num7);
					num6 -= 1.2f * num2 * Mathf.Max(0f, 0f - num7);
					if (i < 6)
					{
						num6 += 0.15f;
					}
					if (i == st.Chosen)
					{
						num6 += 0.15f;
					}
					num6 += Random.Range(0f, 0.05f);
					if (num6 > num4)
					{
						num4 = num6;
						num3 = i;
					}
				}
			}
			st.Chosen = num3;
			st.PathDir = ((num3 >= 0) ? RayHoriz[num3] : Vector2.zero);
		}

		private static float CapHeight()
		{
			int frameCount = Time.frameCount;
			if (frameCount != _capFrame)
			{
				_capFrame = frameCount;
				if (EnvMan.IsFreezing())
				{
					_capValue = Mathf.Max(0f, ModConfig.FreezingCapHeight.Value);
				}
				else if (EnvMan.IsCold())
				{
					_capValue = Mathf.Max(0f, ModConfig.ColdCapHeight.Value);
				}
				else
				{
					_capValue = 0f;
				}
			}
			return _capValue;
		}

		private static float CapRise(float height, float cap)
		{
			float num = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(cap * 0.7f, cap, height));
			return 1f - num;
		}

		private static float WindInfluence(float life)
		{
			return Mathf.Lerp(Mathf.Clamp01(ModConfig.EarlyWindEffect.Value), 1f, Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0f, 0.45f, life)));
		}

		private static void ApplyVelocity(Smoke s, State st, float life, WindInfo wi)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0f, ModConfig.RiseSpeed.Value) * st.SpeedMul;
			float num2 = CapHeight();
			float num3 = 1f;
			if (num2 > 0f)
			{
				num3 = CapRise(((Component)s).transform.position.y - st.SpawnY, num2);
			}
			float num4 = 1f - num3;
			Vector3 val = (wi.Has ? wi.Force : Vector3.zero);
			float num5 = ((Vector3)(ref val)).magnitude * ModConfig.WindDriftSpeed.Value * Mathf.Max(WindInfluence(life), num4);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(val.x, val.z);
			if (((Vector2)(ref val2)).sqrMagnitude > 1E-06f)
			{
				((Vector2)(ref val2)).Normalize();
			}
			float num6 = Mathf.Clamp01(ModConfig.WindTurbulence.Value);
			if (num6 > 0f && ((Vector2)(ref val2)).sqrMagnitude > 1E-06f)
			{
				float time = Time.time;
				float num7 = 1f + num6 * 0.35f * (Mathf.PerlinNoise(time * 0.08f, 7.3f) - 0.5f) * 2f;
				float num8 = 1f + num6 * 0.25f * Mathf.Sin(time * 0.6f + st.Phase2);
				float num9 = num6 * 30f * ((float)Math.PI / 180f) * Mathf.Sin(time * 0.4f + st.Phase1);
				float num10 = Mathf.Cos(num9);
				float num11 = Mathf.Sin(num9);
				((Vector2)(ref val2))..ctor(val2.x * num10 - val2.y * num11, val2.x * num11 + val2.y * num10);
				num5 *= num7 * num8;
			}
			float num16;
			float num17;
			if (st.Free || st.UpClear)
			{
				float num12 = 0.2f * Mathf.Lerp(0.4f, 1f, Mathf.SmoothStep(0f, 1f, life / 0.5f)) * (1f + 1.5f * num4) * (st.Cramped ? 0.25f : 1f);
				Vector2 val3 = st.Spread;
				float num13 = (wi.Has ? Mathf.Clamp01(wi.Intensity / 0.3f) : 0f);
				if (num13 > 0f && ((Vector2)(ref val2)).sqrMagnitude > 1E-06f)
				{
					Vector2 val4 = default(Vector2);
					((Vector2)(ref val4))..ctor(0f - val2.y, val2.x);
					float num14 = Mathf.Abs(Vector2.Dot(val3, val2));
					float num15 = Vector2.Dot(val3, val4);
					Vector2 val5 = val2 * num14 + val4 * num15;
					val3 = Vector2.Lerp(val3, val5, num13);
				}
				num16 = val2.x * num5 * st.Gate + val3.x * num12;
				num17 = val2.y * num5 * st.Gate + val3.y * num12;
				if (((Vector2)(ref st.HoldDir)).sqrMagnitude > 1E-06f)
				{
					float num18 = Mathf.Clamp01((st.HoldUntil - Time.time) / 2f);
					num16 += st.HoldDir.x * 0.5f * num18;
					num17 += st.HoldDir.y * 0.5f * num18;
				}
			}
			else
			{
				float num19 = 0.5f * (st.Cramped ? 0.3f : 1f);
				num16 = val2.x * num5 * st.Gate * 0.1f + st.PathDir.x * num19;
				num17 = val2.y * num5 * st.Gate * 0.1f + st.PathDir.y * num19;
			}
			st.Pull = Mathf.Lerp(st.Pull, (st.Cramped && !st.Free) ? 1f : 0f, 0.4f);
			if (st.Pull > 0.01f)
			{
				float num20 = (wi.Has ? Mathf.Clamp01(wi.Intensity) : 0f);
				num += Mathf.Max(0f, ModConfig.ChimneyPull.Value) * (1f + num20) * st.Pull;
			}
			st.BaseY = num;
			s.m_vel = new Vector3(num16, num * num3, num17);
		}

		private static void IgnoreNearbyPassThroughs(State st, Vector3 pos)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)st.Own == (Object)null)
			{
				return;
			}
			int num = Physics.OverlapSphereNonAlloc(pos, 2.5f, Overlaps, Mask, (QueryTriggerInteraction)1);
			for (int i = 0; i < num; i++)
			{
				Collider val = Overlaps[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)st.Own) && Ignored.Contains(BaseName(((Component)val).transform)))
				{
					Physics.IgnoreCollision(st.Own, val, true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Smoke), "Awake")]
	internal static class Smoke_Awake_Patch
	{
		private static void Prefix(Smoke __instance)
		{
			if (!ModConfig.Enabled.Value)
			{
				return;
			}
			__instance.m_ttl *= Mathf.Max(0.1f, ModConfig.LifetimeMultiplier.Value);
			float value = ModConfig.ColliderSizeMultiplier.Value;
			if (!Mathf.Approximately(value, 1f))
			{
				SphereCollider component = ((Component)__instance).GetComponent<SphereCollider>();
				if ((Object)(object)component != (Object)null)
				{
					component.radius *= value;
				}
			}
		}

		private static void Postfix(Smoke __instance)
		{
			//IL_000e: 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_0015: 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_0027: 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)
			if (ModConfig.Enabled.Value)
			{
				Vector3 vel = __instance.m_vel;
				__instance.m_vel = new Vector3(vel.x, SmokeBrain.InitialRise(__instance), vel.z);
				__instance.m_force *= Mathf.Max(0.1f, ModConfig.AccelerationMultiplier.Value);
			}
		}
	}
	[HarmonyPatch(typeof(Smoke), "CustomUpdate")]
	internal static class Smoke_CustomUpdate_Patch
	{
		private static void Prefix(Smoke __instance, float deltaTime, ref float ___m_time)
		{
			if (ModConfig.Enabled.Value)
			{
				float value = ModConfig.RainDecayBoost.Value;
				if (value > 0f && EnvMan.IsWet())
				{
					___m_time += deltaTime * value;
				}
				SmokeBrain.Tick(__instance, ___m_time);
			}
		}
	}
	[HarmonyPatch(typeof(Smoke), "GetTotalSmoke")]
	internal static class Smoke_GetTotalSmoke_Patch
	{
		private static void Postfix(ref int __result)
		{
			if (ModConfig.Enabled.Value)
			{
				int value = ModConfig.MaxAmount.Value;
				if (value > 0 && value != 100)
				{
					__result = Mathf.RoundToInt((float)__result * 100f / (float)value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SmokeSpawner), "TestBlocked")]
	internal static class SmokeSpawner_TestBlocked_Patch
	{
		private static bool Prefix(SmokeSpawner __instance, ref bool __result)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value)
			{
				return true;
			}
			float value = ModConfig.RequiredSpace.Value;
			if (value <= 0f)
			{
				__result = false;
				return false;
			}
			__result = Physics.CheckSphere(((Component)__instance).transform.position, value, ((LayerMask)(ref __instance.m_testMask)).value);
			return false;
		}
	}
	internal static class SpawnerInfo
	{
		internal class Info
		{
			public float Interval;

			public float Jitter = 1f;

			public Fireplace Fire;

			public float NextSearch;

			public float Strength = 0.8f;
		}

		private static readonly ConditionalWeakTable<SmokeSpawner, Info> Table = new ConditionalWeakTable<SmokeSpawner, Info>();

		private static readonly FieldInfo NviewField = AccessTools.Field(typeof(Fireplace), "m_nview");

		internal static void Restore(SmokeSpawner s)
		{
			if (Table.TryGetValue(s, out var value))
			{
				s.m_interval = value.Interval;
			}
		}

		internal static Info Get(SmokeSpawner s)
		{
			if (Table.TryGetValue(s, out var value))
			{
				return value;
			}
			value = new Info
			{
				Interval = s.m_interval
			};
			Table.Add(s, value);
			return value;
		}

		internal static void RefreshStrength(SmokeSpawner s, Info info)
		{
			if ((Object)(object)info.Fire == (Object)null && Time.time >= info.NextSearch)
			{
				info.NextSearch = Time.time + 5f;
				info.Fire = ((Component)s).GetComponentInParent<Fireplace>();
				if ((Object)(object)info.Fire == (Object)null)
				{
					Fireplace[] array = Object.FindObjectsByType<Fireplace>((FindObjectsSortMode)0);
					foreach (Fireplace val in array)
					{
						if ((Object)(object)val != (Object)null && (Object)(object)val.m_smokeSpawner == (Object)(object)s)
						{
							info.Fire = val;
							break;
						}
					}
				}
			}
			Fireplace fire = info.Fire;
			if ((Object)(object)fire == (Object)null)
			{
				info.Strength = 0.8f;
				return;
			}
			if (fire.m_infiniteFuel)
			{
				info.Strength = 0.9f;
				return;
			}
			ZNetView val2 = (ZNetView)((NviewField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 == (Object)null || !val2.IsValid())
			{
				info.Strength = 0.8f;
				return;
			}
			float num = val2.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
			info.Strength = Mathf.Clamp01(num / Mathf.Max(1f, fire.m_maxFuel));
			FireVisual component = ((Component)fire).GetComponent<FireVisual>();
			if ((Object)(object)component != (Object)null && component.LooksOut)
			{
				info.Strength = Mathf.Min(info.Strength, 0.05f);
			}
		}
	}
	[HarmonyPatch(typeof(SmokeSpawner), "CustomUpdate")]
	internal static class SmokeSpawner_CustomUpdate_Patch
	{
		private static void Prefix(SmokeSpawner __instance)
		{
			if (!ModConfig.Enabled.Value)
			{
				SpawnerInfo.Restore(__instance);
				return;
			}
			SpawnerInfo.Info info = SpawnerInfo.Get(__instance);
			float num = Mathf.Max(0.1f, ModConfig.SpawnRateMultiplier.Value) * SmokeBrain.SpawnFactor(info.Strength);
			__instance.m_interval = info.Interval / Mathf.Max(0.05f, num) * info.Jitter;
		}
	}
	[HarmonyPatch(typeof(SmokeSpawner), "Spawn")]
	internal static class SmokeSpawner_Spawn_Patch
	{
		private static void Prefix(SmokeSpawner __instance)
		{
			if (ModConfig.Enabled.Value)
			{
				SpawnerInfo.Info info = SpawnerInfo.Get(__instance);
				SpawnerInfo.RefreshStrength(__instance, info);
				SmokeBrain.PendingStrength = info.Strength;
			}
		}

		private static void Postfix(SmokeSpawner __instance)
		{
			SmokeBrain.PendingStrength = -1f;
			if (ModConfig.Enabled.Value)
			{
				float num = Mathf.Clamp(ModConfig.SpawnTimingVariance.Value, 0f, 0.9f);
				SpawnerInfo.Get(__instance).Jitter = 1f + Random.Range(0f - num, num);
			}
		}
	}
	[HarmonyPatch(typeof(SmokeRenderer), "LateUpdate")]
	internal static class SmokeRenderer_LateUpdate_Patch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(SmokeRenderer), "m_smokeBallSize");
			MethodInfo methodInfo = AccessTools.Method(typeof(Smoke), "GetParticleValues", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(SmokeBrain), "VisualSize", (Type[])null, (Type[])null);
			CodeInstruction val = null;
			for (int i = 1; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo) && CodeInstructionExtensions.IsLdloc(list[i - 1], (LocalBuilder)null))
				{
					val = list[i - 1];
					break;
				}
			}
			if (val == null)
			{
				Plugin.Log.LogWarning((object)"Smoke renderer patch: could not find the smoke variable. Visual size changes are off.");
				return list;
			}
			bool flag = false;
			for (int j = 0; j < list.Count; j++)
			{
				if (CodeInstructionExtensions.LoadsField(list[j], fieldInfo, false))
				{
					list.Insert(j + 1, new CodeInstruction(val.opcode, val.operand));
					list.Insert(j + 2, new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					j += 2;
					flag = true;
				}
			}
			if (!flag)
			{
				Plugin.Log.LogWarning((object)"Smoke renderer patch: could not find the size field. Visual size changes are off.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Smoke renderer patch applied (visual size per puff).");
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Start")]
	internal static class MenuFire_Reset_Patch
	{
		private static void Postfix()
		{
			MenuFire_Patch.Reset();
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Update")]
	internal static class MenuFire_Patch
	{
		private static bool _done;

		private static float _t;

		internal static void Reset()
		{
			_done = false;
			_t = 0f;
		}

		private static void Postfix()
		{
			if (_done)
			{
				return;
			}
			_t += Time.unscaledDeltaTime;
			if (_t < 4f)
			{
				return;
			}
			_done = true;
			try
			{
				Run();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[menu] menu fire patch failed: " + ex.Message));
			}
		}

		private static MinMaxCurve Spread(MinMaxCurve c, float v)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			float num = (((int)((MinMaxCurve)(ref c)).mode == 3) ? ((MinMaxCurve)(ref c)).constantMin : ((MinMaxCurve)(ref c)).constant);
			float num2 = (((int)((MinMaxCurve)(ref c)).mode == 3) ? ((MinMaxCurve)(ref c)).constantMax : ((MinMaxCurve)(ref c)).constant);
			return new MinMaxCurve(num * (1f - v), num2 * (1f + v));
		}

		private static MinMaxCurve AddForce(MinMaxCurve c, float add)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_002b: 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)
			if ((int)((MinMaxCurve)(ref c)).mode == 3)
			{
				return new MinMaxCurve(((MinMaxCurve)(ref c)).constantMin + add, ((MinMaxCurve)(ref c)).constantMax + add);
			}
			return new MinMaxCurve(((MinMaxCurve)(ref c)).constant + add);
		}

		private static void Run()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0190: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Invalid comparison between Unknown and I4
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Invalid comparison between Unknown and I4
			//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)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Invalid comparison between Unknown and I4
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0551: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_055a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0599: Unknown result type (might be due to invalid IL or missing references)
			//IL_059e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_0624: Unknown result type (might be due to invalid IL or missing references)
			//IL_0633: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_0654: Unknown result type (might be due to invalid IL or missing references)
			//IL_0663: Unknown result type (might be due to invalid IL or missing references)
			//IL_0668: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0680: Unknown result type (might be due to invalid IL or missing references)
			//IL_0684: Unknown result type (might be due to invalid IL or missing references)
			//IL_0693: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06de: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_071f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0724: Unknown result type (might be due to invalid IL or missing references)
			//IL_0764: Unknown result type (might be due to invalid IL or missing references)
			//IL_0781: Unknown result type (might be due to invalid IL or missing references)
			//IL_0786: Unknown result type (might be due to invalid IL or missing references)
			//IL_0798: Unknown result type (might be due to invalid IL or missing references)
			//IL_079d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value || !ModConfig.MenuFire.Value)
			{
				return;
			}
			ParticleSystem val = null;
			ParticleSystem[] array = Object.FindObjectsByType<ParticleSystem>((FindObjectsSortMode)0);
			foreach (ParticleSystem val2 in array)
			{
				if (((Object)val2).name.StartsWith("smoke") && (Object)(object)((Component)val2).transform.parent != (Object)null && (Object)(object)((Component)val2).transform.parent.parent != (Object)null && ((Object)((Component)val2).transform.parent.parent).name == "MenuFire")
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)"[menu] main menu fire smoke not found, nothing changed.");
				return;
			}
			MainModule main = val.main;
			EmissionModule emission = val.emission;
			((MainModule)(ref main)).startLifetimeMultiplier = ((MainModule)(ref main)).startLifetimeMultiplier * Mathf.Max(0.1f, ModConfig.LifetimeMultiplier.Value);
			MinMaxCurve val3 = ((EmissionModule)(ref emission)).rateOverTime;
			if ((int)((MinMaxCurve)(ref val3)).mode == 0)
			{
				val3 = ((EmissionModule)(ref emission)).rateOverTime;
				((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(((MinMaxCurve)(ref val3)).constant * Mathf.Max(0.1f, ModConfig.SpawnRateMultiplier.Value));
			}
			ManualLogSource log = Plugin.Log;
			string name = ((Object)val).name;
			object arg = ((MainModule)(ref main)).startLifetimeMultiplier;
			val3 = ((EmissionModule)(ref emission)).rateOverTime;
			log.LogInfo((object)$"[menu] menu fire smoke '{name}': lifetime now {arg:F1}, rate now {((MinMaxCurve)(ref val3)).constant:F1}");
			MenuScene val4 = Object.FindFirstObjectByType<MenuScene>();
			float value = ModConfig.WindDriftSpeed.Value;
			ForceOverLifetimeModule forceOverLifetime = val.forceOverLifetime;
			int num;
			if (((ForceOverLifetimeModule)(ref forceOverLifetime)).enabled)
			{
				val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime)).x;
				if ((int)((MinMaxCurve)(ref val3)).mode != 1)
				{
					val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime)).y;
					if ((int)((MinMaxCurve)(ref val3)).mode != 1)
					{
						val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime)).z;
						num = (((int)((MinMaxCurve)(ref val3)).mode != 1) ? 1 : 0);
						if (num != 0 && (Object)(object)val4 != (Object)null && value > 0f)
						{
							Vector3 val5 = val4.m_windDir;
							val5.y = 0f;
							if (((Vector3)(ref val5)).sqrMagnitude > 1E-06f)
							{
								((Vector3)(ref val5)).Normalize();
								Camera val6 = Camera.main;
								if ((Object)(object)val6 == (Object)null && Camera.allCamerasCount > 0)
								{
									val6 = Camera.allCameras[0];
								}
								if ((Object)(object)val6 != (Object)null)
								{
									Vector3 val7 = ((Component)val6).transform.position - ((Component)val).transform.position;
									val7.y = 0f;
									if (((Vector3)(ref val7)).sqrMagnitude > 1E-06f)
									{
										((Vector3)(ref val7)).Normalize();
										float num2 = Vector3.Dot(val5, val7);
										if (num2 > 0f)
										{
											val5 -= val7 * num2;
										}
										Plugin.Log.LogInfo((object)$"[menu] wind toward camera was {num2:F2}; removed that part");
									}
								}
								float num3 = val4.m_windIntensity * value / Mathf.Max(1f, ((MainModule)(ref main)).startLifetimeMultiplier);
								((ForceOverLifetimeModule)(ref forceOverLifetime)).x = AddForce(((ForceOverLifetimeModule)(ref forceOverLifetime)).x, val5.x * num3);
								((ForceOverLifetimeModule)(ref forceOverLifetime)).z = AddForce(((ForceOverLifetimeModule)(ref forceOverLifetime)).z, val5.z * num3);
								Plugin.Log.LogInfo((object)$"[menu] added wind force {val5.x * num3:F3}, {val5.z * num3:F3}");
							}
						}
						goto IL_034f;
					}
				}
			}
			num = 0;
			goto IL_034f;
			IL_034f:
			float num4 = Mathf.Clamp(ModConfig.RiseSpeedVariance.Value, 0f, 0.5f);
			if (num != 0 && num4 > 0f)
			{
				((ForceOverLifetimeModule)(ref forceOverLifetime)).y = Spread(((ForceOverLifetimeModule)(ref forceOverLifetime)).y, num4);
			}
			float num5 = Mathf.Clamp(ModConfig.SpawnTimingVariance.Value, 0f, 0.9f);
			if (num5 > 0f)
			{
				val3 = ((EmissionModule)(ref emission)).rateOverTime;
				if ((int)((MinMaxCurve)(ref val3)).mode == 0)
				{
					MenuFireModulator menuFireModulator = ((Component)val).gameObject.AddComponent<MenuFireModulator>();
					ParticleSystem ps = val;
					val3 = ((EmissionModule)(ref emission)).rateOverTime;
					menuFireModulator.Init(ps, ((MinMaxCurve)(ref val3)).constant, num5);
				}
			}
			VelocityOverLifetimeModule velocityOverLifetime = val.velocityOverLifetime;
			ForceOverLifetimeModule forceOverLifetime2 = val.forceOverLifetime;
			SizeOverLifetimeModule sizeOverLifetime = val.sizeOverLifetime;
			NoiseModule noise = val.noise;
			LimitVelocityOverLifetimeModule limitVelocityOverLifetime = val.limitVelocityOverLifetime;
			ShapeModule shape = val.shape;
			MenuScene val8 = Object.FindFirstObjectByType<MenuScene>();
			if ((Object)(object)val8 != (Object)null)
			{
				Plugin.Log.LogInfo((object)$"[menu] menu wind: dir={val8.m_windDir} intensity={val8.m_windIntensity:F2}");
			}
			ManualLogSource log2 = Plugin.Log;
			object[] array2 = new object[6];
			val3 = ((MainModule)(ref main)).startSize;
			array2[0] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((MainModule)(ref main)).startSpeed;
			array2[1] = ((MinMaxCurve)(ref val3)).mode;
			array2[2] = ((MainModule)(ref main)).simulationSpeed;
			array2[3] = ((MainModule)(ref main)).loop;
			array2[4] = ((MainModule)(ref main)).duration;
			array2[5] = ((MainModule)(ref main)).maxParticles;
			log2.LogInfo((object)string.Format("[menu] main: startSize mode={0} startSpeed mode={1} simSpeed={2} loop={3} duration={4:F1} maxParticles={5}", array2));
			ManualLogSource log3 = Plugin.Log;
			object[] obj = new object[11]
			{
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled,
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x;
			obj[2] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x;
			obj[3] = ((MinMaxCurve)(ref val3)).constantMax;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x;
			obj[4] = ((MinMaxCurve)(ref val3)).curveMultiplier;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y;
			obj[5] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y;
			obj[6] = ((MinMaxCurve)(ref val3)).constantMax;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y;
			obj[7] = ((MinMaxCurve)(ref val3)).curveMultiplier;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z;
			obj[8] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z;
			obj[9] = ((MinMaxCurve)(ref val3)).constantMax;
			val3 = ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z;
			obj[10] = ((MinMaxCurve)(ref val3)).curveMultiplier;
			log3.LogInfo((object)string.Format("[menu] velocityOverLifetime: enabled={0} space={1} x={2}/{3:F2}/{4:F2} y={5}/{6:F2}/{7:F2} z={8}/{9:F2}/{10:F2}", obj));
			ManualLogSource log4 = Plugin.Log;
			object[] obj2 = new object[8]
			{
				((ForceOverLifetimeModule)(ref forceOverLifetime2)).enabled,
				((ForceOverLifetimeModule)(ref forceOverLifetime2)).space,
				null,
				null,
				null,
				null,
				null,
				null
			};
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).x;
			obj2[2] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).x;
			obj2[3] = ((MinMaxCurve)(ref val3)).constantMax;
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).y;
			obj2[4] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).y;
			obj2[5] = ((MinMaxCurve)(ref val3)).constantMax;
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).z;
			obj2[6] = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((ForceOverLifetimeModule)(ref forceOverLifetime2)).z;
			obj2[7] = ((MinMaxCurve)(ref val3)).constantMax;
			log4.LogInfo((object)string.Format("[menu] forceOverLifetime: enabled={0} space={1} x={2}/{3:F2} y={4}/{5:F2} z={6}/{7:F2}", obj2));
			ManualLogSource log5 = Plugin.Log;
			object arg2 = ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled;
			val3 = ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size;
			object arg3 = ((MinMaxCurve)(ref val3)).mode;
			val3 = ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size;
			log5.LogInfo((object)$"[menu] sizeOverLifetime: enabled={arg2} mode={arg3} multiplier={((MinMaxCurve)(ref val3)).curveMultiplier:F2}");
			ManualLogSource log6 = Plugin.Log;
			object[] obj3 = new object[9]
			{
				((NoiseModule)(ref noise)).enabled,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			val3 = ((NoiseModule)(ref noise)).strength;
			obj3[1] = ((MinMaxCurve)(ref val3)).constantMax;
			obj3[2] = ((NoiseModule)(ref noise)).frequency;
			obj3[3] = ((LimitVelocityOverLifetimeModule)(ref limitVelocityOverLifetime)).enabled;
			obj3[4] = ((ShapeModule)(ref shape)).enabled;
			obj3[5] = ((ShapeModule)(ref shape)).shapeType;
			obj3[6] = ((ShapeModule)(ref shape)).radius;
			ColorOverLifetimeModule colorOverLifetime = val.colorOverLifetime;
			obj3[7] = ((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled;
			RotationOverLifetimeModule rotationOverLifetime = val.rotationOverLifetime;
			obj3[8] = ((RotationOverLifetimeModule)(ref rotationOverLifetime)).enabled;
			log6.LogInfo((object)string.Format("[menu] noise: enabled={0} strength={1:F2} frequency={2:F2}; limitVelocity: enabled={3}; shape: enabled={4} type={5} radius={6:F2}; colorOverLifetime={7} rotationOverLifetime={8}", obj3));
		}
	}
	internal class MenuFireModulator : MonoBehaviour
	{
		private ParticleSystem _ps;

		private float _baseRate;

		private float _variance;

		private float _seed;

		internal void Init(ParticleSystem ps, float baseRate, float variance)
		{
			_ps = ps;
			_baseRate = baseRate;
			_variance = variance;
			_seed = Random.Range(0f, 100f);
		}

		private void Update()
		{
			//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_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_ps == (Object)null))
			{
				float num = Mathf.PerlinNoise(Time.unscaledTime * 0.6f, _seed) - 0.5f;
				EmissionModule emission = _ps.emission;
				((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(_baseRate * Mathf.Max(0.1f, 1f + num * 4f * _variance));
			}
		}
	}
	internal class FireVisual : MonoBehaviour
	{
		private class PsInfo
		{
			public ParticleSystem Ps;

			public bool Size3D;

			public float SizeX;

			public float SizeY;

			public float SizeZ;

			public float Rate;

			public float Speed;
		}

		private class LightInfo
		{
			public Light L;

			public float Range;

			public float Intensity;

			public bool Flicker;
		}

		internal static readonly ConditionalWeakTable<LightFlicker, FireVisual> LightOwners = new ConditionalWeakTable<LightFlicker, FireVisual>();

		private static readonly FieldInfo NviewField = AccessTools.Field(typeof(Fireplace), "m_nview");

		private const float VanillaBlowoutWind = 0.8f;

		private const float ExposedCover = 0.7f;

		private const float BlownHysteresis = 0.05f;

		private const float BlownMinHold = 4f;

		private const float BlownSize = 0.25f;

		private const float BlownLight = 0.2f;

		private const float FadePerSecond = 0.4f;

		private const float FarRange = 100f;

		private const float CoverRecheck = 15f;

		private const float RainOutSize = 0.08f;

		private const float RainOutLight = 0.06f;

		private const float RainDrySeconds = 30f;

		private Fireplace _fp;

		private ZNetView _nview;

		private bool _gathered;

		private bool _first = true;

		private readonly List<PsInfo> _ps = new List<PsInfo>();

		private readonly List<LightInfo> _lights = new List<LightInfo>();

		private float _nextCheck;

		private float _targetSize = 1f;

		private float _targetLight = 1f;

		private float _size = 1f;

		private float _lightBase = 1f;

		private float _effSize = 1f;

		private float _appliedSize = -1f;

		private float _appliedLight = -1f;

		private float _lastFuel = -1f;

		private float _nextFuelPoll;

		private float _flareStart = -1000f;

		private float _lastBlownChange = -1000f;

		private bool _far;

		private float _lastEval = -1f;

		private bool _rainOut;

		private float _wet;

		private float _cover;

		private bool _underRoof;

		private float _coverNext;

		private float _flicker = 1f;

		private float _targetFlicker = 1f;

		private const float FlareAttack = 0.25f;

		public bool Blown;

		public bool LooksOut;

		public float WindLevel;

		public float LightFactor = 1f;

		private readonly List<ParticleSystemRenderer> _hiddenPs = new List<ParticleSystemRenderer>();

		private bool _outShown;

		public float FlickerAmp => _flicker;

		public float LightOut
		{
			get
			{
				if (!LooksOut)
				{
					return LightFactor;
				}
				return 0f;
			}
		}

		private void OnDisable()
		{
			RemoveOutLook();
		}

		private void Update()
		{
			if (Application.isBatchMode)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			if (!_gathered)
			{
				Gather();
			}
			if ((Object)(object)_fp == (Object)null)
			{
				return;
			}
			if (Time.time >= _nextCheck)
			{
				_nextCheck = Time.time + (_far ? 6f : 2f) + Random.Range(0f, 0.5f);
				Evaluate();
			}
			if (_far)
			{
				return;
			}
			PollFuel();
			float num = FlareEnvelope();
			if (_size != _targetSize || _lightBase != _targetLight || _flicker != _targetFlicker || !(num <= 0f) || !(_appliedSize >= 0f) || !(Mathf.Abs(_size - _appliedSize) <= 0.003f) || !(Mathf.Abs((LooksOut ? 0f : _lightBase) - _appliedLight) <= 0.003f))
			{
				float num2 = Time.deltaTime * 0.4f;
				_size = Mathf.MoveTowards(_size, _targetSize, num2);
				_lightBase = Mathf.MoveTowards(_lightBase, _targetLight, num2);
				_flicker = Mathf.MoveTowards(_flicker, _targetFlicker, Time.deltaTime * 1f);
				float num3 = 1f + Mathf.Clamp01(ModConfig.RefuelFlare.Value) * num;
				_effSize = _size * num3;
				LightFactor = _lightBase * num3;
				if (Mathf.Abs(_effSize - _appliedSize) > 0.003f)
				{
					ApplyParticles();
				}
				if (Mathf.Abs(LightOut - _appliedLight) > 0.003f)
				{
					ApplyLights();
				}
			}
		}

		private static void AddRoot(List<GameObject> roots, GameObject g)
		{
			if ((Object)(object)g != (Object)null && !roots.Contains(g))
			{
				roots.Add(g);
			}
		}

		private void Gather()
		{
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			_gathered = true;
			_fp = ((Component)this).GetComponent<Fireplace>();
			if ((Object)(object)_fp == (Object)null)
			{
				return;
			}
			_nview = (ZNetView)((NviewField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			List<GameObject> list = new List<GameObject>();
			AddRoot(list, _fp.m_enabledObject);
			AddRoot(list, _fp.m_enabledObjectHigh);
			AddRoot(list, _fp.m_enabledObjectLow);
			HashSet<ParticleSystem> hashSet = new HashSet<ParticleSystem>();
			HashSet<Light> hashSet2 = new HashSet<Light>();
			HashSet<Light> hashSet3 = new HashSet<Light>();
			foreach (GameObject item in list)
			{
				LightFlicker[] componentsInChildren = item.GetComponentsInChildren<LightFlicker>(true);
				foreach (LightFlicker val in componentsInChildren)
				{
					LightOwners.Remove(val);
					LightOwners.Add(val, this);
					Light component = ((Component)val).GetComponent<Light>();
					if ((Object)(object)component != (Object)null)
					{
						hashSet3.Add(component);
					}
				}
				Light[] componentsInChildren2 = item.GetComponentsInChildren<Light>(true);
				foreach (Light val2 in componentsInChildren2)
				{
					if (hashSet2.Add(val2))
					{
						bool flicker = hashSet3.Contains(val2);
						_lights.Add(new LightInfo
						{
							L = val2,
							Range = val2.range,
							Intensity = val2.intensity,
							Flicker = flicker
						});
					}
				}
				ParticleSystem[] componentsInChildren3 = item.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val3 in componentsInChildren3)
				{
					if (hashSet.Add(val3) && ((Object)val3).name.IndexOf("smok", StringComparison.OrdinalIgnoreCase) < 0)
					{
						MainModule main = val3.main;
						List<PsInfo> ps = _ps;
						PsInfo obj = new PsInfo
						{
							Ps = val3,
							Size3D = ((MainModule)(ref main)).startSize3D,
							SizeX = ((MainModule)(ref main)).startSizeXMultiplier,
							SizeY = ((MainModule)(ref main)).startSizeYMultiplier,
							SizeZ = ((MainModule)(ref main)).startSizeZMultiplier,
							Speed = ((MainModule)(ref main)).startSpeedMultiplier
						};
						EmissionModule emission = val3.emission;
						obj.Rate = ((EmissionModule)(ref emission)).rateOverTimeMultiplier;
						ps.Add(obj);
					}
				}
			}
		}

		private void PollFuel()
		{
			if (Time.time < _nextFuelPoll)
			{
				return;
			}
			_nextFuelPoll = Time.time + 0.5f;
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				float num = _nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f);
				if (_lastFuel >= 0f && num > _lastFuel + 0.5f && ModConfig.FlamesActive)
				{
					_flareStart = Time.time;
				}
				_lastFuel = num;
			}
		}

		private float FlareEnvelope()
		{
			float num = Time.time - _flareStart;
			if (num < 0f)
			{
				return 0f;
			}
			float num2 = Mathf.Max(0f, ModConfig.RefuelFlareHold.Value);
			float num3 = Mathf.Max(0.1f, ModConfig.RefuelFlareFade.Value);
			if (num < 0.25f)
			{
				return num / 0.25f;
			}
			num -= 0.25f;
			if (num < num2)
			{
				return 1f;
			}
			return Mathf.Clamp01(1f - (num - num2) / num3);
		}

		private float ReadStrength()
		{
			if (_fp.m_infiniteFuel)
			{
				return 1f;
			}
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return 1f;
			}
			return Mathf.Clamp01(_nview.GetZDO().GetFloat(ZDOVars.s_fuel, 0f) / Mathf.Max(0.01f, _fp.m_maxFuel));
		}

		private void Evaluate()
		{
			//IL_0015: 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)
			//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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Vector3 val = ((Component)localPlayer).transform.position - ((Component)this).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude > 10000f)
				{
					_far = true;
					return;
				}
			}
			if (_far)
			{
				_far = false;
				_first = true;
			}
			float dt = ((_lastEval < 0f) ? 0f : Mathf.Clamp(Time.time - _lastEval, 0f, 30f));
			_lastEval = Time.time;
			if (!ModConfig.FlamesActive)
			{
				Blown = false;
				_wet = 0f;
				_rainOut = false;
				LooksOut = false;
				RemoveOutLook();
				_targetSize = 1f;
				_targetLight = 1f;
				_targetFlicker = 1f;
			}
			else
			{
				float num = ReadStrength();
				float num2 = Mathf.Clamp01(ModConfig.FlameEffect.Value);
				float num3 = Mathf.Clamp(ModConfig.DwindleStart.Value, 0.05f, 1f);
				float num4 = Mathf.Pow(Mathf.InverseLerp(Mathf.Clamp(ModConfig.DwindleEnd.Value, 0f, num3 - 0.01f), num3, num), Mathf.Clamp(ModConfig.DwindleCurve.Value, 0.3f, 3f));
				float num5 = Mathf.Lerp(1f, Mathf.Lerp(Mathf.Clamp(ModConfig.WeakFlameSize.Value, 0.1f, 1f), Mathf.Max(1f, ModConfig.FullFlameBoost.Value), num4), num2);
				float num6 = Mathf.Lerp(1f, Mathf.Lerp(Mathf.Clamp(ModConfig.WeakFlameLight.Value, 0.05f, 1f), Mathf.Max(1f, ModConfig.FullFlameLight.Value), num4), num2);
				bool blown = Blown;
				bool flag = ComputeWeather(num4, dt);
				if (flag != blown && Time.time - _lastBlownChange < 4f)
				{
					flag = blown;
				}
				Blown = flag;
				if (Blown != blown)
				{
					_lastBlownChange = Time.time;
				}
				if (Blown)
				{
					num5 *= 0.25f;
					num6 *= 0.2f;
				}
				else if (WindLevel > 0f)
				{
					float num7 = (ModConfig.WindFlameShrinkOn.Value ? (WindLevel * Mathf.Clamp01(ModConfig.WindFlameShrink.Value)) : 0f);
					num5 *= Mathf.Lerp(1f, 0.25f, num7);
					num6 *= Mathf.Lerp(1f, 0.2f, num7 * 0.6f);
				}
				if (_wet > 0.001f)
				{
					num5 *= Mathf.Lerp(1f, 0.08f, _wet);
					num6 *= Mathf.Lerp(1f, 0.06f, _wet);
				}
				if (!_rainOut && _wet >= 0.97f)
				{
					_rainOut = true;
				}
				else if (_rainOut && _wet <= 0.85f)
				{
					_rainOut = false;
				}
				bool flag2 = (Object)(object)_fp.m_enabledObjectLow == (Object)null || (Object)(object)_fp.m_enabledObjectHigh == (Object)null;
				bool flag3 = Blown && flag2 && !_fp.m_canTurnOff && ModConfig.BlowoutMode.Value != "Off";
				bool looksOut = LooksOut;
				LooksOut = _rainOut || flag3;
				if (LooksOut != looksOut)
				{
					if (LooksOut)
					{
						ApplyOutLook();
					}
					else
					{
						RemoveOutLook();
					}
				}
				float num8 = Mathf.Max(new float[3]
				{
					1f - num4,
					Blown ? 0.85f : 0f,
					_wet
				});
				_targetFlicker = Mathf.Lerp(1f, Mathf.Max(1f, ModConfig.LowFuelFlicker.Value), num8 * num2);
				_targetSize = Mathf.Max(0.03f, num5);
				_targetLight = Mathf.Max(0.02f, num6);
			}
			if (_first)
			{
				_first = false;
				_size = _targetSize;
				_lightBase = _targetLight;
				_flicker = _targetFlicker;
				LightFactor = _targetLight;
			}
		}

		private static bool NameKept(string n)
		{
			n = n.ToLowerInvariant();
			if (!n.Contains("smok") && !n.Contains("wisp") && !n.Contains("puff") && !n.Contains("ember"))
			{
				return n.Contains("steam");
			}
			return true;
		}

		internal void ApplyOutLook()
		{
			if ((Object)(object)_fp == (Object)null)
			{
				return;
			}
			bool flag = (Object)(object)_fp.m_enabledObjectLow != (Object)null && (Object)(object)_fp.m_enabledObjectHigh != (Object)null;
			if (!_outShown)
			{
				_outShown = true;
				List<GameObject> list = new List<GameObject>();
				if (flag)
				{
					AddRoot(list, _fp.m_enabledObjectLow);
				}
				else
				{
					AddRoot(list, _fp.m_enabledObject);
					AddRoot(list, _fp.m_enabledObjectHigh);
					AddRoot(list, _fp.m_enabledObjectLow);
				}
				Transform val = (((Object)(object)_fp.m_emptyObject != (Object)null) ? _fp.m_emptyObject.transform : null);
				foreach (GameObject item in list)
				{
					ParticleSystemRenderer[] componentsInChildren = item.GetComponentsInChildren<ParticleSystemRenderer>(true);
					foreach (ParticleSystemRenderer val2 in componentsInChildren)
					{
						if (!((Object)(object)val2 == (Object)null) && (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)) && (!flag || !NameKept(((Object)((Component)val2).gameObject).name)) && ((Renderer)val2).enabled)
						{
							((Renderer)val2).enabled = false;
							_hiddenPs.Add(val2);
						}
					}
				}
				_appliedLight = -1f;
			}
			if (!flag && (Object)(object)_fp.m_emptyObject != (Object)null)
			{
				_fp.m_emptyObject.SetActive(true);
			}
		}

		internal void RemoveOutLook()
		{
			if (!_outShown)
			{
				return;
			}
			_outShown = false;
			foreach (ParticleSystemRenderer hiddenP in _hiddenPs)
			{
				if ((Object)(object)hiddenP != (Object)null)
				{
					((Renderer)