Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of TightBeam v1.0.0
TightBeam.dll
Decompiled 8 hours agousing 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; } }