Decompiled source of EmissiveFX v1.0.1

EmissiveFX.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("EmissiveFX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.2.0.0")]
[assembly: AssemblyInformationalVersion("2.2.0")]
[assembly: AssemblyProduct("EmissiveFX")]
[assembly: AssemblyTitle("EmissiveFX")]
[assembly: AssemblyVersion("2.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EmissiveFX
{
	public enum SlotKind
	{
		Primary,
		Special,
		Tool,
		Melee,
		Other
	}
	[BepInPlugin("gtfoskin.emissivefx", "EmissiveFX", "1.0.1")]
	public class Plugin : BasePlugin
	{
		public const string GUID = "gtfoskin.emissivefx";

		public static ManualLogSource Log;

		public static ConfigEntry<float> CfgPeriod;

		public static ConfigEntry<float> CfgMin;

		public static ConfigEntry<float> CfgMax;

		public static ConfigEntry<float> CfgCurve;

		public static ConfigEntry<bool> CfgEnabled;

		public const string ModeSolid = "Solid";

		public const string ModeBreathing = "Breathing";

		public const string ModeHeartbeat = "Heartbeat";

		public const string ModeAlarm = "Alarm";

		public const string ModeFlicker = "Flicker";

		public const string ModeCharge = "Charge";

		public const string ModeHue = "Hue";

		public const string ModeTwinkle = "Twinkle";

		public const string ModeSparks = "Sparks";

		public const string ModeSweep = "Sweep";

		public const string ModeLowHealth = "LowHealth";

		public const string ModeChase = "Chase";

		public const string ModeGradient = "Gradient";

		public const string ModeRainbow = "Rainbow";

		public const string ModeHeat = "Heat";

		public const string ModeCold = "ColdFire";

		public const string ModeEmber = "Ember";

		public const string ModeNoise = "NoiseDrift";

		public const string ModeAntiPhase = "AntiPhase";

		public static ConfigEntry<string> CfgMode;

		public static ConfigEntry<string> CfgShaderFilter;

		public static ConfigEntry<string> CfgExcludeNames;

		public static ConfigEntry<bool> CfgEquipmentOnly;

		public static ConfigEntry<bool> CfgRequireEmissiveMap;

		public static ConfigEntry<bool> CfgVisibleOnly;

		public static ConfigEntry<float> CfgRetrySeconds;

		public static ConfigEntry<string> CfgScanMode;

		public const string ScanTest = "Test";

		public const string ScanConfirmed = "Confirmed";

		public const string ScanOff = "Off";

		public static volatile bool NeedScan;

		public static volatile bool ManualScanPending;

		public static volatile string FrozenMode;

		public static string ActiveMode()
		{
			string frozenMode = FrozenMode;
			if (!string.IsNullOrEmpty(frozenMode))
			{
				return frozenMode;
			}
			return CfgMode.Value ?? "Breathing";
		}

		public override void Load()
		{
			Log = ((BasePlugin)this).Log;
			CfgPeriod = ((BasePlugin)this).Config.Bind<float>("Breathing", "PeriodSeconds", 3.2f, "One full breath cycle in seconds. 2-4 s reads as breathing.");
			CfgMin = ((BasePlugin)this).Config.Bind<float>("Breathing", "MinFactor", 0.3f, "Emissive multiplier at the dimmest point.");
			CfgMax = ((BasePlugin)this).Config.Bind<float>("Breathing", "MaxFactor", 0.98f, "Emissive multiplier at the brightest point.");
			CfgCurve = ((BasePlugin)this).Config.Bind<float>("Breathing", "CurvePower", 1.6f, "1 = pure sine. Higher = longer dwell at the dim end.");
			CfgEnabled = ((BasePlugin)this).Config.Bind<bool>("Switches", "Enabled", true, "Master switch (also the 总开关 toggle on the in-game page).");
			CfgMode = ((BasePlugin)this).Config.Bind<string>("Switches", "Effect", "Solid", "Which effect drives the emissive. One of:\n  Solid / Breathing / Heartbeat / Alarm / Flicker / Charge / Hue\nAlso selectable on the in-game 效果 page, where the seven switches\nare mutually exclusive.");
			CfgEquipmentOnly = ((BasePlugin)this).Config.Bind<bool>("Advanced", "EquipmentOnly", true, "true  = ONLY weapons/tools are affected (recommended).\nfalse = every emissive object in the level, including terminal\n        screens and door panels.");
			CfgExcludeNames = ((BasePlugin)this).Config.Bind<string>("Advanced", "ExcludeNames", "", "Space separated. Renderers whose GameObject OR material name\ncontains any of these are left alone.\nEMPTY BY DEFAULT on purpose: the EquipmentOnly check already\nkeeps terminal screens out (they do not hang off a player),\nand a word like 'screen' in here also catches the screens\non the weapons themselves.");
			CfgShaderFilter = ((BasePlugin)this).Config.Bind<string>("Advanced", "ShaderFilter", "Gear", "Only renderers whose shader name CONTAINS this are considered.");
			CfgRequireEmissiveMap = ((BasePlugin)this).Config.Bind<bool>("Advanced", "RequireEmissiveMap", true, "Skip materials with no _EmissiveMap assigned.");
			CfgVisibleOnly = ((BasePlugin)this).Config.Bind<bool>("Performance", "VisibleOnly", false, "Only write to renderers that are visible this frame.");
			CfgRetrySeconds = ((BasePlugin)this).Config.Bind<float>("Performance", "RetrySeconds", 12f, "While no gear has been found yet, how often to look again.\nScanning is expensive, so it stops once something is found.");
			CfgScanMode = ((BasePlugin)this).Config.Bind<string>("Performance", "ScanMode", "Test", "Off       = no full scan ever. The held-item path still\n            collects the wielded weapon, so the effect keeps\n            showing; only the safety-net scan is gone.\nTest      = scan on demand, plus 60 s / 300 s safety timers.\n            Fastest response, at the cost of a ~200 ms hitch\n            every few minutes.\nConfirmed = one scan, then a 30 minute safety net only.\n            Set by the manual confirm switch.");
			Log.LogInfo((object)"EmissiveFX v4.0.1 loaded - effects + scan policy. (menu-stutter fix)");
			try
			{
				PatchAll();
				Log.LogInfo((object)"harmony patches applied");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("failed to apply harmony patches: " + ex));
			}
			((BasePlugin)this).AddComponent<BreathBehaviour>();
			try
			{
				TrajectoryCfg.Bind(((BasePlugin)this).Config);
				((BasePlugin)this).AddComponent<TrajectoryBehaviour>();
				Log.LogInfo((object)"trajectory (tracer) ready - default OFF");
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("failed to init trajectory: " + ex2));
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void PatchAll()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("gtfoskin.emissivefx").PatchAll(typeof(SettingsPage));
		}
	}
	public class BreathBehaviour : MonoBehaviour
	{
		private class Target
		{
			public Renderer rend;

			public Color baseColor;

			public SlotKind slot;

			public float phase;

			public float sparkTimer;

			public float spark;

			public float along;

			public bool alongDone;
		}

		private readonly List<Target> _scanCache = new List<Target>();

		private readonly List<Target> _heldTargets = new List<Target>();

		private readonly HashSet<long> _merged = new HashSet<long>();

		private readonly Dictionary<long, Target> _known = new Dictionary<long, Target>();

		private readonly List<Target> _targets = new List<Target>();

		private float _gearTimer;

		private int _lastGearPtr;

		private string _lastGearSig = string.Empty;

		private PlayerInventoryLocal _cachedInv;

		private Transform _wieldedTf;

		private int _cachedItemPtr;

		private float _nextInvRetry;

		private int _invQueryCount;

		private int _invDropped;

		private float _invStaleTimer;

		private float _gearLogTimer;

		private float _rescanFallbackTimer;

		private bool _needScan = true;

		private float _lastScanTime;

		private readonly MaterialPropertyBlock _mpb = new MaterialPropertyBlock();

		private Dam_SyncedDamageBase _playerDmg;

		private float _healthRel = 1f;

		private int _healthStage = 4;

		private float _healthTimer;

		private PlayerStamina _playerStamina;

		private float _tiredness;

		private float _staminaRel = 1f;

		private float _heartPhase;

		private static readonly float[] HealthHz = new float[5] { 2f, 1.55f, 1.15f, 0.8f, 0.5f };

		private static readonly float[] HealthPeak = new float[5] { 1.55f, 1.35f, 1.18f, 1.03f, 0.95f };

		private static readonly HashSet<string> _logged = new HashSet<string>();

		private float _nextRetry;

		private bool _foundAny;

		private int _lastPulsed;

		private int _lastVisible;

		private float _reclassTimer;

		private string _lastTally = string.Empty;

		private float _frameGain = 1f;

		private Color _frameFixed = Color.white;

		private bool _frameUseFixed;

		private float _flicker = 1f;

		private float _sweepPos;

		private string _diagSamples = "";

		private int _diagCount;

		private float _diagTimer;

		private float _diagDeadline = 180f;

		private static float _alongSeq;

		private static string[] _excl = new string[0];

		private static string _exclRaw;

		private static readonly HashSet<string> _seenExcluded = new HashSet<string>();

		private static readonly HashSet<string> _seenMatched = new HashSet<string>();

		private static readonly HashSet<string> _seenScenery = new HashSet<string>();

		private int _owners;

		public BreathBehaviour(IntPtr ptr)
			: base(ptr)
		{
		}//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)


		private static void LogOnce(string where, Exception e)
		{
			try
			{
				string item = where + "|" + e.GetType().Name;
				if (_logged.Add(item))
				{
					Plugin.Log.LogWarning((object)("[once] " + where + ": " + e.Message));
				}
			}
			catch
			{
			}
		}

		private void Awake()
		{
			_nextRetry = Time.time + 4f;
			_reclassTimer = Time.time + 2f;
		}

		private void Reclassify()
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			for (int i = 0; i < _targets.Count; i++)
			{
				Target target = _targets[i];
				if (!((Object)(object)target.rend == (Object)null))
				{
					target.slot = Classify(target.rend);
					switch (target.slot)
					{
					case SlotKind.Primary:
						num++;
						break;
					case SlotKind.Special:
						num2++;
						break;
					case SlotKind.Tool:
						num3++;
						break;
					case SlotKind.Melee:
						num4++;
						break;
					default:
						num5++;
						break;
					}
				}
			}
			string text = $"primary={num} special={num2} tool={num3} melee={num4} other={num5}";
			if (text != _lastTally)
			{
				_lastTally = text;
				Plugin.Log.LogInfo((object)("slots: " + text));
			}
		}

		private void Update()
		{
			try
			{
				SettingsPage.Tick();
				if (Time.time >= _gearTimer)
				{
					_gearTimer = Time.time + 0.2f;
					RefreshGear();
				}
				bool flag = _targets.Count == 0 && Time.time - _lastScanTime > 60f;
				bool flag2 = Time.time - _lastScanTime > 300f;
				bool flag3 = Plugin.CfgScanMode.Value != null && Plugin.CfgScanMode.Value.Equals("Confirmed", StringComparison.OrdinalIgnoreCase);
				int num;
				if (Plugin.CfgScanMode.Value != null)
				{
					num = (Plugin.CfgScanMode.Value.Equals("Off", StringComparison.OrdinalIgnoreCase) ? 1 : 0);
					if (num != 0)
					{
						if (string.IsNullOrEmpty(Plugin.FrozenMode))
						{
							Plugin.FrozenMode = Plugin.CfgMode.Value;
							Plugin.Log.LogInfo((object)("[scan] effect frozen at '" + Plugin.FrozenMode + "'"));
						}
						goto IL_0113;
					}
				}
				else
				{
					num = 0;
				}
				if (!string.IsNullOrEmpty(Plugin.FrozenMode))
				{
					Plugin.FrozenMode = null;
					Plugin.Log.LogInfo((object)"[scan] effect unfrozen");
				}
				goto IL_0113;
				IL_0113:
				bool flag4;
				if (num == 0)
				{
					flag4 = ((!flag3) ? (Plugin.NeedScan || _needScan || flag || flag2) : (_lastScanTime <= 0f || Plugin.NeedScan || Time.time - _lastScanTime > 1800f));
				}
				else
				{
					flag4 = false;
					_needScan = false;
				}
				if (flag4)
				{
					Plugin.NeedScan = false;
					_needScan = false;
					_lastScanTime = Time.time;
					Scan();
					if (Plugin.ManualScanPending)
					{
						Plugin.ManualScanPending = false;
						try
						{
							SettingsPage.RefreshRows();
						}
						catch
						{
						}
					}
				}
				else if (_targets.Count == 0)
				{
					MergeTargets();
				}
				if (Plugin.CfgEnabled.Value && _targets.Count != 0)
				{
					ComputeFrame();
					bool value = Plugin.CfgVisibleOnly.Value;
					int pulsed = 0;
					int visible = 0;
					try
					{
						Pulse(_targets, value, ref pulsed, ref visible);
					}
					catch (Exception e)
					{
						LogOnce("pulse", e);
					}
					_lastPulsed = pulsed;
					_lastVisible = visible;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("update failed: " + ex));
			}
		}

		private void Pulse(List<Target> list, bool visibleOnly, ref int pulsed, ref int visible)
		{
			//IL_0667: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_061d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_0631: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			Color val2 = default(Color);
			for (int i = 0; i < list.Count; i++)
			{
				try
				{
					Target target = list[i];
					Renderer rend = target.rend;
					if (!((Object)(object)rend == (Object)null))
					{
						if (!visibleOnly)
						{
							goto IL_0041;
						}
						bool flag;
						try
						{
							flag = rend.isVisible;
						}
						catch
						{
							flag = true;
						}
						if (flag)
						{
							goto IL_0041;
						}
					}
					goto end_IL_0008;
					IL_0041:
					visible++;
					string text = Plugin.ActiveMode();
					float time = Time.time;
					float num = Mathf.Max(0.2f, Plugin.CfgPeriod.Value);
					float value = Plugin.CfgMin.Value;
					float value2 = Plugin.CfgMax.Value;
					float num2 = _frameGain;
					Color val = (_frameUseFixed ? _frameFixed : target.baseColor);
					if (text.Equals("Twinkle", StringComparison.OrdinalIgnoreCase))
					{
						float num3 = (time / num + target.phase) % 1f;
						float num4 = 0.5f - 0.5f * Mathf.Cos(MathF.PI * 2f * num3);
						num4 = Mathf.Pow(num4, Mathf.Max(0.05f, Plugin.CfgCurve.Value));
						num2 = Mathf.Lerp(value, value2, num4);
					}
					else if (text.Equals("Sparks", StringComparison.OrdinalIgnoreCase))
					{
						target.sparkTimer -= Time.deltaTime;
						if (target.sparkTimer <= 0f)
						{
							target.sparkTimer = Random.Range(0.5f, 3.5f);
							target.spark = 1f;
						}
						target.spark *= Mathf.Exp((0f - Time.deltaTime) * 9f);
						num2 = Mathf.Lerp(value, value2, Mathf.Clamp01(target.spark));
					}
					else if (text.Equals("Sweep", StringComparison.OrdinalIgnoreCase))
					{
						if (!target.alongDone)
						{
							target.along = 0.5f;
							target.alongDone = true;
						}
						float num5 = Mathf.Abs(Mathf.Repeat(target.along - _sweepPos + 0.5f, 1f) - 0.5f);
						float num6 = Mathf.Clamp01(1f - num5 / 0.16f);
						num2 = Mathf.Lerp(value, value2, num6 * num6);
					}
					else if (text.Equals("LowHealth", StringComparison.OrdinalIgnoreCase))
					{
						float num7 = HealthHz[_healthStage];
						float num8 = HealthPeak[_healthStage];
						float x = time * num7 % 1f;
						float num9 = Thump(0.26f, x);
						num2 = Mathf.Lerp(value, value2 * num8, Mathf.Clamp01(num9));
					}
					else if (text.Equals("Chase", StringComparison.OrdinalIgnoreCase))
					{
						if (!target.alongDone)
						{
							target.along = target.phase;
							target.alongDone = true;
						}
						int num10 = Mathf.FloorToInt(time * 0.9f % 1f * 8f);
						float num11 = ((Mathf.FloorToInt(target.along * 8f * 0.999f) == num10) ? 1f : 0.35f);
						num2 = Mathf.Lerp(value + 0.2f, value2 * 1.15f, num11);
					}
					else if (text.Equals("Gradient", StringComparison.OrdinalIgnoreCase))
					{
						if (!target.alongDone)
						{
							target.along = target.phase;
							target.alongDone = true;
						}
						float num12 = 0.5f + 0.5f * Mathf.Sin(time * 0.35f);
						float num13 = Mathf.Lerp(target.along, 1f - target.along, num12);
						num2 = Mathf.Lerp(value + 0.3f, value2 * 1.12f, num13 * num13);
					}
					else if (text.Equals("Rainbow", StringComparison.OrdinalIgnoreCase))
					{
						if (!target.alongDone)
						{
							target.along = target.phase;
							target.alongDone = true;
						}
						val = Color.HSVToRGB(Mathf.Repeat(target.along * 0.8f + time * 0.14f, 1f), 1f, 1f);
						num2 = Mathf.Lerp(value + 0.45f, value2 * 1.15f, 0.45f + 0.25f * Mathf.Sin(time * 1.1f) + 0.3f * target.along);
					}
					else if (text.Equals("Heat", StringComparison.OrdinalIgnoreCase))
					{
						float num14 = 0.5f - 0.5f * Mathf.Cos(MathF.PI * 2f * (time % num) / num);
						val = Color.Lerp(target.baseColor, new Color(1f, 0.72f, 0.32f), num14 * 0.85f);
						num2 = Mathf.Lerp(value, value2 * 1.15f, num14);
					}
					else if (text.Equals("ColdFire", StringComparison.OrdinalIgnoreCase))
					{
						float num15 = 0.5f - 0.5f * Mathf.Cos(MathF.PI * 2f * (time % num) / num);
						val = Color.Lerp(target.baseColor, new Color(0.34f, 0.84f, 1f), 0.85f);
						num2 = Mathf.Lerp(value, value2 * 1.02f, num15);
					}
					else if (text.Equals("Ember", StringComparison.OrdinalIgnoreCase))
					{
						float num16 = Mathf.PerlinNoise(time * 0.55f, target.phase * 7.3f);
						val = Color.Lerp(new Color(0.45f, 0.06f, 0.02f), new Color(1f, 0.42f, 0.1f), num16);
						num2 = Mathf.Lerp(value * 0.7f, value2 * 0.88f, num16);
					}
					else if (text.Equals("NoiseDrift", StringComparison.OrdinalIgnoreCase))
					{
						float num17 = Mathf.PerlinNoise(time * 0.33f, target.phase * 13.7f);
						num2 = Mathf.Lerp(value, value2, num17);
					}
					else if (text.Equals("AntiPhase", StringComparison.OrdinalIgnoreCase))
					{
						float num18 = time % num / num;
						float num19 = 0.5f - 0.5f * Mathf.Cos(MathF.PI * 2f * num18);
						num19 = Mathf.Pow(num19, Mathf.Max(0.05f, Plugin.CfgCurve.Value));
						if (target.phase > 0.5f)
						{
							num19 = 1f - num19;
						}
						num2 = Mathf.Lerp(value, value2, num19);
					}
					((Color)(ref val2))..ctor(val.r * num2, val.g * num2, val.b * num2, target.baseColor.a);
					try
					{
						rend.GetPropertyBlock(_mpb);
					}
					catch
					{
					}
					_mpb.SetColor("_EmissiveColor", val2);
					try
					{
						rend.SetPropertyBlock(_mpb);
					}
					catch
					{
					}
					pulsed++;
					end_IL_0008:;
				}
				catch
				{
				}
			}
		}

		private void LateUpdate()
		{
			try
			{
				SettingsPage.Tick();
			}
			catch
			{
			}
		}

		private bool AllDead()
		{
			if (_targets.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < _targets.Count; i++)
			{
				if ((Object)(object)_targets[i].rend != (Object)null)
				{
					return false;
				}
			}
			return true;
		}

		private static float NextAlong()
		{
			_alongSeq += 0.618034f;
			if (_alongSeq >= 1f)
			{
				_alongSeq -= 1f;
			}
			return _alongSeq;
		}

		private static float Thump(float width, float x)
		{
			if (x < 0f)
			{
				return 0f;
			}
			float num = x / width;
			return Mathf.Exp((0f - num) * num);
		}

		private static float Hash01(float n)
		{
			return Mathf.Abs(Mathf.Sin(n * 12.9898f) * 43758.547f) % 1f;
		}

		private void ComputeFrame()
		{
			//IL_0040: 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_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			string text = Plugin.ActiveMode();
			float num = Mathf.Max(0.2f, Plugin.CfgPeriod.Value);
			float value = Plugin.CfgMin.Value;
			float value2 = Plugin.CfgMax.Value;
			float time = Time.time;
			_frameUseFixed = false;
			_frameFixed = Color.white;
			if (text.Equals("Solid", StringComparison.OrdinalIgnoreCase))
			{
				_frameGain = value2;
			}
			else if (text.Equals("Heartbeat", StringComparison.OrdinalIgnoreCase))
			{
				float num2 = Mathf.Lerp(55f, 185f, _tiredness);
				if (_healthRel < 0.5f)
				{
					num2 += (0.5f - _healthRel) * 60f;
				}
				num2 = Mathf.Clamp(num2, 40f, 210f);
				float num3 = 60f / num2;
				_heartPhase += Time.deltaTime / num3;
				if (_heartPhase >= 1f)
				{
					_heartPhase -= 1f;
				}
				if (_heartPhase < 0f)
				{
					_heartPhase = 0f;
				}
				float width = Mathf.Lerp(0.07f, 0.042f, _tiredness) / num3;
				float width2 = Mathf.Lerp(0.085f, 0.05f, _tiredness) / num3;
				float num4 = Mathf.Lerp(0.28f, 0.15f, _tiredness) / num3;
				float heartPhase = _heartPhase;
				float num5 = Thump(width, heartPhase) + 0.62f * Thump(width2, heartPhase - num4);
				_frameGain = Mathf.Lerp(value, value2, Mathf.Clamp01(num5));
			}
			else if (text.Equals("Alarm", StringComparison.OrdinalIgnoreCase))
			{
				float num6 = num * 0.35f;
				float num7 = time % num6 / num6;
				float num8 = ((num7 < 0.3f) ? Mathf.Clamp01(num7 / 0.05f) : Mathf.Clamp01(1f - (num7 - 0.3f) / 0.25f));
				_frameGain = Mathf.Lerp(value, value2, num8);
			}
			else if (text.Equals("Flicker", StringComparison.OrdinalIgnoreCase))
			{
				float num9 = ((Hash01(Mathf.Floor(time / 0.09f) % 1000f) < 0.3f) ? 0.15f : 1f);
				_flicker = Mathf.Lerp(_flicker, num9, 1f - Mathf.Exp((0f - Time.deltaTime) * 22f));
				_frameGain = Mathf.Lerp(value, value2, Mathf.Clamp01(_flicker));
			}
			else if (text.Equals("Charge", StringComparison.OrdinalIgnoreCase))
			{
				float num10 = num * 0.8f;
				float num11 = time % num10 / num10;
				_frameGain = Mathf.Lerp(value, value2, num11);
			}
			else if (text.Equals("Hue", StringComparison.OrdinalIgnoreCase))
			{
				float num12 = time * 0.12f % 1f;
				_frameUseFixed = true;
				_frameFixed = Color.HSVToRGB(num12, 0.75f, 1f);
				_frameGain = Mathf.Lerp(value, value2, 0.5f + 0.5f * Mathf.Sin(time));
			}
			else
			{
				float num13 = time % num / num;
				float num14 = 0.5f - 0.5f * Mathf.Cos(MathF.PI * 2f * num13);
				num14 = Mathf.Pow(num14, Mathf.Max(0.05f, Plugin.CfgCurve.Value));
				_frameGain = Mathf.Lerp(value, value2, num14);
			}
			_sweepPos = time * 0.45f % 1f;
			if (Time.time >= _healthTimer)
			{
				_healthTimer = Time.time + 0.5f;
				SampleHealth();
			}
		}

		private void SampleHealth()
		{
			try
			{
				if ((Object)(object)_playerDmg == (Object)null)
				{
					if ((Object)(object)_cachedInv == (Object)null)
					{
						return;
					}
					Component componentInParent = ((Component)_cachedInv).gameObject.GetComponentInParent(Il2CppType.Of<Dam_SyncedDamageBase>());
					if ((Object)(object)componentInParent != (Object)null)
					{
						_playerDmg = ((Il2CppObjectBase)componentInParent).TryCast<Dam_SyncedDamageBase>();
					}
				}
				if ((Object)(object)_playerStamina == (Object)null && (Object)(object)_cachedInv != (Object)null)
				{
					try
					{
						Component componentInParent2 = ((Component)_cachedInv).gameObject.GetComponentInParent(Il2CppType.Of<PlayerStamina>());
						if ((Object)(object)componentInParent2 != (Object)null)
						{
							_playerStamina = ((Il2CppObjectBase)componentInParent2).TryCast<PlayerStamina>();
						}
					}
					catch
					{
					}
				}
				if ((Object)(object)_playerStamina != (Object)null)
				{
					try
					{
						_tiredness = Mathf.Clamp01(_playerStamina.TirednessRelative);
						_staminaRel = Mathf.Clamp01(_playerStamina.StaminaRelative);
					}
					catch
					{
						_playerStamina = null;
					}
				}
				if ((Object)(object)_playerDmg != (Object)null)
				{
					_healthRel = Mathf.Clamp01(_playerDmg.GetHealthRel());
					int num = Mathf.Clamp(Mathf.FloorToInt(_healthRel * 100f / 20f), 0, 4);
					if (num != _healthStage)
					{
						_healthStage = num;
						Plugin.Log.LogInfo((object)$"low health stage -> {num} ({num * 20} HP band); {HealthHz[num]} Hz, peak {HealthPeak[num]}x");
					}
				}
			}
			catch
			{
				_playerDmg = null;
			}
		}

		private void ComputeAlong()
		{
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			int count = _heldTargets.Count;
			if (count < 2)
			{
				for (int i = 0; i < count; i++)
				{
					_heldTargets[i].along = 0.5f;
					_heldTargets[i].alongDone = true;
				}
				Plugin.Log.LogInfo((object)$"along: only {count} gear target(s) - no axis to measure, using 0.5");
				return;
			}
			_ = Vector3.zero;
			Transform val = null;
			try
			{
				val = _wieldedTf;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[count];
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(float.MaxValue, float.MaxValue, float.MaxValue);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(float.MinValue, float.MinValue, float.MinValue);
			int num = 0;
			for (int j = 0; j < count; j++)
			{
				Renderer rend = _heldTargets[j].rend;
				if ((Object)(object)rend == (Object)null)
				{
					array[j] = Vector3.zero;
					continue;
				}
				try
				{
					Vector3 val4 = Vector3.zero;
					try
					{
						Bounds bounds = rend.bounds;
						val4 = ((Bounds)(ref bounds)).center;
					}
					catch
					{
					}
					if (val4 == Vector3.zero)
					{
						val4 = ((Component)rend).transform.position;
					}
					Vector3 val5 = (array[j] = val.InverseTransformPoint(val4));
					val2 = Vector3.Min(val2, val5);
					val3 = Vector3.Max(val3, val5);
					num++;
				}
				catch
				{
					array[j] = Vector3.zero;
				}
			}
			if (num >= 2)
			{
				Vector3 val6 = val3 - val2;
				int num2 = 1;
				if (val6.x >= val6.y && val6.x >= val6.z)
				{
					num2 = 0;
				}
				else if (val6.z >= val6.x && val6.z >= val6.y)
				{
					num2 = 2;
				}
				float num3 = num2 switch
				{
					1 => val2.y, 
					0 => val2.x, 
					_ => val2.z, 
				};
				float num4 = num2 switch
				{
					1 => val6.y, 
					0 => val6.x, 
					_ => val6.z, 
				};
				if (num4 < 0.0001f)
				{
					num4 = 0.0001f;
				}
				for (int k = 0; k < count; k++)
				{
					float num5 = num2 switch
					{
						1 => array[k].y, 
						0 => array[k].x, 
						_ => array[k].z, 
					};
					_heldTargets[k].along = Mathf.Clamp01((num5 - num3) / num4);
					_heldTargets[k].alongDone = true;
				}
				string text = "";
				for (int l = 0; l < count && l < 6; l++)
				{
					text += $" {_heldTargets[l].along:F2}";
				}
				Plugin.Log.LogInfo((object)string.Format("along axis = {0} (extent {1:F4}) for {2} target(s); first values:{3}", num2 switch
				{
					1 => "Y", 
					0 => "X", 
					_ => "Z", 
				}, num4, count, (text.Length > 0) ? text : " none"));
			}
		}

		private void PreparePerTargetState()
		{
			try
			{
				ComputeAlong();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("PreparePerTargetState: " + ex.Message));
			}
		}

		private static SlotKind Classify(Renderer r)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Component componentInParent = ((Component)r).gameObject.GetComponentInParent(Il2CppType.Of<ItemEquippable>());
				ItemEquippable val = (((Object)(object)componentInParent != (Object)null) ? ((Il2CppObjectBase)componentInParent).TryCast<ItemEquippable>() : null);
				if ((Object)(object)val == (Object)null)
				{
					return SlotKind.Other;
				}
				Component componentInParent2 = ((Component)val).gameObject.GetComponentInParent(Il2CppType.Of<PlayerInventoryBase>());
				PlayerInventoryBase val2 = (((Object)(object)componentInParent2 != (Object)null) ? ((Il2CppObjectBase)componentInParent2).TryCast<PlayerInventoryBase>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return SlotKind.Other;
				}
				if ((Object)(object)((Il2CppObjectBase)val2).TryCast<PlayerInventoryLocal>() == (Object)null)
				{
					return SlotKind.Other;
				}
				ItemEquippable wieldedItem = val2.WieldedItem;
				if ((Object)(object)wieldedItem == (Object)null || ((Il2CppObjectBase)wieldedItem).Pointer != ((Il2CppObjectBase)val).Pointer)
				{
					return SlotKind.Other;
				}
				return FromSlot(val2.WieldedSlot);
			}
			catch
			{
				return SlotKind.Other;
			}
		}

		private static SlotKind FromSlot(InventorySlot s)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			return (int)s switch
			{
				1 => SlotKind.Primary, 
				2 => SlotKind.Special, 
				3 => SlotKind.Tool, 
				10 => SlotKind.Melee, 
				_ => SlotKind.Other, 
			};
		}

		private static string ClassifyVerbose(Renderer r)
		{
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected I4, but got Unknown
			try
			{
				Component componentInParent = ((Component)r).gameObject.GetComponentInParent(Il2CppType.Of<ItemEquippable>());
				ItemEquippable val = (((Object)(object)componentInParent != (Object)null) ? ((Il2CppObjectBase)componentInParent).TryCast<ItemEquippable>() : null);
				if ((Object)(object)val == (Object)null)
				{
					return "slot=Other (no ItemEquippable ancestor)";
				}
				string text = "<unnamed>";
				try
				{
					text = ((Object)((Component)val).gameObject).name;
				}
				catch
				{
				}
				Component componentInParent2 = ((Component)val).gameObject.GetComponentInParent(Il2CppType.Of<PlayerInventoryBase>());
				PlayerInventoryBase val2 = (((Object)(object)componentInParent2 != (Object)null) ? ((Il2CppObjectBase)componentInParent2).TryCast<PlayerInventoryBase>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return "slot=Other (item='" + text + "' has no PlayerInventoryBase ancestor)";
				}
				bool flag = false;
				try
				{
					flag = (Object)(object)((Il2CppObjectBase)val2).TryCast<PlayerInventoryLocal>() != (Object)null;
				}
				catch
				{
				}
				string text2 = "?";
				try
				{
					ItemEquippable wieldedItem = val2.WieldedItem;
					text2 = ((!((Object)(object)wieldedItem == (Object)null)) ? ((((Il2CppObjectBase)wieldedItem).Pointer == ((Il2CppObjectBase)val).Pointer) ? "THIS" : "other") : "none");
				}
				catch (Exception ex)
				{
					text2 = "err:" + ex.GetType().Name;
				}
				int num = -1;
				try
				{
					num = (int)val2.WieldedSlot;
				}
				catch
				{
				}
				return $"slot={FromSlot(val2.WieldedSlot)} item='{text}' isLocalPlayer={flag} wielded={text2} rawWieldedSlot={num}";
			}
			catch (Exception ex2)
			{
				return "slot=Other (classify threw " + ex2.GetType().Name + ")";
			}
		}

		private void MergeTargets()
		{
			_targets.Clear();
			_merged.Clear();
			for (int i = 0; i < _scanCache.Count; i++)
			{
				AddMerged(_scanCache[i]);
			}
			for (int j = 0; j < _heldTargets.Count; j++)
			{
				AddMerged(_heldTargets[j]);
			}
		}

		private void AddMerged(Target t)
		{
			if (t == null)
			{
				return;
			}
			Renderer rend = t.rend;
			if ((Object)(object)rend == (Object)null)
			{
				return;
			}
			try
			{
				if (!_merged.Add(((Il2CppObjectBase)rend).Pointer.ToInt64()))
				{
					return;
				}
			}
			catch
			{
				return;
			}
			_targets.Add(t);
		}

		private void RefreshGear()
		{
			try
			{
				if ((Object)(object)_cachedInv == (Object)null)
				{
					if (Time.time < _nextInvRetry)
					{
						_wieldedTf = null;
						return;
					}
					_nextInvRetry = Time.time + 3f;
					_cachedInv = FindLocalInventory();
					_invQueryCount++;
					if ((Object)(object)_cachedInv == (Object)null)
					{
						_wieldedTf = null;
						return;
					}
					_needScan = true;
				}
				ItemEquippable wieldedItem = ((PlayerInventoryBase)_cachedInv).WieldedItem;
				_wieldedTf = (((Object)(object)wieldedItem != (Object)null) ? ((Component)wieldedItem).transform : null);
				try
				{
					LogGearIfChanged(_heldTargets.Count, _scanCache.Count, _invQueryCount, ((Object)(object)wieldedItem == (Object)null) ? 1 : 0);
				}
				catch
				{
				}
				if ((Object)(object)wieldedItem == (Object)null)
				{
					if (_heldTargets.Count > 0)
					{
						ReleaseHeld();
						MergeTargets();
					}
					return;
				}
				int num = 0;
				try
				{
					num = ((Il2CppObjectBase)wieldedItem).Pointer.ToInt32();
				}
				catch
				{
				}
				if (num == _cachedItemPtr && _heldTargets.Count > 0)
				{
					MergeTargets();
					return;
				}
				_cachedItemPtr = num;
				ReleaseHeld();
				try
				{
					Il2CppReferenceArray<Component> componentsInChildren = ((Component)wieldedItem).gameObject.GetComponentsInChildren(Il2CppType.Of<Renderer>(), true);
					if (componentsInChildren != null)
					{
						for (int i = 0; i < ((Il2CppArrayBase<Component>)(object)componentsInChildren).Length; i++)
						{
							Component val = ((Il2CppArrayBase<Component>)(object)componentsInChildren)[i];
							if ((Object)(object)val == (Object)null)
							{
								continue;
							}
							Renderer val2 = ((Il2CppObjectBase)val).TryCast<Renderer>();
							if (!((Object)(object)val2 == (Object)null))
							{
								Target target = TryMakeTarget(val2, SlotKind.Other, classifySlot: false, ownerIsPlayer: true);
								if (target != null)
								{
									_heldTargets.Add(target);
								}
							}
						}
					}
				}
				catch
				{
				}
				PreparePerTargetState();
				MergeTargets();
			}
			catch
			{
				_cachedInv = null;
				_wieldedTf = null;
			}
		}

		private static PlayerInventoryLocal FindLocalInventory()
		{
			PlayerInventoryLocal val = QueryInvs(Il2CppType.Of<PlayerInventoryLocal>());
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			try
			{
				Il2CppReferenceArray<Object> val2 = Resources.FindObjectsOfTypeAll(Il2CppType.Of<PlayerInventoryBase>());
				Plugin.Log.LogWarning((object)$"no PlayerInventoryLocal found (FindObjectsOfType=empty, FindObjectsOfTypeAll(PlayerInventoryBase) returned {((Il2CppArrayBase<Object>)(object)val2)?.Length ?? (-1)})");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("inventory probe failed: " + ex.Message));
			}
			return null;
		}

		private static PlayerInventoryLocal QueryInvs(Type t)
		{
			try
			{
				Il2CppReferenceArray<Object> val = Object.FindObjectsOfType(t);
				if (val != null)
				{
					for (int i = 0; i < ((Il2CppArrayBase<Object>)(object)val).Length; i++)
					{
						Object val2 = ((Il2CppArrayBase<Object>)(object)val)[i];
						if (!(val2 == (Object)null))
						{
							PlayerInventoryLocal val3 = ((Il2CppObjectBase)val2).TryCast<PlayerInventoryLocal>();
							if ((Object)(object)val3 != (Object)null)
							{
								return val3;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("FindObjectsOfType(PlayerInventoryLocal): " + ex.Message));
			}
			try
			{
				Il2CppReferenceArray<Object> val4 = Resources.FindObjectsOfTypeAll(t);
				if (val4 != null)
				{
					for (int j = 0; j < ((Il2CppArrayBase<Object>)(object)val4).Length; j++)
					{
						Object val5 = ((Il2CppArrayBase<Object>)(object)val4)[j];
						if (!(val5 == (Object)null))
						{
							PlayerInventoryLocal val6 = ((Il2CppObjectBase)val5).TryCast<PlayerInventoryLocal>();
							if ((Object)(object)val6 != (Object)null)
							{
								return val6;
							}
						}
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("FindObjectsOfTypeAll(PlayerInventoryLocal): " + ex2.Message));
			}
			return null;
		}

		private void ReleaseHeld()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _heldTargets.Count; i++)
			{
				Renderer rend = _heldTargets[i].rend;
				if (!((Object)(object)rend == (Object)null))
				{
					try
					{
						rend.GetPropertyBlock(_mpb);
						_mpb.SetColor("_EmissiveColor", _heldTargets[i].baseColor);
						rend.SetPropertyBlock(_mpb);
					}
					catch
					{
					}
				}
			}
			_heldTargets.Clear();
		}

		private void LogGearIfChanged(int matched, int seen, int invs, int wieldedNull)
		{
			string text = matched + "/" + seen + "/" + _lastGearPtr + "/" + invs + "/" + wieldedNull;
			if (!(text == _lastGearSig))
			{
				_lastGearSig = text;
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < _heldTargets.Count; i++)
				{
					stringBuilder.Append(_heldTargets[i].slot).Append(' ');
				}
				Plugin.Log.LogInfo((object)$"gear: {matched} held of {seen} cached; slots=[{stringBuilder.ToString().Trim()}]; inventoryFound={invs} wieldedNull={wieldedNull} finds={_invQueryCount} targets={_targets.Count}");
			}
		}

		private static void RefreshExclusions()
		{
			string text = Plugin.CfgExcludeNames.Value ?? "";
			if (text == _exclRaw)
			{
				return;
			}
			_exclRaw = text;
			List<string> list = new List<string>();
			string[] array = text.Split(new char[3] { ' ', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				if (text2.Length > 0)
				{
					list.Add(text2);
				}
			}
			_excl = list.ToArray();
		}

		private static bool IsEquipment(Renderer r)
		{
			try
			{
				GameObject gameObject = ((Component)r).gameObject;
				if ((Object)(object)gameObject.GetComponentInParent(Il2CppType.Of<ItemEquippable>()) != (Object)null)
				{
					return true;
				}
				if ((Object)(object)gameObject.GetComponentInParent(Il2CppType.Of<PlayerAgent>()) != (Object)null)
				{
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsExcluded(Renderer r, Material m)
		{
			if (_excl.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < _excl.Length; i++)
			{
				string value = _excl[i];
				string text = null;
				try
				{
					if ((Object)(object)m != (Object)null)
					{
						text = ((Object)m).name;
					}
				}
				catch
				{
				}
				if (text != null && text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				Transform val = null;
				try
				{
					val = ((Component)r).transform;
				}
				catch
				{
				}
				for (int j = 0; j < 5; j++)
				{
					if (!((Object)(object)val != (Object)null))
					{
						break;
					}
					string text2 = null;
					try
					{
						text2 = ((Object)((Component)val).gameObject).name;
					}
					catch
					{
					}
					if (text2 != null && text2.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
					try
					{
						val = val.parent;
					}
					catch
					{
						val = null;
					}
				}
			}
			return false;
		}

		private static string Describe(Renderer r)
		{
			try
			{
				Transform val = null;
				try
				{
					val = ((Component)r).transform;
				}
				catch
				{
				}
				string text = (((Object)(object)val != (Object)null) ? ((Object)((Component)val).gameObject).name : "?");
				try
				{
					val = val.parent;
				}
				catch
				{
					val = null;
				}
				for (int i = 0; i < 3; i++)
				{
					if (!((Object)(object)val != (Object)null))
					{
						break;
					}
					text = ((Object)((Component)val).gameObject).name + "/" + text;
					try
					{
						val = val.parent;
					}
					catch
					{
						val = null;
					}
				}
				return text;
			}
			catch
			{
				return "?";
			}
		}

		private static void NoteScenery(Renderer r, Material m)
		{
			try
			{
			}
			catch
			{
			}
		}

		private static void NoteExcluded(Renderer r, Material m)
		{
			try
			{
			}
			catch
			{
			}
		}

		private static void NoteMatched(Renderer r, Material m)
		{
			try
			{
			}
			catch
			{
			}
		}

		private Target TryMakeTarget(Renderer r, SlotKind slot, bool classifySlot, bool ownerIsPlayer)
		{
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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)
			long key = 0L;
			bool flag = false;
			try
			{
				key = ((Il2CppObjectBase)r).Pointer.ToInt64();
				flag = true;
			}
			catch
			{
			}
			if (flag && _known.TryGetValue(key, out var value))
			{
				if (value != null && (Object)(object)value.rend != (Object)null)
				{
					return value;
				}
				_known.Remove(key);
			}
			RefreshExclusions();
			Material val = null;
			try
			{
				val = r.sharedMaterial;
			}
			catch
			{
				return null;
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			string text = Plugin.CfgShaderFilter.Value ?? "";
			string text2 = "";
			try
			{
				if ((Object)(object)val.shader != (Object)null)
				{
					text2 = ((Object)val.shader).name;
				}
			}
			catch
			{
			}
			if (text.Length > 0 && text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) < 0)
			{
				return null;
			}
			bool flag2 = false;
			try
			{
				flag2 = val.HasProperty("_EmissiveColor");
			}
			catch
			{
			}
			if (!flag2)
			{
				return null;
			}
			if (Plugin.CfgRequireEmissiveMap.Value)
			{
				bool flag3 = false;
				try
				{
					flag3 = (Object)(object)val.GetTexture("_EmissiveMap") != (Object)null;
				}
				catch
				{
				}
				if (!flag3)
				{
					return null;
				}
			}
			if (!ownerIsPlayer && Plugin.CfgEquipmentOnly.Value && !IsEquipment(r))
			{
				NoteScenery(r, val);
				return null;
			}
			if (IsExcluded(r, val))
			{
				NoteExcluded(r, val);
				return null;
			}
			if (classifySlot)
			{
				try
				{
					slot = Classify(r);
				}
				catch
				{
				}
			}
			Color color;
			try
			{
				color = val.GetColor("_EmissiveColor");
			}
			catch
			{
				return null;
			}
			NoteMatched(r, val);
			Target target = new Target();
			target.rend = r;
			target.baseColor = color;
			target.slot = slot;
			target.phase = Random.value;
			target.sparkTimer = Random.Range(0.2f, 2f);
			target.along = NextAlong();
			target.alongDone = true;
			if (flag)
			{
				_known[key] = target;
				if (_known.Count > 4000)
				{
					_known.Clear();
				}
			}
			return target;
		}

		private void Scan()
		{
			_scanCache.Clear();
			_owners = 0;
			int seen = 0;
			try
			{
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				AddFromQuery(Il2CppType.Of<ItemEquippable>(), ref seen);
				AddFromQuery(Il2CppType.Of<PlayerAgent>(), ref seen);
				MergeTargets();
				float num = (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f;
				Plugin.Log.LogInfo((object)$"scan: {_owners} owner(s), {seen} renderer(s), {_scanCache.Count} in scene, {_heldTargets.Count} held, {_targets.Count} merged, took {num:F0} ms");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("scan failed: " + ex));
			}
		}

		private void AddFromQuery(Type type, ref int seen)
		{
			try
			{
				Il2CppReferenceArray<Object> val = Resources.FindObjectsOfTypeAll(type);
				if (val == null)
				{
					return;
				}
				for (int i = 0; i < ((Il2CppArrayBase<Object>)(object)val).Length; i++)
				{
					Object val2 = ((Il2CppArrayBase<Object>)(object)val)[i];
					if (val2 == (Object)null)
					{
						continue;
					}
					Component val3 = null;
					try
					{
						val3 = ((Il2CppObjectBase)val2).TryCast<Component>();
					}
					catch
					{
					}
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					GameObject val4 = null;
					try
					{
						val4 = val3.gameObject;
					}
					catch
					{
					}
					if ((Object)(object)val4 == (Object)null)
					{
						continue;
					}
					_owners++;
					try
					{
						Component componentInParent = val4.GetComponentInParent(Il2CppType.Of<PlayerInventoryBase>());
						if ((Object)(object)componentInParent != (Object)null)
						{
							PlayerInventoryBase val5 = ((Il2CppObjectBase)componentInParent).TryCast<PlayerInventoryBase>();
							PlayerInventoryLocal val6 = (((Object)(object)val5 != (Object)null) ? ((Il2CppObjectBase)val5).TryCast<PlayerInventoryLocal>() : null);
							if ((Object)(object)val6 != (Object)null)
							{
								bool flag = false;
								try
								{
									flag = (Object)(object)((PlayerInventoryBase)val6).WieldedItem != (Object)null;
								}
								catch
								{
								}
								bool flag2 = (Object)(object)_cachedInv == (Object)null;
								if (!flag2 && flag)
								{
									try
									{
										flag2 = ((Il2CppObjectBase)_cachedInv).Pointer != ((Il2CppObjectBase)val6).Pointer;
									}
									catch
									{
										flag2 = false;
									}
								}
								if (flag2)
								{
									_cachedInv = val6;
									_cachedItemPtr = 0;
									Plugin.Log.LogInfo((object)("[scan] local inventory captured from '" + ((Object)val4).name + "' wielded=" + (flag ? "yes" : "no")));
								}
							}
						}
					}
					catch
					{
					}
					try
					{
						Il2CppReferenceArray<Component> componentsInChildren = val4.GetComponentsInChildren(Il2CppType.Of<Renderer>(), true);
						if (componentsInChildren == null)
						{
							continue;
						}
						for (int j = 0; j < ((Il2CppArrayBase<Component>)(object)componentsInChildren).Length; j++)
						{
							Component val7 = ((Il2CppArrayBase<Component>)(object)componentsInChildren)[j];
							if ((Object)(object)val7 == (Object)null)
							{
								continue;
							}
							Renderer val8 = ((Il2CppObjectBase)val7).TryCast<Renderer>();
							if (!((Object)(object)val8 == (Object)null))
							{
								seen++;
								Target target = TryMakeTarget(val8, SlotKind.Other, classifySlot: false, ownerIsPlayer: true);
								if (target != null)
								{
									_scanCache.Add(target);
								}
							}
						}
					}
					catch
					{
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("scan query", e);
			}
		}

		private void ClearOverrides()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				for (int i = 0; i < _targets.Count; i++)
				{
					Renderer rend = _targets[i].rend;
					if (!((Object)(object)rend == (Object)null))
					{
						try
						{
							rend.GetPropertyBlock(_mpb);
							_mpb.SetColor("_EmissiveColor", _targets[i].baseColor);
							rend.SetPropertyBlock(_mpb);
						}
						catch
						{
						}
					}
				}
				for (int j = 0; j < _heldTargets.Count; j++)
				{
					Renderer rend2 = _heldTargets[j].rend;
					if (!((Object)(object)rend2 == (Object)null))
					{
						try
						{
							rend2.GetPropertyBlock(_mpb);
							_mpb.SetColor("_EmissiveColor", _heldTargets[j].baseColor);
							rend2.SetPropertyBlock(_mpb);
						}
						catch
						{
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("clear failed: " + ex));
			}
		}
	}
	public static class SettingsPage
	{
		private class BoolRow
		{
			public TextMeshPro label;

			public Func<bool> getter;
		}

		private static readonly Color Accent = new Color(0.42f, 0.86f, 0.75f, 1f);

		private const string PageLabel = "效果";

		private static CM_PageSettings _page;

		private static CM_ScrollWindow _window;

		private static readonly List<BoolRow> _rows = new List<BoolRow>();

		private static CM_Item _button;

		private static TextMeshPro _buttonTmp;

		public static CM_SettingsInputField ColorInputField;

		public static string ColorInputLastAccepted = "";

		private static GameObject _colorPopupRoot;

		internal static CM_ScrollWindow _pageWindow;

		private static readonly List<GameObject> _colorPopupItems = new List<GameObject>();

		public static bool HexEditing;

		private static string _hexBuffer = "";

		private static float _lastHexStop;

		private static readonly List<TextMeshPro> _hexDisplayTmps = new List<TextMeshPro>();

		private static readonly KeyCode[] _hexKeyMap;

		private static readonly string[] _hexKeyChar;

		private static GameObject _ddEntryPrefab;

		private static CM_SettingsStringArrayDropdownButton _ddWrapper;

		private static TextMeshPro _ddValueText;

		private static CM_ScrollWindow _colorSubWin;

		private static readonly List<TextMeshPro> _colorSubRowTmps;

		private static readonly List<RectTransform> _colorSubRowRTs;

		private static bool _level3Open;

		private static float _lastSubClose;

		public static bool IsColorPanelOpen => _level3Open;

		[HarmonyPatch(typeof(CM_PageSettings), "Setup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		[HarmonyPriority(600)]
		public static void Postfix_Setup(CM_PageSettings __instance)
		{
			try
			{
				if (Plugin.Log != null)
				{
					Build(__instance);
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogError((object)("[settings] build failed: " + ex));
				}
			}
		}

		private static void Build(CM_PageSettings page)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)page == (Object)null)
			{
				return;
			}
			if ((Object)(object)_window != (Object)null)
			{
				_page = page;
				return;
			}
			_page = page;
			_rows.Clear();
			CM_Item val = null;
			try
			{
				val = page.CreateSingleButton(page.m_subMenuButtonPrefab, 0u);
				if ((Object)(object)val != (Object)null)
				{
					StyleButton(val, "效果");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[settings] CreateSingleButton failed: " + ex));
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[settings] no sidebar button - tab will not appear");
				return;
			}
			CM_ScrollWindow window = null;
			try
			{
				RectTransformComp val2 = ((GuiLayer)((CM_PageBase)page).m_guiLayer).AddRectComp(page.m_scrollwindowPrefab, (GuiAnchor)1, new Vector2(420f, -200f), (Transform)(object)((CM_PageBase)page).m_movingContentHolder);
				window = ((Il2CppObjectBase)val2).TryCast<CM_ScrollWindow>();
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("[settings] AddRectComp failed: " + ex2));
			}
			if ((Object)(object)window == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[settings] no content window - tab will not appear");
				return;
			}
			try
			{
				window.Setup(((Component)page).transform);
				((RectTransformComp)window).SetSize(new Vector2(1020f, 900f));
				((RectTransformComp)window).SetVisible(false);
				page.m_allSettingsWindows.Add(window);
				try
				{
					Il2CppReferenceArray<CM_ScrollWindowHeader> headers = window.m_headers;
					if (headers != null && ((Il2CppArrayBase<CM_ScrollWindowHeader>)(object)headers).Length > 0)
					{
						CM_ScrollWindowHeader val3 = ((Il2CppArrayBase<CM_ScrollWindowHeader>)(object)headers)[0];
						if ((Object)(object)val3 != (Object)null)
						{
							TextMeshPro componentInChildren = ((Component)val3).GetComponentInChildren<TextMeshPro>();
							if ((Object)(object)componentInChildren != (Object)null)
							{
								((TMP_Text)componentInChildren).SetText("效果", true);
							}
						}
					}
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogWarning((object)("[settings] header text: " + ex3.Message));
				}
				Populate(page, window);
				_window = window;
				Action<int> onClick = delegate
				{
					try
					{
						CloseColorPopup();
						page.ResetAllInputFields();
						page.ResetAllValueHolders();
						page.m_currentSubMenuId = (eSettingsSubMenuId)0;
						SwapTo(page, window);
					}
					catch (Exception ex5)
					{
						Plugin.Log.LogError((object)("[settings] switch failed: " + ex5));
					}
				};
				WireClick(val, onClick);
				Plugin.Log.LogInfo((object)"[settings] 呼吸 page added");
			}
			catch (Exception ex4)
			{
				Plugin.Log.LogError((object)("[settings] window setup failed: " + ex4));
			}
		}

		private static void Populate(CM_PageSettings page, CM_ScrollWindow window)
		{
			try
			{
				_rows.Clear();
			}
			catch
			{
			}
			ColorInputField = null;
			_ddEntryPrefab = null;
			_ddWrapper = null;
			_ddValueText = null;
			try
			{
				if ((Object)(object)_colorSubWin != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_colorSubWin).gameObject);
				}
			}
			catch
			{
			}
			_colorSubWin = null;
			_colorSubRowTmps.Clear();
			_level3Open = false;
			_colorPopupItems.Clear();
			List<iScrollWindowContent> val = new List<iScrollWindowContent>();
			AddHeader(page, window, val, "弹轨(独立)");
			AddToggle(page, window, val, "弹轨特效", "开火时从枪口到命中点画一条细的发光能量束,约 1.5 秒淡出。\n颜色用下面两行选;时长 / 宽度在配置文件的 [Trajectory] 段改。", () => TrajectoryCfg.Enabled.Value, delegate(bool v)
			{
				TrajectoryCfg.Enabled.Value = v;
			});
			AddColorDropdownV3(page, window, val, "弹轨颜色 >", "点开在右侧浮出 14 个预设色,点一下即选中,下一枪生效;再点一次收起。\n★ 想用任意颜色:用下面的「弹轨颜色代码」。");
			AddColorInput(page, window, val, "弹轨颜色代码", "点一下进入输入状态,直接键入十六进制(0-9 / A-F)。\n★ Enter 确认,Esc 取消,Backspace 删格;输满 6 位实时预览颜色。");
			AddHeader(page, window, val, "总开关");
			AddToggle(page, window, val, "总开关", "", () => Plugin.CfgEnabled.Value, delegate(bool v)
			{
				Plugin.CfgEnabled.Value = v;
			});
			AddHeader(page, window, val, "扫描");
			AddToggle(page, window, val, "关闭扫描", "完全关闭扫描,彻底避免扫描带来的卡顿。\n效果仍会显示,但不再自动更新。", () => IsScanMode("Off"), delegate(bool v)
			{
				SetScanMode(v ? "Off" : "Test");
			});
			AddToggle(page, window, val, "效果尝试扫描", "持续扫描,响应最快。\n★ 会占用帧率,可能有卡顿风险。", () => IsScanMode("Test"), delegate(bool v)
			{
				if (!IsScanMode("Off"))
				{
					SetScanMode(v ? "Test" : "Confirmed");
				}
			});
			AddToggle(page, window, val, "手动确认扫描", "选好效果后点一下,执行一次完整扫描并固定下来。\n★ 此后不再自动扫描;扫描完成后开关自动弹回。", () => Plugin.ManualScanPending, delegate(bool v)
			{
				if (v && !IsScanMode("Off"))
				{
					Plugin.CfgScanMode.Value = "Confirmed";
					Plugin.ManualScanPending = true;
					Plugin.NeedScan = true;
				}
			});
			AddHeader(page, window, val, "基础");
			AddEffect(page, window, val, "常亮", "Solid");
			AddEffect(page, window, val, "呼吸", "Breathing");
			AddEffect(page, window, val, "警报", "Alarm");
			AddEffect(page, window, val, "故障闪烁", "Flicker");
			AddEffect(page, window, val, "充能", "Charge");
			AddEffect(page, window, val, "色相流动", "Hue");
			AddHeader(page, window, val, "逐部件");
			AddEffect(page, window, val, "星空闪烁", "Twinkle");
			AddEffect(page, window, val, "随机火花", "Sparks");
			AddEffect(page, window, val, "噪声流动", "NoiseDrift");
			AddEffect(page, window, val, "反相呼吸", "AntiPhase");
			AddHeader(page, window, val, "位置");
			AddEffect(page, window, val, "流光扫描", "Sweep");
			AddEffect(page, window, val, "逐段轮转", "Chase");
			AddEffect(page, window, val, "前后渐变", "Gradient");
			AddEffect(page, window, val, "彩虹分布", "Rainbow");
			AddHeader(page, window, val, "颜色");
			AddEffect(page, window, val, "炽热", "Heat");
			AddEffect(page, window, val, "冷焰", "ColdFire");
			AddEffect(page, window, val, "余烬", "Ember");
			AddHeader(page, window, val, "状态");
			AddEffect(page, window, val, "心跳", "Heartbeat");
			AddEffect(page, window, val, "低血量警示", "LowHealth");
			try
			{
				window.SetContentItems(val, 5f);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[settings] SetContentItems failed: " + ex));
			}
		}

		private static CM_SettingsItem CreateItem(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label)
		{
			if ((Object)(object)page.m_settingsItemPrefab == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(page.m_settingsItemPrefab, ((Component)window).transform);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			CM_SettingsItem component = val.GetComponent<CM_SettingsItem>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			try
			{
				((CM_Item)component).TextMeshRoot = ((Component)page).transform;
			}
			catch
			{
			}
			try
			{
				Transform val2 = val.transform.Find("Title/TitleText");
				TextMeshPro val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TextMeshPro>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					((TMP_Text)val3).SetText(label, true);
				}
				else
				{
					((CM_Item)component).SetText(label);
				}
			}
			catch
			{
				try
				{
					((CM_Item)component).SetText(label);
				}
				catch
				{
				}
			}
			try
			{
				((RectTransformComp)component).ForcePopupLayer(true, (GameObject)null);
			}
			catch
			{
			}
			try
			{
				iScrollWindowContent val4 = ((Il2CppObjectBase)component).TryCast<iScrollWindowContent>();
				if (val4 != null)
				{
					items.Add(val4);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[settings] item cast failed: " + ex.Message));
			}
			return component;
		}

		public static void Tick()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Object)(object)_buttonTmp == (Object)null) && !((Object)(object)_button == (Object)null))
				{
					string text = null;
					try
					{
						text = ((TMP_Text)_buttonTmp).text;
					}
					catch
					{
					}
					if (text != "效果")
					{
						((TMP_Text)_buttonTmp).SetText("效果", true);
						((Graphic)_buttonTmp).color = new Color(1f, 1f, 1f, 1f);
					}
				}
			}
			catch
			{
			}
		}

		private static void StyleButton(CM_Item item, string label)
		{
			//IL_0032: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			TextMeshPro val = null;
			int num = -1;
			try
			{
				val = ((Component)item).GetComponentInChildren<TextMeshPro>(true);
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)val).SetText(label, true);
					((Graphic)val).color = new Color(1f, 1f, 1f, 1f);
					_button = item;
					_buttonTmp = val;
				}
				else
				{
					item.SetText(label);
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogWarning((object)("[settings] button text failed: " + ex.Message));
				}
			}
			try
			{
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(1f, 1f, 1f, 1f);
				item.m_spriteColorOrg = val2;
				item.m_spriteColorOut = new Color(1f, 1f, 1f, item.m_spriteAlphaOut);
				item.m_spriteColorOver = new Color(1f, 1f, 1f, item.m_spriteAlphaOver);
				Il2CppReferenceArray<TextMeshPro> texts = item.m_texts;
				num = ((Il2CppArrayBase<TextMeshPro>)(object)texts)?.Length ?? (-1);
				if (texts != null)
				{
					for (int i = 0; i < ((Il2CppArrayBase<TextMeshPro>)(object)texts).Length; i++)
					{
						((Il2CppArrayBase<Color>)(object)item.m_textColorOrg)[i] = val2;
						((Il2CppArrayBase<Color>)(object)item.m_textColorOut)[i] = new Color(1f, 1f, 1f, item.m_textAlphaOut);
						((Il2CppArrayBase<Color>)(object)item.m_textColorOver)[i] = new Color(1f, 1f, 1f, item.m_textAlphaOver);
					}
				}
				item.OnHoverOut();
			}
			catch (Exception ex2)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogWarning((object)("[settings] button colour failed: " + ex2.Message));
				}
			}
			if (Plugin.Log == null)
			{
				return;
			}
			string text = "?";
			bool flag = false;
			string text2 = "?";
			if ((Object)(object)val != (Object)null)
			{
				try
				{
					text = ((Object)((Component)val).gameObject).name;
				}
				catch
				{
				}
				try
				{
					flag = ((Component)val).gameObject.activeInHierarchy;
				}
				catch
				{
				}
				try
				{
					text2 = ((TMP_Text)val).text;
				}
				catch
				{
				}
			}
			Plugin.Log.LogInfo((object)$"[settings] button styled: tmp={(Object)(object)val != (Object)null} name='{text}' active={flag} textAfter='{text2}' m_texts={num} alphaOut={item.m_textAlphaOut}");
		}

		private static void AddHeader(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CM_SettingsItem val = CreateItem(page, window, items, label);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				try
				{
					((Renderer)val.m_background).enabled = false;
				}
				catch
				{
				}
				RectTransform component = ((Component)val).gameObject.GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					component.sizeDelta = new Vector2(component.sizeDelta.x, component.sizeDelta.y * 1.5f);
				}
				try
				{
					Transform val2 = ((Component)val).transform.Find("Title/TitleText");
					TextMeshPro val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TextMeshPro>() : null);
					if ((Object)(object)val3 != (Object)null)
					{
						((Graphic)val3).color = Accent;
						((TMP_Text)val3).alignment = (TextAlignmentOptions)513;
						((TMP_Text)val3).fontSizeMax = ((TMP_Text)val3).fontSizeMax * 1.5f;
					}
				}
				catch
				{
				}
				try
				{
					BoxCollider2D component2 = ((Component)val).gameObject.GetComponent<BoxCollider2D>();
					if ((Object)(object)component2 != (Object)null)
					{
						((Behaviour)component2).enabled = false;
					}
				}
				catch
				{
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[settings] AddHeader failed: " + ex));
			}
		}

		private static bool IsScanMode(string id)
		{
			try
			{
				return string.Equals(Plugin.CfgScanMode.Value, id, StringComparison.OrdinalIgnoreCase);
			}
			catch
			{
				return false;
			}
		}

		private static void SetScanMode(string id)
		{
			try
			{
				Plugin.CfgScanMode.Value = id;
				Plugin.NeedScan = true;
				Plugin.Log.LogInfo((object)("[settings] scan mode -> " + id));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[settings] SetScanMode: " + ex));
			}
		}

		private static void AddEffect(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label, string modeId)
		{
			AddToggle(page, window, items, label, "", () => string.Equals(Plugin.CfgMode.Value, modeId, StringComparison.OrdinalIgnoreCase), delegate
			{
				Plugin.CfgMode.Value = modeId;
				RefreshRows();
			});
		}

		public static void RefreshRows()
		{
			for (int i = 0; i < _rows.Count; i++)
			{
				Refresh(_rows[i]);
			}
		}

		private static string[] TrajColorNames()
		{
			try
			{
				return TrajectoryBehaviour.PresetNames;
			}
			catch
			{
				return new string[0];
			}
		}

		private static string[] TrajColorHexes()
		{
			try
			{
				return TrajectoryBehaviour.PresetHexes;
			}
			catch
			{
				return new string[0];
			}
		}

		private static int TrajColorIndex()
		{
			try
			{
				string[] array = TrajColorHexes();
				string text = (TrajectoryCfg.ColorHex.Value ?? "").Trim().ToUpperInvariant();
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i].ToUpperInvariant() == text)
					{
						return i;
					}
				}
			}
			catch
			{
			}
			return 0;
		}

		private static void AddColorDropdown(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label, string tooltip)
		{
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			try
			{
				CM_SettingsItem val = CreateItem(page, window, items, label);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"[settings] dd: CreateItem null");
					return;
				}
				GameObject val2 = null;
				try
				{
					val2 = Object.Instantiate<GameObject>(val.m_stringArrayDropdownInputPrefab, val.m_inputAlign, false);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[settings] dd instantiate: " + ex.Message));
				}
				if ((Object)(object)val2 != (Object)null)
				{
					DumpPrefabComponents("stringArrayDropdown", val2);
					try
					{
						Plugin.Log.LogInfo((object)("[settings] dd prefab root = " + ((Object)val2).name));
					}
					catch
					{
					}
					try
					{
						Component componentInChildren = val2.GetComponentInChildren(Il2CppType.Of<CM_DropdownButton_StringArray>());
						CM_DropdownButton_StringArray val3 = (((Object)(object)componentInChildren != (Object)null) ? ((Il2CppObjectBase)componentInChildren).TryCast<CM_DropdownButton_StringArray>() : null);
						if ((Object)(object)val3 == (Object)null)
						{
							Plugin.Log.LogError((object)"[settings] dd: component not found on prefab");
						}
						else
						{
							string[] array = TrajColorNames();
							string[] hexes = TrajColorHexes();
							val3.SetStrings(Il2CppStringArray.op_Implicit(array));
							val3.SetStartValue((uint)TrajColorIndex());
							val3.OnSelectionChanged = Action<int>.op_Implicit((Action<int>)delegate(int idx)
							{
								try
								{
									if (idx >= 0 && idx < hexes.Length)
									{
										TrajectoryCfg.ColorHex.Value = hexes[idx];
										Plugin.Log.LogInfo((object)("[settings] traj color -> " + hexes[idx]));
									}
								}
								catch
								{
								}
							});
							Plugin.Log.LogInfo((object)("[settings] color dropdown added (" + array.Length + " colors)"));
						}
					}
					catch (Exception ex2)
					{
						Plugin.Log.LogError((object)("[settings] dd setup: " + ex2.Message));
					}
				}
				if (!string.IsNullOrEmpty(tooltip))
				{
					try
					{
						((CM_Item)val).TooltipInfo = new TooltipInfo
						{
							PositionType = (TooltipPositionType)1,
							TooltipHeader = label,
							TooltipText = tooltip,
							UseTooptip = true
						};
					}
					catch
					{
					}
				}
				try
				{
					GameObject val4 = Object.Instantiate<GameObject>(val.m_colorInputPrefab, val.m_inputAlign, false);
					if ((Object)(object)val4 != (Object)null)
					{
						DumpPrefabComponents("colorInput", val4);
						Object.Destroy((Object)(object)val4);
					}
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogWarning((object)("[dd] colorInput instantiate: " + ex3.Message));
				}
				try
				{
					GameObject val5 = Object.Instantiate<GameObject>(val.m_enumDropdownInputPrefab, val.m_inputAlign, false);
					if ((Object)(object)val5 != (Object)null)
					{
						DumpPrefabComponents("enumDropdown", val5);
						Object.Destroy((Object)(object)val5);
					}
				}
				catch (Exception ex4)
				{
					Plugin.Log.LogWarning((object)("[dd] enumDropdown instantiate: " + ex4.Message));
				}
				try
				{
					GameObject val6 = Object.Instantiate<GameObject>(val.m_textInputPrefab, val.m_inputAlign, false);
					if ((Object)(object)val6 != (Object)null)
					{
						DumpPrefabComponents("textInput", val6);
						Object.Destroy((Object)(object)val6);
					}
				}
				catch (Exception ex5)
				{
					Plugin.Log.LogWarning((object)("[dd] textInput instantiate: " + ex5.Message));
				}
			}
			catch (Exception ex6)
			{
				Plugin.Log.LogError((object)("[settings] AddColorDropdown: " + ex6));
			}
		}

		private static void AddColorDropdownV2(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label, string tooltip)
		{
			//IL_0dd9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dde: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c3: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_1311: Unknown result type (might be due to invalid IL or missing references)
			//IL_1316: Unknown result type (might be due to invalid IL or missing references)
			//IL_1332: Unknown result type (might be due to invalid IL or missing references)
			//IL_1337: Unknown result type (might be due to invalid IL or missing references)
			//IL_1353: Unknown result type (might be due to invalid IL or missing references)
			//IL_1358: Unknown result type (might be due to invalid IL or missing references)
			//IL_147a: Unknown result type (might be due to invalid IL or missing references)
			//IL_147f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1486: Unknown result type (might be due to invalid IL or missing references)
			//IL_148d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1495: Unknown result type (might be due to invalid IL or missing references)
			//IL_14a1: Expected O, but got Unknown
			//IL_11e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_11e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_11fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_1203: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CM_SettingsItem val = CreateItem(page, window, items, label);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"[dd2] CreateItem null");
					return;
				}
				GameObject val2 = null;
				try
				{
					val2 = Object.Instantiate<GameObject>(val.m_stringArrayDropdownInputPrefab, val.m_inputAlign, false);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[dd2] instantiate: " + ex.Message));
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				_pageWindow = window;
				try
				{
					CM_Item val3 = val2.AddComponent<CM_Item>();
					if ((Object)(object)val3 != (Object)null)
					{
						try
						{
							RectTransform rectTrans = ((RectTransformComp)val3).RectTrans;
							rectTrans.anchoredPosition3D = new Vector3(-300f, 25f, 100.1f);
							rectTrans.sizeDelta = new Vector2(600f, 50f);
							Plugin.Log.LogInfo((object)"[dd2] aligned to toggle rect (z=100.1)");
						}
						catch (Exception ex2)
						{
							Plugin.Log.LogWarning((object)("[dd2] pos: " + ex2.Message));
						}
						try
						{
							BoxCollider2D component = val2.GetComponent<BoxCollider2D>();
							if ((Object)(object)component != (Object)null)
							{
								component.size = new Vector2(550f, 50f);
								((Collider2D)component).offset = new Vector2(250f, -25f);
							}
						}
						catch
						{
						}
						try
						{
							Collider2D componentInChildren = ((Component)val3).GetComponentInChildren<Collider2D>();
							if ((Object)(object)componentInChildren != (Object)null)
							{
								((Behaviour)componentInChildren).enabled = false;
							}
						}
						catch
						{
						}
						Plugin.Log.LogInfo((object)"[dd2] CM_Item added + positioned");
					}
					else
					{
						Plugin.Log.LogError((object)"[dd2] AddComponent<CM_Item> returned null");
					}
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogError((object)("[dd2] CM_Item: " + ex3.Message));
				}
				DumpRT("dropdown", val2.transform);
				CM_SettingsStringArrayDropdownButton wrapper = null;
				try
				{
					Component componentInChildren2 = val2.GetComponentInChildren(Il2CppType.Of<CM_SettingsStringArrayDropdownButton>());
					wrapper = (((Object)(object)componentInChildren2 != (Object)null) ? ((Il2CppObjectBase)componentInChildren2).TryCast<CM_SettingsStringArrayDropdownButton>() : null);
				}
				catch (Exception ex4)
				{
					Plugin.Log.LogWarning((object)("[dd2] wrapper: " + ex4.Message));
				}
				Plugin.Log.LogInfo((object)("[dd2] wrapper found = " + ((Object)(object)wrapper != (Object)null)));
				CM_DropdownButton_StringArray dd = null;
				try
				{
					Component val4 = val2.AddComponent(Il2CppType.Of<CM_DropdownButton_StringArray>());
					dd = (((Object)(object)val4 != (Object)null) ? ((Il2CppObjectBase)val4).TryCast<CM_DropdownButton_StringArray>() : null);
				}
				catch (Exception ex5)
				{
					Plugin.Log.LogError((object)("[dd2] AddComponent: " + ex5.Message));
				}
				if ((Object)(object)dd == (Object)null)
				{
					Plugin.Log.LogError((object)"[dd2] dropdown component null");
					return;
				}
				if ((Object)(object)wrapper != (Object)null)
				{
					try
					{
						dd.m_popupItemPrefab = wrapper.m_popupItemPrefab;
					}
					catch (Exception ex6)
					{
						Plugin.Log.LogWarning((object)("[dd2] popupItemPrefab: " + ex6.Message));
					}
					try
					{
						dd.m_popupWindowAlign = wrapper.m_popupWindowAlign;
					}
					catch (Exception ex7)
					{
						Plugin.Log.LogWarning((object)("[dd2] popupWindowAlign: " + ex7.Message));
					}
					try
					{
						dd.m_basePage = (CM_PageBase)(object)wrapper.m_basePage;
					}
					catch
					{
					}
					try
					{
						dd.m_popupWindow = wrapper.m_popupWindow;
					}
					catch
					{
					}
					try
					{
						dd.m_currentValue = wrapper.m_currentValue;
						Plugin.Log.LogInfo((object)("[dd2] m_currentValue copied = " + ((Object)(object)dd.m_currentValue != (Object)null)));
					}
					catch (Exception ex8)
					{
						Plugin.Log.LogWarning((object)("[dd2] currentValue: " + ex8.Message));
					}
				}
				if ((Object)(object)dd.m_currentValue == (Object)null)
				{
					try
					{
						Component componentInChildren3 = val2.GetComponentInChildren(Il2CppType.Of<TextMeshPro>());
						TextMeshPro val5 = (((Object)(object)componentInChildren3 != (Object)null) ? ((Il2CppObjectBase)componentInChildren3).TryCast<TextMeshPro>() : null);
						if ((Object)(object)val5 != (Object)null)
						{
							dd.m_currentValue = val5;
							Plugin.Log.LogInfo((object)"[dd2] m_currentValue from children = True");
						}
						else
						{
							Plugin.Log.LogError((object)"[dd2] no TextMeshPro found for m_currentValue");
						}
					}
					catch (Exception ex9)
					{
						Plugin.Log.LogWarning((object)("[dd2] find TMP: " + ex9.Message));
					}
				}
				try
				{
					dd.Setup((CM_PageBase)(object)page, window, 0u);
					Plugin.Log.LogInfo((object)"[dd2] Setup ok");
				}
				catch (Exception ex10)
				{
					Plugin.Log.LogError((object)("[dd2] Setup: " + ex10.Message));
				}
				string[] names = TrajectoryBehaviour.PresetNames;
				string[] hexes = TrajectoryBehaviour.PresetHexes;
				try
				{
					string text = "basePage=" + ((Object)(object)dd.m_basePage != (Object)null) + " popupWindow=" + ((Object)(object)dd.m_popupWindow != (Object)null) + " popupItemPrefab=" + ((Object)(object)dd.m_popupItemPrefab != (Object)null) + " popupWindowAlign=" + ((Object)(object)dd.m_popupWindowAlign != (Object)null) + " strings=" + (dd.m_strings != null) + " currentValue=" + ((Object)(object)dd.m_currentValue != (Object)null);
					Plugin.Log.LogInfo((object)("[dd2] state: " + text));
				}
				catch (Exception ex11)
				{
					Plugin.Log.LogWarning((object)("[dd2] state: " + ex11.Message));
				}
				try
				{
					Il2CppStringArray val6 = new Il2CppStringArray((long)names.Length);
					for (int i = 0; i < names.Length; i++)
					{
						((Il2CppArrayBase<string>)(object)val6)[i] = names[i];
					}
					dd.SetStrings(val6);
					Plugin.Log.LogInfo((object)("[dd2] SetStrings ok (" + names.Length + ")"));
				}
				catch (Exception ex12)
				{
					Plugin.Log.LogError((object)("[dd2] SetStrings: " + ex12.Message));
				}
				try
				{
					int startValue = 0;
					string text2 = (TrajectoryCfg.ColorHex.Value ?? "").Trim().ToUpperInvariant();
					for (int j = 0; j < hexes.Length; j++)
					{
						if (hexes[j].ToUpperInvariant() == text2)
						{
							startValue = j;
							break;
						}
					}
					dd.SetStartValue((uint)startValue);
					Plugin.Log.LogInfo((object)("[dd2] SetStartValue ok (" + startValue + ")"));
				}
				catch (Exception ex13)
				{
					Plugin.Log.LogError((object)("[dd2] SetStartValue: " + ex13.Message));
				}
				try
				{
					dd.UpdateText();
					Plugin.Log.LogInfo((object)"[dd2] UpdateText ok");
				}
				catch (Exception ex14)
				{
					Plugin.Log.LogWarning((object)("[dd2] UpdateText: " + ex14.Message));
				}
				try
				{
					int num = 0;
					string text3 = (TrajectoryCfg.ColorHex.Value ?? "").Trim().ToUpperInvariant();
					for (int k = 0; k < hexes.Length; k++)
					{
						if (hexes[k].ToUpperInvariant() == text3)
						{
							num = k;
							break;
						}
					}
					((TMP_Text)dd.m_currentValue).text = names[num] + "  " + hexes[num];
					((Behaviour)dd.m_currentValue).enabled = true;
					Plugin.Log.LogInfo((object)("[dd2] text forced -> " + names[num] + " " + hexes[num]));
				}
				catch (Exception ex15)
				{
					Plugin.Log.LogWarning((object)("[dd2] force text: " + ex15.Message));
				}
				try
				{
					dd.OnSelectionChanged = Action<int>.op_Implicit((Action<int>)delegate(int num12)
					{
						try
						{
							if (num12 >= 0 && num12 < hexes.Length)
							{
								TrajectoryCfg.ColorHex.Value = hexes[num12];
								Plugin.Log.LogInfo((object)("[dd2] selected -> " + hexes[num12]));
							}
						}
						catch
						{
						}
					});
					Plugin.Log.LogInfo((object)"[dd2] OnSelectionChanged ok");
				}
				catch (Exception ex16)
				{
					Plugin.Log.LogError((object)("[dd2] OnSelectionChanged: " + ex16.Message));
				}
				try
				{
					_ = new bool[1];
					WireClick((CM_Item)(object)val, delegate
					{
						if (_colorPopupItems.Count > 0)
						{
							CloseColorPopup();
							Plugin.Log.LogInfo((object)"[cp] closed by click");
						}
						else
						{
							ShowColorPopup(wrapper, dd.m_currentValue, names, hexes);
						}
					});
					Plugin.Log.LogInfo((object)"[dd2] WireClick ok (custom popup)");
					try
					{
						Il2CppReferenceArray<Object> val7 = Resources.FindObjectsOfTypeAll(Il2CppType.Of<CM_SettingsStringArrayDropdownButton>());
						int num2 = 0;
						try
						{
							num2 = ((Il2CppArrayBase<Object>)(object)val7)?.Length ?? 0;
						}
						catch
						{
						}
						Plugin.Log.LogInfo((object)("[vpop] scan: found " + num2 + " wrappers"));
						for (int num3 = 0; num3 < num2 && num3 < 8; num3++)
						{
							try
							{
								Object val8 = ((Il2CppArrayBase<Object>)(object)val7)[num3];
								if (val8 == (Object)null)
								{
									continue;
								}
								CM_SettingsStringArrayDropdownButton val9 = ((Il2CppObjectBase)val8).TryCast<CM_SettingsStringArrayDropdownButton>();
								if ((Object)(object)val9 == (Object)null)
								{
									continue;
								}
								string text4 = "?";
								try
								{
									text4 = ((Object)((Component)val9).gameObject).name;
								}
								catch
								{
								}
								bool flag = false;
								bool flag2 = false;
								try
								{
									flag = val9.m_isSetup;
								}
								catch
								{
								}
								try
								{
									flag2 = (Object)(object)val9.m_popupWindow != (Object)null;
								}
								catch
								{
								}
								Plugin.Log.LogInfo((object)("[vpop] w[" + num3 + "] go='" + text4 + "' isSetup=" + flag + " popupWindow=" + flag2));
								if (!flag2)
								{
									continue;
								}
								CM_ScrollWindow popupWindow = val9.m_popupWindow;
								Transform transform = ((Component)popupWindow).transform;
								string text5 = "?";
								string text6 = "?";
								try
								{
									text5 = ((Object)((Component)popupWindow).gameObject).name;
								}
								catch
								{
								}
								try
								{
									text6 = (((Object)(object)transform.parent != (Object)null) ? ((Object)transform.parent).name : "(root)");
								}
								catch
								{
								}
								int num4 = 0;
								try
								{
									num4 = transform.childCount;
								}
								catch
								{
								}
								bool flag3 = false;
								try
								{
									flag3 = (Object)(object)popupWindow.m_contentContainer != (Object)null;
								}
								catch
								{
								}
								bool flag4 = false;
								try
								{
									flag4 = popupWindow.m_isSetup;
								}
								catch
								{
								}
								Plugin.Log.LogInfo((object)("[vpop]   win='" + text5 + "' parent='" + text6 + " children=" + num4 + " contentContainer=" + flag3 + " isSetup=" + flag4));
								for (int num5 = 0; num5 < num4 && num5 < 6; num5++)
								{
									try
									{
										Transform child = transform.GetChild(num5);
										if ((Object)(object)child != (Object)null)
										{
											Plugin.Log.LogInfo((object)("[vpop]     child[" + num5 + "] '" + ((Object)((Component)child).gameObject).name + "'"));
										}
									}
									catch
									{
									}
								}
							}
							catch
							{
							}
						}
					}
					catch (Exception ex17)
					{
						Plugin.Log.LogWarning((object)("[vpop] " + ex17.Message));
					}
					try
					{
						ShowColorPopup(wrapper, dd.m_currentValue, names, hexes);
						Plugin.Log.LogInfo((object)("[cp] SELFTEST built items=" + _colorPopupItems.Count));
						CloseColorPopup();
						Plugin.Log.LogInfo((object)"[cp] SELFTEST closed ok");
						return;
					}
					catch (Exception ex18)
					{
						Plugin.Log.LogError((object)("[cp] SELFTEST: " + ex18));
						return;
					}
				}
				catch (Exception ex19)
				{
					Plugin.Log.LogError((object)("[dd2] WireClick custom: " + ex19.Message));
				}
				try
				{
					bool[] popupState = new bool[1];
					WireClick((CM_Item)(object)val, delegate
					{
						if (popupState[0])
						{
							try
							{
								dd.SetPopupVisible(false);
								Plugin.Log.LogInfo((object)"[dd2] click -> popup closed");
							}
							catch (Exception ex29)
							{
								Plugin.Log.LogWarning((object)("[dd2] close: " + ex29.Message));
							}
							popupState[0] = false;
						}
						else
						{
							bool flag5 = false;
							try
							{
								dd.CreateAndShowEnumPopup();
								Plugin.Log.LogInfo((object)"[dd2] click -> CreateAndShowEnumPopup ok (list shown)");
								flag5 = true;
							}
							catch (Exception ex30)
							{
								Plugin.Log.LogWarning((object)("[dd2] CreateAndShowEnumPopup: " + ex30.Message));
							}
							if (!flag5)
							{
								try
								{
									dd.SetPopupVisible(true);
									Plugin.Log.LogInfo((object)"[dd2] click -> SetPopupVisible(true) ok (fallback)");
									flag5 = true;
								}
								catch (Exception ex31)
								{
									Plugin.Log.LogWarning((object)("[dd2] SetPopupVisible: " + ex31.Message));
								}
							}
							if (!flag5)
							{
								try
								{
									((CM_Item)dd).OnBtnPress((iCellMenuInputHandler)null);
									Plugin.Log.LogInfo((object)"[dd2] click -> OnBtnPress(null) ok (last resort)");
									return;
								}
								catch (Exception ex32)
								{
									Plugin.Log.LogError((object)("[dd2] OnBtnPress: " + ex32.Message));
									return;
								}
							}
							popupState[0] = true;
						}
					});
					Plugin.Log.LogInfo((object)"[dd2] WireClick ok");
					try
					{
						Action<int> prev = dd.OnSelectionChanged;
						dd.OnSelectionChanged = Action<int>.op_Implicit((Action<int>)delegate(int num12)
						{
							try
							{
								if (prev != null)
								{
									prev.Invoke(num12);
								}
							}
							catch
							{
							}
							try
							{
								if (num12 >= 0 && num12 < hexes.Length)
								{
									TrajectoryCfg.ColorHex.Value = hexes[num12];
								}
								((TMP_Text)dd.m_currentValue).text = names[num12] + "  " + hexes[num12];
							}
							catch
							{
							}
							try
							{
								dd.SetPopupVisible(false);
							}
							catch
							{
							}
							popupState[0] = false;
							Plugin.Log.LogInfo((object)("[dd2] selected -> " + ((num12 >= 0 && num12 < hexes.Length) ? hexes[num12] : "?") + " (popup closed)"));
						});
						Plugin.Log.LogInfo((object)"[dd2] OnSelectionChanged wrapped (auto-close)");
					}
					catch (Exception ex20)
					{
						Plugin.Log.LogError((object)("[dd2] wrap selection: " + ex20.Message));
					}
				}
				catch (Exception ex21)
				{
					Plugin.Log.LogError((object)("[dd2] WireClick: " + ex21.Message));
				}
				try
				{
					Il2CppReferenceArray<Object> val10 = Resources.FindObjectsOfTypeAll(Il2CppType.Of<CM_SettingsStringArrayDropdownButton>());
					if (val10 != null)
					{
						int num6 = 0;
						try
						{
							num6 = ((Il2CppArrayBase<Object>)(object)val10).Length;
						}
						catch
						{
						}
						Plugin.Log.LogInfo((object)("[cmp] 场景里下拉按钮数量 = " + num6));
						for (int num7 = 0; num7 < num6 && num7 < 12; num7++)
						{
							try
							{
								Object val11 = ((Il2CppArrayBase<Object>)(object)val10)[num7];
								if (val11 == (Object)null)
								{
									continue;
								}
								CM_SettingsStringArrayDropdownButton val12 = ((Il2CppObjectBase)val11).TryCast<CM_SettingsStringArrayDropdownButton>();
								if ((Object)(object)val12 == (Object)null)
								{
									continue;
								}
								string text7 = "?";
								string text8 = "?";
								try
								{
									text7 = ((Object)((Component)val12).gameObject).name;
								}
								catch
								{
								}
								try
								{
									text8 = (((Object)(object)((Component)val12).transform.parent != (Object)null) ? ((Object)((Component)val12).transform.parent).name : "(no parent)");
								}
								catch
								{
								}
								string text9 = "isSetup=" + val12.m_isSetup + " settingId=" + ((object)val12.m_settingId/*cast due to .constrained prefix*/).ToString() + " popupWindow=" + ((Object)(object)val12.m_popupWindow != (Object)null) + " popupAlign=" + ((Object)(object)val12.m_popupWindowAlign != (Object)null) + " basePage=" + ((Object)(object)val12.m_basePage != (Object)null) + " receiver=" + (val12.m_receiver != null) + " curValue=" + ((Object)(object)val12.m_currentValue != (Object)null);
								Plugin.Log.LogInfo((object)("[cmp] dd[" + num7 + "] go='" + text7 + "' parent='" + text8 + "' " + text9));
								if (!val12.m_isSetup || !((Object)(object)val12.m_popupWindow != (Object)null))
								{
									continue;
								}
								try
								{
									CM_ScrollWindow popupWindow2 = val12.m_popupWindow;
									Transform transform2 = ((Component)popupWindow2).transform;
									Plugin.Log.LogInfo((object)("[vpop] === 原版弹窗窗 === go='" + ((Object)((Component)popupWindow2).gameObject).name + "' active=" + ((Component)popupWindow2).gameObject.activeSelf + " parent='" + (((Object)(object)transform2.parent != (Object)null) ? ((Object)transform2.parent).name : "?") + "'"));
									try
									{
										Il2CppReferenceArray<iScrollWindowContent> contentItems = popupWindow2.ContentItems;
										int num8 = 0;
										try
										{
											num8 = ((Il2CppArrayBase<iScrollWindowContent>)(object)contentItems)?.Length ?? 0;
										}
										catch
										{
										}
										Plugin.Log.LogInfo((object)("[vpop] ContentItems=" + num8));
									}
									catch (Exception ex22)
									{
										Plugin.Log.LogWarning((object)("[vpop] ContentItems: " + ex22.Message));
									}
									try
									{
										Plugin.Log.LogInfo((object)("[vpop] m_contentContainer=" + ((Object)(object)popupWindow2.m_contentContainer != (Object)null) + " isSetup=" + popupWindow2.m_isSetup));
									}
									catch
									{
									}
									try
									{
										int childCount = transform2.childCount;
										Plugin.Log.LogInfo((object)("[vpop] childCount=" + childCount));
										for (int num9 = 0; num9 < childCount && num9 < 6; num9++)
										{
											try
											{
												Transform child2 = transform2.GetChild(num9);
												if ((Object)(object)child2 != (Object)null)
												{
													Plugin.Log.LogInfo((object)("[vpop]   child[" + num9 + "] '" + ((Object)((Component)child2).gameObject).name + "'"));
												}
											}
											catch
											{
											}
										}
									}
									catch
									{
									}
								}
								catch (Exception ex23)
								{
									Plugin.Log.LogWarning((object)("[vpop] " + ex23.Message));
								}
							}
							catch
							{
							}
						}
					}
				}
				catch (Exception ex24)
				{
					Plugin.Log.LogWarning((object)("[cmp] scan: " + ex24.Message));
				}
				if ((Object)(object)wrapper != (Object)null)
				{
					try
					{
						GameObject popupItemPrefab = wrapper.m_popupItemPrefab;
						if ((Object)(object)popupItemPrefab != (Object)null)
						{
							Plugin.Log.LogInfo((object)("[pop] popupItemPrefab name='" + ((Object)popupItemPrefab).name + "'"));
							Transform transform3 = popupItemPrefab.transform;
							int num10 = 0;
							try
							{
								num10 = transform3.childCount;
							}
							catch
							{
							}
							for (int num11 = 0; num11 < num10 && num11 < 8; num11++)
							{
								try
								{
									Transform child3 = transform3.GetChild(num11);
									if (!((Object)(object)child3 == (Object)null))
									{
										string text10 = "";
										RectTransform val13 = ((Il2CppObjectBase)child3).TryCast<RectTransform>();
										if ((Object)(object)val13 != (Object)null)
										{
											text10 = " size=" + ((object)val13.sizeDelta/*cast due to .constrained prefix*/).ToString() + " pos=" + ((object)val13.anchoredPosition/*cast due to .constrained prefix*/).ToString();
										}
										Plugin.Log.LogInfo((object)("[pop]   child[" + num11 + "] '" + ((Object)((Component)child3).gameObject).name + "'" + text10));
									}
								}
								catch
								{
								}
							}
						}
						else
						{
							Plugin.Log.LogWarning((object)"[pop] popupItemPrefab is null");
						}
					}
					catch (Exception ex25)
					{
						Plugin.Log.LogWarning((object)("[pop] item prefab: " + ex25.Message));
					}
					try
					{
						Transform popupWindowAlign = wrapper.m_popupWindowAlign;
						if ((Object)(object)popupWindowAlign != (Object)null)
						{
							RectTransform val14 = ((Il2CppObjectBase)popupWindowAlign).TryCast<RectTransform>();
							string text11 = "name='" + ((Object)((Component)popupWindowAlign).gameObject).name + "'";
							if ((Object)(object)val14 != (Object)null)
							{
								text11 = text11 + " size=" + ((object)val14.sizeDelta/*cast due to .constrained prefix*/).ToString() + " anchoredPos=" + ((object)val14.anchoredPosition/*cast due to .constrained prefix*/).ToString() + " worldPos=" + ((object)((Transform)val14).position/*cast due to .constrained prefix*/).ToString();
							}
							text11 = text11 + " parent='" + (((Object)(object)popupWindowAlign.parent != (Object)null) ? ((Object)popupWindowAlign.parent).name : "?") + "'";
							Plugin.Log.LogInfo((object)("[pop] popupWindowAlign " + text11));
						}
						else
						{
							Plugin.Log.LogWarning((object)"[pop] popupWindowAlign is null");
						}
					}
					catch (Exception ex26)
					{
						Plugin.Log.LogWarning((object)("[pop] align: " + ex26.Message));
					}
				}
				try
				{
					ShowColorPopup(wrapper, dd.m_currentValue, TrajectoryBehaviour.PresetNames, TrajectoryBehaviour.PresetHexes);
					Plugin.Log.LogInfo((object)("[cp] SELFTEST built items=" + _colorPopupItems.Count));
					CloseColorPopup();
					Plugin.Log.LogInfo((object)"[cp] SELFTEST closed ok");
				}
				catch (Exception ex27)
				{
					Plugin.Log.LogError((object)("[cp] SELFTEST: " + ex27));
				}
				if (string.IsNullOrEmpty(tooltip))
				{
					return;
				}
				try
				{
					((CM_Item)val).TooltipInfo = new TooltipInfo
					{
						PositionType = (TooltipPositionType)1,
						TooltipHeader = label,
						TooltipText = tooltip,
						UseTooptip = true
					};
				}
				catch
				{
				}
			}
			catch (Exception ex28)
			{
				Plugin.Log.LogError((object)("[dd2] AddColorDropdownV2: " + ex28));
			}
		}

		private static void AddColorInput(CM_PageSettings page, CM_ScrollWindow window, List<iScrollWindowContent> items, string label, string tooltip)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CM_SettingsItem val = CreateItem(page, window, items, label);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"[settings] ci: CreateItem null");
					return;
				}
				try
				{
					GameObject val2 = Object.Instantiate<GameObject>(val.m_toggleInputPrefab, val.m_inputAlign, false);
					if ((Object)(object)val2 != (Object)null)
					{
						try
						{
							CM_Item val3 = val2.GetComponent<CM_Item>();
							if ((Object)(object)val3 == (Object)null)
							{
								val3 = val2.AddComponent<CM_Item>();
							}
							if ((Object)(object)val3 != (Object)null)
							{
								try
								{
									((RectTransformComp)val3).RectTrans.anchoredPosition3D = new Vector3(-325f, 0f, 0f);
								}
								catch
								{
								}
							}
						}
						catch
						{
						}
						try
						{
							Collider2D componentInChildren = val2.GetComponentInChildren<Collider2D>();
							if ((Object)(object)componentInChildren != (Object)null)
							{
								((Behaviour)componentInChildren).enabled = false;
							}
						}
						catch
						{
						}
						_hexDisplayTmps.Clear();
						try
						{
							Il2CppReferenceArray<Component> componentsInChildren = val2.GetComponentsInChildren(Il2CppType.Of<TextMeshPro>(), true);
							if (componentsInChildren != null)
							{
								int num = 0;
								try
								{
									num = ((Il2CppA