Decompiled source of WispTorchHeeler v1.5.0

WispTorchHeeler.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSync;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using WispTorchHeeler.Configuration;
using WispTorchHeeler.Lighting;
using WispTorchHeeler.Localization;
using WispTorchHeeler.Painter;
using WispTorchHeeler.Pieces;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("DreamWraith (https://github.com/dreamwraith)")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 DreamWraith")]
[assembly: AssemblyDescription("Tiered Mistlands wisp torches and lamps with expanded mist clearance, interactive torch painting, body-worn Wisplight customization, and multiplayer color synchronization.")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: AssemblyInformationalVersion("1.5.0+794fd07ea212d3465359189dbca1f67c926751d3")]
[assembly: AssemblyProduct("WispTorchHeeler")]
[assembly: AssemblyTitle("WispTorchHeeler")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dreamwraith/Valheim-WispTorchHeeler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WispTorchHeeler
{
	[BepInPlugin("dreamwraith.WispTorchHeeler", "WispTorchHeeler", "1.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGUID = "dreamwraith.WispTorchHeeler";

		public const string ModName = "WispTorchHeeler";

		public const string ModVersion = "1.5.0";

		internal static ManualLogSource Log;

		private Harmony? _harmony;

		internal static Plugin? Instance { get; private set; }

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Initialize(((BaseUnityPlugin)this).Config);
			new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			if (!ModConfig.EnableMod.Value)
			{
				Log.LogInfo((object)"WispTorchHeeler is disabled in configuration.");
				return;
			}
			WispPieceManager.Initialize();
			WispPieceRegistration.Initialize();
			if (!GUIManager.IsHeadless())
			{
				ModLocalization.Initialize();
				ModConfig.RegisterInputButtons();
				((Component)this).gameObject.AddComponent<TorchPainterInput>();
				WispTorchColorController.Initialize();
				WispDemisterColorController.Initialize();
				WispDemisterHipTemplates.Initialize();
				WispDemisterIdleMotion.Initialize();
				_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "dreamwraith.WispTorchHeeler");
				Log.LogInfo((object)"WispTorchHeeler v1.5.0 loaded successfully.");
			}
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static void LogDebug(string message)
		{
			if (ModConfig.EnableDebugLogs.Value)
			{
				Log.LogInfo((object)("[DEBUG] " + message));
			}
		}
	}
	internal static class VersionInfo
	{
		public const string Version = "1.5.0";
	}
}
namespace WispTorchHeeler.Pieces
{
	public static class WispPieceManager
	{
		public class PieceBaseStats
		{
			public float BaseHealth;

			public float[] ForceFieldStartRanges = Array.Empty<float>();

			public float[] ForceFieldEndRanges = Array.Empty<float>();

			public float[] LightIntensities = Array.Empty<float>();

			public float[] LightRanges = Array.Empty<float>();
		}

		public record struct PieceTier(string PrefabName, string BasePrefabName, string NameToken, string DescriptionToken, float ScaleFactor, Vector3 ColliderCenter, Vector3 ColliderSize, string? PlaceEffectSource, string? WearEffectSource, ConfigEntry<string> Recipe, ConfigEntry<string> CraftingStation, ConfigEntry<float> Health, ConfigEntry<float> MistClearRangeMultiplier, ConfigEntry<float> LightIntensityMultiplier, ConfigEntry<float> LightRangeMultiplier);

		public const string Tier1TorchPrefab = "piece_wisptorch_heeler_lg";

		public const string Tier2SmallLampPrefab = "piece_wisplamp_heeler";

		public const string Tier3LargeLampPrefab = "piece_wisplamp_heeler_lg";

		public const string Tier4GrandLampPrefab = "piece_wisplamp_heeler_grand";

		public const string NativeMistTorchPrefab = "piece_groundtorch_mist";

		public const string NativeWallTorchPrefab = "piece_walltorch";

		public const string NativeDvergrLanternPrefab = "piece_dvergr_lantern";

		public const string NativeDemisterPrefab = "dverger_demister";

		public const string NativeDemisterLargePrefab = "dverger_demister_large";

		public const float NativePlayerBaseRadius = 20f;

		public const float NativeMistClearRadius = 24f;

		public const float NativeLightRange = 10f;

		public static readonly Dictionary<string, PieceBaseStats> BaseStats = new Dictionary<string, PieceBaseStats>();

		private static PieceTier[] s_tiers = Array.Empty<PieceTier>();

		private static Dictionary<string, PieceTier> s_tiersByPrefab = new Dictionary<string, PieceTier>();

		private static GameObject? s_areaMarkerTemplate;

		public static IReadOnlyList<PieceTier> Tiers => s_tiers;

		public static GameObject? AreaMarkerTemplate
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)s_areaMarkerTemplate))
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab("guard_stone");
					if (Object.op_Implicit((Object)(object)prefab))
					{
						PrivateArea component = prefab.GetComponent<PrivateArea>();
						if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_areaMarker))
						{
							s_areaMarkerTemplate = ((Component)component.m_areaMarker).gameObject;
						}
					}
					if (!Object.op_Implicit((Object)(object)s_areaMarkerTemplate))
					{
						GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_workbench");
						if (Object.op_Implicit((Object)(object)prefab2))
						{
							CraftingStation component2 = prefab2.GetComponent<CraftingStation>();
							if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.m_areaMarker))
							{
								s_areaMarkerTemplate = component2.m_areaMarker;
							}
						}
					}
				}
				return s_areaMarkerTemplate;
			}
		}

		public static void Initialize()
		{
			s_tiers = CreateTiers();
			s_tiersByPrefab = s_tiers.ToDictionary((PieceTier pieceTier) => pieceTier.PrefabName);
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
			PieceTier[] array = s_tiers;
			for (int num = 0; num < array.Length; num++)
			{
				PieceTier tier = array[num];
				EventHandler eventHandler = delegate
				{
					UpdatePieceConfiguration(tier);
				};
				tier.Recipe.SettingChanged += eventHandler;
				tier.CraftingStation.SettingChanged += eventHandler;
				tier.Health.SettingChanged += eventHandler;
				tier.MistClearRangeMultiplier.SettingChanged += eventHandler;
				tier.LightIntensityMultiplier.SettingChanged += eventHandler;
				tier.LightRangeMultiplier.SettingChanged += eventHandler;
			}
			ModConfig.PlayerBaseMistRadiusBonus.SettingChanged += delegate
			{
				UpdateAllPieceConfigurations();
			};
			Plugin.LogDebug("[PieceManager] Subscribed to piece lifecycle and config property events.");
		}

		private static PieceTier[] CreateTiers()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			return new PieceTier[4]
			{
				new PieceTier("piece_wisptorch_heeler_lg", "piece_groundtorch_mist", "$piece_wisptorch_heeler_lg", "$piece_wisptorch_heeler_lg_description", 1.25f, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f), null, null, ModConfig.Torch_Recipe, ModConfig.Torch_CraftingStation, ModConfig.Torch_Health, ModConfig.Torch_MistClearRangeMultiplier, ModConfig.Torch_LightIntensityMultiplier, ModConfig.Torch_LightRangeMultiplier),
				new PieceTier("piece_wisplamp_heeler", "dverger_demister", "$piece_wisplamp_heeler", "$piece_wisplamp_heeler_description", 1f, new Vector3(0f, -0.1f, 0f), new Vector3(0.26f, 1.1f, 0.26f), "piece_walltorch", "piece_dvergr_lantern", ModConfig.SmallLamp_Recipe, ModConfig.SmallLamp_CraftingStation, ModConfig.SmallLamp_Health, ModConfig.SmallLamp_MistClearRangeMultiplier, ModConfig.SmallLamp_LightIntensityMultiplier, ModConfig.SmallLamp_LightRangeMultiplier),
				new PieceTier("piece_wisplamp_heeler_lg", "dverger_demister_large", "$piece_wisplamp_heeler_lg", "$piece_wisplamp_heeler_lg_description", 1.1f, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern", ModConfig.LargeLamp_Recipe, ModConfig.LargeLamp_CraftingStation, ModConfig.LargeLamp_Health, ModConfig.LargeLamp_MistClearRangeMultiplier, ModConfig.LargeLamp_LightIntensityMultiplier, ModConfig.LargeLamp_LightRangeMultiplier),
				new PieceTier("piece_wisplamp_heeler_grand", "dverger_demister_large", "$piece_wisplamp_heeler_grand", "$piece_wisplamp_heeler_grand_description", 1.5f, new Vector3(0f, -0.18f, 0f), new Vector3(0.32f, 1.45f, 0.32f), "piece_walltorch", "piece_dvergr_lantern", ModConfig.GrandLamp_Recipe, ModConfig.GrandLamp_CraftingStation, ModConfig.GrandLamp_Health, ModConfig.GrandLamp_MistClearRangeMultiplier, ModConfig.GrandLamp_LightIntensityMultiplier, ModConfig.GrandLamp_LightRangeMultiplier)
			};
		}

		private static void OnPiecesRegistered()
		{
			Plugin.LogDebug("[PieceManager] OnPiecesRegistered triggered. Updating piece recipes and stations.");
			UpdateAllPieceConfigurations();
		}

		public static void UpdateAllPieceConfigurations()
		{
			PieceTier[] array = s_tiers;
			for (int i = 0; i < array.Length; i++)
			{
				UpdatePieceConfiguration(array[i]);
			}
		}

		public static void UpdatePieceConfiguration(PieceTier tier)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0110: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			string prefabName = tier.PrefabName;
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "main")
			{
				string[] obj = new string[5] { "[PieceManager] Active scene is '", null, null, null, null };
				activeScene = SceneManager.GetActiveScene();
				obj[1] = ((Scene)(ref activeScene)).name;
				obj[2] = "'. Deferring piece update for '";
				obj[3] = prefabName;
				obj[4] = "' until game world loads.";
				Plugin.LogDebug(string.Concat(obj));
				return;
			}
			CustomPiece piece = PieceManager.Instance.GetPiece(prefabName);
			if (piece == null || !Object.op_Implicit((Object)(object)piece.PiecePrefab))
			{
				Plugin.LogDebug("[PieceManager] CustomPiece '" + prefabName + "' not found in PieceManager registry for config update.");
				return;
			}
			Piece component = piece.PiecePrefab.GetComponent<Piece>();
			if (TryParseAndValidateRecipe(tier.Recipe.Value, prefabName, out RequirementConfig[] requirements))
			{
				List<Requirement> list = new List<Requirement>();
				RequirementConfig[] array = requirements;
				foreach (RequirementConfig val in array)
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(val.Item);
					ItemDrop val2 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null);
					if (Object.op_Implicit((Object)(object)val2))
					{
						list.Add(new Requirement
						{
							m_resItem = val2,
							m_amount = val.Amount,
							m_amountPerLevel = val.AmountPerLevel,
							m_recover = val.Recover
						});
					}
					else
					{
						Plugin.Log.LogError((object)("[PieceManager] Could not resolve ItemDrop for requirement '" + val.Item + "' on piece '" + prefabName + "'."));
					}
				}
				if (Object.op_Implicit((Object)(object)component))
				{
					component.m_resources = list.ToArray();
				}
			}
			else
			{
				Plugin.Log.LogError((object)("[PieceManager] Rejecting recipe update for piece '" + prefabName + "' due to validation errors. Keeping existing recipe."));
			}
			if (Object.op_Implicit((Object)(object)component))
			{
				string internalName = CraftingStations.GetInternalName(tier.CraftingStation.Value);
				if (string.IsNullOrEmpty(internalName) || internalName.Equals("None", StringComparison.OrdinalIgnoreCase))
				{
					component.m_craftingStation = null;
				}
				else
				{
					GameObject prefab2 = PrefabManager.Instance.GetPrefab(internalName);
					if (Object.op_Implicit((Object)(object)prefab2))
					{
						component.m_craftingStation = prefab2.GetComponent<CraftingStation>();
					}
					else
					{
						Plugin.Log.LogWarning((object)("[PieceManager] Crafting station prefab '" + internalName + "' not found for piece '" + prefabName + "'."));
						component.m_craftingStation = null;
					}
				}
			}
			ApplyProperties(piece.PiecePrefab, prefabName);
			WispTorchColorController.RefreshPropertiesForPrefab(prefabName);
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Player.m_localPlayer.UpdateKnownRecipesList();
				Player.m_localPlayer.UpdateAvailablePiecesList();
			}
			Plugin.LogDebug("[PieceManager] Updated '" + prefabName + "' configuration in real time.");
		}

		public static void ApplyProperties(GameObject targetGameObject, string prefabName)
		{
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			if (!BaseStats.TryGetValue(prefabName, out PieceBaseStats value))
			{
				return;
			}
			PieceTier pieceTier = s_tiersByPrefab[prefabName];
			float value2 = pieceTier.MistClearRangeMultiplier.Value;
			float value3 = pieceTier.LightIntensityMultiplier.Value;
			float value4 = pieceTier.LightRangeMultiplier.Value;
			ParticleSystemForceField[] componentsInChildren = targetGameObject.GetComponentsInChildren<ParticleSystemForceField>(true);
			for (int i = 0; i < componentsInChildren.Length && i < value.ForceFieldStartRanges.Length; i++)
			{
				componentsInChildren[i].startRange = value.ForceFieldStartRanges[i] * value2;
				componentsInChildren[i].endRange = value.ForceFieldEndRanges[i] * value2;
			}
			Light[] componentsInChildren2 = targetGameObject.GetComponentsInChildren<Light>(true);
			for (int j = 0; j < componentsInChildren2.Length && j < value.LightIntensities.Length; j++)
			{
				WispVisualApplicator.SetLightIntensity(componentsInChildren2[j], value.LightIntensities[j] * value3);
				WispVisualApplicator.SetLightRange(componentsInChildren2[j], value.LightRanges[j] * value4);
			}
			WearNTear component = targetGameObject.GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_health = pieceTier.Health.Value;
			}
			Transform val = targetGameObject.transform.Find("PlayerBase");
			if (Object.op_Implicit((Object)(object)val))
			{
				SphereCollider component2 = ((Component)val).GetComponent<SphereCollider>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					float num = 24f * value2;
					float num2 = Mathf.Clamp01(ModConfig.PlayerBaseMistRadiusBonus.Value);
					float num3 = 20f + (num - 20f) * num2;
					Vector3 lossyScale = targetGameObject.transform.lossyScale;
					float num4 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
					component2.radius = ((num4 > 0.001f) ? (num3 / num4) : num3);
				}
			}
		}

		public static bool IsValidItemPrefab(string itemName)
		{
			if (string.IsNullOrWhiteSpace(itemName))
			{
				return false;
			}
			if (itemName.Equals("<PrefabName>", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(itemName);
			ItemDrop val = default(ItemDrop);
			if (Object.op_Implicit((Object)(object)prefab))
			{
				return prefab.TryGetComponent<ItemDrop>(ref val);
			}
			return false;
		}

		public static bool TryParseAndValidateRecipe(string recipeString, string pieceName, out RequirementConfig[] requirements)
		{
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			requirements = Array.Empty<RequirementConfig>();
			if (string.IsNullOrWhiteSpace(recipeString))
			{
				Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' is empty or whitespace."));
				return false;
			}
			string[] array = recipeString.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains no valid tokens ('" + recipeString + "')."));
				return false;
			}
			List<RequirementConfig> list = new List<RequirementConfig>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Trim().Split(new char[1] { ':' });
				if (array3.Length != 2)
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains malformed token '" + text + "'. Expected 'ItemPrefab:Amount'."));
					return false;
				}
				string text2 = array3[0].Trim();
				if (string.IsNullOrEmpty(text2))
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains an empty item prefab name in token '" + text + "'."));
					return false;
				}
				if (!int.TryParse(array3[1].Trim(), out var result) || result <= 0)
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' contains invalid amount '" + array3[1] + "' in token '" + text + "'. Amount must be a positive integer."));
					return false;
				}
				if (!IsValidItemPrefab(text2))
				{
					Plugin.Log.LogError((object)("[PieceManager] Recipe for piece '" + pieceName + "' requires item '" + text2 + "' which does not exist in the game!"));
					return false;
				}
				list.Add(new RequirementConfig(text2, result, 0, true));
			}
			requirements = list.ToArray();
			return true;
		}
	}
	public static class WispPieceRegistration
	{
		public static void Initialize()
		{
			PrefabManager.OnVanillaPrefabsAvailable += RegisterCustomPieces;
		}

		private static void RegisterCustomPieces()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterCustomPieces;
			Plugin.LogDebug("[PieceManager] RegisterCustomPieces triggered.");
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist");
			if (Object.op_Implicit((Object)(object)prefab))
			{
				WispTorchColorController wispTorchColorController = default(WispTorchColorController);
				if (!prefab.TryGetComponent<WispTorchColorController>(ref wispTorchColorController))
				{
					prefab.AddComponent<WispTorchColorController>();
					Plugin.LogDebug("[PieceManager] Injected WispTorchColorController into native prefab 'piece_groundtorch_mist'.");
				}
				EnsurePieceCollider(prefab, new Vector3(0f, 0.025f, 0f), new Vector3(0.25f, 1.35f, 0.25f));
			}
			else
			{
				Plugin.Log.LogWarning((object)"[PieceManager] Native prefab 'piece_groundtorch_mist' not found for controller injection.");
			}
			foreach (WispPieceManager.PieceTier tier in WispPieceManager.Tiers)
			{
				RegisterPiece(tier);
			}
		}

		private static void RegisterPiece(WispPieceManager.PieceTier tier)
		{
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Expected O, but got Unknown
			//IL_0578: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Expected O, but got Unknown
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			string prefabName = tier.PrefabName;
			string value = tier.Recipe.Value;
			string text = (string)((ConfigEntryBase)tier.Recipe).DefaultValue;
			if (!WispPieceManager.TryParseAndValidateRecipe(value, prefabName, out RequirementConfig[] requirements))
			{
				Plugin.Log.LogError((object)("[PieceManager] Config recipe for piece '" + prefabName + "' is invalid ('" + value + "'). Falling back to default recipe: '" + text + "'."));
				if (!WispPieceManager.TryParseAndValidateRecipe(text, prefabName, out requirements))
				{
					Plugin.Log.LogError((object)("[PieceManager] Default recipe for piece '" + prefabName + "' is also invalid ('" + text + "'). Aborting piece registration."));
					return;
				}
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, tier.BasePrefabName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Plugin.Log.LogError((object)("[PieceManager] Failed to clone prefab '" + tier.BasePrefabName + "' as '" + prefabName + "'."));
				return;
			}
			ParticleSystemForceField[] componentsInChildren = val.GetComponentsInChildren<ParticleSystemForceField>(true);
			Light[] componentsInChildren2 = val.GetComponentsInChildren<Light>(true);
			WearNTear component = val.GetComponent<WearNTear>();
			WispPieceManager.PieceBaseStats pieceBaseStats = new WispPieceManager.PieceBaseStats
			{
				BaseHealth = (Object.op_Implicit((Object)(object)component) ? component.m_health : 100f),
				ForceFieldStartRanges = new float[componentsInChildren.Length],
				ForceFieldEndRanges = new float[componentsInChildren.Length],
				LightIntensities = new float[componentsInChildren2.Length],
				LightRanges = new float[componentsInChildren2.Length]
			};
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				pieceBaseStats.ForceFieldStartRanges[i] = componentsInChildren[i].startRange;
				pieceBaseStats.ForceFieldEndRanges[i] = 24f;
			}
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				pieceBaseStats.LightIntensities[j] = componentsInChildren2[j].intensity;
				pieceBaseStats.LightRanges[j] = 10f;
			}
			WispPieceManager.BaseStats[prefabName] = pieceBaseStats;
			if (Mathf.Abs(tier.ScaleFactor - 1f) > 0.001f)
			{
				val.transform.localScale = val.transform.localScale * tier.ScaleFactor;
				Plugin.LogDebug($"[PieceManager] Scaled '{prefabName}' by {tier.ScaleFactor}x.");
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<ZNetView>()))
			{
				val.AddComponent<ZNetView>().m_syncInitialScale = true;
			}
			Piece val2 = val.GetComponent<Piece>();
			if (!Object.op_Implicit((Object)(object)val2))
			{
				val2 = val.AddComponent<Piece>();
			}
			val2.m_name = tier.NameToken;
			val2.m_description = tier.DescriptionToken;
			val2.m_canBeRemoved = true;
			val2.m_category = (PieceCategory)0;
			HoverText val3 = val.GetComponent<HoverText>();
			if (!Object.op_Implicit((Object)(object)val3))
			{
				val3 = val.AddComponent<HoverText>();
			}
			val3.m_text = tier.NameToken;
			if (!string.IsNullOrEmpty(tier.PlaceEffectSource))
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(tier.PlaceEffectSource);
				Piece val4 = default(Piece);
				if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Piece>(ref val4) && val4.m_placeEffect != null)
				{
					val2.m_placeEffect = val4.m_placeEffect;
				}
			}
			if (!Object.op_Implicit((Object)(object)val2.m_icon))
			{
				GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_groundtorch_mist");
				Piece val5 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<Piece>() : null);
				if (Object.op_Implicit((Object)(object)val5) && Object.op_Implicit((Object)(object)val5.m_icon))
				{
					val2.m_icon = val5.m_icon;
				}
			}
			try
			{
				Sprite val6 = RenderManager.Instance.Render(val);
				if (Object.op_Implicit((Object)(object)val6))
				{
					val2.m_icon = val6;
					Plugin.LogDebug("[PieceManager] Generated custom 3D snapshot icon for '" + prefabName + "'.");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[PieceManager] Failed to render 3D icon for '" + prefabName + "': " + ex.Message));
			}
			WearNTear val7 = val.GetComponent<WearNTear>();
			if (!Object.op_Implicit((Object)(object)val7))
			{
				val7 = val.AddComponent<WearNTear>();
			}
			val7.m_noRoofWear = false;
			val7.m_noSupportWear = true;
			if (!string.IsNullOrEmpty(tier.WearEffectSource))
			{
				GameObject prefab3 = PrefabManager.Instance.GetPrefab(tier.WearEffectSource);
				WearNTear val8 = default(WearNTear);
				if (Object.op_Implicit((Object)(object)prefab3) && prefab3.TryGetComponent<WearNTear>(ref val8))
				{
					val7.m_hitEffect = val8.m_hitEffect;
					val7.m_destroyedEffect = val8.m_destroyedEffect;
				}
			}
			int num = LayerMask.NameToLayer("piece");
			if (num >= 0)
			{
				val.layer = num;
				Collider[] componentsInChildren3 = val.GetComponentsInChildren<Collider>(true);
				foreach (Collider val9 in componentsInChildren3)
				{
					if (!val9.isTrigger)
					{
						((Component)val9).gameObject.layer = num;
					}
				}
			}
			EnsurePieceCollider(val, tier.ColliderCenter, tier.ColliderSize);
			EnsurePlayerBase(val);
			WispPieceManager.ApplyProperties(val, prefabName);
			WispTorchColorController wispTorchColorController = default(WispTorchColorController);
			if (!val.TryGetComponent<WispTorchColorController>(ref wispTorchColorController))
			{
				val.AddComponent<WispTorchColorController>();
			}
			PieceConfig val10 = new PieceConfig();
			val10.Name = tier.NameToken;
			val10.Description = tier.DescriptionToken;
			val10.PieceTable = PieceTables.Hammer;
			val10.Category = PieceCategories.Misc;
			val10.Usage = new string[2]
			{
				PieceUsages.Lighting,
				PieceUsages.Misc
			};
			val10.CraftingStation = tier.CraftingStation.Value;
			val10.Requirements = requirements;
			PieceConfig val11 = val10;
			CustomPiece val12 = new CustomPiece(val, true, val11);
			PieceManager.Instance.AddPiece(val12);
			Plugin.LogDebug("[PieceManager] Successfully registered CustomPiece '" + prefabName + "' in Hammer (Category=Misc, Usages=Lighting,Misc).");
		}

		private static void EnsurePieceCollider(GameObject targetGameObject, in Vector3 center, in Vector3 size)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider val = targetGameObject.GetComponent<BoxCollider>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = targetGameObject.AddComponent<BoxCollider>();
			}
			int num = LayerMask.NameToLayer("piece");
			if (num >= 0)
			{
				((Component)val).gameObject.layer = num;
			}
			((Collider)val).isTrigger = false;
			val.center = center;
			val.size = size;
		}

		private static void EnsurePlayerBase(GameObject targetGameObject)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			Transform val = targetGameObject.transform.Find("PlayerBase");
			GameObject val2;
			if (Object.op_Implicit((Object)(object)val))
			{
				val2 = ((Component)val).gameObject;
			}
			else
			{
				val2 = new GameObject("PlayerBase");
				val2.transform.SetParent(targetGameObject.transform, false);
				val2.transform.localPosition = Vector3.zero;
				val2.transform.localRotation = Quaternion.identity;
			}
			int num = LayerMask.NameToLayer("character_trigger");
			if (num >= 0)
			{
				val2.layer = num;
			}
			SphereCollider val3 = val2.GetComponent<SphereCollider>();
			if (!Object.op_Implicit((Object)(object)val3))
			{
				val3 = val2.AddComponent<SphereCollider>();
			}
			((Collider)val3).isTrigger = true;
			val3.center = Vector3.zero;
			EffectArea val4 = val2.GetComponent<EffectArea>();
			if (!Object.op_Implicit((Object)(object)val4))
			{
				val4 = val2.AddComponent<EffectArea>();
			}
			val4.m_type = (Type)4;
			Plugin.LogDebug($"[PieceManager] Configured PlayerBase on '{((Object)targetGameObject).name}' (layer: {val2.layer}).");
		}
	}
}
namespace WispTorchHeeler.Patches
{
	public static class DemisterPatches
	{
		[HarmonyPatch(typeof(ZNetView), "Awake")]
		public static class ZNetView_Awake_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(ZNetView __instance)
			{
				WispDemisterColorController.AttachIfDemisterBall(__instance);
			}
		}

		[HarmonyPatch(typeof(SE_Demister), "Setup")]
		public static class SE_Demister_Setup_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(SE_Demister __instance)
			{
				WispDemisterIdleMotion.OnSetup(__instance);
			}
		}

		[HarmonyPatch(typeof(SE_Demister), "UpdateStatusEffect")]
		public static class SE_Demister_UpdateStatusEffect_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(SE_Demister __instance)
			{
				WispDemisterColorController.PinBallToHip(__instance);
			}
		}
	}
	public static class PainterPatches
	{
		[HarmonyPatch(typeof(HoverText), "GetHoverText")]
		public static class HoverText_GetHoverText_Patch
		{
			[HarmonyPostfix]
			public static void Postfix(HoverText __instance, ref string __result)
			{
				TorchPainter.AppendPaintPrompt(__instance, ref __result);
			}
		}
	}
}
namespace WispTorchHeeler.Painter
{
	public static class TorchPainter
	{
		private static int s_baseRaycastMask = -1;

		private static readonly string[] s_feedbackPrefabNames = new string[3] { "sfx_wisp_spawn", "vfx_wisp_spawn", "sfx_build_hammer_metal" };

		private static int GetBaseRaycastMask()
		{
			if (s_baseRaycastMask == -1)
			{
				s_baseRaycastMask = LayerMask.GetMask(new string[4] { "piece", "piece_nonsolid", "Default", "static_solid" });
			}
			return s_baseRaycastMask;
		}

		public static void TryPaintOrReset(bool isReset)
		{
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			WispTorchColorController wispTorchColorController = null;
			if (Object.op_Implicit((Object)(object)localPlayer.m_hovering))
			{
				wispTorchColorController = ResolveControllerFromObject(localPlayer.m_hovering);
				if (Object.op_Implicit((Object)(object)wispTorchColorController))
				{
					Plugin.LogDebug("[TorchPainter] Targeted torch via native hover: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.");
				}
			}
			if (!Object.op_Implicit((Object)(object)wispTorchColorController) && Object.op_Implicit((Object)(object)localPlayer.m_hoveringPiece))
			{
				wispTorchColorController = ResolveControllerFromObject(((Component)localPlayer.m_hoveringPiece).gameObject);
				if (Object.op_Implicit((Object)(object)wispTorchColorController))
				{
					Plugin.LogDebug("[TorchPainter] Targeted torch via hovering piece: '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.");
				}
			}
			if (!Object.op_Implicit((Object)(object)wispTorchColorController))
			{
				float value = ModConfig.PainterRaycastDistance.Value;
				int layerMask = GetBaseRaycastMask() | localPlayer.m_interactMask;
				Camera val = ((Object.op_Implicit((Object)(object)GameCamera.instance) && Object.op_Implicit((Object)(object)GameCamera.instance.m_camera)) ? GameCamera.instance.m_camera : (Object.op_Implicit((Object)(object)Camera.main) ? Camera.main : (Object.op_Implicit((Object)(object)GameCamera.instance) ? ((Component)GameCamera.instance).GetComponent<Camera>() : null)));
				if (Object.op_Implicit((Object)(object)val))
				{
					wispTorchColorController = RaycastForController(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), value, layerMask);
				}
				if (!Object.op_Implicit((Object)(object)wispTorchColorController))
				{
					wispTorchColorController = RaycastForController(new Ray(((Character)localPlayer).GetEyePoint(), ((Character)localPlayer).GetLookDir()), value, layerMask);
				}
			}
			if (!Object.op_Implicit((Object)(object)wispTorchColorController))
			{
				Plugin.LogDebug("[TorchPainter] No valid wisp torch/lamp targeted.");
				return;
			}
			if (Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist" && !ModConfig.AffectNativeMistTorches.Value)
			{
				Plugin.LogDebug("[TorchPainter] Painting native mist torches is disabled in config.");
				return;
			}
			if (!ModConfig.AllowTorchPainting.Value)
			{
				Plugin.LogDebug("[TorchPainter] Painting is globally disabled by server policy.");
				if (Object.op_Implicit((Object)(object)MessageHud.instance))
				{
					MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_disabled"), 0, (Sprite)null, false, true);
				}
				return;
			}
			Vector3 position = ((Component)wispTorchColorController).transform.position;
			if (!ModConfig.AllowPaintingInProtectedWards.Value && !PrivateArea.CheckAccess(position, 0f, true, false))
			{
				bool flag = ((ConditionalConfigSync)ModConfig.ConfigSync).IsAdmin || SynchronizationManager.Instance.PlayerIsAdmin;
				if (!(ModConfig.AdminBypassesWardCheck.Value && flag))
				{
					Plugin.LogDebug("[TorchPainter] Ward access denied. Painting blocked.");
					if (Object.op_Implicit((Object)(object)MessageHud.instance))
					{
						MessageHud.instance.ShowMessage((MessageType)2, ModLocalization.Localize("$msg_cantpaint_warded"), 0, (Sprite)null, false, true);
					}
					return;
				}
				Plugin.LogDebug("[TorchPainter] Ward access denied, but player is admin and AdminBypassesWardCheck is enabled. Access granted.");
			}
			ZNetView component = ((Component)wispTorchColorController).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				Plugin.Log.LogWarning((object)"[TorchPainter] Target piece has no valid ZNetView.");
				return;
			}
			string text;
			string text2;
			if (isReset)
			{
				text = string.Empty;
				wispTorchColorController.RefreshColor();
				text2 = ModLocalization.Localize("$msg_torch_reset");
			}
			else
			{
				Color value2 = ModConfig.PainterColor.Value;
				bool value3 = ModConfig.EnableAlphaCustomization.Value;
				value2.a = (value3 ? Mathf.Clamp(value2.a, 0.15f, 1f) : 1f);
				text = (value3 ? ColorUtility.ToHtmlStringRGBA(value2) : ColorUtility.ToHtmlStringRGB(value2));
				wispTorchColorController.ApplyColor(value2);
				text2 = ModLocalization.Localize("$msg_torch_painted", "#" + text);
			}
			component.ClaimOwnership();
			component.GetZDO().Set(WispTorchColorController.ColorKeyHash, text);
			component.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text });
			if (ModConfig.ShowPainterFeedback.Value && Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false, true);
			}
			PlayFeedbackEffect(position);
			Plugin.LogDebug(isReset ? ("[TorchPainter] Reset color on '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'.") : ("[TorchPainter] Applied color #" + text + " to '" + ((Object)((Component)wispTorchColorController).gameObject).name + "'."));
		}

		public static void AppendPaintPrompt(HoverText hoverText, ref string displayText)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.AllowTorchPainting.Value)
			{
				return;
			}
			WispTorchColorController wispTorchColorController = ResolveControllerFromObject(((Component)hoverText).gameObject);
			if (Object.op_Implicit((Object)(object)wispTorchColorController) && (!(Utils.GetPrefabName(((Component)wispTorchColorController).gameObject) == "piece_groundtorch_mist") || ModConfig.AffectNativeMistTorches.Value))
			{
				string text = ((object)ModConfig.PaintTorchHotkey.Value/*cast due to .constrained prefix*/).ToString();
				string text2 = ((object)ModConfig.ResetTorchHotkey.Value/*cast due to .constrained prefix*/).ToString();
				string text3 = ColorUtility.ToHtmlStringRGB(ModConfig.PainterColor.Value);
				string text4 = ModLocalization.Localize("$prompt_torch_paint");
				string text5 = ModLocalization.Localize("$prompt_torch_reset");
				if (string.IsNullOrEmpty(displayText))
				{
					displayText = Localization.instance.Localize(hoverText.m_text);
				}
				displayText = displayText + "\n[<color=#" + text3 + "><b>" + text + "</b></color>] " + text4 + "\n[<color=yellow><b>" + text2 + "</b></color>] " + text5;
			}
		}

		private static WispTorchColorController? ResolveControllerFromObject(GameObject targetGameObject)
		{
			if (!Object.op_Implicit((Object)(object)targetGameObject))
			{
				return null;
			}
			WispTorchColorController componentInParent = targetGameObject.GetComponentInParent<WispTorchColorController>();
			if (!Object.op_Implicit((Object)(object)componentInParent))
			{
				return targetGameObject.GetComponentInChildren<WispTorchColorController>();
			}
			return componentInParent;
		}

		private static WispTorchColorController? RaycastForController(Ray ray, float maxDistance, int layerMask)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit[] array = Physics.RaycastAll(ray, maxDistance, layerMask);
			if (array == null || array.Length == 0)
			{
				return null;
			}
			Array.Sort(array, (RaycastHit firstHit, RaycastHit secondHit) => ((RaycastHit)(ref firstHit)).distance.CompareTo(((RaycastHit)(ref secondHit)).distance));
			RaycastHit[] array2 = array;
			for (int num = 0; num < array2.Length; num++)
			{
				RaycastHit val = array2[num];
				if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider))
				{
					WispTorchColorController wispTorchColorController = ResolveControllerFromObject(((Component)((RaycastHit)(ref val)).collider).gameObject);
					if (Object.op_Implicit((Object)(object)wispTorchColorController))
					{
						Plugin.LogDebug($"[TorchPainter] Targeted torch via raycast ({((RaycastHit)(ref val)).distance:F1}m): '{((Object)((Component)wispTorchColorController).gameObject).name}'.");
						return wispTorchColorController;
					}
				}
			}
			return null;
		}

		private static void PlayFeedbackEffect(Vector3 position)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			string[] array = s_feedbackPrefabNames;
			foreach (string text in array)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if (Object.op_Implicit((Object)(object)prefab))
				{
					Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
					break;
				}
			}
		}
	}
	public class TorchPainterInput : MonoBehaviour
	{
		private void Update()
		{
			if (ModConfig.EnableMod.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				if (ModConfig.ButtonResetConfig != null && ZInput.GetButtonDown(ModConfig.ButtonResetConfig.Name))
				{
					TorchPainter.TryPaintOrReset(isReset: true);
				}
				else if (ModConfig.ButtonPaintConfig != null && ZInput.GetButtonDown(ModConfig.ButtonPaintConfig.Name))
				{
					TorchPainter.TryPaintOrReset(isReset: false);
				}
			}
		}
	}
}
namespace WispTorchHeeler.Localization
{
	public static class ModLocalization
	{
		public const string TokenPieceTorchLg = "$piece_wisptorch_heeler_lg";

		public const string TokenPieceTorchLgDesc = "$piece_wisptorch_heeler_lg_description";

		public const string TokenPieceSmallLamp = "$piece_wisplamp_heeler";

		public const string TokenPieceSmallLampDesc = "$piece_wisplamp_heeler_description";

		public const string TokenPieceLampLg = "$piece_wisplamp_heeler_lg";

		public const string TokenPieceLampLgDesc = "$piece_wisplamp_heeler_lg_description";

		public const string TokenPieceLampGrand = "$piece_wisplamp_heeler_grand";

		public const string TokenPieceLampGrandDesc = "$piece_wisplamp_heeler_grand_description";

		public const string TokenMsgPainted = "$msg_torch_painted";

		public const string TokenMsgReset = "$msg_torch_reset";

		public const string TokenMsgCantPaintWarded = "$msg_cantpaint_warded";

		public const string TokenMsgCantPaintDisabled = "$msg_cantpaint_disabled";

		public const string TokenPromptPaint = "$prompt_torch_paint";

		public const string TokenPromptReset = "$prompt_torch_reset";

		public static void Initialize()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "$piece_wisptorch_heeler_lg", "Large Wisp Torch" },
				{ "$piece_wisptorch_heeler_lg_description", "A large wisp torch that clears mist across a wide area." },
				{ "$piece_wisplamp_heeler", "Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_description", "A sturdy dwarven demister lamp that clears mist across a wide area." },
				{ "$piece_wisplamp_heeler_lg", "Large Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_lg_description", "An advanced dwarven demister with an expanded core that clears mist across a wide radius." },
				{ "$piece_wisplamp_heeler_grand", "Grand Dvergr Wisp Lamp" },
				{ "$piece_wisplamp_heeler_grand_description", "A colossal, reinforced dwarven demister monument that clears mist across a vast perimeter." },
				{ "$msg_torch_painted", "Wisp piece painted: {0}" },
				{ "$msg_torch_reset", "Wisp piece color reset to default." },
				{ "$msg_cantpaint_warded", "Piece is protected by a ward." },
				{ "$msg_cantpaint_disabled", "Painting wisp pieces is disabled on this server." },
				{ "$prompt_torch_paint", "Paint Light" },
				{ "$prompt_torch_reset", "Reset Color" }
			});
			Plugin.LogDebug("[ModLocalization] Default English localizations registered.");
		}

		public static string Localize(string token, params string[] arguments)
		{
			string text = LocalizationManager.Instance.GetLocalization().TryTranslate(token);
			if (arguments != null && arguments.Length != 0)
			{
				text = string.Format(text, arguments);
			}
			return text;
		}
	}
}
namespace WispTorchHeeler.Lighting
{
	public class WispDemisterColorController : MonoBehaviour
	{
		public static readonly int DemisterColorHash = StringExtensionMethods.GetStableHashCode("wisptorch_demister_color");

		public static readonly int DemisterMountHash = StringExtensionMethods.GetStableHashCode("wisptorch_demister_mount");

		public static readonly KeyValuePair<int, int> DemisterWearerHash = ZDO.GetHashZDOID("wisptorch_demister_wearer");

		private static readonly int s_demisterBallHash = StringExtensionMethods.GetStableHashCode("demister_ball");

		public static readonly HashSet<WispDemisterColorController> Instances = new HashSet<WispDemisterColorController>();

		private ZNetView _networkView;

		private readonly WispVisualApplicator _visualApplicator = new WispVisualApplicator();

		private readonly WispDemisterHipMount _hipMount = new WispDemisterHipMount();

		private Coroutine? _remoteSyncCoroutine;

		private string _lastRemoteHexColor = string.Empty;

		public ZNetView? NetView => _networkView;

		private void Awake()
		{
			_networkView = ((Component)this).GetComponent<ZNetView>();
			_visualApplicator.Initialize(((Component)this).gameObject);
			_hipMount.Initialize(((Component)this).gameObject);
		}

		private void OnEnable()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Instances.Add(this);
			if (_networkView.IsValid() && _networkView.IsOwner())
			{
				_networkView.GetZDO().Set(DemisterWearerHash, ((Character)Player.m_localPlayer).GetZDOID());
				SyncLocalPlayerDemisterState();
			}
			RefreshMount();
			RefreshColor();
		}

		private void OnDisable()
		{
			Instances.Remove(this);
			if (_remoteSyncCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_remoteSyncCoroutine);
				_remoteSyncCoroutine = null;
			}
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
			if (_remoteSyncCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_remoteSyncCoroutine);
				_remoteSyncCoroutine = null;
			}
			_visualApplicator.CleanupRuntimeMaterials();
			_hipMount.DestroyVisual();
		}

		public bool IsRemoteWisplight()
		{
			if (_networkView.IsValid())
			{
				return !_networkView.IsOwner();
			}
			return false;
		}

		private void EnsureRemoteSyncCoroutine()
		{
			if (_remoteSyncCoroutine == null && IsRemoteWisplight())
			{
				_remoteSyncCoroutine = ((MonoBehaviour)this).StartCoroutine(MonitorRemoteZDOState());
			}
		}

		private IEnumerator MonitorRemoteZDOState()
		{
			WaitForSeconds waitInterval = new WaitForSeconds(1.5f);
			while (IsRemoteWisplight() && ModConfig.EnableMod.Value && ModConfig.EnableDemisterCustomization.Value)
			{
				string text = QueryRemoteHexColor();
				if (RefreshMount() || text != _lastRemoteHexColor)
				{
					_lastRemoteHexColor = text;
					RefreshColor();
				}
				yield return waitInterval;
			}
			_remoteSyncCoroutine = null;
		}

		private string QueryRemoteHexColor()
		{
			if (_networkView.IsValid())
			{
				return _networkView.GetZDO().GetString(DemisterColorHash, string.Empty);
			}
			return string.Empty;
		}

		public static void AttachIfDemisterBall(ZNetView netView)
		{
			WispDemisterColorController wispDemisterColorController = default(WispDemisterColorController);
			if (ModConfig.EnableMod.Value && netView.IsValid() && netView.GetZDO().GetPrefab() == s_demisterBallHash && !((Component)netView).TryGetComponent<WispDemisterColorController>(ref wispDemisterColorController))
			{
				((Component)netView).gameObject.AddComponent<WispDemisterColorController>();
				Plugin.LogDebug("[DemisterPatch] Attached WispDemisterColorController to networked Wisplight '" + ((Object)netView).name + "'.");
			}
		}

		public static void Initialize()
		{
			Action syncAndRefresh = delegate
			{
				SyncLocalPlayerDemisterState();
				RefreshAll();
			};
			ModConfig.EnableMod.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.EnableDemisterCustomization.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.DemisterColor.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.DemisterEnableAlpha.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.DemisterSyncMultiplayer.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.DemisterMountStyle.SettingChanged += delegate
			{
				syncAndRefresh();
			};
			ModConfig.DemisterLightIntensityMultiplier.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.DemisterLightRangeMultiplier.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.DemisterEmissionIntensityMultiplier.SettingChanged += delegate
			{
				RefreshAll();
			};
		}

		public void RefreshColor()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.EnableDemisterCustomization.Value)
			{
				if (_remoteSyncCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_remoteSyncCoroutine);
					_remoteSyncCoroutine = null;
				}
				RestoreOriginalVisuals();
				return;
			}
			EnsureRemoteSyncCoroutine();
			if (!TryResolveColor(out var targetColor))
			{
				RestoreOriginalVisuals();
				return;
			}
			bool num = IsRemoteWisplight();
			float value = ((!num) ? ModConfig.DemisterLightIntensityMultiplier.Value : 1f);
			float value2 = ((!num) ? ModConfig.DemisterLightRangeMultiplier.Value : 1f);
			float emissionMultiplier = ((!num) ? ModConfig.DemisterEmissionIntensityMultiplier.Value : 1f);
			bool allowAlpha = num || ModConfig.DemisterEnableAlpha.Value;
			_visualApplicator.ApplyColor(targetColor, value, value2, emissionMultiplier, allowAlpha);
			WispDemisterHipVisual visual = _hipMount.Visual;
			if (Object.op_Implicit((Object)(object)visual))
			{
				visual.Applicator.ApplyColor(targetColor, value, value2, emissionMultiplier, allowAlpha);
			}
		}

		private void RestoreOriginalVisuals()
		{
			_visualApplicator.RestoreOriginalColors();
			WispDemisterHipVisual visual = _hipMount.Visual;
			if (Object.op_Implicit((Object)(object)visual))
			{
				visual.Applicator.RestoreOriginalColors();
			}
		}

		private (WornDemisterMount Mount, Player? Wearer) ResolveMount()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.EnableDemisterCustomization.Value || !_networkView.IsValid())
			{
				return (Mount: WornDemisterMount.Floating, Wearer: null);
			}
			ZDO zDO = _networkView.GetZDO();
			GameObject val = ZNetScene.instance.FindInstance(zDO.GetZDOID(DemisterWearerHash));
			Player val2 = default(Player);
			Player item = ((Object.op_Implicit((Object)(object)val) && val.TryGetComponent<Player>(ref val2)) ? val2 : null);
			return (Mount: (WornDemisterMount)zDO.GetInt(DemisterMountHash, 0), Wearer: item);
		}

		private bool RefreshMount()
		{
			var (wornDemisterMount, val) = ResolveMount();
			if (wornDemisterMount == WornDemisterMount.Floating || !Object.op_Implicit((Object)(object)val))
			{
				return _hipMount.Detach();
			}
			return _hipMount.Attach(wornDemisterMount, val);
		}

		public static void PinBallToHip(SE_Demister demisterEffect)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			GameObject ballInstance = demisterEffect.m_ballInstance;
			WispDemisterColorController wispDemisterColorController = default(WispDemisterColorController);
			if (ballInstance.TryGetComponent<WispDemisterColorController>(ref wispDemisterColorController))
			{
				WispDemisterHipVisual visual = wispDemisterColorController._hipMount.Visual;
				if (Object.op_Implicit((Object)(object)visual))
				{
					ballInstance.transform.position = visual.Anchor.position;
					demisterEffect.m_ballVel = Vector3.zero;
				}
			}
		}

		public bool TryResolveColor(out Color targetColor)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.EnableDemisterCustomization.Value)
			{
				targetColor = WispVisualApplicator.NativeFallbackColor;
				return false;
			}
			if (IsRemoteWisplight())
			{
				return WispVisualApplicator.TryParseColorHex(_lastRemoteHexColor = QueryRemoteHexColor(), out targetColor);
			}
			targetColor = ModConfig.DemisterColor.Value;
			return true;
		}

		public Color ResolveColor()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!TryResolveColor(out var targetColor))
			{
				return WispVisualApplicator.NativeFallbackColor;
			}
			return targetColor;
		}

		public static void SyncLocalPlayerDemisterState()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			string targetHexColor = ((!ModConfig.EnableMod.Value || !ModConfig.EnableDemisterCustomization.Value || !ModConfig.DemisterSyncMultiplayer.Value) ? string.Empty : WispVisualApplicator.FormatColorHex(ModConfig.DemisterColor.Value, ModConfig.DemisterEnableAlpha.Value));
			WornDemisterMount targetMount = ((ModConfig.EnableMod.Value && ModConfig.EnableDemisterCustomization.Value) ? ModConfig.DemisterMountStyle.Value : WornDemisterMount.Floating);
			foreach (WispDemisterColorController instance in Instances)
			{
				if (Object.op_Implicit((Object)(object)instance))
				{
					instance.SyncOwnedOrbState(targetHexColor, targetMount);
				}
			}
		}

		private void SyncOwnedOrbState(string targetHexColor, WornDemisterMount targetMount)
		{
			if (_networkView.IsValid() && _networkView.IsOwner())
			{
				ZDO zDO = _networkView.GetZDO();
				if (zDO.GetString(DemisterColorHash, string.Empty) != targetHexColor)
				{
					zDO.Set(DemisterColorHash, targetHexColor);
					Plugin.LogDebug("[DemisterSync] Synced demister color #" + targetHexColor + " to ball ZDO.");
				}
				if (zDO.GetInt(DemisterMountHash, 0) != (int)targetMount)
				{
					zDO.Set(DemisterMountHash, (int)targetMount, false);
					Plugin.LogDebug($"[DemisterSync] Synced demister mount style {targetMount} to ball ZDO.");
				}
			}
		}

		public static void RefreshAll()
		{
			foreach (WispDemisterColorController instance in Instances)
			{
				if (Object.op_Implicit((Object)(object)instance))
				{
					instance.RefreshMount();
					instance.RefreshColor();
				}
			}
		}
	}
	public class WispDemisterHipMount
	{
		private static readonly string[] s_ballVisualPaths = new string[3] { "demister_ball", "effects/flame", "effects/Point light" };

		private GameObject[] _ballVisuals = Array.Empty<GameObject>();

		private WispDemisterHipVisual? _hipVisual;

		private WornDemisterMount _activeMount;

		public WispDemisterHipVisual? Visual => _hipVisual;

		public void Initialize(GameObject ballRoot)
		{
			_ballVisuals = s_ballVisualPaths.Select((string path) => ((Component)ballRoot.transform.Find(path)).gameObject).ToArray();
		}

		public bool Attach(WornDemisterMount mount, Player wearer)
		{
			//IL_006a: 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)
			if (mount == _activeMount && Object.op_Implicit((Object)(object)_hipVisual))
			{
				return false;
			}
			WispDemisterHipVisual template = WispDemisterHipTemplates.GetTemplate(mount);
			if (!Object.op_Implicit((Object)(object)template))
			{
				return Detach();
			}
			DestroyVisual();
			WispDemisterHipVisual wispDemisterHipVisual = Object.Instantiate<WispDemisterHipVisual>(template);
			((Component)wispDemisterHipVisual).gameObject.SetActive(true);
			VisEquipment.CleanupInstance(((Component)wispDemisterHipVisual).gameObject);
			Transform transform = ((Component)wispDemisterHipVisual).transform;
			transform.SetParent(((Humanoid)wearer).m_visEquipment.m_backTool);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			_hipVisual = wispDemisterHipVisual;
			_activeMount = mount;
			GameObject[] ballVisuals = _ballVisuals;
			for (int i = 0; i < ballVisuals.Length; i++)
			{
				ballVisuals[i].SetActive(false);
			}
			Plugin.LogDebug($"[DemisterHipMount] Attached {mount} visual to '{wearer.GetPlayerName()}'.");
			return true;
		}

		public bool Detach()
		{
			DestroyVisual();
			if (_activeMount == WornDemisterMount.Floating)
			{
				return false;
			}
			_activeMount = WornDemisterMount.Floating;
			GameObject[] ballVisuals = _ballVisuals;
			for (int i = 0; i < ballVisuals.Length; i++)
			{
				ballVisuals[i].SetActive(true);
			}
			return true;
		}

		public void DestroyVisual()
		{
			if (Object.op_Implicit((Object)(object)_hipVisual))
			{
				Object.Destroy((Object)(object)((Component)_hipVisual).gameObject);
			}
			_hipVisual = null;
		}
	}
	public static class WispDemisterHipTemplates
	{
		private const string OrbTemplateName = "wisptorch_hip_orb";

		private const string CageTemplateName = "wisptorch_hip_cage";

		private const string DemisterBallPrefab = "demister_ball";

		private const string OrbModelChild = "demister_ball";

		private const string OrbEffectsChild = "effects";

		private const string LanternItemPrefab = "Lantern";

		private const string HolsterVisualChild = "attach_back";

		private const string LanternModelChild = "default";

		private const string CageMaterialName = "HipWispLantern_mat";

		private const string CageAlbedoResource = "HipWispLantern_d.png";

		private const string CageEmissionResource = "HipWispLantern_e.png";

		private static readonly int s_mainTexId = Shader.PropertyToID("_MainTex");

		private static readonly int s_emissionMapId = Shader.PropertyToID("_EmissionMap");

		private static readonly Vector3 s_cageOffset = new Vector3(-0.22f, -0.1f, 0.1f);

		private static readonly Vector3 s_orbOffset = new Vector3(-0.18f, -0.12f, 0.03f);

		private static readonly Quaternion s_cageRotation = Quaternion.Euler(306.55f, 215.5f, 117.64f);

		private const float CageScale = 0.25f;

		private const float HipLightIntensityBoost = 1.1666666f;

		private static WispDemisterHipVisual? s_orbTemplate;

		private static WispDemisterHipVisual? s_cageTemplate;

		public static void Initialize()
		{
			PrefabManager.OnVanillaPrefabsAvailable += CreateTemplates;
		}

		public static WispDemisterHipVisual? GetTemplate(WornDemisterMount mount)
		{
			return mount switch
			{
				WornDemisterMount.HipOrb => s_orbTemplate, 
				WornDemisterMount.HipCage => s_cageTemplate, 
				_ => null, 
			};
		}

		private static void CreateTemplates()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= CreateTemplates;
			s_orbTemplate = CreateOrbTemplate();
			s_cageTemplate = CreateCageTemplate();
		}

		private static WispDemisterHipVisual? CreateOrbTemplate()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("wisptorch_hip_orb", "demister_ball");
			if (!Object.op_Implicit((Object)(object)val))
			{
				Plugin.Log.LogWarning((object)"[HipTemplates] Failed to clone 'demister_ball'. The HipOrb mount style is unavailable.");
				return null;
			}
			DestroyComponents<Demister>(val);
			DestroyComponents<ParticleSystemForceField>(val);
			DestroyComponents<ZSyncTransform>(val);
			DestroyComponents<ZNetView>(val);
			Transform val2 = val.transform.Find("demister_ball");
			val2.localPosition = s_orbOffset;
			val.transform.Find("effects").localPosition = s_orbOffset;
			WispDemisterHipVisual result = FinishTemplate(val, val2);
			Plugin.LogDebug("[HipTemplates] Created hip orb template 'wisptorch_hip_orb'.");
			return result;
		}

		private static WispDemisterHipVisual? CreateCageTemplate()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("Lantern");
			Transform val = (Object.op_Implicit((Object)(object)prefab) ? prefab.transform.Find("attach_back") : null);
			GameObject val2 = (Object.op_Implicit((Object)(object)val) ? PrefabManager.Instance.CreateClonedPrefab("wisptorch_hip_cage", ((Component)val).gameObject) : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Plugin.Log.LogWarning((object)"[HipTemplates] Failed to clone 'Lantern/attach_back'. The HipCage mount style is unavailable.");
				return null;
			}
			MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren)
			{
				((Renderer)obj).sharedMaterial = CreateCageMaterial(((Renderer)obj).sharedMaterial);
			}
			WispVisualApplicator.EmissionOnlyMaterialNames.Add("HipWispLantern_mat");
			Transform val3 = val2.transform.Find("default");
			val3.localPosition = s_cageOffset;
			val3.localRotation = s_cageRotation;
			val3.localScale = Vector3.one * 0.25f;
			WispDemisterHipVisual result = FinishTemplate(val2, val3);
			Plugin.LogDebug("[HipTemplates] Created hip cage template 'wisptorch_hip_cage'.");
			return result;
		}

		private static Material CreateCageMaterial(Material donorMaterial)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0052: Expected O, but got Unknown
			Material val = new Material(donorMaterial)
			{
				name = "HipWispLantern_mat"
			};
			val.SetTexture(s_mainTexId, (Texture)(object)LoadEmbeddedTexture("HipWispLantern_d.png", donorMaterial.GetTexture(s_mainTexId)));
			val.SetTexture(s_emissionMapId, (Texture)(object)LoadEmbeddedTexture("HipWispLantern_e.png", donorMaterial.GetTexture(s_emissionMapId)));
			return val;
		}

		private static Texture2D LoadEmbeddedTexture(string resourceName, Texture donorTexture)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(WispDemisterHipTemplates).Assembly.GetManifestResourceStream(resourceName);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D obj = AssetUtils.LoadImage(memoryStream.ToArray());
			((Object)obj).name = Path.GetFileNameWithoutExtension(resourceName);
			((Texture)obj).filterMode = donorTexture.filterMode;
			((Texture)obj).wrapMode = donorTexture.wrapMode;
			((Texture)obj).anisoLevel = donorTexture.anisoLevel;
			return obj;
		}

		private static WispDemisterHipVisual FinishTemplate(GameObject template, Transform anchor)
		{
			DestroyComponents<AudioSource>(template);
			Light[] componentsInChildren = template.GetComponentsInChildren<Light>(true);
			foreach (Light obj in componentsInChildren)
			{
				obj.intensity *= 1.1666666f;
			}
			WispDemisterHipVisual wispDemisterHipVisual = template.AddComponent<WispDemisterHipVisual>();
			wispDemisterHipVisual.SetAnchor(anchor);
			return wispDemisterHipVisual;
		}

		private static void DestroyComponents<T>(GameObject root) where T : Component
		{
			T[] componentsInChildren = root.GetComponentsInChildren<T>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}
	}
	public class WispDemisterHipVisual : MonoBehaviour
	{
		[SerializeField]
		private Transform _anchor;

		public WispVisualApplicator Applicator { get; } = new WispVisualApplicator();

		public Transform Anchor => _anchor;

		public void SetAnchor(Transform anchor)
		{
			_anchor = anchor;
		}

		private void Awake()
		{
			Applicator.Initialize(((Component)this).gameObject);
		}

		private void OnDestroy()
		{
			Applicator.CleanupRuntimeMaterials();
		}
	}
	public static class WispDemisterIdleMotion
	{
		private record struct IdleMotion(float NoiseSpeed, float RotationSpeed, float NoiseDistance, float NoiseDistanceInterior);

		private static readonly Dictionary<int, IdleMotion> s_baseMotion = new Dictionary<int, IdleMotion>();

		public static void Initialize()
		{
			ModConfig.EnableMod.SettingChanged += delegate
			{
				ApplyToLocalPlayer();
			};
			ModConfig.EnableDemisterCustomization.SettingChanged += delegate
			{
				ApplyToLocalPlayer();
			};
			ModConfig.DemisterIdleSpeedMultiplier.SettingChanged += delegate
			{
				ApplyToLocalPlayer();
			};
			ModConfig.DemisterIdleRadiusMultiplier.SettingChanged += delegate
			{
				ApplyToLocalPlayer();
			};
		}

		public static void OnSetup(SE_Demister demisterEffect)
		{
			int key = ((StatusEffect)demisterEffect).NameHash();
			if (!s_baseMotion.TryGetValue(key, out var value))
			{
				value = new IdleMotion(demisterEffect.m_noiseSpeed, demisterEffect.m_rotationSpeed, demisterEffect.m_noiseDistance, demisterEffect.m_noiseDistanceInterior);
				s_baseMotion[key] = value;
			}
			Apply(demisterEffect, value);
		}

		private static void ApplyToLocalPlayer()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			foreach (SE_Demister item in ((Character)Player.m_localPlayer).m_seman.m_statusEffects.OfType<SE_Demister>())
			{
				if (s_baseMotion.TryGetValue(((StatusEffect)item).NameHash(), out var value))
				{
					Apply(item, value);
				}
			}
		}

		private static void Apply(SE_Demister demisterEffect, IdleMotion baseMotion)
		{
			int num;
			float num2;
			if (ModConfig.EnableMod.Value)
			{
				num = (ModConfig.EnableDemisterCustomization.Value ? 1 : 0);
				if (num != 0)
				{
					num2 = ModConfig.DemisterIdleSpeedMultiplier.Value;
					goto IL_002d;
				}
			}
			else
			{
				num = 0;
			}
			num2 = 1f;
			goto IL_002d;
			IL_002d:
			float num3 = num2;
			float num4 = ((num != 0) ? ModConfig.DemisterIdleRadiusMultiplier.Value : 1f);
			demisterEffect.m_noiseSpeed = baseMotion.NoiseSpeed * num3;
			demisterEffect.m_rotationSpeed = baseMotion.RotationSpeed * num3;
			demisterEffect.m_noiseDistance = baseMotion.NoiseDistance * num4;
			demisterEffect.m_noiseDistanceInterior = baseMotion.NoiseDistanceInterior * num4;
		}
	}
	public class WispTorchColorController : MonoBehaviour, IPlaced
	{
		public static readonly int ColorKeyHash = StringExtensionMethods.GetStableHashCode("wisptorch_light_color");

		public const float MinimumAlphaFloor = 0.15f;

		public static readonly HashSet<WispTorchColorController> Instances = new HashSet<WispTorchColorController>();

		private ZNetView? _netView;

		private readonly WispVisualApplicator _visualApplicator = new WispVisualApplicator();

		private CircleProjector? _circleProjector;

		private GameObject? _areaMarkerGameObject;

		private void Awake()
		{
			_netView = ((Component)this).GetComponent<ZNetView>();
			_visualApplicator.Initialize(((Component)this).gameObject);
			if (Object.op_Implicit((Object)(object)_netView))
			{
				_netView.Register<string>("WTH_SetColor", (Action<long, string>)RPC_SetColor);
			}
		}

		private void OnEnable()
		{
			Instances.Add(this);
			EnsureAreaMarker();
			RefreshColor();
			RefreshProperties();
		}

		private void Start()
		{
			if (Object.op_Implicit((Object)(object)_netView) && !_netView.IsValid())
			{
				((MonoBehaviour)this).StartCoroutine(WaitForZDOAndInit());
			}
		}

		private IEnumerator WaitForZDOAndInit()
		{
			int maxFrames = 30;
			while (Object.op_Implicit((Object)(object)_netView) && !_netView.IsValid() && maxFrames-- > 0)
			{
				yield return null;
			}
			if (Object.op_Implicit((Object)(object)_netView) && _netView.IsValid())
			{
				RefreshColor();
			}
		}

		public void OnPlaced()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value || !ModConfig.AutoPaintOnPlacement.Value || !ModConfig.AllowTorchPainting.Value)
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
			if (!(prefabName == "piece_groundtorch_mist") || ModConfig.AffectNativeMistTorches.Value)
			{
				if (!Object.op_Implicit((Object)(object)_netView))
				{
					_netView = ((Component)this).GetComponent<ZNetView>();
				}
				if (Object.op_Implicit((Object)(object)_netView) && _netView.IsValid())
				{
					Color value = ModConfig.PainterColor.Value;
					bool value2 = ModConfig.EnableAlphaCustomization.Value;
					string text = WispVisualApplicator.FormatColorHex(value, value2);
					_netView.ClaimOwnership();
					_netView.GetZDO().Set(ColorKeyHash, text);
					_netView.InvokeRPC(ZNetView.Everybody, "WTH_SetColor", new object[1] { text });
					ApplyColor(value);
					Plugin.LogDebug("[PiecePlacement] Auto-painted newly placed '" + prefabName + "' with color #" + text + ".");
				}
			}
		}

		private void OnDisable()
		{
			Instances.Remove(this);
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
			_visualApplicator.CleanupRuntimeMaterials();
		}

		private void RPC_SetColor(long sender, string hexColor)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (WispVisualApplicator.TryParseColorHex(hexColor, out var color))
			{
				ApplyColor(color);
			}
			else
			{
				RefreshColor();
			}
		}

		public void RefreshColor()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.AffectNativeMistTorches.Value && Utils.GetPrefabName(((Component)this).gameObject) == "piece_groundtorch_mist")
			{
				RestoreOriginalColors();
			}
			else
			{
				ApplyColor(ResolveColor());
			}
		}

		public void RestoreOriginalColors()
		{
			_visualApplicator.RestoreOriginalColors();
		}

		public Color ResolveColor()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_netView) && _netView.IsValid() && WispVisualApplicator.TryParseColorHex(_netView.GetZDO().GetString(ColorKeyHash, string.Empty), out var color))
			{
				return color;
			}
			if (!ModConfig.EnforceServerDefaultColor.Value)
			{
				return ModConfig.DefaultLightColor.Value;
			}
			return ModConfig.ServerDefaultLightColor.Value;
		}

		public void ApplyColor(Color color)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			bool value = ModConfig.EnableAlphaCustomization.Value;
			_visualApplicator.ApplyColor(color, null, null, 1f, value);
		}

		public void RefreshProperties()
		{
			string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
			WispPieceManager.ApplyProperties(((Component)this).gameObject, prefabName);
			UpdateAreaMarkerRadius();
		}

		public float GetMistSuppressionRadius()
		{
			ParticleSystemForceField componentInChildren = ((Component)this).GetComponentInChildren<ParticleSystemForceField>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.endRange > 0f)
			{
				return componentInChildren.endRange;
			}
			return 0f;
		}

		public void EnsureAreaMarker()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0076: 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_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)
			if (Object.op_Implicit((Object)(object)_areaMarkerGameObject))
			{
				return;
			}
			GameObject areaMarkerTemplate = WispPieceManager.AreaMarkerTemplate;
			if (Object.op_Implicit((Object)(object)areaMarkerTemplate))
			{
				CircleProjector componentInChildren = default(CircleProjector);
				if (!areaMarkerTemplate.TryGetComponent<CircleProjector>(ref componentInChildren))
				{
					componentInChildren = areaMarkerTemplate.GetComponentInChildren<CircleProjector>();
				}
				if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.m_prefab))
				{
					_areaMarkerGameObject = new GameObject("_MistSuppressionMarker");
					_areaMarkerGameObject.transform.SetParent(((Component)this).transform, false);
					_areaMarkerGameObject.transform.localPosition = Vector3.zero;
					_areaMarkerGameObject.transform.localRotation = Quaternion.identity;
					_circleProjector = _areaMarkerGameObject.AddComponent<CircleProjector>();
					_circleProjector.m_prefab = componentInChildren.m_prefab;
					_circleProjector.m_mask = componentInChildren.m_mask;
					_circleProjector.m_speed = componentInChildren.m_speed;
					_circleProjector.m_turns = 1f;
					UpdateAreaMarkerRadius();
				}
			}
		}

		public void UpdateAreaMarkerRadius()
		{
			if (Object.op_Implicit((Object)(object)_circleProjector))
			{
				float mistSuppressionRadius = GetMistSuppressionRadius();
				if (mistSuppressionRadius <= 0f)
				{
					((Component)_circleProjector).gameObject.SetActive(false);
					return;
				}
				_circleProjector.m_radius = mistSuppressionRadius;
				_circleProjector.m_nrOfSegments = Mathf.Clamp(Mathf.RoundToInt(mistSuppressionRadius * 5f), 24, 250);
				_circleProjector.CreateSegments();
				RefreshMarkerVisibility();
			}
		}

		public void RefreshMarkerVisibility()
		{
			if (Object.op_Implicit((Object)(object)_areaMarkerGameObject))
			{
				bool active = ModConfig.ShowMistSuppressionRadius.Value && GetMistSuppressionRadius() > 0f;
				_areaMarkerGameObject.SetActive(active);
			}
		}

		public static void RefreshAllMarkers()
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if (Object.op_Implicit((Object)(object)instance))
				{
					instance.EnsureAreaMarker();
					instance.RefreshMarkerVisibility();
				}
			}
		}

		public static void RefreshPropertiesForPrefab(string prefabName)
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && Utils.GetPrefabName(((Component)instance).gameObject) == prefabName)
				{
					instance.RefreshProperties();
				}
			}
		}

		public static void Initialize()
		{
			ModConfig.EnableMod.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.DefaultLightColor.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.ServerDefaultLightColor.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.EnforceServerDefaultColor.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.AffectNativeMistTorches.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.EnableAlphaCustomization.SettingChanged += delegate
			{
				RefreshAll();
			};
			ModConfig.ShowMistSuppressionRadius.SettingChanged += delegate
			{
				RefreshAllMarkers();
			};
		}

		public static void RefreshAll()
		{
			foreach (WispTorchColorController instance in Instances)
			{
				if (Object.op_Implicit((Object)(object)instance))
				{
					instance.RefreshColor();
					instance.RefreshProperties();
				}
			}
		}
	}
	public class WispVisualApplicator
	{
		public static readonly Color NativeFallbackColor = new Color(0.706f, 0.941f, 1f, 1f);

		public const float MinimumAlphaFloor = 0.15f;

		private static readonly int s_emissionColor = Shader.PropertyToID("_EmissionColor");

		private static readonly int s_color = Shader.PropertyToID("_Color");

		private static readonly int s_tintColor = Shader.PropertyToID("_TintColor");

		public static readonly HashSet<string> TargetedMaterialNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "demister_ball", "demister_ball_intense", "demister_ball_weak", "demister_ball_v_intense", "demister", "demister_sparcs", "wispysmoke", "slowwispysmoke" };

		public static readonly HashSet<string> EmissionOnlyMaterialNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private Light[] _lights = Array.Empty<Light>();

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

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

		private Color[] _originalLightColors = Array.Empty<Color>();

		private ParticleSystem[] _particleSystems = Array.Empty<ParticleSystem>();

		private MinMaxGradient[] _originalParticleGradients = Array.Empty<MinMaxGradient>();

		private bool[] _isInfiniteLifetimeParticle = Array.Empty<bool>();

		private Renderer[] _targetRenderers = Array.Empty<Renderer>();

		private Material[] _originalSharedMaterials = Array.Empty<Material>();

		private Color[] _originalEmissionColors = Array.Empty<Color>();

		private Color[] _originalAlbedoColors = Array.Empty<Color>();

		private Color[] _originalTintColors = Array.Empty<Color>();

		private bool[] _isEmissionOnlyRenderer = Array.Empty<bool>();

		public int LightCount => _lights.Length;

		public int ParticleSystemCount => _particleSystems.Length;

		public int TargetRendererCount => _targetRenderers.Length;

		public void Initialize(GameObject rootGameObject)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)rootGameObject))
			{
				return;
			}
			_lights = rootGameObject.GetComponentsInChildren<Light>(true);
			_originalLightColors = (Color[])(object)new Color[_lights.Length];
			_originalLightIntensities = new float[_lights.Length];
			_originalLightRanges = new float[_lights.Length];
			LightFlicker val2 = default(LightFlicker);
			LightLod val3 = default(LightLod);
			for (int i = 0; i < _lights.Length; i++)
			{
				Light val = _lights[i];
				_originalLightColors[i] = val.color;
				_originalLightIntensities[i] = ((((Component)val).TryGetComponent<LightFlicker>(ref val2) && Object.op_Implicit((Object)(object)val2.m_light)) ? val2.m_baseIntensity : val.intensity);
				_originalLightRanges[i] = ((((Component)val).TryGetComponent<LightLod>(ref val3) && Object.op_Implicit((Object)(object)val3.m_light)) ? val3.m_baseRange : val.range);
			}
			_particleSystems = rootGameObject.GetComponentsInChildren<ParticleSystem>(true);
			_originalParticleGradients = (MinMaxGradient[])(object)new MinMaxGradient[_particleSystems.Length];
			_isInfiniteLifetimeParticle = new bool[_particleSystems.Length];
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				ParticleSystem val4 = _particleSystems[j];
				MinMaxGradient[] originalParticleGradients = _originalParticleGradients;
				int num = j;
				MainModule main = val4.main;
				originalParticleGradients[num] = ((MainModule)(ref main)).startColor;
				bool[] isInfiniteLifetimeParticle = _isInfiniteLifetimeParticle;
				int num2 = j;
				main = val4.main;
				MinMaxCurve startLifetime = ((MainModule)(ref main)).startLifetime;
				isInfiniteLifetimeParticle[num2] = float.IsInfinity(((MinMaxCurve)(ref startLifetime)).constant);
			}
			List<Renderer> list = new List<Renderer>();
			Renderer[] componentsInChildren = rootGameObject.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val5) && (IsTargetMaterial(val5.sharedMaterial) || IsEmissionOnlyMaterial(val5.sharedMaterial)))
				{
					list.Add(val5);
				}
			}
			_targetRenderers = list.ToArray();
			_originalSharedMaterials = (Material[])(object)new Material[_targetRenderers.Length];
			_originalEmissionColors = (Color[])(object)new Color[_targetRenderers.Length];
			_originalAlbedoColors = (Color[])(object)new Color[_targetRenderers.Length];
			_originalTintColors = (Color[])(object)new Color[_targetRenderers.Length];
			_isEmissionOnlyRenderer = new bool[_targetRenderers.Length];
			for (int l = 0; l < _targetRenderers.Length; l++)
			{
				Material sharedMaterial = _targetRenderers[l].sharedMaterial;
				_originalSharedMaterials[l] = sharedMaterial;
				_isEmissionOnlyRenderer[l] = IsEmissionOnlyMaterial(sharedMaterial);
				_originalEmissionColors[l] = (sharedMaterial.HasProperty(s_emissionColor) ? sharedMaterial.GetColor(s_emissionColor) : Color.white);
				_originalAlbedoColors[l] = (sharedMaterial.HasProperty(s_color) ? sharedMaterial.GetColor(s_color) : Color.white);
				_originalTintColors[l] = (sharedMaterial.HasProperty(s_tintColor) ? sharedMaterial.GetColor(s_tintColor) : Color.white);
			}
		}

		public void ApplyColor(Color targetColor, float? lightIntensityMultiplier = null, float? lightRangeMultiplier = null, float emissionMultiplier = 1f, bool allowAlpha = false)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _lights.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)_lights[i]))
				{
					_lights[i].color = targetColor;
					if (lightIntensityMultiplier.HasValue && i < _originalLightIntensities.Length)
					{
						SetLightIntensity(_lights[i], _originalLightIntensities[i] * lightIntensityMultiplier.Value);
					}
					if (lightRangeMultiplier.HasValue)
					{
						SetLightRange(_lights[i], _originalLightRanges[i] * lightRangeMultiplier.Value);
					}
				}
			}
			float alphaMultiplier = (allowAlpha ? Mathf.Clamp(targetColor.a, 0.15f, 1f) : 1f);
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)_particleSystems[j]) && j < _originalParticleGradients.Length)
				{
					MainModule main = _particleSystems[j].main;
					((MainModule)(ref main)).startColor = TintMinMaxGradient(in _originalParticleGradients[j], targetColor, alphaMultiplier);
					if (j < _isInfiniteLifetimeParticle.Length && _isInfiniteLifetimeParticle[j])
					{
						_particleSystems[j].Stop(true, (ParticleSystemStopBehavior)0);
						_particleSystems[j].Play();
					}
				}
			}
			for (int k = 0; k < _targetRenderers.Length; k++)
			{
				Renderer val = _targetRenderers[k];
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Material material = val.material;
				if (Object.op_Implicit((Object)(object)material))
				{
					TintEmissiveMaterialProperty(material, s_emissionColor, in _originalEmissionColors[k], targetColor, emissionMultiplier);
					if (!_isEmissionOnlyRenderer[k])
					{
						TintStandardMaterialProperty(material, s_color, in _originalAlbedoColors[k], targetColor, alphaMultiplier);
						TintStandardMaterialProperty(material, s_tintColor, in _originalTintColors[k], targetColor, alphaMultiplier);
					}
				}
			}
		}

		public void RestoreOriginalColors()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _lights.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)_lights[i]) && i < _originalLightColors.Length && i < _originalLightIntensities.Length)
				{
					_lights[i].color = _originalLightColors[i];
					SetLightIntensity(_lights[i], _originalLightIntensities[i]);
					SetLightRange(_lights[i], _originalLightRanges[i]);
				}
			}
			for (int j = 0; j < _particleSystems.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)_particleSystems[j]) && j < _originalParticleGradients.Length)
				{
					MainModule main = _particleSystems[j].main;
					((MainModule)(ref main)).startColor = _originalParticleGradients[j];
					if (j < _isInfiniteLifetimeParticle.Length && _isInfiniteLifetimeParticle[j])
					{
						_particleSystems[j].Stop(true, (ParticleSystemStopBehavior)0);
						_particleSystems[j].Play();
					}
				}
			}
			for (int k = 0; k < _targetRenderers.Length; k++)
			{
				if (Object.op_Implicit((Object)(object)_targetRenderers[k]) && k < _originalSharedMaterials.Length)
				{
					Material sharedMaterial = _targetRenderers[k].sharedMaterial;
					if (Object.op_Implicit((Object)(object)sharedMaterial) && (Object)(object)sharedMaterial != (Object)(object)_originalSharedMaterials[k])
					{
						Object.Destroy((Object)(object)sharedMaterial);
						_targetRenderers[k].sharedMaterial = _originalSharedMaterials[k];
					}
				}
			}
		}

		public void CleanupRuntimeMaterials()
		{
			for (int i = 0; i < _targetRenderers.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)_targetRenderers[i]) && i < _originalSharedMaterials.Length)
				{
					Material sharedMaterial = _targetRenderers[i].sharedMaterial;
					if (Object.op_Implicit((Object)(object)sharedMaterial) && (Object)(object)sharedMaterial != (Object)(object)_originalSharedMaterials[i])
					{
						Object.Destroy((Object)(object)sharedMaterial, 10f);
					}
				}
			}
		}

		public static void SetLightIntensity(Light light, float intensity)
		{
			light.intensity = intensity;
			LightFlicker val = default(LightFlicker);
			if (((Component)light).TryGetComponent<LightFlicker>(ref val))
			{
				val.m_baseIntensity = intensity;
			}
		}

		public static void SetLightRange(Light light, float range)
		{
			light.range = range;
			LightLod val = default(LightLod);
			if (((Component)light).TryGetComponent<LightLod>(ref val))
			{
				val.m_baseRange = range;
			}
		}

		private static void TintEmissiveMaterialProperty(Material material, int propertyId, in Color originalColor, Color targetColor, float emissionMultiplier)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(propertyId))
			{
				float num = Mathf.Max(originalColor.r, Mathf.Max(originalColor.g, originalColor.b)) * emissionMultiplier;
				material.SetColor(propertyId, new Color(targetColor.r * num, targetColor.g * num, targetColor.b * num, originalColor.a));
			}
		}

		private static void TintStandardMaterialProperty(Material material, int propertyId, in Color originalColor, Color targetColor, float alphaMultiplier)
		{
			//IL_0029: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(propertyId))
			{
				float num = Mathf.Max(originalColor.r, Mathf.Max(originalColor.g, originalColor.b));
				material.SetColor(propertyId, new Color(targetColor.r * num, targetColor.g * num, targetColor.b * num, originalColor.a * alphaMultiplier));
			}
		}

		public static MinMaxGradient TintMinMaxGradient(in MinMaxGradient originalGradient, Color targetColor, float alphaMultiplier)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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)
			//IL_0025: Expected I4, but got Unknown
			//IL_002a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			MinMaxGradient val = originalGradient;
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref val)).mode;
			switch ((int)mode)
			{
			case 0:
			{
				float r3 = targetColor.r;
				float g3 = targetColor.g;
				float b3 = targetColor.b;
				val = originalGradient;
				return MinMaxGradient.op_Implicit(new Color(r3, g3, b3, ((MinMaxGradient)(ref val)).color.a * alphaMultiplier));
			}
			case 2:
			{
				float r = targetColor.r;
				float g = targetColor.g;
				float b = targetColor.b;
				val = originalGradient;
				Color val2 = new Color(r, g, b, ((MinMaxGradient)(ref val)).colorMin.a * alphaMultiplier);
				float r2 = targetColor.r;
				float g2 = targetColor.g;
				float b2 = targetColor.b;
				val = originalGradient;
				return new MinMaxGradient(val2, new Color(r2, g2, b2, ((MinMaxGradient)(ref val)).colorMax.a * alphaMultiplier));
			}
			case 1:
				val = originalGradient;
				return MinMaxGradient.op_Implicit(TintGradient(((MinMaxGradient)(ref val)).gradient, targetColor, alphaMultiplier));
			case 3:
			{
				val = originalGradient;
				Gradient obj = TintGradient(((MinMaxGradient)(ref val)).gradientMin, targetColor, alphaMultiplier);
				val = originalGradient;
				return new MinMaxGradient(obj, TintGradient(((MinMaxGradient)(ref val)).gradientMax, targetColor, alphaMultiplier));
			}
			default:
				return originalGradient;
			}
		}

		public static Gradient TintGradient(Gradient? sourceGradient, Color targetColor, float alphaMultiplier)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_001f: 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_002b: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (sourceGradient != null)
			{
				GradientColorKey[] colorKeys = sourceGradient.colorKeys;
				GradientColorKey[] array = (GradientColorKey[])(object)new GradientColorKey[colorKeys.Length];
				for (int i = 0; i < colorKeys.Length; i++)
				{
					array[i] = new GradientColorKey(new Color(targetColor.r, targetColor.g, targetColor.b), colorKeys[i].time);
				}
				GradientAlphaKey[] array2;
				if (alphaMultiplier < 0.999f)
				{
					GradientAlphaKey[] alphaKeys = sourceGradient.alphaKeys;
					array2 = (GradientAlphaKey[])(object)new GradientAlphaKey[alphaKeys.Length];
					for (int j = 0; j < alphaKeys.Length; j++)
					{
						array2[j] = new GradientAlphaKey(alphaKeys[j].alpha * alphaMultiplier, alphaKeys[j].time);
					}
				}
				else
				{
					array2 = sourceGradient.alphaKeys;
				}
				Gradient val = new Gradient();
				val.SetKeys(array, array2);
				return val;
			}
			return new Gradient();
		}

		public static string FormatColorHex(Color color, bool allowAlpha)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			float num = (allowAlpha ? Mathf.Clamp(color.a, 0.15f, 1f) : 1f);
			Color val = default(Color);
			((Color)(ref val))..ctor(c