Decompiled source of Flashlight Overhaul v2.0.0

FlashlightOverhaul.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Enemies;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("FlashlightOverhaul")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Realistic soft-edge flashlight for GTFO using light sandwich technique")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+2cb5a57295b1efac41542353d9335b042c826c3c")]
[assembly: AssemblyProduct("FlashlightOverhaul")]
[assembly: AssemblyTitle("FlashlightOverhaul")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 GTFO_SuperFlashlight
{
	[BepInPlugin("FlashlightOverhaul", "Flashlight Overhaul", "2.0.0")]
	public class Plugin : BasePlugin
	{
		public static ConfigEntry<bool> HazeEnabled = null;

		public static ConfigEntry<float> HazeStrength = null;

		public static ConfigEntry<bool> FogBeamEnabled = null;

		public static ConfigEntry<float> FogBeamNearDensity = null;

		public static ConfigEntry<float> FogBeamFarDensity = null;

		public static ConfigEntry<float> HazeTierA = null;

		public static ConfigEntry<float> HazeTierB = null;

		public static ConfigEntry<float> HazeTierC = null;

		public static ConfigEntry<float> HazeTierD = null;

		public static ConfigEntry<float> HazeTierE = null;

		internal static ManualLogSource Logger = null;

		internal static readonly Dictionary<int, float> _customBuildup = new Dictionary<int, float>();

		internal static readonly Dictionary<int, float> _customDetectionCurrent = new Dictionary<int, float>();

		internal static readonly Dictionary<int, float> _lastUpdateTime = new Dictionary<int, float>();

		internal static readonly HashSet<int> _triggeredEnemies = new HashSet<int>();

		internal static readonly HashSet<int> _headlightTriggeredEnemies = new HashSet<int>();

		internal static Func<object, float>? _hibGetDetectionCurrent;

		internal static Action<object, float>? _hibSetDetectionCurrent;

		internal static Func<object, float>? _hibGetDetectionTarget;

		internal static Action<object, bool>? _hibSetWantToWakeUp;

		internal static Action<object, bool>? _hibSetHeartbeatActive;

		internal static MethodInfo? _hibMethodMasterStartDetection;

		internal static MethodInfo? _dmgMethodBulletDamage;

		internal static Type? _hibType;

		internal static Type? _dmgType;

		private static Dictionary<int, float> _lastDamageTime = new Dictionary<int, float>();

		private const float PinchRetryInterval = 2f;

		private static bool _hibDiagDone = false;

		public static ConfigEntry<bool> Enabled = null;

		public static ConfigEntry<FlashLightMode> Mode = null;

		public static ConfigEntry<bool> AttachLightToWeaponBone = null;

		public static ConfigEntry<float> Step1 = null;

		public static ConfigEntry<float> I1 = null;

		public static ConfigEntry<float> R1 = null;

		public static ConfigEntry<float> MidStepFraction = null;

		public static ConfigEntry<float> I2 = null;

		public static ConfigEntry<float> R2 = null;

		public static ConfigEntry<float> Step2 = null;

		public static ConfigEntry<float> MeleeAngle = null;

		public static ConfigEntry<float> MeleeIntensity = null;

		public static ConfigEntry<float> MeleeRange = null;

		public static ConfigEntry<bool> FlickerEnabled = null;

		public static ConfigEntry<float> FlickerSpeed = null;

		public static ConfigEntry<float> FlickerAmplitude = null;

		public static ConfigEntry<bool> RareFlickerEnabled = null;

		public static ConfigEntry<float> RareFlickerIntervalMin = null;

		public static ConfigEntry<float> RareFlickerIntervalMax = null;

		public static ConfigEntry<bool> HorrorFlickerEnabled = null;

		public static ConfigEntry<float> HorrorFlickerIntervalMin = null;

		public static ConfigEntry<float> HorrorFlickerIntervalMax = null;

		public static ConfigEntry<bool> BrownoutEnabled = null;

		public static ConfigEntry<float> BrownoutIntervalMin = null;

		public static ConfigEntry<float> BrownoutIntervalMax = null;

		public static ConfigEntry<bool> StutterEnabled = null;

		public static ConfigEntry<float> StutterIntervalMin = null;

		public static ConfigEntry<float> StutterIntervalMax = null;

		public static ConfigEntry<bool> RestrikeEnabled = null;

		public static ConfigEntry<float> RestrikeIntervalMin = null;

		public static ConfigEntry<float> RestrikeIntervalMax = null;

		public static ConfigEntry<float> P_Short_CoreAngle = null;

		public static ConfigEntry<float> P_Short_CoreIntensity = null;

		public static ConfigEntry<float> P_Short_CoreRange = null;

		public static ConfigEntry<float> P_Short_MidAngle = null;

		public static ConfigEntry<float> P_Short_MidIntensity = null;

		public static ConfigEntry<float> P_Short_MidRange = null;

		public static ConfigEntry<float> P_Short_FallAngle = null;

		public static ConfigEntry<float> P_Short_FallIntensity = null;

		public static ConfigEntry<float> P_Short_FallRange = null;

		public static ConfigEntry<float> P_Med1_CoreAngle = null;

		public static ConfigEntry<float> P_Med1_CoreIntensity = null;

		public static ConfigEntry<float> P_Med1_CoreRange = null;

		public static ConfigEntry<float> P_Med1_MidAngle = null;

		public static ConfigEntry<float> P_Med1_MidIntensity = null;

		public static ConfigEntry<float> P_Med1_MidRange = null;

		public static ConfigEntry<float> P_Med1_FallAngle = null;

		public static ConfigEntry<float> P_Med1_FallIntensity = null;

		public static ConfigEntry<float> P_Med1_FallRange = null;

		public static ConfigEntry<float> P_Med2_CoreAngle = null;

		public static ConfigEntry<float> P_Med2_CoreIntensity = null;

		public static ConfigEntry<float> P_Med2_CoreRange = null;

		public static ConfigEntry<float> P_Med2_MidAngle = null;

		public static ConfigEntry<float> P_Med2_MidIntensity = null;

		public static ConfigEntry<float> P_Med2_MidRange = null;

		public static ConfigEntry<float> P_Med2_FallAngle = null;

		public static ConfigEntry<float> P_Med2_FallIntensity = null;

		public static ConfigEntry<float> P_Med2_FallRange = null;

		public static ConfigEntry<float> P_Wide_CoreAngle = null;

		public static ConfigEntry<float> P_Wide_CoreIntensity = null;

		public static ConfigEntry<float> P_Wide_CoreRange = null;

		public static ConfigEntry<float> P_Wide_MidAngle = null;

		public static ConfigEntry<float> P_Wide_MidIntensity = null;

		public static ConfigEntry<float> P_Wide_MidRange = null;

		public static ConfigEntry<float> P_Wide_FallAngle = null;

		public static ConfigEntry<float> P_Wide_FallIntensity = null;

		public static ConfigEntry<float> P_Wide_FallRange = null;

		public static ConfigEntry<float> P_Ext_CoreAngle = null;

		public static ConfigEntry<float> P_Ext_CoreIntensity = null;

		public static ConfigEntry<float> P_Ext_CoreRange = null;

		public static ConfigEntry<float> P_Ext_MidAngle = null;

		public static ConfigEntry<float> P_Ext_MidIntensity = null;

		public static ConfigEntry<float> P_Ext_MidRange = null;

		public static ConfigEntry<float> P_Ext_FallAngle = null;

		public static ConfigEntry<float> P_Ext_FallIntensity = null;

		public static ConfigEntry<float> P_Ext_FallRange = null;

		public static ConfigEntry<bool> DustEnabled = null;

		public static ConfigEntry<float> DustOpacity = null;

		public static ConfigEntry<float> Pick_Angle = null;

		public static ConfigEntry<float> Pick_Intensity = null;

		public static ConfigEntry<float> Pick_Range = null;

		public static ConfigEntry<float> Pick_RareWeight = null;

		public static ConfigEntry<int> Pick_MaxPerLevel = null;

		public static ConfigEntry<int> Pick_GuaranteeFloor = null;

		public static ConfigEntry<float> I3 = null;

		public static ConfigEntry<float> I4 = null;

		public static ConfigEntry<float> I5 = null;

		public static ConfigEntry<float> R3 = null;

		public static ConfigEntry<float> R4 = null;

		public static ConfigEntry<float> R5 = null;

		public static ConfigEntry<float> Step3 = null;

		public static ConfigEntry<float> Step4 = null;

		public static ConfigEntry<float> Step5 = null;

		internal static float HelmetAngle;

		internal static float HelmetIntensity;

		internal static float HelmetRange;

		internal static float HelmetFallRange;

		internal static float PickAngle;

		internal static float PickIntensity;

		internal static float PickRange;

		internal static Color PickColor = new Color(1f, 0.84f, 0.6f);

		private void BindConfigHaze()
		{
			HazeEnabled = ((BasePlugin)this).Config.Bind<bool>("17 - Haze (atmospheric fog in the beam)", "Haze_Enabled", true, "EN: Subtle 'thick air' glow inside the flashlight beam (in Core\n    + Middle layers). Fades smoothly toward the cone edges so it\n    blends naturally with the rest of the scene. Turn off if you\n    don't want any extra atmosphere on top of the dust motes.\nUA: Легке відчуття 'густого повітря' всередині променя (в шарах\n    Core + Middle). Плавно згасає до країв конуса, гармонійно\n    зливаючись зі сценою. Вимкни, якщо не хочеш додаткової\n    атмосфери поверх пилу.");
			HazeStrength = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_Strength", 1f, "EN: Overall potency. 1.0 = the tuned baseline (intentionally\n    very faint). 0.5 = half as visible, 2.0 = twice as visible.\n    The haze also 'breathes' on its own — drifts smoothly between\n    values inside a band that depends on the rundown letter (A..E),\n    re-rolling every 15-65 minutes. This setting just multiplies\n    the final result.\nUA: Загальна сила. 1.0 = базове (свідомо ледь помітне). 0.5 —\n    вдвічі слабше, 2.0 — вдвічі сильніше. Димка також сама\n    'дихає' — плавно гуляє в межах, які залежать від літери\n    глибини рандауну (A..E), і змінює ціль кожні 15-65 хв.\n    Це налаштування просто множить підсумок.");
			FogBeamEnabled = ((BasePlugin)this).Config.Bind<bool>("17 - Haze (atmospheric fog in the beam)", "FogBeam_Enabled", true, "EN: Enables the volumetric FogSphere chain (GTFO's native GPU fog\n    pipeline). Independent of Haze_Enabled — you can keep the\n    billboard quad on the helmet without the volumetric spheres,\n    or vice versa.\nUA: Вмикає ланцюжок об'ємних FogSphere (власний GPU-конвеєр GTFO).\n    Незалежно від Haze_Enabled — можна тримати квад-overlay на\n    шоломі без об'ємних сфер, або навпаки.");
			FogBeamNearDensity = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "FogBeam_NearDensity", 0.0025f, "EN: Density of the volumetric fog sphere nearest to the beam apex\n    (first 25 % of cone range). The chain lerps from this value\n    toward FogBeam_FarDensity. Set to 0 to disable the near\n    cluster entirely. Hard-capped at 0.0086 to prevent\n    visibility blackout. Also scaled by Haze_Strength and the\n    per-tier multiplier (Haze_TierA..E).\nUA: Густота об'ємного туману у ближній сфері (перші 25% дальності\n    конуса). Ланцюжок плавно переходить від цього значення до\n    FogBeam_FarDensity. 0 = вимкнути ближній кластер. Жорстко\n    обмежено 0.0086 щоб не перекривати видимість. Також\n    множиться на Haze_Strength та множник рівня (Haze_TierA..E).");
			FogBeamFarDensity = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "FogBeam_FarDensity", 0.0005f, "EN: Density of the fog sphere furthest from the apex (at 50 % of\n    cone range). Spheres beyond this depth are not placed. Keep\n    this lower than FogBeam_NearDensity for a natural near-to-\n    far density gradient.\nUA: Густота туману у найдальшій сфері (50% дальності конуса).\n    Сфери далі цієї точки не розміщуються. Тримай менше ніж\n    FogBeam_NearDensity для природного градієнту.");
			HazeTierA = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_TierA", 0.12f, "EN: Base haze multiplier for rundown tier A (shallowest).\n    The breathing system drifts ±13 % around this value.\nUA: Базовий множник димки для рівня A (найменша глибина).\n    Система 'дихання' гуляє ±13 % навколо цього значення.");
			HazeTierB = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_TierB", 0.19f, "EN: Base haze multiplier for rundown tier B.\nUA: Базовий множник димки для рівня B.");
			HazeTierC = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_TierC", 0.26f, "EN: Base haze multiplier for rundown tier C.\nUA: Базовий множник димки для рівня C.");
			HazeTierD = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_TierD", 0.32f, "EN: Base haze multiplier for rundown tier D.\nUA: Базовий множник димки для рівня D.");
			HazeTierE = ((BasePlugin)this).Config.Bind<float>("17 - Haze (atmospheric fog in the beam)", "Haze_TierE", 0.38f, "EN: Base haze multiplier for rundown tier E (deepest).\n    At 1.0 the effect reaches the maximum breathing ceiling.\nUA: Базовий множник димки для рівня E (найбільша глибина).\n    При 1.0 ефект на максимальній стелі дихання.");
		}

		internal static AgentTarget? TryBuildFlashlightTarget(EnemyAgent enemy, float detectionRel)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemy == (Object)null)
			{
				return null;
			}
			try
			{
				if (!PlayerManager.HasLocalPlayerAgent())
				{
					return null;
				}
				Agent localPlayerAgent = (Agent)(object)PlayerManager.GetLocalPlayerAgent();
				if ((Object)(object)localPlayerAgent == (Object)null)
				{
					return null;
				}
				Vector3 position = localPlayerAgent.Position;
				Vector3 aimTargetPosition = position;
				Vector3 navigationPosition = position;
				try
				{
					aimTargetPosition = localPlayerAgent.EyePosition;
				}
				catch
				{
				}
				try
				{
					navigationPosition = localPlayerAgent.NavigationPosition;
				}
				catch
				{
				}
				Vector3 position2 = enemy.Position;
				Vector3 val = position - position2;
				float magnitude = ((Vector3)(ref val)).magnitude;
				val = ((!(magnitude > 0.0001f)) ? ((Agent)enemy).Forward : (val / magnitude));
				return new AgentTarget
				{
					m_globalID = localPlayerAgent.GlobalID,
					m_agent = localPlayerAgent,
					m_position = position,
					m_navigationPosition = navigationPosition,
					m_aimTargetPosition = aimTargetPosition,
					m_viewDir = localPlayerAgent.Forward,
					m_dir = val,
					m_viewDot = Mathf.Clamp01(Vector3.Dot(((Agent)enemy).Forward, val)),
					m_distance = magnitude,
					m_inTargetsLOS = true,
					m_hasLineOfSight = true,
					m_isOccluded = false,
					m_autoDetect = false,
					m_wakesHibernators = true,
					m_detectionType = (AgentTargetDetectionType)2,
					m_propagation = (AgentTargetPropagationType)0,
					m_score = Mathf.Max(1f, detectionRel),
					m_detectionBuildup = Mathf.Clamp01(detectionRel),
					m_lightDetectionBuildup = Mathf.Clamp01(detectionRel),
					m_attackBuildup = 0f,
					m_offGraphBuildup = 0f,
					m_rndWeight = 1f
				};
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[FO] Build flashlight AgentTarget failed: " + ex.Message));
				return null;
			}
		}

		private static void FireWakeupPinch(EnemyAgent agent, float damage = 0.01f)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)agent == (Object)null || (Object)(object)agent.Damage == (Object)null)
			{
				return;
			}
			try
			{
				Agent val = null;
				try
				{
					if (PlayerManager.HasLocalPlayerAgent())
					{
						val = (Agent)(object)PlayerManager.GetLocalPlayerAgent();
					}
				}
				catch
				{
				}
				Vector3 position = agent.Position;
				Vector3 val2 = ((Agent)agent).Forward;
				if ((Object)(object)val != (Object)null)
				{
					Vector3 val3 = position - ((Component)val).transform.position;
					if (((Vector3)(ref val3)).sqrMagnitude > 0.0001f)
					{
						val2 = ((Vector3)(ref val3)).normalized;
					}
				}
				agent.Damage.BulletDamage(damage, val, position, val2, -val2, false, 0, 1f, 1f, 0u);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[FO] BulletDamage pinch failed: " + ex.Message));
			}
		}

		internal static void RetryWakeupPinchIfDue(EnemyAgent agent, int id)
		{
			if (!((Object)(object)agent == (Object)null) && !((Object)(object)agent.Damage == (Object)null))
			{
				float time = Time.time;
				_lastDamageTime.TryGetValue(id, out var value);
				if (!(time - value <= 2f))
				{
					_lastDamageTime[id] = time;
					Logger.LogInfo((object)("[FO] Wakeup PINCH retry id=" + id));
					FireWakeupPinch(agent, _headlightTriggeredEnemies.Contains(id) ? 0.2f : 0.01f);
				}
			}
		}

		public override void Load()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			BindConfig();
			BindConfigHaze();
			ApplyPreset(Mode.Value);
			SceneManager.sceneLoaded += UnityAction<Scene, LoadSceneMode>.op_Implicit((Action<Scene, LoadSceneMode>)delegate
			{
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Expected O, but got Unknown
				LightSandwich.RebuildAll();
				LightSandwich.ProcessAllSpotLights();
				PickableFlashlightTracker.Reset();
				FlashlightEnemyDetection.Reset();
				_customBuildup.Clear();
				_customDetectionCurrent.Clear();
				_lastUpdateTime.Clear();
				_triggeredEnemies.Clear();
				_headlightTriggeredEnemies.Clear();
				if (!_hibDiagDone)
				{
					try
					{
						Il2CppArrayBase<EnemyAgent> val7 = Object.FindObjectsOfType<EnemyAgent>();
						if (val7 != null && val7.Length > 0)
						{
							_hibDiagDone = true;
							EnemyAgent val8 = val7[0];
							ManualLogSource logger4 = Logger;
							bool flag3 = default(bool);
							BepInExInfoLogInterpolatedStringHandler val9 = new BepInExInfoLogInterpolatedStringHandler(23, 2, ref flag3);
							if (flag3)
							{
								((BepInExLogInterpolatedStringHandler)val9).AppendLiteral("[FO] DiagAgent: ");
								((BepInExLogInterpolatedStringHandler)val9).AppendFormatted<string>((val8 != null) ? ((Object)val8).name : null);
								((BepInExLogInterpolatedStringHandler)val9).AppendLiteral(" count=");
								((BepInExLogInterpolatedStringHandler)val9).AppendFormatted<int>(val7.Length);
							}
							logger4.LogInfo(val9);
							EnemyLocomotion val10 = ((val8 != null) ? val8.Locomotion : null);
							if ((Object)(object)val10 != (Object)null)
							{
								Type type = ((object)val10).GetType();
								PropertyInfo[] properties2 = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
								foreach (PropertyInfo propertyInfo2 in properties2)
								{
									Logger.LogInfo((object)("[FO] Loc-PROP: " + propertyInfo2.PropertyType.Name + " " + propertyInfo2.Name));
								}
								FieldInfo[] fields2 = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
								foreach (FieldInfo fieldInfo2 in fields2)
								{
									Logger.LogInfo((object)("[FO] Loc-FIELD: " + fieldInfo2.FieldType.Name + " " + fieldInfo2.Name));
								}
								MethodInfo[] methods2 = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
								foreach (MethodInfo methodInfo3 in methods2)
								{
									Logger.LogInfo((object)("[FO] Loc-MTD: " + methodInfo3.ReturnType.Name + " " + methodInfo3.Name));
								}
								ES_Hibernate hibernate = val10.Hibernate;
								if (hibernate != null)
								{
									Type type2 = ((object)hibernate).GetType();
									Logger.LogInfo((object)("[FO] Hib-TYPE: " + type2.FullName));
									properties2 = type2.GetProperties(BindingFlags.Instance | BindingFlags.Public);
									foreach (PropertyInfo propertyInfo3 in properties2)
									{
										Logger.LogInfo((object)("[FO] Hib-PROP: " + propertyInfo3.PropertyType.Name + " " + propertyInfo3.Name));
									}
									fields2 = type2.GetFields(BindingFlags.Instance | BindingFlags.Public);
									foreach (FieldInfo fieldInfo3 in fields2)
									{
										Logger.LogInfo((object)("[FO] Hib-FIELD: " + fieldInfo3.FieldType.Name + " " + fieldInfo3.Name));
									}
									methods2 = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
									foreach (MethodInfo methodInfo4 in methods2)
									{
										Logger.LogInfo((object)("[FO] Hib-MTD: " + methodInfo4.ReturnType.Name + " " + methodInfo4.Name));
									}
								}
								EnemyAI aI = val8.AI;
								if ((Object)(object)aI != (Object)null)
								{
									Type type3 = ((object)aI).GetType();
									Logger.LogInfo((object)("[FO] AI-TYPE: " + type3.FullName));
									methods2 = type3.GetMethods(BindingFlags.Instance | BindingFlags.Public);
									foreach (MethodInfo methodInfo5 in methods2)
									{
										Logger.LogInfo((object)("[FO] AI-MTD: " + methodInfo5.ReturnType.Name + " " + methodInfo5.Name));
									}
								}
								Dam_EnemyDamageBase damage2 = val8.Damage;
								if ((Object)(object)damage2 != (Object)null)
								{
									Type type4 = ((object)damage2).GetType();
									Logger.LogInfo((object)("[FO] DMG-TYPE: " + type4.FullName));
									methods2 = type4.GetMethods(BindingFlags.Instance | BindingFlags.Public);
									foreach (MethodInfo methodInfo6 in methods2)
									{
										Logger.LogInfo((object)("[FO] DMG-MTD: " + methodInfo6.ReturnType.Name + " " + methodInfo6.Name + "(" + string.Join(",", Array.ConvertAll(methodInfo6.GetParameters(), (ParameterInfo p) => p.ParameterType.Name)) + ")"));
									}
								}
								else
								{
									Logger.LogWarning((object)"[FO] Hib-DIAG: loc.Hibernate is null");
								}
							}
							else
							{
								Logger.LogWarning((object)"[FO] Hib-DIAG: agent.Locomotion is null");
							}
						}
						else
						{
							Logger.LogInfo((object)"[FO] Hib-DIAG: no EnemyAgents in scene yet");
						}
					}
					catch (Exception ex6)
					{
						Logger.LogWarning((object)("[FO] Hib-DIAG sceneLoad threw: " + ex6.Message));
					}
				}
			});
			FlashlightEnemyDetection.OnEnemyInBeam = (Action<EnemyAgent, float, float>)Delegate.Combine(FlashlightEnemyDetection.OnEnemyInBeam, (Action<EnemyAgent, float, float>)delegate(EnemyAgent agent, float dist, float angle)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Invalid comparison between Unknown and I4
				try
				{
					if (!((Object)(object)agent == (Object)null) && !((Object)(object)agent.AI == (Object)null))
					{
						int instanceID = ((Object)agent).GetInstanceID();
						if ((int)((AgentAI)agent.AI).Mode == 1)
						{
							if (_triggeredEnemies.Contains(instanceID))
							{
								Logger.LogInfo((object)("[FO] Enemy " + instanceID + " is now Agressive. Clearing tracking."));
								_triggeredEnemies.Remove(instanceID);
							}
							_headlightTriggeredEnemies.Remove(instanceID);
							_customBuildup.Remove(instanceID);
							_customDetectionCurrent.Remove(instanceID);
							_lastUpdateTime.Remove(instanceID);
							_lastDamageTime.Remove(instanceID);
						}
						else if (_triggeredEnemies.Contains(instanceID))
						{
							if (_headlightTriggeredEnemies.Contains(instanceID))
							{
								RetryWakeupPinchIfDue(agent, instanceID);
							}
							else
							{
								if (_hibSetDetectionCurrent != null && _hibGetDetectionTarget != null)
								{
									EnemyLocomotion locomotion = agent.Locomotion;
									ES_Hibernate val5 = ((locomotion != null) ? locomotion.Hibernate : null);
									if (val5 != null)
									{
										float num = 1f;
										try
										{
											num = _hibGetDetectionTarget(val5);
										}
										catch
										{
										}
										try
										{
											_hibSetDetectionCurrent(val5, num * 1.05f);
										}
										catch
										{
										}
										if (_hibSetHeartbeatActive != null)
										{
											try
											{
												_hibSetHeartbeatActive(val5, arg2: true);
											}
											catch
											{
											}
										}
									}
								}
								RetryWakeupPinchIfDue(agent, instanceID);
							}
						}
						else
						{
							EnemyLocomotion locomotion2 = agent.Locomotion;
							ES_Hibernate val6 = ((locomotion2 != null) ? locomotion2.Hibernate : null);
							if (val6 == null)
							{
								_customBuildup.Remove(instanceID);
								_customDetectionCurrent.Remove(instanceID);
								_lastUpdateTime.Remove(instanceID);
							}
							else
							{
								if (_hibType == null)
								{
									_hibType = ((object)val6).GetType();
									(Func<object, float>? getter, Action<object, float>? setter) tuple = ResolveAccessors<float>(_hibType, "m_detectionCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									_hibGetDetectionCurrent = tuple.getter;
									_hibSetDetectionCurrent = tuple.setter;
									_hibGetDetectionTarget = ResolveAccessors<float>(_hibType, "m_detectionTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).getter;
									_hibSetWantToWakeUp = ResolveAccessors<bool>(_hibType, "m_wantToWakeUp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).setter;
									_hibSetHeartbeatActive = ResolveAccessors<bool>(_hibType, "m_heartbeatActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).setter;
									_hibMethodMasterStartDetection = _hibType.GetMethod("MasterStartDetection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									Dam_EnemyDamageBase damage = agent.Damage;
									if ((Object)(object)damage != (Object)null)
									{
										_dmgType = ((object)damage).GetType();
										MethodInfo[] methods = _dmgType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										foreach (MethodInfo methodInfo in methods)
										{
											if (methodInfo.Name == "BulletDamage" && methodInfo.GetParameters().Length == 10)
											{
												_dmgMethodBulletDamage = methodInfo;
												break;
											}
										}
										Logger.LogInfo((object)("[FO] DMG-RESOLVE type=" + _dmgType.FullName));
										Logger.LogInfo((object)("[FO]   BulletDamage found: " + (_dmgMethodBulletDamage != null)));
									}
									Logger.LogInfo((object)("[FO] Hib-RESOLVE type=" + _hibType.FullName));
									Logger.LogInfo((object)("[FO]   m_detectionCurrent : get=" + (_hibGetDetectionCurrent != null) + " set=" + (_hibSetDetectionCurrent != null)));
									Logger.LogInfo((object)("[FO]   m_detectionTarget  : get=" + (_hibGetDetectionTarget != null)));
									Logger.LogInfo((object)("[FO]   m_wantToWakeUp     : set=" + (_hibSetWantToWakeUp != null)));
									Logger.LogInfo((object)("[FO]   MasterStartDetection: " + (_hibMethodMasterStartDetection != null)));
									if (_hibSetWantToWakeUp == null)
									{
										Logger.LogWarning((object)"[FO] m_wantToWakeUp not found. Dumping bool members:");
										PropertyInfo[] properties = _hibType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										foreach (PropertyInfo propertyInfo in properties)
										{
											if (propertyInfo.PropertyType == typeof(bool))
											{
												Logger.LogWarning((object)("[FO]   BOOL-PROP " + propertyInfo.Name + " R=" + propertyInfo.CanRead + " W=" + propertyInfo.CanWrite));
											}
										}
										FieldInfo[] fields = _hibType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										foreach (FieldInfo fieldInfo in fields)
										{
											if (fieldInfo.FieldType == typeof(bool))
											{
												Logger.LogWarning((object)("[FO]   BOOL-FIELD " + fieldInfo.Name));
											}
										}
										Logger.LogWarning((object)"[FO] All methods on ES_Hibernate:");
										MethodInfo[] methods = _hibType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
										foreach (MethodInfo methodInfo2 in methods)
										{
											Logger.LogWarning((object)("[FO]   MTD " + methodInfo2.ReturnType.Name + " " + methodInfo2.Name + "(" + string.Join(",", Array.ConvertAll(methodInfo2.GetParameters(), (ParameterInfo p2) => p2.ParameterType.Name)) + ")"));
										}
									}
								}
								float unscaledTime = Time.unscaledTime;
								float value;
								float num2 = (_lastUpdateTime.TryGetValue(instanceID, out value) ? (unscaledTime - value) : Time.deltaTime);
								_lastUpdateTime[instanceID] = unscaledTime;
								if (!_customBuildup.TryGetValue(instanceID, out var value2))
								{
									value2 = 0f;
								}
								float lastBeamRange = FlashlightEnemyDetection.LastBeamRange;
								float lastBeamIntensity = FlashlightEnemyDetection.LastBeamIntensity;
								float num3 = Mathf.Clamp01(1f - dist / Mathf.Max(lastBeamRange, 1f));
								float num4 = Mathf.Clamp01(1f - angle / 45f);
								float num5 = Mathf.Clamp01(lastBeamIntensity);
								float num6 = num3 * num4 * num5;
								float num7 = ((value2 > 0.7f) ? 2.2f : 1.5f);
								value2 = Mathf.Clamp01(value2 + num7 * num6 * num2);
								_customBuildup[instanceID] = value2;
								if (!_lastUpdateTime.TryGetValue(~instanceID, out var value3) || !(unscaledTime - value3 < 0.5f))
								{
									_lastUpdateTime[~instanceID] = unscaledTime;
									Logger.LogInfo((object)("[FO] Buildup id=" + instanceID + " buildup=" + value2.ToString("F3") + " exposure=" + num6.ToString("F3") + " dist=" + dist.ToString("F1") + " angle=" + angle.ToString("F1")));
								}
								if (_hibSetDetectionCurrent != null)
								{
									float num8 = 1f;
									if (_hibGetDetectionTarget != null)
									{
										try
										{
											num8 = _hibGetDetectionTarget(val6);
										}
										catch
										{
										}
									}
									if (!_customDetectionCurrent.TryGetValue(instanceID, out var value4))
									{
										value4 = 0f;
										if (_hibGetDetectionCurrent != null)
										{
											try
											{
												value4 = _hibGetDetectionCurrent(val6);
											}
											catch
											{
											}
										}
									}
									float num9 = value2 * num8;
									float num10 = 2f;
									float num11 = Mathf.Lerp(value4, num9, 1f - Mathf.Exp((0f - num10) * num2));
									float num12 = Mathf.Max(value4, num11);
									_customDetectionCurrent[instanceID] = num12;
									try
									{
										_hibSetDetectionCurrent(val6, num12);
									}
									catch
									{
									}
								}
								if (value2 >= 1f)
								{
									_customBuildup[instanceID] = 1f;
									bool flag2 = _triggeredEnemies.Add(instanceID);
									bool lastBeamIsHeadlight = FlashlightEnemyDetection.LastBeamIsHeadlight;
									if (lastBeamIsHeadlight)
									{
										_headlightTriggeredEnemies.Add(instanceID);
									}
									float num13 = 1f;
									if (_hibGetDetectionTarget != null)
									{
										try
										{
											num13 = _hibGetDetectionTarget(val6);
										}
										catch
										{
										}
									}
									float num14 = num13 * 1.05f;
									_customDetectionCurrent[instanceID] = num14;
									if (_hibSetDetectionCurrent != null)
									{
										try
										{
											_hibSetDetectionCurrent(val6, num14);
										}
										catch
										{
										}
									}
									if (_hibSetHeartbeatActive != null)
									{
										try
										{
											_hibSetHeartbeatActive(val6, arg2: true);
										}
										catch
										{
										}
									}
									if (!lastBeamIsHeadlight && flag2 && _hibMethodMasterStartDetection != null)
									{
										try
										{
											_hibMethodMasterStartDetection.Invoke(val6, null);
											Logger.LogInfo((object)("[FO] MasterStartDetection once id=" + instanceID));
										}
										catch (Exception ex4)
										{
											Logger.LogWarning((object)("[FO] MasterStartDetection failed id=" + instanceID + " err=" + ex4.Message));
										}
									}
									Logger.LogInfo((object)("[FO] Wakeup PINCH firing id=" + instanceID));
									_lastDamageTime[instanceID] = Time.time;
									FireWakeupPinch(agent, lastBeamIsHeadlight ? 0.2f : 0.01f);
								}
							}
						}
					}
				}
				catch (Exception ex5)
				{
					Logger.LogWarning((object)("[FO] OnEnemyInBeam threw: " + ex5.Message));
				}
			});
			Harmony val = new Harmony("FlashlightOverhaul");
			bool flag = default(bool);
			try
			{
				val.PatchAll();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[FO] Harmony PatchAll threw: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val2);
			}
			try
			{
				MethodInfo method = typeof(EnemyDetection).GetMethod("UpdateHibernationDetection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					MethodInfo method2 = typeof(Patch_HibernationDetectionUpdate).GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic);
					if (method2 != null)
					{
						val.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					Logger.LogInfo((object)"[FO] HibernationDetection patch applied.");
				}
				else
				{
					Logger.LogWarning((object)"[FO] UpdateHibernationDetection not found — detection-decay patch skipped.");
				}
			}
			catch (Exception ex2)
			{
				Logger.LogWarning((object)("[FO] HibernationDetection patch failed (non-critical): " + ex2.Message));
			}
			try
			{
				ClassInjector.RegisterTypeInIl2Cpp<LightUpdater>();
				ClassInjector.RegisterTypeInIl2Cpp<PreCullEnforcer>();
				GameObject val3 = new GameObject("LightUpdater");
				Object.DontDestroyOnLoad((Object)val3);
				((Object)val3).hideFlags = (HideFlags)61;
				val3.AddComponent<LightUpdater>();
			}
			catch (Exception ex3)
			{
				ManualLogSource logger2 = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(41, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[FO] ClassInjector / AddComponent threw: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex3);
				}
				logger2.LogError(val2);
			}
			ManualLogSource logger3 = Logger;
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(18, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("Flashlight Overhaul");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" v");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("2.0.0");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" loaded (Mode=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<FlashLightMode>(Mode.Value);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(").");
			}
			logger3.LogInfo(val4);
			static (Func<object, T>? getter, Action<object, T>? setter) ResolveAccessors<T>(Type t, string name, BindingFlags f) where T : notnull
			{
				PropertyInfo prop = t.GetProperty(name, f);
				if (prop != null)
				{
					Func<object, T> item = (prop.CanRead ? ((Func<object, T>)((object o) => (T)prop.GetValue(o))) : null);
					Action<object, T> item2 = (prop.CanWrite ? ((Action<object, T>)delegate(object o, T v)
					{
						prop.SetValue(o, v);
					}) : null);
					return (item, item2);
				}
				FieldInfo field = t.GetField(name, f);
				if (field != null)
				{
					Func<object, T> item3 = (object o) => (T)field.GetValue(o);
					Action<object, T> item4 = delegate(object o, T v)
					{
						field.SetValue(o, v);
					};
					return (item3, item4);
				}
				return (null, null);
			}
		}

		private void BindConfig()
		{
			Enabled = ((BasePlugin)this).Config.Bind<bool>("01 - General", "Enabled", true, "EN: Master switch for the entire mod. False = fully disabled.\nUA: Головний вимикач мода. False = повністю вимкнено.");
			Mode = ((BasePlugin)this).Config.Bind<FlashLightMode>("01 - General", "Mode", FlashLightMode.MINIMAL, "EN: Pick the flashlight style you want.\n    MINIMAL       — For near-vanilla gameplay. Just a clean\n                    main beam and a soft outer glow. (Default)\n    CASUAL        — I think it's balanced.\n    VERY_CASUAL   — A bit wider and a bit further than CASUAL.\n    ITS_2050_BRUH — Sleepers will hear you, but they probably\n                    won't see you. Shine!\n    VANILLA       — Fully disables all mod changes.\nUA: Обери стиль ліхтариків.\n    MINIMAL       — Для около-ванільного геймплею. Просто чистий\n                    основний промінь і м'яке зовнішнє світло. (Дефолт)\n    CASUAL        — По-моєму, збалансовано.\n    VERY_CASUAL   — Трохи ширше і трохи далі за CASUAL.\n    ITS_2050_BRUH — Сплячі тебе почують, але побачити вже\n                    навряд. Сяй!\n    VANILLA       — Повністю вимикає всі зміни мода.");
			AttachLightToWeaponBone = ((BasePlugin)this).Config.Bind<bool>("01 - General", "AttachLightToWeaponBone", true, "EN: True — the flashlight rides along with the gun model, so the\n    beam moves during reload and weapon-swap animations instead of\n    staring straight ahead. False — beam locked rigidly to the\n    camera.\nUA: True — ліхтарик їздить разом з моделлю зброї, тож промінь\n    рухається під час перезарядки та зміни зброї, а не дивиться\n    рівно вперед. False — промінь жорстко прив'язаний до камери.");
			Step1 = ((BasePlugin)this).Config.Bind<float>("02 - Core Layer (RF_Core)", "AngleStep", 30f, "EN: Widens the beam of the pickable (found) flashlight and\n    environment lights in the level. Does not affect\n    weapon flashlights — those have their own width settings\n    in sections 09-13.\nUA: Розширює промінь підбираного ліхтарика і освітлення\n    на рівні. На ліхтарики зброї не впливає — в них є\n    власні налаштування ширини у секціях 09-13.");
			I1 = ((BasePlugin)this).Config.Bind<float>("03 - Middle Layer (RF_L1) — multiplier path", "IntensityFraction", 0.625f, "EN: How bright the middle glow ring is, as a fraction of the\n    inner beam's brightness. Affects the pickable flashlight\n    and environment lights only.\nUA: Яскравість середнього кільця відносно центру.\n    Стосується лише підбираного ліхтарика і освітлення на рівні.");
			R1 = ((BasePlugin)this).Config.Bind<float>("03 - Middle Layer (RF_L1) — multiplier path", "RangeFraction", 0.62f, "EN: How far the middle glow ring reaches, as a fraction of the\n    inner beam's reach. Affects the pickable flashlight\n    and environment lights only.\nUA: Як далеко сягає середнє кільце відносно дальності центру.\n    Стосується лише підбираного ліхтарика і освітлення на рівні.");
			MidStepFraction = ((BasePlugin)this).Config.Bind<float>("03 - Middle Layer (RF_L1) — multiplier path", "AngleStepFraction", 0.252f, "EN: How much wider the middle glow ring is than the inner beam,\n    relative to the outer glow's width.\nUA: Наскільки середнє кільце ширше за центр, відносно\n    ширини зовнішнього кільця.");
			I2 = ((BasePlugin)this).Config.Bind<float>("04 - Falloff Layer (RF_L2) — multiplier path", "IntensityFraction", 0.3125f, "EN: How bright the soft outer glow is, as a fraction of the\n    inner beam (pickable / map lights only).\nUA: Яскравість м'якого зовнішнього світла, відносно центру\n    (лише для підбираного ліхтарика і світла на рівні).");
			R2 = ((BasePlugin)this).Config.Bind<float>("04 - Falloff Layer (RF_L2) — multiplier path", "RangeFraction", 0.38f, "EN: How far the soft outer glow reaches, as a fraction of the\n    inner beam's reach (pickable / map lights only).\nUA: Як далеко сягає м'яке зовнішнє світло, відносно дальності\n    центру (лише для підбираного ліхтарика і світла на рівні).");
			Step2 = ((BasePlugin)this).Config.Bind<float>("04 - Falloff Layer (RF_L2) — multiplier path", "AngleStep", 119f, "EN: How much wider the soft outer glow is than the inner beam,\n    in degrees.\nUA: Наскільки м'яке зовнішнє світло ширше за центр, у градусах.");
			MeleeAngle = ((BasePlugin)this).Config.Bind<float>("05 - Helmet Synth (melee/tools) — CASUAL", "Angle", 85f, "EN: How wide the helmet light is, in degrees.\nUA: Наскільки широке світло шолома, у градусах.");
			MeleeIntensity = ((BasePlugin)this).Config.Bind<float>("05 - Helmet Synth (melee/tools) — CASUAL", "Intensity", 1f, "EN: How bright the helmet light is.\nUA: Наскільки яскраве світло шолома.");
			MeleeRange = ((BasePlugin)this).Config.Bind<float>("05 - Helmet Synth (melee/tools) — CASUAL", "Range", 13f, "EN: How far the helmet light reaches, in metres.\nUA: Як далеко світить шолом, у метрах.");
			FlickerEnabled = ((BasePlugin)this).Config.Bind<bool>("06 - Perlin Flicker (continuous tremor)", "Enabled", true, "EN: Subtle, always-on light tremor — like a real flashlight.\nUA: Тонкий постійний тремор світла — як у справжнього ліхтарика.");
			FlickerSpeed = ((BasePlugin)this).Config.Bind<float>("06 - Perlin Flicker (continuous tremor)", "Speed", 2.5f, "EN: How fast the tremor wobbles. Higher = faster.\nUA: Швидкість тремору. Більше = швидше.");
			FlickerAmplitude = ((BasePlugin)this).Config.Bind<float>("06 - Perlin Flicker (continuous tremor)", "Amplitude", 0.04f, "EN: How strong the tremor is (0.04 = ±4% brightness).\nUA: Сила тремору (0.04 = ±4% яскравості).");
			RareFlickerEnabled = ((BasePlugin)this).Config.Bind<bool>("07 - Rare Flicker (bad-contact bursts)", "Enabled", true, "EN: Occasional bursts of 3-7 quick blinks, like a loose battery.\nUA: Випадкові серії з 3-7 швидких миготінь — наче поганий\n    контакт батареї.");
			RareFlickerIntervalMin = ((BasePlugin)this).Config.Bind<float>("07 - Rare Flicker (bad-contact bursts)", "IntervalMinSeconds", 180f, "EN: Minimum seconds between blink bursts.\nUA: Мінімум секунд між серіями миготінь.");
			RareFlickerIntervalMax = ((BasePlugin)this).Config.Bind<float>("07 - Rare Flicker (bad-contact bursts)", "IntervalMaxSeconds", 420f, "EN: Maximum seconds between blink bursts.\nUA: Максимум секунд між серіями миготінь.");
			HorrorFlickerEnabled = ((BasePlugin)this).Config.Bind<bool>("08 - Horror Flicker (long dark pause)", "Enabled", true, "EN: Horror-movie blinks: 6-14 flickers with one long dark pause.\n    Pretty creepy.\nUA: Хоррор-миготіння: 6-14 спалахів з однією довгою темною\n    паузою. Доволі моторошно.");
			HorrorFlickerIntervalMin = ((BasePlugin)this).Config.Bind<float>("08 - Horror Flicker (long dark pause)", "IntervalMinSeconds", 240f, "EN: Minimum seconds between horror events.\nUA: Мінімум секунд між хоррор-подіями.");
			HorrorFlickerIntervalMax = ((BasePlugin)this).Config.Bind<float>("08 - Horror Flicker (long dark pause)", "IntervalMaxSeconds", 600f, "EN: Maximum seconds between horror events.\nUA: Максимум секунд між хоррор-подіями.");
			BrownoutEnabled = ((BasePlugin)this).Config.Bind<bool>("08a - Brownout (slow dim-hold-recover)", "Enabled", true, "EN: The light slowly dims to about half brightness, holds, then\n    recovers. No blinks — feels like the battery is sagging.\nUA: Світло плавно тьмяніє приблизно до половини, тримається,\n    потім відновлюється. Без миготінь — наче батарея просіла.");
			BrownoutIntervalMin = ((BasePlugin)this).Config.Bind<float>("08a - Brownout (slow dim-hold-recover)", "IntervalMinSeconds", 600f, "EN: Minimum seconds between battery sags.\nUA: Мінімум секунд між просіданнями.");
			BrownoutIntervalMax = ((BasePlugin)this).Config.Bind<float>("08a - Brownout (slow dim-hold-recover)", "IntervalMaxSeconds", 2400f, "EN: Maximum seconds between battery sags.\nUA: Максимум секунд між просіданнями.");
			StutterEnabled = ((BasePlugin)this).Config.Bind<bool>("08b - Stutter (high-frequency flutter)", "Enabled", true, "EN: A short bout of nervous flutter — like a loose, vibrating\n    contact.\nUA: Короткий нервовий трепет світла — наче торохтить контакт.");
			StutterIntervalMin = ((BasePlugin)this).Config.Bind<float>("08b - Stutter (high-frequency flutter)", "IntervalMinSeconds", 900f, "EN: Minimum seconds between flutter bursts.\nUA: Мінімум секунд між нервовими спалахами.");
			StutterIntervalMax = ((BasePlugin)this).Config.Bind<float>("08b - Stutter (high-frequency flutter)", "IntervalMaxSeconds", 2700f, "EN: Maximum seconds between flutter bursts.\nUA: Максимум секунд між нервовими спалахами.");
			RestrikeEnabled = ((BasePlugin)this).Config.Bind<bool>("08c - Restrike (LED bulb restart)", "Enabled", true, "EN: The light cuts out, gives a weak strike, cuts again, then\n    comes back — like an LED bulb restarting after a power hiccup.\n    The rarest event.\nUA: Світло гасне, дає слабкий проблиск, знову гасне і повертається\n    — наче LED-лампа перезапускається після стрибка живлення.\n    Найрідкісніша подія.");
			RestrikeIntervalMin = ((BasePlugin)this).Config.Bind<float>("08c - Restrike (LED bulb restart)", "IntervalMinSeconds", 1200f, "EN: Minimum seconds between LED restarts.\nUA: Мінімум секунд між перезапусками лампи.");
			RestrikeIntervalMax = ((BasePlugin)this).Config.Bind<float>("08c - Restrike (LED bulb restart)", "IntervalMaxSeconds", 3600f, "EN: Maximum seconds between LED restarts.\nUA: Максимум секунд між перезапусками лампи.");
			P_Short_CoreAngle = Cfg("09 - Preset Short Range — CASUAL", "Core_Angle", 50f, "Pistols/revolvers — width of the bright inner beam (°). / Ширина яскравого центру для пістолетів і револьверів (°).");
			P_Short_CoreIntensity = Cfg("09 - Preset Short Range — CASUAL", "Core_Intensity", 0.5f, "Pistols/revolvers — brightness of the inner beam. / Яскравість центру для пістолетів і револьверів.");
			P_Short_CoreRange = Cfg("09 - Preset Short Range — CASUAL", "Core_Range", 18f, "Pistols/revolvers — how far the inner beam reaches (m). / Як далеко б'є центр для пістолетів і револьверів (м).");
			P_Short_MidAngle = Cfg("09 - Preset Short Range — CASUAL", "Mid_Angle", 80f, "Pistols/revolvers — width of the middle glow (°). / Ширина середнього світла для пістолетів і револьверів (°).");
			P_Short_MidIntensity = Cfg("09 - Preset Short Range — CASUAL", "Mid_Intensity", 0.4f, "Pistols/revolvers — brightness of the middle glow. / Яскравість середнього світла для пістолетів і револьверів.");
			P_Short_MidRange = Cfg("09 - Preset Short Range — CASUAL", "Mid_Range", 12.4f, "Pistols/revolvers — how far the middle glow reaches (m). / Як далеко сягає середнє світло для пістолетів і револьверів (м).");
			P_Short_FallAngle = Cfg("09 - Preset Short Range — CASUAL", "Fall_Angle", 169f, "Pistols/revolvers — width of the soft outer glow (°). / Ширина м'якого зовнішнього світла для пістолетів і револьверів (°).");
			P_Short_FallIntensity = Cfg("09 - Preset Short Range — CASUAL", "Fall_Intensity", 0.45f, "Pistols/revolvers — brightness of the soft outer glow. / Яскравість м'якого зовнішнього світла для пістолетів і револьверів.");
			P_Short_FallRange = Cfg("09 - Preset Short Range — CASUAL", "Fall_Range", 5.6f, "Pistols/revolvers — how far the soft outer glow reaches (m). / Як далеко сягає м'яке зовнішнє світло для пістолетів і револьверів (м).");
			P_Med1_CoreAngle = Cfg("10 - Preset Medium Range 1 — CASUAL", "Core_Angle", 50f, "SMGs/ARs — width of the bright inner beam (°). / Ширина яскравого центру для SMG і автоматів (°).");
			P_Med1_CoreIntensity = Cfg("10 - Preset Medium Range 1 — CASUAL", "Core_Intensity", 0.5f, "SMGs/ARs — brightness of the inner beam. / Яскравість центру для SMG і автоматів.");
			P_Med1_CoreRange = Cfg("10 - Preset Medium Range 1 — CASUAL", "Core_Range", 21f, "SMGs/ARs — how far the inner beam reaches (m). / Як далеко б'є центр для SMG і автоматів (м).");
			P_Med1_MidAngle = Cfg("10 - Preset Medium Range 1 — CASUAL", "Mid_Angle", 80f, "SMGs/ARs — width of the middle glow (°). / Ширина середнього світла для SMG і автоматів (°).");
			P_Med1_MidIntensity = Cfg("10 - Preset Medium Range 1 — CASUAL", "Mid_Intensity", 0.4f, "SMGs/ARs — brightness of the middle glow. / Яскравість середнього світла для SMG і автоматів.");
			P_Med1_MidRange = Cfg("10 - Preset Medium Range 1 — CASUAL", "Mid_Range", 14.3f, "SMGs/ARs — how far the middle glow reaches (m). / Як далеко сягає середнє світло для SMG і автоматів (м).");
			P_Med1_FallAngle = Cfg("10 - Preset Medium Range 1 — CASUAL", "Fall_Angle", 169f, "SMGs/ARs — width of the soft outer glow (°). / Ширина м'якого зовнішнього світла для SMG і автоматів (°).");
			P_Med1_FallIntensity = Cfg("10 - Preset Medium Range 1 — CASUAL", "Fall_Intensity", 0.45f, "SMGs/ARs — brightness of the soft outer glow. / Яскравість м'якого зовнішнього світла для SMG і автоматів.");
			P_Med1_FallRange = Cfg("10 - Preset Medium Range 1 — CASUAL", "Fall_Range", 6.7f, "SMGs/ARs — how far the soft outer glow reaches (m). / Як далеко сягає м'яке зовнішнє світло для SMG і автоматів (м).");
			P_Med2_CoreAngle = Cfg("11 - Preset Medium Range 2 — CASUAL", "Core_Angle", 40f, "DMRs/precision guns — width of the bright inner beam (°). / Ширина яскравого центру для DMR і точної зброї (°).");
			P_Med2_CoreIntensity = Cfg("11 - Preset Medium Range 2 — CASUAL", "Core_Intensity", 0.5f, "DMRs/precision guns — brightness of the inner beam. / Яскравість центру для DMR і точної зброї.");
			P_Med2_CoreRange = Cfg("11 - Preset Medium Range 2 — CASUAL", "Core_Range", 21f, "DMRs/precision guns — how far the inner beam reaches (m). / Як далеко б'є центр для DMR і точної зброї (м).");
			P_Med2_MidAngle = Cfg("11 - Preset Medium Range 2 — CASUAL", "Mid_Angle", 75f, "DMRs/precision guns — width of the middle glow (°). / Ширина середнього світла для DMR і точної зброї (°).");
			P_Med2_MidIntensity = Cfg("11 - Preset Medium Range 2 — CASUAL", "Mid_Intensity", 0.4f, "DMRs/precision guns — brightness of the middle glow. / Яскравість середнього світла для DMR і точної зброї.");
			P_Med2_MidRange = Cfg("11 - Preset Medium Range 2 — CASUAL", "Mid_Range", 14.3f, "DMRs/precision guns — how far the middle glow reaches (m). / Як далеко сягає середнє світло для DMR і точної зброї (м).");
			P_Med2_FallAngle = Cfg("11 - Preset Medium Range 2 — CASUAL", "Fall_Angle", 169f, "DMRs/precision guns — width of the soft outer glow (°). / Ширина м'якого зовнішнього світла для DMR і точної зброї (°).");
			P_Med2_FallIntensity = Cfg("11 - Preset Medium Range 2 — CASUAL", "Fall_Intensity", 0.45f, "DMRs/precision guns — brightness of the soft outer glow. / Яскравість м'якого зовнішнього світла для DMR і точної зброї.");
			P_Med2_FallRange = Cfg("11 - Preset Medium Range 2 — CASUAL", "Fall_Range", 6.7f, "DMRs/precision guns — how far the soft outer glow reaches (m). / Як далеко сягає м'яке зовнішнє світло для DMR і точної зброї (м).");
			P_Wide_CoreAngle = Cfg("12 - Preset Wide Range — CASUAL", "Core_Angle", 50f, "Shotguns — width of the bright inner beam (°). / Ширина яскравого центру для дробовиків (°).");
			P_Wide_CoreIntensity = Cfg("12 - Preset Wide Range — CASUAL", "Core_Intensity", 0.5f, "Shotguns — brightness of the inner beam. / Яскравість центру для дробовиків.");
			P_Wide_CoreRange = Cfg("12 - Preset Wide Range — CASUAL", "Core_Range", 24f, "Shotguns — how far the inner beam reaches (m). / Як далеко б'є центр для дробовиків (м).");
			P_Wide_MidAngle = Cfg("12 - Preset Wide Range — CASUAL", "Mid_Angle", 90f, "Shotguns — width of the middle glow (°). / Ширина середнього світла для дробовиків (°).");
			P_Wide_MidIntensity = Cfg("12 - Preset Wide Range — CASUAL", "Mid_Intensity", 0.47f, "Shotguns — brightness of the middle glow. / Яскравість середнього світла для дробовиків.");
			P_Wide_MidRange = Cfg("12 - Preset Wide Range — CASUAL", "Mid_Range", 16.1f, "Shotguns — how far the middle glow reaches (m). / Як далеко сягає середнє світло для дробовиків (м).");
			P_Wide_FallAngle = Cfg("12 - Preset Wide Range — CASUAL", "Fall_Angle", 169f, "Shotguns — width of the soft outer glow (°). / Ширина м'якого зовнішнього світла для дробовиків (°).");
			P_Wide_FallIntensity = Cfg("12 - Preset Wide Range — CASUAL", "Fall_Intensity", 0.45f, "Shotguns — brightness of the soft outer glow. / Яскравість м'якого зовнішнього світла для дробовиків.");
			P_Wide_FallRange = Cfg("12 - Preset Wide Range — CASUAL", "Fall_Range", 7.9f, "Shotguns — how far the soft outer glow reaches (m). / Як далеко сягає м'яке зовнішнє світло для дробовиків (м).");
			P_Ext_CoreAngle = Cfg("13 - Preset Extended Range — CASUAL", "Core_Angle", 50f, "Snipers/long-range guns — width of the bright inner beam (°). / Ширина яскравого центру для снайперок і дальнобоїв (°).");
			P_Ext_CoreIntensity = Cfg("13 - Preset Extended Range — CASUAL", "Core_Intensity", 0.5f, "Snipers/long-range guns — brightness of the inner beam. / Яскравість центру для снайперок і дальнобоїв.");
			P_Ext_CoreRange = Cfg("13 - Preset Extended Range — CASUAL", "Core_Range", 24f, "Snipers/long-range guns — how far the inner beam reaches (m). / Як далеко б'є центр для снайперок і дальнобоїв (м).");
			P_Ext_MidAngle = Cfg("13 - Preset Extended Range — CASUAL", "Mid_Angle", 80f, "Snipers/long-range guns — width of the middle glow (°). / Ширина середнього світла для снайперок і дальнобоїв (°).");
			P_Ext_MidIntensity = Cfg("13 - Preset Extended Range — CASUAL", "Mid_Intensity", 0.4f, "Snipers/long-range guns — brightness of the middle glow. / Яскравість середнього світла для снайперок і дальнобоїв.");
			P_Ext_MidRange = Cfg("13 - Preset Extended Range — CASUAL", "Mid_Range", 16.1f, "Snipers/long-range guns — how far the middle glow reaches (m). / Як далеко сягає середнє світло для снайперок і дальнобоїв (м).");
			P_Ext_FallAngle = Cfg("13 - Preset Extended Range — CASUAL", "Fall_Angle", 169f, "Snipers/long-range guns — width of the soft outer glow (°). / Ширина м'якого зовнішнього світла для снайперок і дальнобоїв (°).");
			P_Ext_FallIntensity = Cfg("13 - Preset Extended Range — CASUAL", "Fall_Intensity", 0.45f, "Snipers/long-range guns — brightness of the soft outer glow. / Яскравість м'якого зовнішнього світла для снайперок і дальнобоїв.");
			P_Ext_FallRange = Cfg("13 - Preset Extended Range — CASUAL", "Fall_Range", 7.9f, "Snipers/long-range guns — how far the soft outer glow reaches (m). / Як далеко сягає м'яке зовнішнє світло для снайперок і дальнобоїв (м).");
			Pick_Angle = ((BasePlugin)this).Config.Bind<float>("14 - Pickable Flashlight — CASUAL", "Angle", 50f, "EN: The big pick-up flashlight — how wide its main beam is (°).\nUA: Підбираний ліхтарик — наскільки широкий основний промінь (°).");
			Pick_Intensity = ((BasePlugin)this).Config.Bind<float>("14 - Pickable Flashlight — CASUAL", "Intensity", 0.7f, "EN: The big pick-up flashlight — how bright its main beam is.\nUA: Підбираний ліхтарик — наскільки яскравий основний промінь.");
			Pick_Range = ((BasePlugin)this).Config.Bind<float>("14 - Pickable Flashlight — CASUAL", "Range", 40f, "EN: The big pick-up flashlight — how far its main beam reaches (m).\nUA: Підбираний ліхтарик — як далеко б'є основний промінь (м).");
			Pick_RareWeight = ((BasePlugin)this).Config.Bind<float>("15 - Pickable Flashlight Rarity", "RareWeight", 0.001f, "EN: Spawn weight applied to every loot-table entry that drops the\n    consumable flashlight. Lower = rarer, higher = more common.\n    Reference scale (rolls are random against the table totals):\n       0.001  (DEFAULT) — near-zero natural rolls. The guarantee\n                          floor below force-promotes one mid-level\n                          so the player still gets ~1 per run.\n                          Feels like a special upgrade find.\n       0.01            — still very rare; ~10× more likely than\n                          default but most levels still rely on\n                          the guarantee.\n       0.1             — noticeably uncommon; 0-2 natural rolls\n                          per level on top of the guarantee.\n       1.0             — normal item rarity (same weight as a\n                          regular pickup); several per level,\n                          MaxPerLevel cap kicks in regularly.\n       10.0+           — flooded; almost every container.\n    The MaxPerLevel cap (section below) clamps over-quota rolls\n    by replacing them with a category-matching item, so even at\n    very high weights you won't see more flashlights than that\n    cap allows.\nUA: Вага появи (spawn weight) для consumable-ліхтарика у лут-\n    таблицях. Менше = рідше, більше = частіше.\n    Орієнтовна шкала (рандом проти суми ваг у таблиці):\n       0.001  (DEFAULT) — майже ніколи не випадає природно.\n                          Нижній «гарантійний поріг» примусово\n                          ставить ~1 ліхтарик на рівень, тож\n                          без нього теж не залишишся. Відчуття:\n                          рідкісний апгрейд-предмет.\n       0.01            — все ще дуже рідко; у ~10× ймовірніше\n                          за default, але рівні все одно тримають\n                          на гарантії.\n       0.1             — помітно нечасто; 0-2 природних випадки\n                          на рівень понад гарантію.\n       1.0             — звичайна рідкість предмета (як інший\n                          ресурс); кілька на рівень, ліміт\n                          MaxPerLevel спрацьовує регулярно.\n       10.0+           — буквально в кожному ящику.\n    Ліміт MaxPerLevel (нижче) обріже зайві випадання, заміняючи\n    їх на інший предмет тієї ж категорії — тож навіть при дуже\n    високій вазі ти не побачиш більше ліхтариків ніж ліміт.");
			Pick_MaxPerLevel = ((BasePlugin)this).Config.Bind<int>("15 - Pickable Flashlight Rarity", "MaxPerLevel", 2, "EN: Hard cap on how many consumable flashlights can appear in a\n    single level. Over-quota rolls are replaced with a different\n    item from the same loot category (so containers never end up\n    empty). 2 (DEFAULT) keeps the upgrade feeling scarce; raise\n    to 4-6 for a flashlight-rich run, set to 1 for hardcore.\nUA: Жорсткий ліміт скільки consumable-ліхтариків взагалі може\n    зʼявитись на рівні. Понад-лімітні випадання заміняються на\n    інший предмет тієї ж категорії (контейнери не лишаються\n    порожніми). 2 (DEFAULT) тримає апгрейд дефіцитним; постав\n    4-6 для забагів-ліхтариків, 1 для хардкору.");
			Pick_GuaranteeFloor = ((BasePlugin)this).Config.Bind<int>("15 - Pickable Flashlight Rarity", "GuaranteeAfterNPickups", 300, "EN: If RareWeight is so low that natural rolls don't produce a\n    flashlight, after this many non-flashlight pickups in a level\n    the NEXT pickup is force-converted into one. Ensures the\n    player gets at least one flashlight per run even with the\n    default RareWeight=0.001. Set to a very high number (e.g.\n    9999) to disable the guarantee — you'll then rely purely on\n    RareWeight.\nUA: Якщо RareWeight настільки малий, що природні випадання не\n    дають ліхтарика, то після стількох не-ліхтариків на рівні\n    НАСТУПНИЙ пікап буде примусово замінений на ліхтарик. Це\n    гарантує, що гравець отримає хоча б один за пробіг навіть\n    при default RareWeight=0.001. Постав велике число (наприклад\n    9999) щоб вимкнути гарантію — тоді все залежить лише від\n    RareWeight.");
			DustEnabled = ((BasePlugin)this).Config.Bind<bool>("16 - Dust Effect", "Dust_Enabled", true, "EN: Tiny dust motes drifting in the flashlight beam. They're\n    only visible when caught by the light, like real dust in a\n    torch beam. Turn off if your PC struggles or you just don't\n    like the look.\nUA: Дрібні пилинки, які плавають у промені ліхтарика. Вони\n    видимі тільки тоді, коли світло на них падає — як справжній\n    пил у промені. Вимкни, якщо комп слабкий або просто не\n    подобається ефект.");
			DustOpacity = ((BasePlugin)this).Config.Bind<float>("16 - Dust Effect", "Dust_Opacity", 1f, "EN: Opacity multiplier for all dust mote types (soft, star, medium).\n    1.0 = default tuned opacity. 0.5 = half as visible. 2.0 = twice\n    as visible. Values below 0 are clamped to 0 (invisible but pool\n    still runs — use Dust_Enabled = false to save CPU/GPU instead).\nUA: Множник непрозорості для всіх типів пилинок (soft, star, medium).\n    1.0 = забалансована базова прозорість. 0.5 = вдвічі слабше. 2.0 = вдвічі\n    сильніше. Значення нижче 0 затискається до 0 (невидимі, але пул\n    все одно працює — для економії ресурсів вимкни Dust_Enabled).");
			I3 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "I3_unused", 0f, "EN: Unused. / UA: Не використовується.");
			I4 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "I4_unused", 0f, "EN: Unused. / UA: Не використовується.");
			I5 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "I5_unused", 0f, "EN: Unused. / UA: Не використовується.");
			R3 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "R3_unused", 0f, "EN: Unused. / UA: Не використовується.");
			R4 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "R4_unused", 0f, "EN: Unused. / UA: Не використовується.");
			R5 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "R5_unused", 0f, "EN: Unused. / UA: Не використовується.");
			Step3 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "Step3_unused", 0f, "EN: Unused. / UA: Не використовується.");
			Step4 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "Step4_unused", 0f, "EN: Unused. / UA: Не використовується.");
			Step5 = ((BasePlugin)this).Config.Bind<float>("99 - Legacy", "Step5_unused", 0f, "EN: Unused. / UA: Не використовується.");
		}

		private ConfigEntry<float> Cfg(string section, string key, float defaultValue, string desc)
		{
			return ((BasePlugin)this).Config.Bind<float>(section, key, defaultValue, "EN/UA: " + desc);
		}

		internal static void ApplyPreset(FlashLightMode m)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			ModeAdjustments modeAdjustments = ModePresets.For(m);
			RangedPresets.BuildFromConfig(modeAdjustments.Ranged, m == FlashLightMode.MINIMAL);
			HelmetAngle = MeleeAngle.Value;
			HelmetIntensity = MeleeIntensity.Value;
			HelmetRange = MeleeRange.Value - 6f;
			HelmetFallRange = HelmetRange + 2f + 6f + 0f;
			PickAngle = Mathf.Min(Pick_Angle.Value + modeAdjustments.PickAngleOffset, 89f);
			PickIntensity = Mathf.Max(0f, Pick_Intensity.Value + modeAdjustments.PickIntensityOffset);
			PickRange = Pick_Range.Value + modeAdjustments.PickRangeOffset;
			PickColor = (Color)(((??)modeAdjustments.PickColorOverride) ?? new Color(1f, 0.84f, 0.6f));
		}
	}
	internal static class FlashlightEnemyDetection
	{
		private static readonly Dictionary<int, EnemyAgent> _agents = new Dictionary<int, EnemyAgent>();

		internal static Action<EnemyAgent, float, float>? OnEnemyInBeam;

		internal static float LastBeamRange = 24f;

		internal static float LastBeamIntensity = 0.75f;

		internal static bool LastBeamIsHeadlight = false;

		private static bool _tickEverCalled = false;

		private static bool _enemyLayerLogged = false;

		private static float _lastDiagAt = -999f;

		private static float _lastRegistryRefreshAt = -999f;

		internal static void RegisterAgent(EnemyAgent agent)
		{
			if ((Object)(object)agent == (Object)null)
			{
				return;
			}
			try
			{
				int instanceID = ((Object)agent).GetInstanceID();
				_agents[instanceID] = agent;
			}
			catch
			{
			}
		}

		internal static void UnregisterAgent(EnemyAgent agent)
		{
			if ((Object)(object)agent == (Object)null)
			{
				return;
			}
			try
			{
				_agents.Remove(((Object)agent).GetInstanceID());
			}
			catch
			{
			}
		}

		private static void RefreshRegistryFromScene(float now, bool force)
		{
			if (!force && now - _lastRegistryRefreshAt < 10f)
			{
				return;
			}
			_lastRegistryRefreshAt = now;
			try
			{
				Il2CppArrayBase<EnemyAgent> val = Object.FindObjectsOfType<EnemyAgent>();
				if (val == null || val.Length == 0)
				{
					return;
				}
				int count = _agents.Count;
				int num = 0;
				foreach (EnemyAgent item in val)
				{
					if (!((Object)(object)item == (Object)null))
					{
						int instanceID;
						try
						{
							instanceID = ((Object)item).GetInstanceID();
						}
						catch
						{
							continue;
						}
						if (!_agents.ContainsKey(instanceID))
						{
							num++;
						}
						_agents[instanceID] = item;
					}
				}
				if (force || num > 0)
				{
					Plugin.Logger.LogInfo((object)("[FO] Registry refresh: before=" + count + " found=" + val.Length + " added=" + num + " total=" + _agents.Count));
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[FO] Registry refresh threw: " + ex.Message));
			}
		}

		internal static void LogEnemyLayer(EnemyAgent agent)
		{
			if (_enemyLayerLogged)
			{
				return;
			}
			_enemyLayerLogged = true;
			try
			{
				int layer = ((Component)agent).gameObject.layer;
				Plugin.Logger.LogInfo((object)("[FO] EnemyAgent root layer: " + layer + " (\"" + LayerMask.LayerToName(layer) + "\") agent=" + ((Object)((Component)agent).gameObject).name));
				Il2CppArrayBase<Collider> componentsInChildren = ((Component)agent).GetComponentsInChildren<Collider>(true);
				if (componentsInChildren == null)
				{
					return;
				}
				HashSet<int> hashSet = new HashSet<int>();
				StringBuilder stringBuilder = new StringBuilder();
				foreach (Collider item in componentsInChildren)
				{
					if (!((Object)(object)item == (Object)null))
					{
						int layer2 = ((Component)item).gameObject.layer;
						if (hashSet.Add(layer2))
						{
							stringBuilder.Append(layer2).Append('(').Append(LayerMask.LayerToName(layer2))
								.Append(") ");
						}
					}
				}
				Plugin.Logger.LogInfo((object)("[FO] EnemyAgent child collider layers: " + stringBuilder.ToString().TrimEnd()));
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[FO] EnemyLayer probe threw: " + ex.Message));
			}
		}

		internal static void Tick(Transform coneRoot, Light coneLight, float? detectionRangeOverride = null, float? spotAngleOverride = null, float intensityScale = 1f, bool isHeadlight = false)
		{
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Invalid comparison between Unknown and I4
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			float num = spotAngleOverride ?? coneLight.spotAngle;
			float num2 = num * 0.5f;
			float num3 = detectionRangeOverride ?? coneLight.range;
			Vector3 position = coneRoot.position;
			Vector3 forward = coneRoot.forward;
			LastBeamRange = num3;
			LastBeamIntensity = coneLight.intensity * Mathf.Max(0f, intensityScale);
			LastBeamIsHeadlight = isHeadlight;
			RefreshRegistryFromScene(unscaledTime, _agents.Count == 0);
			if (!_tickEverCalled)
			{
				_tickEverCalled = true;
				Plugin.Logger.LogInfo((object)("[FO] Tick first call: spotAngle=" + num.ToString("F1") + " range=" + num3.ToString("F1") + " registry=" + _agents.Count));
			}
			if (_agents.Count == 0 && unscaledTime - _lastDiagAt > 10f)
			{
				_lastDiagAt = unscaledTime;
				Plugin.Logger.LogInfo((object)"[FO] Tick diag: registry empty — no EnemyAgent instances found yet.");
				return;
			}
			int num4 = 0;
			int num5 = 0;
			foreach (KeyValuePair<int, EnemyAgent> agent in _agents)
			{
				EnemyAgent value = agent.Value;
				if ((Object)(object)value == (Object)null)
				{
					continue;
				}
				num4++;
				try
				{
					if ((Object)(object)value.AI == (Object)null || (int)((AgentAI)value.AI).Mode == 1)
					{
						continue;
					}
					goto IL_0199;
				}
				catch
				{
				}
				continue;
				IL_0199:
				Vector3 val;
				float magnitude;
				try
				{
					val = ((Component)value).transform.position - position;
					magnitude = ((Vector3)(ref val)).magnitude;
				}
				catch
				{
					continue;
				}
				if (magnitude > num3 || magnitude < 0.1f)
				{
					continue;
				}
				float num6 = Vector3.Angle(forward, val);
				if (num6 > num2)
				{
					continue;
				}
				try
				{
					if (Physics.Raycast(position, val / magnitude, magnitude, 257, (QueryTriggerInteraction)1))
					{
						continue;
					}
				}
				catch
				{
					continue;
				}
				num5++;
				try
				{
					OnEnemyInBeam?.Invoke(value, magnitude, num6);
				}
				catch
				{
				}
			}
			if (unscaledTime - _lastDiagAt > 5f && num4 > 0)
			{
				_lastDiagAt = unscaledTime;
				Plugin.Logger.LogInfo((object)("[FO] Tick diag: registry=" + _agents.Count + " checked=" + num4 + " inBeam=" + num5 + " range=" + num3.ToString("F1")));
			}
		}

		internal static void Reset()
		{
			_agents.Clear();
			_tickEverCalled = false;
			_enemyLayerLogged = false;
			_lastDiagAt = -999f;
			_lastRegistryRefreshAt = -999f;
		}
	}
	internal static class RangedPresets
	{
		internal struct Preset
		{
			public string Name;

			public Color Tint;

			public bool HasMid;

			public float CoreAngle;

			public float CoreIntensity;

			public float CoreRange;

			public float MidAngle;

			public float MidIntensity;

			public float MidRange;

			public float FallAngle;

			public float FallIntensity;

			public float FallRange;
		}

		internal static readonly Color CoolWhite = new Color(0.85f, 0.93f, 1f);

		internal static readonly Color WarmYellow = new Color(1f, 0.93f, 0.75f);

		internal static Preset ShortRange;

		internal static Preset MediumRange1;

		internal static Preset MediumRange2;

		internal static Preset WideRange;

		internal static Preset ExtendedRange;

		internal static Preset Default;

		internal static readonly Dictionary<uint, Preset> ByPID = new Dictionary<uint, Preset>();

		private static readonly Dictionary<int, Preset?> _ownerPresetCache = new Dictionary<int, Preset?>();

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

		internal static void BuildFromConfig(PresetOffset offset, bool minimalMode = false)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			bool hasMid = true;
			Preset shortRange = default(Preset);
			shortRange.Name = "Short range (Yellow, Wide)";
			shortRange.Tint = WarmYellow;
			shortRange.HasMid = hasMid;
			shortRange.CoreAngle = Plugin.P_Short_CoreAngle.Value + offset.CoreAngle;
			shortRange.CoreIntensity = Plugin.P_Short_CoreIntensity.Value + offset.CoreIntensity;
			shortRange.CoreRange = Plugin.P_Short_CoreRange.Value + offset.CoreRange;
			shortRange.MidAngle = Plugin.P_Short_MidAngle.Value + offset.MidAngle;
			shortRange.MidIntensity = Plugin.P_Short_MidIntensity.Value + offset.MidIntensity;
			shortRange.MidRange = Plugin.P_Short_MidRange.Value + offset.MidRange;
			shortRange.FallAngle = Plugin.P_Short_FallAngle.Value + offset.FallAngle;
			shortRange.FallIntensity = Plugin.P_Short_FallIntensity.Value + offset.FallIntensity;
			shortRange.FallRange = Plugin.P_Short_FallRange.Value + offset.FallRange;
			ShortRange = shortRange;
			shortRange = default(Preset);
			shortRange.Name = "Medium range #1 (White, Medium)";
			shortRange.Tint = CoolWhite;
			shortRange.HasMid = hasMid;
			shortRange.CoreAngle = Plugin.P_Med1_CoreAngle.Value + offset.CoreAngle;
			shortRange.CoreIntensity = Plugin.P_Med1_CoreIntensity.Value + offset.CoreIntensity;
			shortRange.CoreRange = Plugin.P_Med1_CoreRange.Value + offset.CoreRange;
			shortRange.MidAngle = Plugin.P_Med1_MidAngle.Value + offset.MidAngle;
			shortRange.MidIntensity = Plugin.P_Med1_MidIntensity.Value + offset.MidIntensity;
			shortRange.MidRange = Plugin.P_Med1_MidRange.Value + offset.MidRange;
			shortRange.FallAngle = Plugin.P_Med1_FallAngle.Value + offset.FallAngle;
			shortRange.FallIntensity = Plugin.P_Med1_FallIntensity.Value + offset.FallIntensity;
			shortRange.FallRange = Plugin.P_Med1_FallRange.Value + offset.FallRange;
			MediumRange1 = shortRange;
			shortRange = default(Preset);
			shortRange.Name = "Medium range #2 (White, Tight)";
			shortRange.Tint = CoolWhite;
			shortRange.HasMid = hasMid;
			shortRange.CoreAngle = Plugin.P_Med2_CoreAngle.Value + offset.CoreAngle;
			shortRange.CoreIntensity = Plugin.P_Med2_CoreIntensity.Value + offset.CoreIntensity;
			shortRange.CoreRange = Plugin.P_Med2_CoreRange.Value + offset.CoreRange;
			shortRange.MidAngle = Plugin.P_Med2_MidAngle.Value + offset.MidAngle;
			shortRange.MidIntensity = Plugin.P_Med2_MidIntensity.Value + offset.MidIntensity;
			shortRange.MidRange = Plugin.P_Med2_MidRange.Value + offset.MidRange;
			shortRange.FallAngle = Plugin.P_Med2_FallAngle.Value + offset.FallAngle;
			shortRange.FallIntensity = Plugin.P_Med2_FallIntensity.Value + offset.FallIntensity;
			shortRange.FallRange = Plugin.P_Med2_FallRange.Value + offset.FallRange;
			MediumRange2 = shortRange;
			shortRange = default(Preset);
			shortRange.Name = "Wide range (White, Wide)";
			shortRange.Tint = CoolWhite;
			shortRange.HasMid = hasMid;
			shortRange.CoreAngle = Plugin.P_Wide_CoreAngle.Value + offset.CoreAngle;
			shortRange.CoreIntensity = Plugin.P_Wide_CoreIntensity.Value + offset.CoreIntensity;
			shortRange.CoreRange = Plugin.P_Wide_CoreRange.Value + offset.CoreRange;
			shortRange.MidAngle = Plugin.P_Wide_MidAngle.Value + offset.MidAngle;
			shortRange.MidIntensity = Plugin.P_Wide_MidIntensity.Value + offset.MidIntensity;
			shortRange.MidRange = Plugin.P_Wide_MidRange.Value + offset.MidRange;
			shortRange.FallAngle = Plugin.P_Wide_FallAngle.Value + offset.FallAngle;
			shortRange.FallIntensity = Plugin.P_Wide_FallIntensity.Value + offset.FallIntensity;
			shortRange.FallRange = Plugin.P_Wide_FallRange.Value + offset.FallRange;
			WideRange = shortRange;
			shortRange = default(Preset);
			shortRange.Name = "Extended range (White, Tight) — base";
			shortRange.Tint = CoolWhite;
			shortRange.HasMid = hasMid;
			shortRange.CoreAngle = Plugin.P_Ext_CoreAngle.Value + offset.CoreAngle;
			shortRange.CoreIntensity = Plugin.P_Ext_CoreIntensity.Value + offset.CoreIntensity;
			shortRange.CoreRange = Plugin.P_Ext_CoreRange.Value + offset.CoreRange;
			shortRange.MidAngle = Plugin.P_Ext_MidAngle.Value + offset.MidAngle;
			shortRange.MidIntensity = Plugin.P_Ext_MidIntensity.Value + offset.MidIntensity;
			shortRange.MidRange = Plugin.P_Ext_MidRange.Value + offset.MidRange;
			shortRange.FallAngle = Plugin.P_Ext_FallAngle.Value + offset.FallAngle;
			shortRange.FallIntensity = Plugin.P_Ext_FallIntensity.Value + offset.FallIntensity;
			shortRange.FallRange = Plugin.P_Ext_FallRange.Value + offset.FallRange;
			ExtendedRange = shortRange;
			if (minimalMode)
			{
				CollapseMidToCore(ref ShortRange);
				CollapseMidToCore(ref MediumRange1);
				CollapseMidToCore(ref MediumRange2);
				CollapseMidToCore(ref WideRange);
				CollapseMidToCore(ref ExtendedRange);
			}
			ClampFallAngle(ref ShortRange, 165f);
			ClampFallAngle(ref MediumRange1, 165f);
			ClampFallAngle(ref MediumRange2, 165f);
			ClampFallAngle(ref WideRange, 165f);
			ClampFallAngle(ref ExtendedRange, 165f);
			Default = ExtendedRange;
		}

		private static void ClampFallAngle(ref Preset p, float deg)
		{
			if (p.FallAngle > deg)
			{
				p.FallAngle = deg;
			}
		}

		private static void CollapseMidToCore(ref Preset p)
		{
			p.MidAngle = p.CoreAngle;
			p.MidRange = p.CoreRange;
		}

		internal static Preset Classify(string blockName, float origAngle, float origRange)
		{
			string obj = blockName ?? "";
			bool flag = obj.IndexOf("wide", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag2 = obj.IndexOf("tight", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag3 = obj.IndexOf("medium", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag4 = obj.IndexOf("short", StringComparison.OrdinalIgnoreCase) >= 0;
			bool flag5 = obj.IndexOf("extend", StringComparison.OrdinalIgnoreCase) >= 0;
			if (flag4)
			{
				return ShortRange;
			}
			if (flag3 && flag2)
			{
				return MediumRange2;
			}
			if (flag3)
			{
				return MediumRange1;
			}
			if (flag && flag5)
			{
				return WideRange;
			}
			if (flag)
			{
				return WideRange;
			}
			if (flag5)
			{
				return ExtendedRange;
			}
			if (flag2)
			{
				return ExtendedRange;
			}
			bool flag6 = origAngle <= 40f;
			bool flag7 = origAngle >= 55f;
			bool flag8 = origRange <= 12f;
			bool flag9 = origRange >= 17f;
			if (flag7 && flag8)
			{
				return ShortRange;
			}
			if (flag6 && flag9)
			{
				return ExtendedRange;
			}
			if (flag7 && flag9)
			{
				return WideRange;
			}
			if (flag7)
			{
				return WideRange;
			}
			if (flag6)
			{
				return MediumRange2;
			}
			return MediumRange1;
		}

		internal static void ClearOwnerCaches()
		{
			_ownerPresetCache.Clear();
		}

		internal static void ClearOwnerCacheEntry(ItemEquippable? owner)
		{
			if (!((Object)(object)owner == (Object)null))
			{
				int instanceID;
				try
				{
					instanceID = ((Object)owner).GetInstanceID();
				}
				catch
				{
					return;
				}
				_ownerPresetCache.Remove(instanceID);
			}
		}

		internal static Preset? ResolveByOwner(ItemEquippable? owner)
		{
			if ((Object)(object)owner == (Object)null)
			{
				return null;
			}
			int instanceID;
			try
			{
				instanceID = ((Object)owner).GetInstanceID();
			}
			catch
			{
				return null;
			}
			if (_ownerPresetCache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			StringBuilder stringBuilder = new StringBuilder(256);
			try
			{
				GameObject gameObject = ((Component)owner).gameObject;
				if ((Object)(object)gameObject != (Object)null)
				{
					stringBuilder.Append(" goName=").Append(((Object)gameObject).name);
				}
			}
			catch
			{
			}
			try
			{
				Transform val = ((Component)owner).transform;
				int num = 8;
				stringBuilder.Append(" path=");
				bool flag = true;
				while ((Object)(object)val != (Object)null && num-- > 0)
				{
					if (!flag)
					{
						stringBuilder.Append('/');
					}
					stringBuilder.Append(((Object)val).name ?? "?");
					flag = false;
					val = val.parent;
				}
			}
			catch
			{
			}
			try
			{
				Transform transform = ((Component)owner).transform;
				if ((Object)(object)transform != (Object)null)
				{
					int childCount = transform.childCount;
					stringBuilder.Append(" children=[");
					for (int i = 0; i < childCount && i < 12; i++)
					{
						Transform child = transform.GetChild(i);
						if (i > 0)
						{
							stringBuilder.Append(',');
						}
						stringBuilder.Append(((Object)child).name ?? "?");
					}
					stringBuilder.Append(']');
				}
			}
			catch
			{
			}
			try
			{
				Transform transform2 = ((Component)owner).transform;
				if ((Object)(object)transform2 != (Object)null)
				{
					StringBuilder stringBuilder2 = new StringBuilder();
					CollectDescendantNamesContaining(transform2, "Flashlight", stringBuilder2, 8, 6);
					if (stringBuilder2.Length > 0)
					{
						stringBuilder.Append(" flashlightGOs=[").Append(stringBuilder2).Append(']');
					}
					stringBuilder2.Clear();
					CollectDescendantNamesContaining(transform2, "WPN_", stringBuilder2, 8, 6);
					if (stringBuilder2.Length > 0)
					{
						stringBuilder.Append(" wpnGOs=[").Append(stringBuilder2).Append(']');
					}
				}
			}
			catch
			{
			}
			string text = stringBuilder.ToString();
			Preset? preset = MatchKeywords(text);
			_ownerPresetCache[instanceID] = preset;
			try
			{
				string text2 = (preset.HasValue ? (preset.Value.Name ?? "Unnamed") : "null");
				string text3 = text + " => " + text2;
				if (_loggedProbes.Add(text3))
				{
					Plugin.Logger.LogInfo((object)("[RF] OwnerNameProbe " + text3));
				}
			}
			catch
			{
			}
			return preset;
		}

		private static void CollectDescendantNamesContaining(Transform t, string substring, StringBuilder sink, int maxDepth, int maxResults)
		{
			if ((Object)(object)t == (Object)null || maxDepth < 0)
			{
				return;
			}
			try
			{
				int childCount = t.childCount;
				for (int i = 0; i < childCount; i++)
				{
					Transform child = t.GetChild(i);
					string text = ((Object)child).name ?? "";
					if (text.IndexOf(substring, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						if (sink.Length > 0)
						{
							sink.Append(',');
						}
						sink.Append(text);
						if (sink.Length >= maxResults * 32)
						{
							break;
						}
					}
					if (maxDepth > 0)
					{
						CollectDescendantNamesContaining(child, substring, sink, maxDepth - 1, maxResults);
					}
				}
			}
			catch
			{
			}
		}

		private static Preset? MatchKeywords(string s)
		{
			string s2 = s;
			if (C("Flashlight_A"))
			{
				return ShortRange;
			}
			if (C("Flashlight_B"))
			{
				return MediumRange2;
			}
			if (C("Flashlight_C"))
			{
				return ExtendedRange;
			}
			if (C("Flashlight_D"))
			{
				return WideRange;
			}
			if (C("Flashlight_E"))
			{
				return MediumRange1;
			}
			if (C("Sniper"))
			{
				return ExtendedRange;
			}
			if (C("HELRifle") || (C("HEL") && C("Rifle") && !C("HELShotgun")))
			{
				return ExtendedRange;
			}
			if (C("BurstRifle"))
			{
				return ExtendedRange;
			}
			if (C("Veruta"))
			{
				return WideRange;
			}
			if (C("Arbalist"))
			{
				return WideRange;
			}
			if (C("BurstCannon"))
			{
				return WideRange;
			}
			if (C("PDW"))
			{
				return WideRange;
			}
			if (C("Bullpup"))
			{
				return MediumRange1;
			}
			if (C("HELShotgun") || C("HELGun"))
			{
				return MediumRange1;
			}
			if (C("HeavyAssault"))
			{
				return MediumRange1;
			}
			if (C("Scattergun"))
			{
				return MediumRange1;
			}
			if (C("DoubleTap"))
			{
				return MediumRange1;
			}
			if (C("SlugShotgun"))
			{
				return MediumRange1;
			}
			if (C("ChokeMod"))
			{
				return MediumRange1;
			}
			if (C("DMR"))
			{
				return MediumRange2;
			}
			if (C("Carbine"))
			{
				return MediumRange2;
			}
			if (C("MachinePistol"))
			{
				return MediumRange2;
			}
			if (C("Sawed"))
			{
				return MediumRange2;
			}
			if (C("HELRevolver"))
			{
				return MediumRange2;
			}
			if (C("HELAuto") && C("Pistol"))
			{
				return MediumRange2;
			}
			if (C("HighCal") && C("Pistol"))
			{
				return MediumRange2;
			}
			if (C("BurstPistol"))
			{
				return MediumRange2;
			}
			if (C("AssaultRifle"))
			{
				return MediumRange2;
			}
			if (C("ShortRifle"))
			{
				return MediumRange2;
			}
			if (C("HeavySMG"))
			{
				return MediumRange2;
			}
			if (C("Pistol"))
			{
				return MediumRange2;
			}
			if (C("Revolver"))
			{
				return ShortRange;
			}
			if (C("CombatShotgun"))
			{
				return ShortRange;
			}
			if (C("PrecisionRifle"))
			{
				return ShortRange;
			}
			if (C("SMG"))
			{
				return ShortRange;
			}
			if (C("Shotgun"))
			{
				return ShortRange;
			}
			if (C("Rifle"))
			{
				return MediumRange1;
			}
			return null;
			bool C(string k)
			{
				return s2.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0;
			}
		}

		internal static Preset ResolveByLight(Light light)
		{
			if ((Object)(object)light == (Object)null || ByPID.Count == 0)
			{
				return Default;
			}
			float spotAngle = light.spotAngle;
			float range = light.range;
			float intensity = light.intensity;
			foreach (KeyValuePair<uint, Preset> item in ByPID)
			{
				Preset value = item.Value;
				float num = value.CoreAngle - Plugin.Step1.Value;
				if (Mathf.Abs(spotAngle - num) <= 1f && Mathf.Abs(range - value.CoreRange) <= 1f && Mathf.Abs(intensity - value.CoreIntensity) <= 0.005f)
				{
					return value;
				}
			}
			return Default;
		}
	}
	internal static class LightSandwich
	{
		internal enum ManagedKind
		{
			None,
			Pickable,
			MeleeOrTool,
			Ranged
		}

		internal const string RFCORE = "RF_Core";

		internal const string L1 = "RF_L1";

		internal const string L2 = "RF_L2";

		internal const string SPILL = "RF_Spill";

		internal const string DUST = "RF_Dust";

		internal const string L3 = "RF_L3";

		internal const string L4 = "RF_L4";

		internal const string L5 = "RF_L5";

		private static readonly string[] AllLayers = new string[3] { "RF_Core", "RF_L1", "RF_L2" };

		private const float CoreLayerOverlap = 0.28f;

		private const float MidLayerOverlap = 0.2f;

		private static readonly string[] LegacyLayers = new string[8] { "RF_Core", "RF_L1", "RF_L2", "RF_Spill", "RF_Dust", "RF_L3", "RF_L4", "RF_L5" };

		private static readonly Dictionary<int, ManagedKind> _managed = new Dictionary<int, ManagedKind>();

		internal static readonly Dictionary<int, RangedPresets.Preset> _lightPreset = new Dictionary<int, RangedPresets.Preset>();

		private static Texture2D? _smoothCookie;

		private static Texture2D? _coreCookie;

		private static Texture2D? _midCookie;

		private static Texture2D? _falloffCookie;

		internal static readonly HashSet<int> HelmetEditedIDs = new HashSet<int>();

		private static float WithLayerOverlap(float nominalAngle, int idx)
		{
			return Mathf