Decompiled source of TightBeam v1.0.0

TightBeam.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppScheduleOne;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Equipping;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Tools;
using Il2CppScheduleOne.UI.Phone;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using TightBeam;
using TightBeam.Bridge;
using TightBeam.Config;
using TightBeam.Lighting;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "TightBeam", "1.0.0", "DooDesch", "https://github.com/DooDesch-Mods/ScheduleOne-TightBeam")]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TightBeam")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2356d0d8d4071b704c23e86fab0a84b04562e318")]
[assembly: AssemblyProduct("TightBeam")]
[assembly: AssemblyTitle("TightBeam")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TightBeam
{
	public sealed class Core : MelonMod
	{
		private bool _inMain;

		private bool _patched;

		public static Instance Log { get; private set; }

		public override void OnInitializeMelon()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Log = ((MelonBase)this).LoggerInstance;
			TightBeamPreferences.Initialize();
			FlashlightController.Instance.InitFromPrefs();
			BridgeHost.Install();
			Log.Msg($"TightBeam initialized. Enabled={TightBeamPreferences.Enabled}. On/off follows the game flashlight; hold {TightBeamPreferences.FocusModifierKey} + mouse wheel = focus/Pegel.");
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			_inMain = sceneName == "Main";
			if (_inMain && !_patched)
			{
				((MelonBase)this).HarmonyInstance.PatchAll(typeof(Core).Assembly);
				_patched = true;
				Log.Msg("TightBeam: hotbar ALT+scroll guard applied.");
			}
		}

		public override void OnUpdate()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!TightBeamPreferences.Enabled || !_inMain)
			{
				return;
			}
			FlashlightController instance = FlashlightController.Instance;
			instance.SyncOnFromGame();
			if (instance.IsOn)
			{
				if (Input.GetKey(TightBeamPreferences.FocusModifierKey))
				{
					instance.UpdateFocusScroll(GameInput.MouseScrollDelta, Time.deltaTime);
				}
				else
				{
					instance.ResetFocusScrollVelocity();
				}
			}
		}

		public override void OnLateUpdate()
		{
			if (TightBeamPreferences.Enabled)
			{
				FlashlightController instance = FlashlightController.Instance;
				if (!_inMain)
				{
					instance.DisableRig();
					return;
				}
				instance.EnsureRig();
				instance.Follow();
				instance.Tick(Time.deltaTime);
			}
		}
	}
}
namespace TightBeam.Patches
{
	[HarmonyPatch(typeof(PlayerInventory), "UpdateHotbarSelection")]
	internal static class HotbarScrollGuard
	{
		private static bool Prefix()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!TightBeamPreferences.Enabled)
			{
				return true;
			}
			if (Input.GetKey(TightBeamPreferences.FocusModifierKey) && GameInput.MouseScrollDelta != 0f)
			{
				return false;
			}
			return true;
		}
	}
}
namespace TightBeam.Lighting
{
	internal sealed class FlashlightController
	{
		private sealed class Ov
		{
			public int Token;

			public string Owner;

			public float? I;

			public float? R;

			public float? A;

			public Color? C;

			public float Expiry;
		}

		private enum FxMode
		{
			None,
			Flicker,
			Pulse
		}

		private GameObject _go;

		private Light _light;

		private Camera _cam;

		private bool _isOn;

		private float _focus;

		private float _focusTarget;

		private float _scrollVelEma;

		private float _intensity;

		private Color _color = Color.white;

		private float? _manualRange;

		private float? _manualAngle;

		private readonly List<Ov> _overrides = new List<Ov>();

		private int _nextToken = 1;

		private FxMode _fx;

		private float _fxStrength;

		private float _fxFreq;

		private float _fxAmp;

		private float _fxPeriod;

		private float _fxEnd;

		private float _fxSeed;

		private int _blinkLeft;

		private float _blinkInterval;

		private float _blinkNext;

		private bool _blinkDark;

		public static FlashlightController Instance { get; } = new FlashlightController();

		public bool IsOn => _isOn;

		public bool HasLight => (Object)(object)_light != (Object)null;

		public float Focus => _focus;

		public float CurrentIntensity
		{
			get
			{
				if (!((Object)(object)_light != (Object)null))
				{
					return 0f;
				}
				return _light.intensity;
			}
		}

		public float CurrentRange
		{
			get
			{
				if (!((Object)(object)_light != (Object)null))
				{
					return 0f;
				}
				return _light.range;
			}
		}

		public float CurrentSpotAngle
		{
			get
			{
				if (!((Object)(object)_light != (Object)null))
				{
					return 0f;
				}
				return _light.spotAngle;
			}
		}

		public Color CurrentColor
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_light != (Object)null))
				{
					return Color.black;
				}
				return _light.color;
			}
		}

		public event Action<bool> Toggled;

		public void InitFromPrefs()
		{
			//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)
			_focus = TightBeamPreferences.DefaultFocus;
			_focusTarget = _focus;
			_scrollVelEma = 0f;
			_intensity = TightBeamPreferences.DefaultIntensity;
			_color = TightBeamPreferences.Color;
		}

		public void EnsureRig()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if ((Object)(object)_light == (Object)null)
			{
				_go = new GameObject("TightBeamLight");
				Object.DontDestroyOnLoad((Object)(object)_go);
				_light = _go.AddComponent<Light>();
				_light.type = (LightType)0;
				_light.renderMode = (LightRenderMode)0;
				_light.shadows = (LightShadows)(TightBeamPreferences.CastShadows ? 2 : 0);
				_light.shadowBias = 0.05f;
				_light.shadowNormalBias = 0.4f;
				((Behaviour)_light).enabled = false;
			}
			if ((Object)(object)_cam == (Object)null)
			{
				_cam = Camera.main;
			}
		}

		public void DisableRig()
		{
			if ((Object)(object)_light != (Object)null)
			{
				((Behaviour)_light).enabled = false;
			}
			VanillaLightSync.Restore();
		}

		public void Follow()
		{
			//IL_004f: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_light == (Object)null)
			{
				return;
			}
			if ((Object)(object)_cam == (Object)null)
			{
				_cam = Camera.main;
				if ((Object)(object)_cam == (Object)null)
				{
					return;
				}
			}
			Transform transform = ((Component)_cam).transform;
			_go.transform.position = transform.position + transform.forward * 0.25f + transform.right * 0.15f - transform.up * 0.2f;
			_go.transform.rotation = transform.rotation;
		}

		public void Tick(float dt)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_light == (Object)null)
			{
				return;
			}
			float num = 1f - Mathf.Exp((0f - dt) / TightBeamPreferences.FocusEaseTau);
			_focus = Mathf.Lerp(_focus, _focusTarget, num);
			if (Mathf.Abs(_focusTarget - _focus) < 0.0005f)
			{
				_focus = _focusTarget;
			}
			float num2 = _manualRange ?? Mathf.Lerp(TightBeamPreferences.RangeNarrow, TightBeamPreferences.RangeWide, _focus);
			float num3 = _manualAngle ?? Mathf.Lerp(TightBeamPreferences.AngleNarrow, TightBeamPreferences.AngleWide, _focus);
			float intensity = _intensity;
			Color color = _color;
			PruneOverrides();
			float num4 = num2;
			float num5 = num3;
			float num6 = intensity;
			Color val = color;
			for (int num7 = _overrides.Count - 1; num7 >= 0; num7--)
			{
				Ov ov = _overrides[num7];
				if (ov.I.HasValue && num6 == intensity)
				{
					num6 = ov.I.Value;
				}
				if (ov.R.HasValue && num4 == num2)
				{
					num4 = ov.R.Value;
				}
				if (ov.A.HasValue && num5 == num3)
				{
					num5 = ov.A.Value;
				}
				if (ov.C.HasValue && val == color)
				{
					val = ov.C.Value;
				}
			}
			num6 *= EffectMultiplier(dt);
			_light.intensity = Mathf.Max(0f, num6);
			_light.range = Mathf.Clamp(num4, 2f, 60f);
			_light.spotAngle = Mathf.Clamp(num5, 8f, 90f);
			_light.innerSpotAngle = _light.spotAngle * 0.6f;
			_light.color = val;
			((Behaviour)_light).enabled = _isOn;
			VanillaLightSync.Apply(_isOn);
		}

		private float EffectMultiplier(float dt)
		{
			float num = 1f;
			if (_fx == FxMode.Flicker)
			{
				if (Time.time >= _fxEnd)
				{
					_fx = FxMode.None;
				}
				else
				{
					float num2 = Mathf.PerlinNoise(Time.time * _fxFreq + _fxSeed, _fxSeed * 0.37f);
					num *= Mathf.Lerp(1f - _fxStrength, 1f, num2);
				}
			}
			else if (_fx == FxMode.Pulse)
			{
				if (Time.time >= _fxEnd)
				{
					_fx = FxMode.None;
				}
				else
				{
					num *= 1f + _fxAmp * Mathf.Sin(Time.time * ((float)Math.PI * 2f / Mathf.Max(0.05f, _fxPeriod)) + _fxSeed);
				}
			}
			if (_blinkLeft > 0)
			{
				if (Time.time >= _blinkNext)
				{
					_blinkDark = !_blinkDark;
					_blinkLeft--;
					_blinkNext = Time.time + _blinkInterval;
				}
				if (_blinkDark)
				{
					num *= 0.04f;
				}
			}
			return Mathf.Max(0f, num);
		}

		private void PruneOverrides()
		{
			for (int num = _overrides.Count - 1; num >= 0; num--)
			{
				if (_overrides[num].Expiry > 0f && Time.time > _overrides[num].Expiry)
				{
					_overrides.RemoveAt(num);
				}
			}
		}

		public void SyncOnFromGame()
		{
			bool flag = false;
			try
			{
				if (PlayerSingleton<Phone>.InstanceExists)
				{
					GameObject phoneFlashlight = PlayerSingleton<Phone>.Instance.PhoneFlashlight;
					flag = (Object)(object)phoneFlashlight != (Object)null && phoneFlashlight.activeSelf;
				}
			}
			catch
			{
				return;
			}
			if (flag != _isOn)
			{
				_isOn = flag;
				try
				{
					this.Toggled?.Invoke(flag);
				}
				catch
				{
				}
			}
		}

		public void SetOn(bool on)
		{
			try
			{
				if (PlayerSingleton<Phone>.InstanceExists && PlayerSingleton<Phone>.Instance.FlashlightOn != on)
				{
					PlayerSingleton<Phone>.Instance.ToggleFlashlight();
				}
			}
			catch
			{
			}
		}

		public void Toggle()
		{
			try
			{
				if (PlayerSingleton<Phone>.InstanceExists)
				{
					PlayerSingleton<Phone>.Instance.ToggleFlashlight();
				}
			}
			catch
			{
			}
		}

		private void MoveFocusTarget(float delta)
		{
			_focusTarget = Mathf.Clamp01(_focusTarget + delta);
			_manualRange = null;
			_manualAngle = null;
		}

		private void SnapFocusTarget(float value)
		{
			_focusTarget = Mathf.Clamp01(value);
			_manualRange = null;
			_manualAngle = null;
		}

		public void NudgeFocus(float delta)
		{
			MoveFocusTarget(delta);
		}

		public void UpdateFocusScroll(float scrollDelta, float dt)
		{
			if (Mathf.Abs(scrollDelta) > 0.0001f)
			{
				float num = Mathf.Abs(scrollDelta) / Mathf.Max(dt, 0.004166667f);
				float num2 = 1f - Mathf.Exp((0f - dt) / TightBeamPreferences.FocusVelAttackTau);
				_scrollVelEma = Mathf.Lerp(_scrollVelEma, num, num2);
				float focusVelocityRefRate = TightBeamPreferences.FocusVelocityRefRate;
				float num3 = focusVelocityRefRate * TightBeamPreferences.FocusFlickRateMultiplier;
				float num4 = (TightBeamPreferences.InvertFocusScroll ? (-1f) : 1f);
				float num5 = Mathf.Sign(scrollDelta) * num4;
				if (_scrollVelEma >= num3)
				{
					SnapFocusTarget((num5 > 0f) ? 1f : 0f);
					return;
				}
				float num6 = Mathf.Clamp01((_scrollVelEma - focusVelocityRefRate) / Mathf.Max(0.0001f, num3 - focusVelocityRefRate));
				float num7 = Mathf.Lerp(TightBeamPreferences.FocusSensitivity, TightBeamPreferences.FocusMaxStep, Mathf.Pow(num6, TightBeamPreferences.FocusVelocityGamma));
				MoveFocusTarget(num5 * num7);
			}
			else
			{
				float num8 = 1f - Mathf.Exp((0f - dt) / TightBeamPreferences.FocusVelDecayTau);
				_scrollVelEma = Mathf.Lerp(_scrollVelEma, 0f, num8);
			}
		}

		public void ResetFocusScrollVelocity()
		{
			_scrollVelEma = 0f;
		}

		public void SetIntensity(float v)
		{
			_intensity = Mathf.Clamp(v, TightBeamPreferences.MinIntensity, TightBeamPreferences.MaxIntensity);
		}

		public void SetColor(Color c)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_color = c;
		}

		public void SetBaseRange(float v)
		{
			_manualRange = Mathf.Clamp(v, 2f, 60f);
		}

		public void SetBaseSpotAngle(float v)
		{
			_manualAngle = Mathf.Clamp(v, 8f, 90f);
		}

		public int BeginOverride(string owner)
		{
			Ov ov = new Ov
			{
				Token = _nextToken++,
				Owner = owner
			};
			_overrides.Add(ov);
			return ov.Token;
		}

		public void EndOverride(int token)
		{
			for (int i = 0; i < _overrides.Count; i++)
			{
				if (_overrides[i].Token == token)
				{
					_overrides.RemoveAt(i);
					break;
				}
			}
		}

		private Ov Find(int token)
		{
			for (int i = 0; i < _overrides.Count; i++)
			{
				if (_overrides[i].Token == token)
				{
					return _overrides[i];
				}
			}
			return null;
		}

		public void OverrideIntensity(int token, float v)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.I = v;
			}
		}

		public void OverrideRange(int token, float v)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.R = v;
			}
		}

		public void OverrideSpotAngle(int token, float v)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.A = v;
			}
		}

		public void OverrideColor(int token, Color c)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.C = c;
			}
		}

		public void ClearOverrideIntensity(int token)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.I = null;
			}
		}

		public void ClearOverrideRange(int token)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.R = null;
			}
		}

		public void ClearOverrideSpotAngle(int token)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.A = null;
			}
		}

		public void ClearOverrideColor(int token)
		{
			Ov ov = Find(token);
			if (ov != null)
			{
				ov.C = null;
			}
		}

		public void TemporaryIntensity(float v, float seconds)
		{
			_overrides.Add(new Ov
			{
				Token = _nextToken++,
				Owner = "$temp",
				I = v,
				Expiry = Time.time + Mathf.Max(0.05f, seconds)
			});
		}

		public void TemporaryColor(float r, float g, float b, float a, float seconds)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			_overrides.Add(new Ov
			{
				Token = _nextToken++,
				Owner = "$temp",
				C = new Color(r, g, b, a),
				Expiry = Time.time + Mathf.Max(0.05f, seconds)
			});
		}

		public void Flicker(float strength01, float durationSeconds, float freqHz)
		{
			_fx = FxMode.Flicker;
			_fxStrength = Mathf.Clamp01(strength01);
			_fxFreq = Mathf.Max(0.1f, freqHz);
			_fxEnd = Time.time + Mathf.Max(0.05f, durationSeconds);
			_fxSeed = Random.value * 100f;
		}

		public void Pulse(float amp01, float periodSeconds, float durationSeconds)
		{
			_fx = FxMode.Pulse;
			_fxAmp = Mathf.Clamp01(amp01);
			_fxPeriod = Mathf.Max(0.1f, periodSeconds);
			_fxEnd = (float.IsInfinity(durationSeconds) ? float.MaxValue : (Time.time + Mathf.Max(0.05f, durationSeconds)));
			_fxSeed = Random.value * 6.28f;
		}

		public void StopFlicker()
		{
			if (_fx == FxMode.Flicker)
			{
				_fx = FxMode.None;
			}
		}

		public void StopPulse()
		{
			if (_fx == FxMode.Pulse)
			{
				_fx = FxMode.None;
			}
		}

		public void Blink(int times, float intervalSeconds)
		{
			if (_isOn && times > 0)
			{
				_blinkLeft = times * 2;
				_blinkInterval = Mathf.Max(0.02f, intervalSeconds);
				_blinkNext = Time.time;
				_blinkDark = false;
			}
		}
	}
	internal static class VanillaLightSync
	{
		private static readonly List<OptimizedLight> _opt = new List<OptimizedLight>();

		private static readonly List<Light> _bare = new List<Light>();

		private static bool _dark;

		private static float _nextRescan;

		public static void Apply(bool dark)
		{
			if (dark)
			{
				if (!_dark)
				{
					_dark = true;
					_nextRescan = 0f;
				}
				ReassertDisabled();
				if (Time.time >= _nextRescan)
				{
					_nextRescan = Time.time + 0.1f;
					Capture();
				}
			}
			else if (_dark)
			{
				Restore();
			}
		}

		private static void ReassertDisabled()
		{
			for (int i = 0; i < _opt.Count; i++)
			{
				OptimizedLight val = _opt[i];
				if ((Object)(object)val != (Object)null && val.Enabled)
				{
					val.Enabled = false;
					val.UpdateLightState();
				}
			}
			for (int j = 0; j < _bare.Count; j++)
			{
				Light val2 = _bare[j];
				if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).enabled)
				{
					((Behaviour)val2).enabled = false;
				}
			}
		}

		private static void Capture()
		{
			try
			{
				if (PlayerSingleton<PlayerInventory>.InstanceExists)
				{
					Equippable equippable = PlayerSingleton<PlayerInventory>.Instance.equippable;
					if ((Object)(object)equippable != (Object)null && (Object)(object)((Il2CppObjectBase)equippable).TryCast<Flashlight>() != (Object)null)
					{
						DisableUnder(((Component)equippable).gameObject);
					}
				}
				if (PlayerSingleton<Phone>.InstanceExists)
				{
					GameObject phoneFlashlight = PlayerSingleton<Phone>.Instance.PhoneFlashlight;
					if ((Object)(object)phoneFlashlight != (Object)null)
					{
						DisableUnder(phoneFlashlight);
					}
				}
			}
			catch (Exception ex)
			{
				Instance log = Core.Log;
				if (log != null)
				{
					log.Warning("VanillaLightSync capture failed: " + ex.Message);
				}
			}
		}

		private static void DisableUnder(GameObject root)
		{
			foreach (OptimizedLight componentsInChild in root.GetComponentsInChildren<OptimizedLight>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && componentsInChild.Enabled)
				{
					componentsInChild.Enabled = false;
					componentsInChild.UpdateLightState();
					_opt.Add(componentsInChild);
				}
			}
			foreach (Light componentsInChild2 in root.GetComponentsInChildren<Light>(true))
			{
				if (!((Object)(object)componentsInChild2 == (Object)null) && ((Behaviour)componentsInChild2).enabled && !((Object)(object)((Component)componentsInChild2).GetComponent<OptimizedLight>() != (Object)null))
				{
					((Behaviour)componentsInChild2).enabled = false;
					_bare.Add(componentsInChild2);
				}
			}
		}

		public static void Restore()
		{
			_dark = false;
			foreach (OptimizedLight item in _opt)
			{
				try
				{
					if ((Object)(object)item != (Object)null)
					{
						item.Enabled = true;
						item.UpdateLightState();
					}
				}
				catch
				{
				}
			}
			foreach (Light item2 in _bare)
			{
				try
				{
					if ((Object)(object)item2 != (Object)null)
					{
						((Behaviour)item2).enabled = true;
					}
				}
				catch
				{
				}
			}
			_opt.Clear();
			_bare.Clear();
		}
	}
}
namespace TightBeam.Config
{
	internal static class TightBeamPreferences
	{
		private static MelonPreferences_Category _cat;

		private static MelonPreferences_Entry<bool> _enabled;

		private static MelonPreferences_Entry<string> _focusModifierKey;

		private static MelonPreferences_Entry<float> _defaultIntensity;

		private static MelonPreferences_Entry<float> _minIntensity;

		private static MelonPreferences_Entry<float> _maxIntensity;

		private static MelonPreferences_Entry<float> _defaultFocus;

		private static MelonPreferences_Entry<float> _focusSensitivity;

		private static MelonPreferences_Entry<float> _focusEaseTau;

		private static MelonPreferences_Entry<float> _focusMaxStep;

		private static MelonPreferences_Entry<float> _focusVelocityGamma;

		private static MelonPreferences_Entry<float> _focusVelocityRefRate;

		private static MelonPreferences_Entry<float> _focusFlickRateMultiplier;

		private static MelonPreferences_Entry<float> _focusVelAttackTau;

		private static MelonPreferences_Entry<float> _focusVelDecayTau;

		private static MelonPreferences_Entry<bool> _invertFocusScroll;

		private static MelonPreferences_Entry<float> _rangeWide;

		private static MelonPreferences_Entry<float> _rangeNarrow;

		private static MelonPreferences_Entry<float> _angleWide;

		private static MelonPreferences_Entry<float> _angleNarrow;

		private static MelonPreferences_Entry<string> _colorHex;

		private static MelonPreferences_Entry<bool> _castShadows;

		public static bool Enabled => _enabled.Value;

		public static KeyCode FocusModifierKey => ParseKey(_focusModifierKey.Value, (KeyCode)308);

		public static float DefaultIntensity => Mathf.Clamp(_defaultIntensity.Value, MinIntensity, MaxIntensity);

		public static float MinIntensity => Mathf.Max(0.05f, _minIntensity.Value);

		public static float MaxIntensity => Mathf.Max(MinIntensity + 0.1f, _maxIntensity.Value);

		public static float DefaultFocus => Mathf.Clamp01(_defaultFocus.Value);

		public static float FocusSensitivity => Mathf.Clamp(_focusSensitivity.Value, 0.005f, 1f);

		public static float FocusEaseTau => Mathf.Clamp(_focusEaseTau.Value, 0.02f, 0.15f);

		public static float FocusMaxStep => Mathf.Clamp(_focusMaxStep.Value, FocusSensitivity, 1f);

		public static float FocusVelocityGamma => Mathf.Clamp(_focusVelocityGamma.Value, 1f, 4f);

		public static float FocusVelocityRefRate => Mathf.Clamp(_focusVelocityRefRate.Value, 0.5f, 30f);

		public static float FocusFlickRateMultiplier => Mathf.Clamp(_focusFlickRateMultiplier.Value, 1.5f, 10f);

		public static float FocusVelAttackTau => Mathf.Clamp(_focusVelAttackTau.Value, 0.01f, 0.2f);

		public static float FocusVelDecayTau => Mathf.Clamp(_focusVelDecayTau.Value, 0.05f, 0.4f);

		public static bool InvertFocusScroll => _invertFocusScroll.Value;

		public static float RangeWide => Mathf.Clamp(_rangeWide.Value, 3f, 25f);

		public static float RangeNarrow => Mathf.Clamp(_rangeNarrow.Value, 15f, 45f);

		public static float AngleWide => Mathf.Clamp(_angleWide.Value, 40f, 90f);

		public static float AngleNarrow => Mathf.Clamp(_angleNarrow.Value, 8f, 35f);

		public static Color Color => ParseColor(_colorHex.Value, new Color(0.9f, 0.95f, 1f));

		public static bool CastShadows => _castShadows.Value;

		public static void Initialize()
		{
			_cat = MelonPreferences.CreateCategory("TightBeam");
			_enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, "Master switch for the whole mod.", false, false, (ValueValidator)null, (string)null);
			_focusModifierKey = _cat.CreateEntry<string>("FocusModifierKey", "LeftAlt", (string)null, "Hold this key and scroll the mouse wheel to adjust FOCUS (Pegel): wide near flood <-> narrow far throw.", false, false, (ValueValidator)null, (string)null);
			_defaultIntensity = _cat.CreateEntry<float>("DefaultIntensity", 7f, (string)null, "Base beam brightness the flashlight rests at (clamped to Min/Max). Not player-adjustable in-game; mods can drive it via the API.", false, false, (ValueValidator)null, (string)null);
			_minIntensity = _cat.CreateEntry<float>("MinIntensity", 1f, (string)null, "Hard floor for brightness (also clamps mod/API overrides).", false, false, (ValueValidator)null, (string)null);
			_maxIntensity = _cat.CreateEntry<float>("MaxIntensity", 20f, (string)null, "Hard ceiling for brightness (also clamps mod/API overrides, so nothing can blind the screen).", false, false, (ValueValidator)null, (string)null);
			_defaultFocus = _cat.CreateEntry<float>("DefaultFocus", 0.5f, (string)null, "Starting focus/Pegel 0..1. 1 = wide short-range flood, 0 = narrow long-range throw, 0.5 = a balanced ~mid beam.", false, false, (ValueValidator)null, (string)null);
			_focusSensitivity = _cat.CreateEntry<float>("FocusSensitivity", 0.08f, (string)null, "Focus change per notch at SLOW/precise scroll speed (the fine-adjustment floor step).", false, false, (ValueValidator)null, (string)null);
			_focusEaseTau = _cat.CreateEntry<float>("FocusEaseTau", 0.05f, (string)null, "Seconds for the displayed beam to ease toward the target focus after a scroll (settle ~4x this). 0.02 = near-instant/steppy, 0.15 = very smooth.", false, false, (ValueValidator)null, (string)null);
			_focusMaxStep = _cat.CreateEntry<float>("FocusMaxStep", 0.35f, (string)null, "Largest per-notch focus step from a fast (but not flick-threshold) scroll.", false, false, (ValueValidator)null, (string)null);
			_focusVelocityGamma = _cat.CreateEntry<float>("FocusVelocityGamma", 2f, (string)null, "Curve exponent shaping how step size ramps up with scroll speed (higher = more ease-in, slow stays fine longer).", false, false, (ValueValidator)null, (string)null);
			_focusVelocityRefRate = _cat.CreateEntry<float>("FocusVelocityRefRate", 5f, (string)null, "Scroll rate (units/sec) at/below which focus changes by plain FocusSensitivity per notch (slow single ticks read ~2-4).", false, false, (ValueValidator)null, (string)null);
			_focusFlickRateMultiplier = _cat.CreateEntry<float>("FocusFlickRateMultiplier", 2f, (string)null, "Flick threshold = FocusVelocityRefRate * this (default 5*2=10); crossing it races focus to the nearest extreme. Fast flicks read ~27+.", false, false, (ValueValidator)null, (string)null);
			_focusVelAttackTau = _cat.CreateEntry<float>("FocusVelAttackTau", 0.05f, (string)null, "How quickly the scroll-speed estimate reacts to a new, faster scroll.", false, false, (ValueValidator)null, (string)null);
			_focusVelDecayTau = _cat.CreateEntry<float>("FocusVelDecayTau", 0.15f, (string)null, "How quickly the scroll-speed estimate cools down once scrolling pauses/stops.", false, false, (ValueValidator)null, (string)null);
			_invertFocusScroll = _cat.CreateEntry<bool>("InvertFocusScroll", false, (string)null, "Flip which scroll direction widens the beam.", false, false, (ValueValidator)null, (string)null);
			_rangeWide = _cat.CreateEntry<float>("RangeWide", 8f, (string)null, "Beam range (m) at full WIDE focus - a short near flood.", false, false, (ValueValidator)null, (string)null);
			_rangeNarrow = _cat.CreateEntry<float>("RangeNarrow", 34f, (string)null, "Beam range (m) at full NARROW focus - a long far throw.", false, false, (ValueValidator)null, (string)null);
			_angleWide = _cat.CreateEntry<float>("AngleWide", 66f, (string)null, "Cone angle (deg) at full WIDE focus.", false, false, (ValueValidator)null, (string)null);
			_angleNarrow = _cat.CreateEntry<float>("AngleNarrow", 16f, (string)null, "Cone angle (deg) at full NARROW focus.", false, false, (ValueValidator)null, (string)null);
			_colorHex = _cat.CreateEntry<string>("ColorHex", "#E6F2FF", (string)null, "Beam colour (hex). Cool white by default so it reads against warm/sickly environments.", false, false, (ValueValidator)null, (string)null);
			_castShadows = _cat.CreateEntry<bool>("CastShadows", true, (string)null, "Cast soft shadows so the beam is blocked by walls (turn off on low-end machines).", false, false, (ValueValidator)null, (string)null);
		}

		private static KeyCode ParseKey(string s, KeyCode fallback)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<KeyCode>(s, ignoreCase: true, out KeyCode result))
			{
				return fallback;
			}
			return result;
		}

		private static Color ParseColor(string input, Color fallback)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(input))
			{
				return fallback;
			}
			Color result = default(Color);
			if (ColorUtility.TryParseHtmlString(input.StartsWith("#") ? input : ("#" + input), ref result))
			{
				return result;
			}
			return fallback;
		}
	}
}
namespace TightBeam.Bridge
{
	internal static class BridgeHost
	{
		private static readonly List<Action<bool>> _toggleListeners = new List<Action<bool>>();

		public static void Install()
		{
			FlashlightController c = FlashlightController.Instance;
			FlashlightBridge.IsOn = () => c.IsOn;
			FlashlightBridge.GetIntensity = () => c.CurrentIntensity;
			FlashlightBridge.GetRange = () => c.CurrentRange;
			FlashlightBridge.GetSpotAngle = () => c.CurrentSpotAngle;
			FlashlightBridge.GetColor = delegate
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				Color currentColor = c.CurrentColor;
				return new float[4] { currentColor.r, currentColor.g, currentColor.b, currentColor.a };
			};
			FlashlightBridge.SetOn = delegate(bool on)
			{
				c.SetOn(on);
			};
			FlashlightBridge.Toggle = delegate
			{
				c.Toggle();
			};
			FlashlightBridge.SetIntensity = delegate(float v)
			{
				c.SetIntensity(v);
			};
			FlashlightBridge.SetRange = delegate(float v)
			{
				c.SetBaseRange(v);
			};
			FlashlightBridge.SetSpotAngle = delegate(float v)
			{
				c.SetBaseSpotAngle(v);
			};
			FlashlightBridge.SetColor = delegate(float r, float g, float b, float a)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				c.SetColor(new Color(r, g, b, a));
			};
			FlashlightBridge.Blink = delegate(int t, float i)
			{
				c.Blink(t, i);
			};
			FlashlightBridge.Flicker = delegate(float s, float d, float f)
			{
				c.Flicker(s, d, f);
			};
			FlashlightBridge.StopFlicker = delegate
			{
				c.StopFlicker();
			};
			FlashlightBridge.Pulse = delegate(float a, float p, float d)
			{
				c.Pulse(a, p, d);
			};
			FlashlightBridge.StopPulse = delegate
			{
				c.StopPulse();
			};
			FlashlightBridge.TempIntensity = delegate(float v, float s)
			{
				c.TemporaryIntensity(v, s);
			};
			FlashlightBridge.TempColor = delegate(float r, float g, float b, float a, float s)
			{
				c.TemporaryColor(r, g, b, a, s);
			};
			FlashlightBridge.BeginOverride = (string owner) => c.BeginOverride(owner);
			FlashlightBridge.EndOverride = delegate(int tok)
			{
				c.EndOverride(tok);
			};
			FlashlightBridge.OvIntensity = delegate(int tok, float v)
			{
				c.OverrideIntensity(tok, v);
			};
			FlashlightBridge.OvRange = delegate(int tok, float v)
			{
				c.OverrideRange(tok, v);
			};
			FlashlightBridge.OvSpotAngle = delegate(int tok, float v)
			{
				c.OverrideSpotAngle(tok, v);
			};
			FlashlightBridge.OvColor = delegate(int tok, float r, float g, float b, float a)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				c.OverrideColor(tok, new Color(r, g, b, a));
			};
			FlashlightBridge.ClrIntensity = delegate(int tok)
			{
				c.ClearOverrideIntensity(tok);
			};
			FlashlightBridge.ClrRange = delegate(int tok)
			{
				c.ClearOverrideRange(tok);
			};
			FlashlightBridge.ClrSpotAngle = delegate(int tok)
			{
				c.ClearOverrideSpotAngle(tok);
			};
			FlashlightBridge.ClrColor = delegate(int tok)
			{
				c.ClearOverrideColor(tok);
			};
			FlashlightBridge.RegisterToggledListener = delegate(Action<bool> cb)
			{
				if (cb != null)
				{
					_toggleListeners.Add(cb);
				}
			};
			c.Toggled += delegate(bool on)
			{
				for (int i = 0; i < _toggleListeners.Count; i++)
				{
					try
					{
						_toggleListeners[i](on);
					}
					catch
					{
					}
				}
			};
		}
	}
	public static class FlashlightBridge
	{
		public const int AbiVersion = 1;

		public static Func<bool> IsOn;

		public static Func<float> GetIntensity;

		public static Func<float> GetRange;

		public static Func<float> GetSpotAngle;

		public static Func<float[]> GetColor;

		public static Action<bool> SetOn;

		public static Action Toggle;

		public static Action<float> SetIntensity;

		public static Action<float> SetRange;

		public static Action<float> SetSpotAngle;

		public static Action<float, float, float, float> SetColor;

		public static Action<int, float> Blink;

		public static Action<float, float, float> Flicker;

		public static Action StopFlicker;

		public static Action<float, float, float> Pulse;

		public static Action StopPulse;

		public static Action<float, float> TempIntensity;

		public static Action<float, float, float, float, float> TempColor;

		public static Func<string, int> BeginOverride;

		public static Action<int> EndOverride;

		public static Action<int, float> OvIntensity;

		public static Action<int, float> OvRange;

		public static Action<int, float> OvSpotAngle;

		public static Action<int, float, float, float, float> OvColor;

		public static Action<int> ClrIntensity;

		public static Action<int> ClrRange;

		public static Action<int> ClrSpotAngle;

		public static Action<int> ClrColor;

		public static Action<Action<bool>> RegisterToggledListener;
	}
}