Decompiled source of Echolocation v1.10.0
Mods/Echolocation.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using BoneLib.BoneMenu.UI; using Echolocation; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Bonelab; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.AI; using Il2CppSLZ.Marrow.Audio; using Il2CppSLZ.Marrow.Input; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.PuppetMasta; using Il2CppSLZ.Marrow.Utilities; using Il2CppSLZ.Rig; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(EcholocationMod), "Echolocation", "1.10.0", "Echolocation", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Echolocation { internal sealed class BlackoutView : IDisposable { internal const int BlackQueue = 4998; internal const int EchoQueue = 4999; private readonly Action<string> _warning; private Mesh? _mesh; private Material? _material; private int _attempts; private float _nextAttempt; private bool _disposed; private readonly Camera?[] _desktopCameras = (Camera?[])(object)new Camera[64]; private readonly bool[] _knownDesktopCameras = new bool[64]; private readonly Camera?[] _overlayCameras = (Camera?[])(object)new Camera[16]; private Il2CppReferenceArray<Camera>? _cameraBuffer; private int _desktopCount; private int _overlayCount; private int _lastCameraCount = -1; private float _nextCameraRefresh; private bool _cameraWarning; internal bool Active { get; private set; } internal string Status { get; private set; } = "Waiting for player"; internal BlackoutView(Action<string> warning) { _warning = warning; } internal void Tick(float now, bool enabled) { Active = false; if (_disposed) { return; } if (!enabled) { Status = "Normal vision"; return; } GUIMenu instance = GUIMenu.Instance; UIRig uIRig = Player.UIRig; if (((Object)(object)uIRig != (Object)null && (Object)(object)uIRig.popUpMenu != (Object)null && uIRig.popUpMenu.isActive) || ((Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeInHierarchy)) { Status = "Normal vision while a game menu is open"; return; } EnsureAssets(now); if ((Object)(object)_mesh == (Object)null || (Object)(object)_material == (Object)null) { return; } OpenControllerRig controllerRig = Player.ControllerRig; Il2CppReferenceArray<Camera> val = (((Object)(object)controllerRig != (Object)null) ? controllerRig.cameras : null); Camera main = Camera.main; RefreshDesktopCameras(now); bool flag = false; int num = 0; while (val != null && num < ((Il2CppArrayBase<Camera>)(object)val).Length) { Camera val2 = ((Il2CppArrayBase<Camera>)(object)val)[num]; if ((Object)(object)val2 == (Object)(object)main) { flag = true; } DrawCamera(val2); num++; } if (!flag) { DrawCamera(main); } for (int i = 0; i < _desktopCount; i++) { Camera val3 = _desktopCameras[i]; if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)main || (!_knownDesktopCameras[i] && !IsDisplayCamera(val3))) { continue; } bool flag2 = false; int num2 = 0; while (val != null && num2 < ((Il2CppArrayBase<Camera>)(object)val).Length) { if ((Object)(object)((Il2CppArrayBase<Camera>)(object)val)[num2] == (Object)(object)val3) { flag2 = true; break; } num2++; } if (!flag2) { DrawCamera(val3); } } Status = (Active ? "Blackout active: echolocation only" : "Waiting for player camera"); } private void RefreshDesktopCameras(float now) { int allCamerasCount = Camera.allCamerasCount; if (now < _nextCameraRefresh && allCamerasCount == _lastCameraCount) { return; } _nextCameraRefresh = now + 0.5f; _lastCameraCount = allCamerasCount; Array.Clear(_desktopCameras, 0, _desktopCameras.Length); Array.Clear(_overlayCameras, 0, _overlayCameras.Length); _desktopCount = (_overlayCount = 0); try { Il2CppArrayBase<RigScreenOptions> val = Object.FindObjectsOfType<RigScreenOptions>(); for (int i = 0; i < val.Length && i < _overlayCameras.Length; i++) { RigScreenOptions val2 = val[i]; if (!((Object)(object)val2 == (Object)null)) { if ((Object)(object)val2.OverlayCam != (Object)null) { _overlayCameras[_overlayCount++] = val2.OverlayCam; } AddDesktopCamera(val2.cam, knownView: true); } } RigManager rigManager = Player.RigManager; PancakeControllerRig val3 = (((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.controllerRig != (Object)null) ? ((Il2CppObjectBase)rigManager.controllerRig).TryCast<PancakeControllerRig>() : null); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.wasdCam != (Object)null) { AddDesktopCamera(val3.wasdCam.Camera, knownView: true); } if (allCamerasCount < 1 || allCamerasCount > 1024) { return; } if (_cameraBuffer == null || ((Il2CppArrayBase<Camera>)(object)_cameraBuffer).Length < allCamerasCount) { _cameraBuffer = new Il2CppReferenceArray<Camera>((long)Math.Max(32, allCamerasCount)); } allCamerasCount = Camera.GetAllCameras(_cameraBuffer); for (int j = 0; j < allCamerasCount; j++) { Camera val4 = ((Il2CppArrayBase<Camera>)(object)_cameraBuffer)[j]; if ((Object)(object)val4 != (Object)null && IsDisplayCamera(val4)) { AddDesktopCamera(val4, knownView: false); } } } catch (Exception ex) { if (!_cameraWarning) { _cameraWarning = true; _warning("Desktop blackout camera discovery will retry: " + ex.Message); } } } private static bool IsDisplayCamera(Camera camera) { if (!camera.stereoEnabled && (Object)(object)camera.targetTexture == (Object)null) { return camera.targetDisplay >= 0; } return false; } private void AddDesktopCamera(Camera? camera, bool knownView) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 if ((Object)(object)camera == (Object)null || !((Behaviour)camera).isActiveAndEnabled || (int)camera.cameraType != 1 || (camera.cullingMask & -33) == 0 || _desktopCount >= _desktopCameras.Length) { return; } for (int i = 0; i < _desktopCount; i++) { if ((Object)(object)_desktopCameras[i] == (Object)(object)camera) { return; } } _knownDesktopCameras[_desktopCount] = knownView; _desktopCameras[_desktopCount++] = camera; } private void DrawCamera(Camera? camera) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null || !((Behaviour)camera).isActiveAndEnabled || (int)camera.cameraType != 1 || (camera.cullingMask & -33) == 0) { return; } for (int i = 0; i < _overlayCount; i++) { if ((Object)(object)_overlayCameras[i] == (Object)(object)camera) { return; } } float num = Mathf.Max(2f, camera.nearClipPlane * 4f + camera.stereoSeparation); num = Mathf.Min(num, camera.farClipPlane * 0.4f); Matrix4x4 val = Matrix4x4.TRS(((Component)camera).transform.position, Quaternion.identity, Vector3.one * num); int num2 = VisibleLayer(camera.cullingMask); if (num2 >= 0) { Graphics.DrawMesh(_mesh, val, _material, num2, camera, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null); Active = true; } } internal void Reset() { Active = false; _attempts = 0; _nextAttempt = 0f; _lastCameraCount = -1; _nextCameraRefresh = 0f; _cameraWarning = false; _desktopCount = (_overlayCount = 0); Array.Clear(_desktopCameras, 0, _desktopCameras.Length); Array.Clear(_overlayCameras, 0, _overlayCameras.Length); _cameraBuffer = null; Status = "Waiting for player"; } private void EnsureAssets(float now) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (((Object)(object)_mesh != (Object)null && (Object)(object)_material != (Object)null) || _attempts >= 6 || now < _nextAttempt) { return; } _attempts++; _nextAttempt = now + 2f; DestroyAssets(); string[] array = new string[2] { "Hidden/Internal-Colored", "GUI/Text Shader" }; foreach (string text in array) { Shader val = Shader.Find(text); if ((Object)(object)val == (Object)null || !val.isSupported) { continue; } Material val2 = new Material(val) { hideFlags = (HideFlags)61, renderQueue = 4998 }; if (text == "Hidden/Internal-Colored" && (!val2.HasProperty("_ZTest") || !val2.HasProperty("_ZWrite"))) { Object.Destroy((Object)(object)val2); continue; } _material = val2; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.black); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture); } SetInt(val2, "_ZTest", 8); SetInt(val2, "_ZWrite", 0); SetInt(val2, "_Cull", 0); SetInt(val2, "_SrcBlend", 1); SetInt(val2, "_DstBlend", 0); _mesh = MakeCube(); return; } Status = "Blackout shader unavailable"; if (_attempts == 1 || _attempts == 6) { _warning("Blackout could not find an always-visible shader. F6 restores normal vision; check Echolocation diagnostics."); } } private static Mesh MakeCube() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Expected O, but got Unknown Vector3[] array = (Vector3[])(object)new Vector3[8] { new Vector3(-1f, -1f, -1f), new Vector3(1f, -1f, -1f), new Vector3(1f, 1f, -1f), new Vector3(-1f, 1f, -1f), new Vector3(-1f, -1f, 1f), new Vector3(1f, -1f, 1f), new Vector3(1f, 1f, 1f), new Vector3(-1f, 1f, 1f) }; int[] array2 = new int[36] { 0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 0, 4, 7, 0, 7, 3, 1, 2, 6, 1, 6, 5, 3, 7, 6, 3, 6, 2, 0, 1, 5, 0, 5, 4 }; Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>((long)array.Length); Il2CppStructArray<Color> val2 = new Il2CppStructArray<Color>((long)array.Length); Il2CppStructArray<Vector2> val3 = new Il2CppStructArray<Vector2>((long)array.Length); Il2CppStructArray<int> val4 = new Il2CppStructArray<int>((long)(array2.Length * 2)); for (int i = 0; i < array.Length; i++) { ((Il2CppArrayBase<Vector3>)(object)val)[i] = array[i]; ((Il2CppArrayBase<Color>)(object)val2)[i] = Color.black; ((Il2CppArrayBase<Vector2>)(object)val3)[i] = new Vector2(0.5f, 0.5f); } for (int j = 0; j < array2.Length; j += 3) { ((Il2CppArrayBase<int>)(object)val4)[j] = array2[j]; ((Il2CppArrayBase<int>)(object)val4)[j + 1] = array2[j + 1]; ((Il2CppArrayBase<int>)(object)val4)[j + 2] = array2[j + 2]; ((Il2CppArrayBase<int>)(object)val4)[array2.Length + j] = array2[j]; ((Il2CppArrayBase<int>)(object)val4)[array2.Length + j + 1] = array2[j + 2]; ((Il2CppArrayBase<int>)(object)val4)[array2.Length + j + 2] = array2[j + 1]; } Mesh val5 = new Mesh { name = "Echolocation.Blackout", hideFlags = (HideFlags)61 }; val5.SetVertices(val, 0, array.Length); val5.SetColors(val2, 0, array.Length); val5.SetUVs(0, val3, 0, array.Length); val5.SetTriangles(val4, 0, ((Il2CppArrayBase<int>)(object)val4).Length, 0, true, 0); return val5; } private static int VisibleLayer(int mask) { for (int i = 0; i < 32; i++) { if ((mask & (1 << i)) != 0) { return i; } } return -1; } private static void SetInt(Material material, string name, int value) { if (material.HasProperty(name)) { material.SetInt(name, value); } } private void DestroyAssets() { if ((Object)(object)_mesh != (Object)null) { Object.Destroy((Object)(object)_mesh); } if ((Object)(object)_material != (Object)null) { Object.Destroy((Object)(object)_material); } _mesh = null; _material = null; } public void Dispose() { if (!_disposed) { _disposed = true; Reset(); DestroyAssets(); } } } internal sealed class DoubleClapGesture { private const float MinimumClapInterval = 0.12f; private const float MaximumClapInterval = 1.5f; private const float PulseCooldown = 0.6f; private const float MaximumSampleGap = 0.3f; private bool _initialized; private bool _armed; private bool _hasFirstClap; private Vector3 _lastLeft; private Vector3 _lastRight; private float _lastTime; private float _lastDistance; private float _firstClapTime; private float _nextPulseTime; private float _lastContactDistance; internal bool ContactDetected { get; private set; } public bool Tick(float now, Vector3 left, Vector3 right, bool available, float contactDistance = 0.3f) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00ac: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00f8: 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_00ff: Unknown result type (might be due to invalid IL or missing references) ContactDetected = false; if (!available || !float.IsFinite(now) || !Finite(left) || !Finite(right)) { Reset(); return false; } float num = Vector3.Distance(left, right); if (!float.IsFinite(num)) { Reset(); return false; } contactDistance = (float.IsFinite(contactDistance) ? Math.Clamp(contactDistance, 0.15f, 0.45f) : 0.3f); float num2 = contactDistance + 0.1f; float num3 = now - _lastTime; float num4 = Math.Max(0.6f, num3 * 14f); if (!_initialized || contactDistance != _lastContactDistance || num3 <= 0f || num3 > 0.3f || Vector3.Distance(left, _lastLeft) > num4 || Vector3.Distance(right, _lastRight) > num4) { BeginSample(now, left, right, num, contactDistance); return false; } bool flag = _lastDistance > contactDistance && num <= contactDistance; _lastTime = now; _lastLeft = left; _lastRight = right; _lastDistance = num; if (_hasFirstClap && now - _firstClapTime > 1.5f) { _hasFirstClap = false; } if (now < _nextPulseTime) { _armed = false; _hasFirstClap = false; return false; } if (num >= num2) { _armed = true; } if (!_armed || !flag) { return false; } _armed = false; if (!_hasFirstClap) { _hasFirstClap = true; _firstClapTime = now; ContactDetected = true; return false; } if (now - _firstClapTime < 0.12f) { return false; } _hasFirstClap = false; _nextPulseTime = now + 0.6f; ContactDetected = true; return true; } private void BeginSample(float now, Vector3 left, Vector3 right, float distance, float contactDistance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (_initialized && now < _lastTime) { _nextPulseTime = 0f; } _initialized = true; _lastTime = now; _lastLeft = left; _lastRight = right; _lastDistance = distance; _lastContactDistance = contactDistance; _armed = distance >= contactDistance + 0.1f && now >= _nextPulseTime; _hasFirstClap = false; } private static bool Finite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (float.IsFinite(value.x) && float.IsFinite(value.y)) { return float.IsFinite(value.z); } return false; } public void Reset() { ContactDetected = false; _initialized = false; _armed = false; _hasFirstClap = false; _nextPulseTime = 0f; } } internal enum EchoKind { Manual, Microphone, Footstep, World, Voice } internal readonly struct EchoEvent { public Vector3 Origin { get; } public float Strength { get; } public EchoKind Kind { get; } public float Time { get; } public int PlayerId { get; } public AudioSource? Source { get; } public NpcSoundEmission? NpcEmission { get; } public SoundEmitterSurface? SurfaceEmission { get; } public EchoEvent(Vector3 origin, float strength, EchoKind kind, float time, int playerId = -1, AudioSource? source = null, NpcSoundEmission? npcEmission = null, SoundEmitterSurface? surfaceEmission = null) { //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) Origin = origin; Strength = (float.IsFinite(strength) ? Mathf.Clamp01(strength) : 0f); Kind = kind; Time = time; PlayerId = playerId; Source = source; NpcEmission = npcEmission; SurfaceEmission = surfaceEmission ?? npcEmission; } internal EchoEvent WithTime(float time) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new EchoEvent(Origin, Strength, Kind, time, PlayerId, Source, NpcEmission, SurfaceEmission); } } public sealed class EcholocationMod : MelonMod { private Settings _settings; private EchoRenderer _renderer; private MicrophoneInput _microphone; private WorldSoundInput _world; private ObjectSoundSources _objectSources; private WorldAudioMonitor _worldMonitor; private LocomotionInput _locomotion; private MenuPage _menu; private PulseAudio _audio; private Action<EchoEvent> _emit; private Action<EchoEvent> _observeSound; private Transform? _head; private Transform? _rigRoot; private bool _active; private float _nextWarning; private float _nextPulse; private readonly int[] _counts = new int[5]; private readonly EchoEvent[] _pending = new EchoEvent[5]; private readonly bool[] _hasPending = new bool[5]; private int _inputCursor = 1; private float _gestureStarted = -1f; private bool _gestureLatched; private readonly DoubleClapGesture _clap = new DoubleClapGesture(); private readonly SonarClock _sonar = new SonarClock(); private readonly HandScanInput _leftScan = new HandScanInput(); private readonly HandScanInput _rightScan = new HandScanInput(); private readonly HandScanInput _desktopScan = new HandScanInput(); private int _clapPulseCount; private int _sonarPulseCount; private int _lidarScanCount; public override void OnInitializeMelon() { _settings = new Settings(); _renderer = new EchoRenderer(_settings, Warn); _microphone = new MicrophoneInput(_settings, Warn); _objectSources = new ObjectSoundSources(Warn); _world = new WorldSoundInput(_settings, Warn, _objectSources.Capture); _locomotion = new LocomotionInput(_settings); _menu = new MenuPage(_settings, this, Warn); _audio = new PulseAudio(Warn); _emit = Emit; _observeSound = ObserveSound; _worldMonitor = new WorldAudioMonitor(RegisterWorldPlayback, Warn); ((MelonBase)this).LoggerInstance.Msg("Echolocation 1.10.0 loaded. Sound, rotating Sonar and hand LiDAR in BoneMenu; F6 toggle; F5 scan."); ((MelonBase)this).LoggerInstance.Msg("Visuals are local. Mic loudness is measured in memory only; no audio is saved or sent by this mod."); Save(); } public override void OnUpdate() { //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) if (_settings == null) { return; } _menu.EnsureBuilt(); ReadVisionGesture(); if (_settings.DesktopHotkeys) { if (Input.GetKeyDown((KeyCode)287)) { SetEnabled(!_settings.Enabled); } if (_settings.Mode != ScanMode.Lidar && Input.GetKeyDown((KeyCode)286)) { ManualPulse(); } } Transform val = null; Transform val2 = null; try { val = Player.Head; if ((Object)(object)Player.RigManager != (Object)null) { val2 = ((Component)Player.RigManager).transform; } } catch (Exception) { } if (!_settings.Enabled || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { _clap.Reset(); if (_active) { ResetState(); } return; } if (_active && ((Object)(object)_head != (Object)(object)val || (Object)(object)_rigRoot != (Object)(object)val2)) { ResetState(); } _head = val; _rigRoot = val2; _active = true; float unscaledTime = Time.unscaledTime; ReadClapGesture(unscaledTime, val); try { _microphone.Tick(unscaledTime, val.position, _emit, _observeSound); } catch (Exception ex2) { Warn("Microphone/voice input: " + ex2.Message); } try { _locomotion.Tick(unscaledTime, val, val2, _emit); } catch (Exception ex3) { Warn("Footstep input: " + ex3.Message); } try { _renderer.TickRemoteFootsteps(unscaledTime, val.position, val2, _emit, _observeSound); } catch (Exception ex4) { Warn("Remote footstep input: " + ex4.Message); } try { if (_settings.WorldSoundEnabled) { _worldMonitor.Tick(unscaledTime); } else { _worldMonitor.Reset(); } } catch (Exception ex5) { Warn("World playback monitoring: " + ex5.Message); } try { _world.Tick(unscaledTime, val.position, _emit, _observeSound); } catch (Exception ex6) { Warn("World sound input: " + ex6.Message); } if (_settings.Mode == ScanMode.Sound) { FlushInput(unscaledTime); } try { bool flag = _renderer.Ready && CanAutoScan(); bool flag2 = _settings.Mode == ScanMode.Sonar && flag; if (flag2) { _renderer.UpdateSonar(val.position, unscaledTime, 0.5f); } else { _renderer.StopSonar(); } if (_sonar.TryPulse(unscaledTime, flag2)) { _sonarPulseCount++; if (_settings.PulseSoundEnabled) { _audio.PlayPulse(_settings.PulseSoundVolume); } } ReadLidar(unscaledTime, val, _settings.Mode == ScanMode.Lidar && flag); } catch (Exception ex7) { _sonar.Reset(); _renderer.StopSonar(); ResetHandScans(); Warn("Scan input: " + ex7.Message); } } public override void OnLateUpdate() { if (!_active || !_settings.Enabled || (Object)(object)_head == (Object)null) { return; } try { _renderer.Tick(Time.unscaledTime, _head, _rigRoot); } catch (Exception ex) { Warn("Surface renderer: " + ex.Message); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (_settings != null) { ResetState(); } } public override void OnDeinitializeMelon() { if (_settings != null) { ResetState(); try { _worldMonitor.Dispose(); } catch (Exception ex) { Warn(ex.Message); } try { _microphone.Dispose(); } catch (Exception ex2) { Warn(ex2.Message); } try { _world.Dispose(); } catch (Exception ex3) { Warn(ex3.Message); } try { _renderer.Dispose(); } catch (Exception ex4) { Warn(ex4.Message); } try { _audio.Dispose(); } catch (Exception ex5) { Warn(ex5.Message); } Save(); } } internal void SetEnabled(bool enabled) { _settings.Enabled = enabled; if (!enabled) { ResetState(); } Save(); } internal void SetBlackout(bool enabled) { _settings.Blackout = enabled; Save(); } internal void SetScanMode(ScanMode mode) { if (_settings.Mode != mode) { _settings.Mode = mode; ResetState(); Save(); } } private static bool CanAutoScan() { OpenControllerRig controllerRig = Player.ControllerRig; if (((Object)(object)controllerRig != (Object)null && ((ControllerRig)controllerRig).IsPaused) || Time.timeScale <= 0f) { return false; } UIRig uIRig = Player.UIRig; GUIMenu instance = GUIMenu.Instance; if (!((Object)(object)uIRig != (Object)null) || !((Object)(object)uIRig.popUpMenu != (Object)null) || !uIRig.popUpMenu.isActive) { if ((Object)(object)instance != (Object)null) { return !((Component)instance).gameObject.activeInHierarchy; } return true; } return false; } internal void SetDoubleClap(bool enabled) { _settings.DoubleClapEnabled = enabled; _clap.Reset(); Save(); } internal void SetClapDistance(float distance) { _settings.ClapContactDistance = distance; _clap.Reset(); Save(); } internal void SetPulseSound(bool enabled) { _settings.PulseSoundEnabled = enabled; if (!enabled) { _audio.Stop(); } Save(); } internal void TestPulseSound() { _audio.PlayPulse(_settings.PulseSoundVolume); } private void ReadClapGesture(float now, Transform head) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) if (!_settings.DoubleClapEnabled) { _clap.Reset(); return; } try { OpenControllerRig controllerRig = Player.ControllerRig; BaseController leftController = Player.LeftController; BaseController rightController = Player.RightController; UIRig uIRig = Player.UIRig; GUIMenu instance = GUIMenu.Instance; if (((Object)(object)uIRig != (Object)null && (Object)(object)uIRig.popUpMenu != (Object)null && uIRig.popUpMenu.isActive) || ((Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeInHierarchy) || !((Object)(object)controllerRig != (Object)null) || ((ControllerRig)controllerRig).IsPaused || !((Object)(object)leftController != (Object)null) || !((Object)(object)rightController != (Object)null) || !((Behaviour)leftController).isActiveAndEnabled || !((Behaviour)rightController).isActiveAndEnabled || !Player.HandsExist || Player.LeftHand.HasAttachedObject() || Player.RightHand.HasAttachedObject() || (Player.LeftHand._indexButton && Player.RightHand._indexButton)) { _clap.Reset(); return; } if (!_clap.Tick(now, ((Component)leftController).transform.position, ((Component)rightController).transform.position, available: true, _settings.ClapContactDistance)) { if (_clap.ContactDetected && _settings.PulseSoundEnabled) { _audio.PlayClap(_settings.PulseSoundVolume); } return; } Transform val = head; if (controllerRig.cameras != null) { foreach (Camera item in (Il2CppArrayBase<Camera>)(object)controllerRig.cameras) { if ((Object)(object)item != (Object)null && ((Behaviour)item).isActiveAndEnabled) { val = ((Component)item).transform; break; } } } if (_renderer.EnqueueClap(val.position, now)) { _clapPulseCount++; if (_settings.PulseSoundEnabled) { _audio.PlayPulse(_settings.PulseSoundVolume); } } } catch (Exception ex) { _clap.Reset(); Warn("Double-clap input: " + ex.Message); } } private void ReadVisionGesture() { if (_settings.Mode == ScanMode.Lidar) { _gestureStarted = -1f; _gestureLatched = false; return; } bool flag = false; try { flag = Player.HandsExist && Player.LeftHand._indexButton && Player.RightHand._indexButton && !Player.LeftHand.HasAttachedObject() && !Player.RightHand.HasAttachedObject(); } catch (Exception) { } if (!flag) { _gestureStarted = -1f; _gestureLatched = false; } else if (!_gestureLatched) { float unscaledTime = Time.unscaledTime; if (_gestureStarted < 0f) { _gestureStarted = unscaledTime; } if (!(unscaledTime - _gestureStarted < 1.5f)) { _gestureLatched = true; SetBlackout(!_settings.Blackout); } } } internal void ManualPulse() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!_settings.Enabled) { return; } try { Transform head = Player.Head; if ((Object)(object)head != (Object)null) { Emit(new EchoEvent(head.position, 1f, EchoKind.Manual, Time.unscaledTime)); } } catch (Exception ex) { Warn("Manual pulse needs a loaded player rig: " + ex.Message); } } private void ReadLidar(float now, Transform head, bool available) { if (!available) { ResetHandScans(); return; } BaseController leftController = Player.LeftController; BaseController rightController = Player.RightController; XRApi xr = MarrowGame.xr; XRController val = ((xr != null) ? xr.LeftController : null); XRApi xr2 = MarrowGame.xr; XRController val2 = ((xr2 != null) ? xr2.RightController : null); bool handsExist = Player.HandsExist; bool flag = handsExist && (Object)(object)leftController != (Object)null && ((Behaviour)leftController).isActiveAndEnabled && val != null && ((XRDevice)val).IsConnected && !Player.LeftHand.HasAttachedObject(); bool flag2 = handsExist && (Object)(object)rightController != (Object)null && ((Behaviour)rightController).isActiveAndEnabled && val2 != null && ((XRDevice)val2).IsConnected && !Player.RightHand.HasAttachedObject(); if (_leftScan.TryScan(now, flag, flag && (val.TriggerButton || val.Trigger >= 0.65f))) { SendLidar(((Component)leftController).transform, now); } if (_rightScan.TryScan(now, flag2, flag2 && (val2.TriggerButton || val2.Trigger >= 0.65f))) { SendLidar(((Component)rightController).transform, now); } if (_desktopScan.TryScan(now, _settings.DesktopHotkeys, _settings.DesktopHotkeys && Input.GetKey((KeyCode)286))) { SendLidar(head, now); } } private void SendLidar(Transform source, float now) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (_renderer.EnqueueLidar(source.position, source.rotation, now)) { _lidarScanCount++; } } private void ResetHandScans() { _leftScan.Reset(); _rightScan.Reset(); _desktopScan.Reset(); } internal void RestartMicrophone() { _microphone.Restart(); } internal void Diagnostics() { ((MelonBase)this).LoggerInstance.Msg($"Enabled={_settings.Enabled}; rig={_active}; renderer={_renderer.Ready}; dots={_renderer.DotCount}"); ((MelonBase)this).LoggerInstance.Msg($"Scan mode={_settings.Mode}; sonar turn={0.5f:F1}s; sonar turns={_sonarPulseCount}; LiDAR scans={_lidarScanCount}"); ((MelonBase)this).LoggerInstance.Msg($"Vision: {_renderer.VisionStatus}; blackout setting={_settings.Blackout}"); ((MelonBase)this).LoggerInstance.Msg($"Players: {_renderer.PlayerStatus}; highlights={_settings.PlayerHighlights}"); ((MelonBase)this).LoggerInstance.Msg($"Faint nearby players={_settings.ProximitySilhouettes}; proximity radius={_settings.ProximityRange:F2}m; reveal range={_settings.Range:F0}m; dot brightness={_settings.DotBrightness:F2}"); ((MelonBase)this).LoggerInstance.Msg($"Double clap enabled={_settings.DoubleClapEnabled}; contact distance={_settings.ClapContactDistance:F2}m; 360 pulses={_clapPulseCount}"); ((MelonBase)this).LoggerInstance.Msg($"Pulse sound enabled={_settings.PulseSoundEnabled}; volume={_settings.PulseSoundVolume:F2}; {_audio.Status}"); ((MelonBase)this).LoggerInstance.Msg($"Visual limits: rays/pulse={_settings.RayCount}; rays/frame={_settings.RaysPerFrame}; max dots={_settings.MaxDots}"); ((MelonBase)this).LoggerInstance.Msg($"Optimize walking/sound echoes={_settings.OptimizeAutomaticEchoes}; when enabled: 512 rays/pulse, 256 rays/frame, 0.85s dot lifetime caps"); ((MelonBase)this).LoggerInstance.Msg($"Microphone: {_microphone.Status}; level={_microphone.Level:F4}; threshold={_settings.MicThreshold:F4}"); ((MelonBase)this).LoggerInstance.Msg($"World sources={_world.SourceCount}; threshold={_settings.SoundThreshold:F4}; range={_settings.WorldRange:F0}m"); ((MelonBase)this).LoggerInstance.Msg("Impact audio: " + _worldMonitor.Status); ((MelonBase)this).LoggerInstance.Msg($"Footsteps: {_locomotion.Status}; world: {_world.Status}; peak={_world.PeakLevel:F4}"); ((MelonBase)this).LoggerInstance.Msg($"Remote footstep sensitivity={_settings.RemoteFootstepSensitivity:F1}x; effective threshold={_settings.SoundThreshold / _settings.RemoteFootstepSensitivity:F5}; walking enabled={_settings.FootstepsEnabled}"); ((MelonBase)this).LoggerInstance.Msg($"Remote walking without audio={_settings.RemoteWalkingDetection}"); ((MelonBase)this).LoggerInstance.Msg($"Accepted pulses: manual={_counts[0]}, microphone={_counts[1]}, footsteps={_counts[2]}, world={_counts[3]}, voice={_counts[4]}"); } internal void Save() { try { _settings.Save(); } catch (Exception ex) { Warn("Could not save settings: " + ex.Message); } } private void ObserveSound(EchoEvent echo) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (_active && _settings.Enabled && Finite(echo.Origin)) { _renderer.ObserveSound(echo, _rigRoot); } } private void RegisterWorldPlayback(AudioSource source) { if (_active && _settings.Enabled && _settings.WorldSoundEnabled && !((Object)(object)source == (Object)null) && ((Behaviour)source).isActiveAndEnabled && !source.mute && !(source.volume <= 0f) && WorldSoundInput.IsSpatialSource(source) && (!source.loop || _settings.IncludeLoopingAudio) && !((Object)(object)_head == (Object)null)) { float unscaledTime = Time.unscaledTime; _world.RegisterPlayingSource(source, _objectSources.Capture(unscaledTime, source)); } } private void Emit(EchoEvent echo) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!_settings.Enabled || !float.IsFinite(echo.Time) || !Finite(echo.Origin)) { return; } if (echo.Kind == EchoKind.World && echo.SurfaceEmission != null && echo.SurfaceEmission.Count > 0) { if (_renderer.Enqueue(echo)) { _counts[(int)echo.Kind]++; } } else { if (_settings.Mode != ScanMode.Sound && echo.Kind != EchoKind.Manual) { return; } if (echo.Kind != EchoKind.Manual) { int kind = (int)echo.Kind; if (!_hasPending[kind] || echo.Time - _pending[kind].Time > 0.3f || echo.Strength > _pending[kind].Strength) { _pending[kind] = echo; } _hasPending[kind] = true; } else if (!(echo.Time < _nextPulse) && _renderer.Enqueue(echo)) { _nextPulse = echo.Time + 0.12f; _counts[(int)echo.Kind]++; } } } private void FlushInput(float now) { if (now < _nextPulse) { return; } for (int i = 0; i < 4; i++) { int inputCursor = _inputCursor; _inputCursor = _inputCursor % 4 + 1; if (_hasPending[inputCursor]) { EchoEvent echoEvent = _pending[inputCursor]; _hasPending[inputCursor] = false; if (!(now - echoEvent.Time > 0.35f) && _renderer.Enqueue(echoEvent.WithTime(now))) { _nextPulse = now + 0.12f; _counts[inputCursor]++; break; } } } } private void ResetState() { _active = false; _head = (_rigRoot = null); _nextPulse = 0f; _gestureStarted = -1f; _gestureLatched = false; _clap.Reset(); _sonar.Reset(); ResetHandScans(); Array.Clear(_hasPending, 0, _hasPending.Length); try { _audio.Stop(); } catch (Exception ex) { Warn(ex.Message); } try { _microphone.Restart(); } catch (Exception ex2) { Warn(ex2.Message); } try { _world.Reset(); } catch (Exception ex3) { Warn(ex3.Message); } _worldMonitor.Reset(); _objectSources.Reset(); _locomotion.Reset(); try { _renderer.Reset(); } catch (Exception ex4) { Warn(ex4.Message); } } private void Warn(string message) { float unscaledTime = Time.unscaledTime; if (!(unscaledTime < _nextWarning)) { _nextWarning = unscaledTime + 5f; ((MelonBase)this).LoggerInstance.Warning(message); } } private static bool Finite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (float.IsFinite(value.x) && float.IsFinite(value.y)) { return float.IsFinite(value.z); } return false; } } internal static class EchoMeshSpace { internal static bool TryGetDrawMatrix(Renderer renderer, SkinnedMeshRenderer? skin, Mesh snapshot, out Matrix4x4 matrix, Bounds? trackedBounds = null) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) matrix = (((Object)(object)skin != (Object)null) ? Matrix4x4.TRS(((Component)skin).transform.position, ((Component)skin).transform.rotation, Vector3.one) : renderer.localToWorldMatrix); Bounds bounds = snapshot.bounds; Bounds bounds2 = renderer.bounds; if (!Usable(bounds) || !Usable(bounds2)) { return false; } bool flag = FitsSource(matrix, bounds, bounds2); if ((Object)(object)skin == (Object)null) { return flag; } Matrix4x4 localToWorldMatrix = ((Component)skin).transform.localToWorldMatrix; if (!FitsSource(localToWorldMatrix, bounds, bounds2)) { return flag; } if (!flag) { goto IL_00e1; } if (trackedBounds.HasValue) { Bounds valueOrDefault = trackedBounds.GetValueOrDefault(); if (Usable(valueOrDefault) && FitsSource(localToWorldMatrix, bounds, valueOrDefault) && FitError(localToWorldMatrix, bounds, valueOrDefault) < FitError(matrix, bounds, valueOrDefault) && FitError(localToWorldMatrix, bounds, bounds2) < FitError(matrix, bounds, bounds2)) { goto IL_00e1; } } goto IL_00e8; IL_00e1: matrix = localToWorldMatrix; goto IL_00e8; IL_00e8: return true; } private static float FitError(Matrix4x4 matrix, Bounds local, Bounds source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) WorldBounds(matrix, local, out var center, out var half); Vector3 val = center - ((Bounds)(ref source)).center; Vector3 val2 = half - ((Bounds)(ref source)).extents; return (Math.Abs(val.x) + Math.Abs(val2.x)) / Math.Max(0.05f, ((Bounds)(ref source)).extents.x) + (Math.Abs(val.y) + Math.Abs(val2.y)) / Math.Max(0.05f, ((Bounds)(ref source)).extents.y) + (Math.Abs(val.z) + Math.Abs(val2.z)) / Math.Max(0.05f, ((Bounds)(ref source)).extents.z); } private static bool FitsSource(Matrix4x4 matrix, Bounds local, Bounds source) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (!float.IsFinite(((Matrix4x4)(ref matrix))[i, j])) { return false; } } } if (Math.Abs(((Matrix4x4)(ref matrix))[3, 0]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 1]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 2]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 3] - 1f) > 1E-05f) { return false; } WorldBounds(matrix, local, out var center, out var half); if (!Finite(center) || !Finite(half)) { return false; } Vector3 val = center - ((Bounds)(ref source)).center; Vector3 val2 = ((Bounds)(ref source)).extents * 1.5f + Vector3.one * 0.15f; if (Math.Abs(val.x) + half.x <= val2.x && Math.Abs(val.y) + half.y <= val2.y) { return Math.Abs(val.z) + half.z <= val2.z; } return false; } private static void WorldBounds(Matrix4x4 matrix, Bounds local, out Vector3 center, out Vector3 half) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00e5: Unknown result type (might be due to invalid IL or missing references) Vector3 extents = ((Bounds)(ref local)).extents; center = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(((Bounds)(ref local)).center); half = new Vector3(Math.Abs(((Matrix4x4)(ref matrix))[0, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[0, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[0, 2]) * extents.z, Math.Abs(((Matrix4x4)(ref matrix))[1, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[1, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[1, 2]) * extents.z, Math.Abs(((Matrix4x4)(ref matrix))[2, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[2, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[2, 2]) * extents.z); } internal static bool SameScale(Vector3 first, Vector3 second) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (Finite(first) && Finite(second) && Close(first.x, second.x) && Close(first.y, second.y)) { return Close(first.z, second.z); } return false; } private static bool Close(float first, float second) { return Math.Abs(first - second) <= 0.0001f * Math.Max(0.0001f, Math.Max(Math.Abs(first), Math.Abs(second))); } private static bool Usable(Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_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) if (Finite(((Bounds)(ref bounds)).center) && Finite(((Bounds)(ref bounds)).extents) && ((Bounds)(ref bounds)).extents.x >= 0f && ((Bounds)(ref bounds)).extents.y >= 0f && ((Bounds)(ref bounds)).extents.z >= 0f) { Vector3 extents = ((Bounds)(ref bounds)).extents; return ((Vector3)(ref extents)).sqrMagnitude > 0f; } return false; } private static bool Finite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (float.IsFinite(value.x) && float.IsFinite(value.y)) { return float.IsFinite(value.z); } return false; } } internal sealed class EchoRenderer : IDisposable { private struct Pulse { internal Vector3 Origin; internal Quaternion Rotation; internal bool Clap; internal bool Sonar; internal bool Lidar; internal bool Automatic; internal bool Deduplicate; internal EchoKind Kind; internal SoundEmitterSurface? SurfaceEmission; internal Vector3 ListenerOrigin; internal int SurfaceRays; internal float Strength; internal float Time; internal float Range; internal float Phase; internal float Sweep; internal int SampleOffset; internal int Total; internal int Next; internal int ShuffleBits; internal int ShuffleCursor; } private struct Dot { internal Vector3 Position; internal Color Color; internal float Birth; internal float FadeInStart; internal float Lifetime; internal float Strength; internal bool Indexed; internal bool Clap; internal SurfaceCell Cell; } private struct ColliderFlags { internal Collider Collider; internal bool Local; internal bool Player; } private struct RecentSound { internal Vector3 Origin; internal float Time; internal Collider? Owner; internal bool Valid; } private readonly struct SurfaceCell : IEquatable<SurfaceCell> { private readonly int _collider; private readonly int _x; private readonly int _y; private readonly int _z; private readonly int _facing; private readonly bool _detail; internal SurfaceCell(int collider, Vector3 point, Vector3 normal, float spacing, bool detail) { //IL_0008: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_008a: 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_009d: Unknown result type (might be due to invalid IL or missing references) _collider = collider; _x = (int)MathF.Floor(point.x / spacing); _y = (int)MathF.Floor(point.y / spacing); _z = (int)MathF.Floor(point.z / spacing); float num = MathF.Abs(normal.x); float num2 = MathF.Abs(normal.y); float num3 = MathF.Abs(normal.z); _facing = ((num > num2 && num > num3) ? ((!(normal.x >= 0f)) ? 1 : 0) : ((!(num2 > num3)) ? ((normal.z >= 0f) ? 4 : 5) : ((normal.y >= 0f) ? 2 : 3))); _detail = detail; } public bool Equals(SurfaceCell other) { if (_collider == other._collider && _x == other._x && _y == other._y && _z == other._z && _facing == other._facing) { return _detail == other._detail; } return false; } public override bool Equals(object? obj) { if (obj is SurfaceCell other) { return Equals(other); } return false; } public override int GetHashCode() { return HashCode.Combine(_collider, _x, _y, _z, _facing, _detail); } } private const int QueueLimit = 4; private const int HardDotLimit = 65536; private const float QueueLifetime = 1.25f; private const float WaveSpeed = 45f; private const float MaximumWaveTravelTime = 1.25f; private const float GoldenAngle = 2.3999631f; private const int ShaderAttempts = 6; private const int AutomaticRaysPerPulse = 512; private const int SonarRaysPerTurn = 2048; private const int LidarRaysPerScan = 128; private const int AutomaticRaysPerFrame = 256; private const int EmitterSurfaceRayLimit = 128; private const float AutomaticLifetime = 0.85f; private const float AutomaticDotSpacing = 0.09f; private const int ColliderCacheLimit = 512; private static readonly string[] ShaderNames = new string[3] { "Sprites/Default", "Legacy Shaders/Particles/Alpha Blended", "Hidden/Internal-Colored" }; private readonly Settings _settings; private readonly Action<string> _warning; private readonly BlackoutView _blackout; private readonly PlayerEchoes _players; private readonly Pulse[] _pulses = new Pulse[4]; private readonly Il2CppStructArray<RaycastHit> _hits = new Il2CppStructArray<RaycastHit>(32L); private readonly Dictionary<SurfaceCell, int> _surfaceCells = new Dictionary<SurfaceCell, int>(); private readonly Dictionary<int, ColliderFlags> _colliderFlags = new Dictionary<int, ColliderFlags>(512); private readonly RecentSound[] _recentSounds = new RecentSound[8]; private int _recentSoundCursor; private Dot[] _dots = Array.Empty<Dot>(); private int _dotCount; private int _pulseCount; private int _pulseCursor; private int _overwriteCursor; private uint _sequence; private Mesh? _mesh; private Material? _material; private Il2CppStructArray<Vector3>? _vertices; private Il2CppStructArray<Color>? _colors; private Il2CppStructArray<Vector2>? _uvs; private Il2CppStructArray<int>? _indices; private int _uploadCapacity; private int _shaderAttempts; private float _nextShaderAttempt; private bool _disposed; private bool _sonarActive; private float _sonarTime; private double _sonarTurn; private double _sonarRemainder; private int _sonarSample; internal bool Ready { get { if (!_disposed && (Object)(object)_mesh != (Object)null) { return (Object)(object)_material != (Object)null; } return false; } } internal int DotCount => _dotCount; internal string VisionStatus => _blackout.Status; internal string PlayerStatus => _players.Status; internal EchoRenderer(Settings settings, Action<string> warning) { _settings = settings; _warning = warning; _blackout = new BlackoutView(warning); _players = new PlayerEchoes(settings, warning); } internal void TickRemoteFootsteps(float now, Vector3 head, Transform? rigRoot, Action<EchoEvent> emit, Action<EchoEvent> observeSound) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!_disposed) { _players.TickFootsteps(now, head, rigRoot, emit, observeSound); } } internal void ObserveSound(EchoEvent echo, Transform? localRoot) { if (_disposed) { return; } try { _players.ObserveSound(echo, localRoot); } catch (Exception ex) { _warning("Player sound ownership: " + ex.Message); } } internal bool Enqueue(EchoEvent echo) { return Enqueue(echo, clap: false); } internal bool EnqueueClap(Vector3 origin, float now) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Enqueue(new EchoEvent(origin, 1f, EchoKind.Manual, now), clap: true); } internal void UpdateSonar(Vector3 origin, float now, float secondsPerTurn) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) if (_disposed || !Finite(origin) || !float.IsFinite(now) || now < 0f || !float.IsFinite(secondsPerTurn) || secondsPerTurn <= 0f) { StopSonar(); return; } if (!_sonarActive || now < _sonarTime) { StopSonar(); _sonarActive = true; _sonarTime = now; return; } double num = (double)now - (double)_sonarTime; if (num <= 0.0) { return; } _sonarTime = now; double num2 = num / (double)Math.Clamp(secondsPerTurn, 0.25f, 10f); double num3 = _sonarTurn; _sonarTurn = (_sonarTurn + num2) % 1.0; if (num > 0.25 || num2 > 0.25) { num2 = 1.0 / 64.0; num3 = _sonarTurn - num2; _sonarRemainder = 0.0; } double num4 = (double)Math.Clamp(_settings.RayCount, 32, 2048) * num2 + _sonarRemainder; int num5 = (int)Math.Floor(num4 + 1E-06); _sonarRemainder = Math.Max(0.0, num4 - (double)num5); for (int num6 = _pulseCount - 1; num6 >= 0; num6--) { if (_pulses[num6].Sonar) { RemovePulse(num6); } } if (num5 != 0) { Pulse pulse = ScanPulse(origin, now, Math.Min(num5, 256)); pulse.Sonar = true; pulse.SampleOffset = _sonarSample; _sonarSample = (_sonarSample + num5) % 65536; pulse.Phase = (float)(num3 * Math.PI * 2.0); pulse.Sweep = (float)(num2 * Math.PI * 2.0); QueueScan(pulse); } } internal void StopSonar() { _sonarActive = false; _sonarTime = 0f; _sonarTurn = 0.0; _sonarRemainder = 0.0; _sonarSample = 0; for (int num = _pulseCount - 1; num >= 0; num--) { if (_pulses[num].Sonar) { RemovePulse(num); } } } internal bool EnqueueLidar(Vector3 origin, Quaternion rotation, float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) float num = rotation.x * rotation.x + rotation.y * rotation.y + rotation.z * rotation.z + rotation.w * rotation.w; if (_disposed || !Finite(origin) || !float.IsFinite(now) || now < 0f || !float.IsFinite(num) || num < 0.0001f) { return false; } float num2 = 1f / Mathf.Sqrt(num); Pulse pulse = ScanPulse(origin, now, Math.Clamp(_settings.RayCount, 32, 128)); pulse.Lidar = true; pulse.Rotation = new Quaternion(rotation.x * num2, rotation.y * num2, rotation.z * num2, rotation.w * num2); return QueueScan(pulse); } private Pulse ScanPulse(Vector3 origin, float now, int total) { //IL_000a: 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) return new Pulse { Origin = origin, Time = now, Strength = 1f, Range = (float.IsFinite(_settings.Range) ? Mathf.Clamp(_settings.Range, 2f, 3000f) : 3000f), Kind = EchoKind.Manual, Total = total, Phase = (float)(++_sequence % 65536) * 2.3999631f, Automatic = true, Deduplicate = true }; } private bool QueueScan(Pulse pulse) { PrunePulses(pulse.Time); int num = 0; int num2 = -1; for (int i = 0; i < _pulseCount; i++) { if (_pulses[i].Lidar) { num++; if (num2 < 0 || _pulses[i].Time < _pulses[num2].Time) { num2 = i; } } } if (pulse.Lidar && num >= 2) { RemovePulse(num2); } if (_pulseCount >= 4) { int num3 = -1; for (int j = 0; j < _pulseCount; j++) { ref Pulse reference = ref _pulses[j]; if (!reference.Clap && !reference.Lidar && reference.SurfaceEmission == null && (reference.Kind != EchoKind.Manual || reference.Sonar) && (num3 < 0 || reference.Time < _pulses[num3].Time)) { num3 = j; } } if (num3 < 0) { return false; } RemovePulse(num3); } _pulses[_pulseCount++] = pulse; return true; } private bool Enqueue(EchoEvent echo, bool clap) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) if (_disposed || !Finite(echo.Origin) || !float.IsFinite(echo.Time) || !float.IsFinite(echo.Strength) || echo.Strength <= 0f) { return false; } PrunePulses(echo.Time); bool flag = _settings.OptimizeAutomaticEchoes && !clap && echo.Kind != EchoKind.Manual; SoundEmitterSurface soundEmitterSurface = ((echo.Kind == EchoKind.World) ? echo.SurfaceEmission : null); if (soundEmitterSurface != null && soundEmitterSurface.Count == 0) { soundEmitterSurface = null; } Collider owner = ((soundEmitterSurface != null && soundEmitterSurface.Count > 0) ? soundEmitterSurface.GetCollider(0) : null); if (flag && HasRecentNearbySound(echo.Origin, echo.Time, owner)) { return false; } if (clap && ClapPulseIndex() >= 0) { return false; } if (_pulseCount >= 4 && (clap || echo.Kind == EchoKind.Manual || soundEmitterSurface != null)) { for (int i = 0; i < _pulseCount; i++) { if (_pulses[i].Sonar || (_pulses[i].Lidar && (clap || echo.Kind == EchoKind.Manual))) { RemovePulse(i); break; } } } if (_pulseCount >= 4) { bool flag2 = soundEmitterSurface != null && soundEmitterSurface.Count > 0; if (!clap && !flag2) { return false; } int num = -1; for (int j = 0; j < _pulseCount; j++) { if ((clap || (!_pulses[j].Clap && _pulses[j].Kind != EchoKind.Manual && _pulses[j].SurfaceEmission == null)) && (num < 0 || _pulses[j].Time < _pulses[num].Time)) { num = j; } } if (num < 0) { return false; } RemovePulse(num); } float num2 = Mathf.Clamp01(echo.Strength); int num3 = Mathf.Clamp(_settings.RayCount, 32, 16384); int num4 = (clap ? Math.Min(Math.Clamp(num3 * 3, 256, 32768), Math.Clamp(_settings.RaysPerFrame, 8, 4096) * 45) : Mathf.Max(16, Mathf.RoundToInt((float)num3 * Mathf.Lerp(0.55f, 1f, num2)))); if (flag) { num4 = Math.Min(num4, 512); } int k = 0; if (clap) { for (; 1 << k < num4; k++) { } } _pulses[_pulseCount++] = new Pulse { Origin = echo.Origin, Strength = num2, Time = echo.Time, Kind = echo.Kind, SurfaceEmission = soundEmitterSurface, SurfaceRays = ((soundEmitterSurface != null && soundEmitterSurface.Count > 0) ? Math.Min(num4 / 4, 128) : 0), Range = (float.IsFinite(_settings.Range) ? Mathf.Clamp(_settings.Range, 2f, 3000f) : 3000f) * Mathf.Lerp(0.4f, 1f, num2), Total = num4, Phase = (float)(++_sequence % 65536) * 2.3999631f, Clap = clap, Automatic = flag, Deduplicate = _settings.OptimizeAutomaticEchoes, ShuffleBits = k }; if (flag) { _recentSounds[_recentSoundCursor++ % _recentSounds.Length] = new RecentSound { Origin = echo.Origin, Time = echo.Time, Owner = owner, Valid = true }; } if (_recentSoundCursor >= _recentSounds.Length) { _recentSoundCursor = 0; } return true; } internal void Tick(float now, Transform head, Transform? rigRoot) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if (_disposed || (Object)(object)head == (Object)null || !float.IsFinite(now)) { return; } _players.PrepareTargets(now, rigRoot); EnsureAssets(now); PrunePulses(now); if (!Ready) { return; } _blackout.Tick(now, _settings.Blackout); _material.renderQueue = (_blackout.Active ? 4999 : 3001); EnsureCapacity(Mathf.Clamp(_settings.MaxDots, 64, 65536)); ExpireDots(now); _colliderFlags.Clear(); int val = Mathf.Clamp(_settings.RaysPerFrame, 8, 4096); int num = Math.Min(val, 256); while (val-- > 0 && _pulseCount > 0) { int num2 = NextPulseIndex(num > 0); if (num2 < 0) { break; } _pulseCursor = num2; ref Pulse reference = ref _pulses[_pulseCursor]; if (reference.Automatic) { num--; } if (reference.Next == 0 && !reference.Clap && !reference.Sonar && !reference.Lidar) { reference.Rotation = head.rotation; reference.ListenerOrigin = head.position; } CastReturn(ref reference, now, rigRoot); if (reference.Next >= reference.Total) { RemovePulse(_pulseCursor); } else { _pulseCursor++; } } Draw(now, head); try { _players.Tick(now, head, rigRoot); } catch (Exception ex) { _warning("Player visibility: " + ex.Message); } } internal void Reset() { _blackout.Reset(); _players.Reset(); _dotCount = 0; _pulseCount = 0; StopSonar(); _pulseCursor = 0; _overwriteCursor = 0; _surfaceCells.Clear(); _colliderFlags.Clear(); Array.Clear(_recentSounds, 0, _recentSounds.Length); _recentSoundCursor = 0; _shaderAttempts = 0; _nextShaderAttempt = 0f; if ((Object)(object)_mesh != (Object)null) { _mesh.Clear(); } } public void Dispose() { if (!_disposed) { _disposed = true; _blackout.Dispose(); _players.Dispose(); _pulseCount = 0; _dotCount = 0; _surfaceCells.Clear(); _colliderFlags.Clear(); DestroyAssets(); _dots = Array.Empty<Dot>(); _vertices = null; _colors = null; _uvs = null; _indices = null; _uploadCapacity = 0; } } private void CastReturn(ref Pulse pulse, float now, Transform? rigRoot) { //IL_015b: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) int num = pulse.Next++; if (num % 4 == 0 && num / 4 < pulse.SurfaceRays && TryEmitterRay(pulse, num / 4, rigRoot, out var direction, out var range)) { if (FindReturn(pulse.ListenerOrigin, direction, range, rigRoot, null, out var selected) && pulse.SurfaceEmission.IsOwnCollider(((RaycastHit)(ref selected)).collider)) { AddReturn(ref pulse, selected, ((RaycastHit)(ref selected)).distance, now); } return; } float num2 = ((float)num + 0.5f) / (float)pulse.Total; float num3 = (float)num * 2.3999631f + pulse.Phase; Vector3 direction2 = default(Vector3); if (pulse.Sonar) { float num4 = 1f - 2f * (float)(((double)(num + pulse.SampleOffset) * 0.61803398875 + 0.5) % 1.0); float num5 = Mathf.Sqrt(Mathf.Max(0f, 1f - num4 * num4)); float num6 = pulse.Phase + pulse.Sweep * num2; ((Vector3)(ref direction2))..ctor(num5 * Mathf.Sin(num6), num4, num5 * Mathf.Cos(num6)); } else if (pulse.Lidar) { float num7 = Mathf.Lerp(1f, 0.819152f, num2); float num8 = Mathf.Sqrt(Mathf.Max(0f, 1f - num7 * num7)); direction2 = pulse.Rotation * new Vector3(num8 * Mathf.Cos(num3), num8 * Mathf.Sin(num3), num7); } else if (pulse.Clap) { int num9; do { num9 = ReverseLowBits(pulse.ShuffleCursor++, pulse.ShuffleBits); } while (num9 >= pulse.Total); float num10 = 1f - 2f * (((float)num9 + 0.5f) / (float)pulse.Total); float num11 = Mathf.Sqrt(Mathf.Max(0f, 1f - num10 * num10)); float num12 = (float)num9 * 2.3999631f + pulse.Phase; ((Vector3)(ref direction2))..ctor(num11 * Mathf.Cos(num12), num10, num11 * Mathf.Sin(num12)); } else if (num % 3 == 0) { float num13 = Mathf.Lerp(1f, 0.25f, num2); float num14 = Mathf.Sqrt(Mathf.Max(0f, 1f - num13 * num13)); direction2 = pulse.Rotation * new Vector3(num14 * Mathf.Cos(num3), num14 * Mathf.Sin(num3), num13); } else { float num15 = 1f - 2f * num2; float num16 = Mathf.Sqrt(Mathf.Max(0f, 1f - num15 * num15)); ((Vector3)(ref direction2))..ctor(num16 * Mathf.Cos(num3), num15, num16 * Mathf.Sin(num3)); } if (FindReturn(pulse.Origin, direction2, pulse.Range, rigRoot, pulse.SurfaceEmission, out var selected2)) { AddReturn(ref pulse, selected2, ((RaycastHit)(ref selected2)).distance, now); } } private bool TryEmitterRay(Pulse pulse, int sample, Transform? rigRoot, out Vector3 direction, out float range) { //IL_0002: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) direction = default(Vector3); range = 0f; SoundEmitterSurface? surfaceEmission = pulse.SurfaceEmission; int count = surfaceEmission.Count; int index = ((count > pulse.SurfaceRays) ? (sample * count / pulse.SurfaceRays) : (sample % count)); Collider collider = surfaceEmission.GetCollider(index); if ((Object)(object)collider == (Object)null) { return false; } ColliderFlags colliderFlags = GetColliderFlags(collider, rigRoot); if (colliderFlags.Local || colliderFlags.Player) { return false; } Bounds bounds = collider.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; if (!Finite(center) || !Finite(extents) || ((Vector3)(ref extents)).sqrMagnitude < 1E-06f || ((Bounds)(ref bounds)).Contains(pulse.ListenerOrigin) || !Finite(pulse.ListenerOrigin) || Vector3.Distance(pulse.ListenerOrigin, pulse.Origin) > _settings.WorldRange) { return false; } Vector3 val = pulse.ListenerOrigin - center; int num = sample / count; float num2 = ((num == 0) ? 0f : (0.85f * Mathf.Sqrt((float)num * 0.618034f % 1f))); float num3 = (float)num * 2.3999631f + pulse.Phase; float num4 = num2 * Mathf.Cos(num3); float num5 = num2 * Mathf.Sin(num3); float num6 = Mathf.Abs(val.x); float num7 = Mathf.Abs(val.y); float num8 = Mathf.Abs(val.z); Vector3 val2 = ((num6 > num7 && num6 > num8) ? new Vector3((val.x >= 0f) ? extents.x : (0f - extents.x), num4 * extents.y, num5 * extents.z) : ((num7 > num8) ? new Vector3(num4 * extents.x, (val.y >= 0f) ? extents.y : (0f - extents.y), num5 * extents.z) : new Vector3(num4 * extents.x, num5 * extents.y, (val.z >= 0f) ? extents.z : (0f - extents.z)))); Vector3 val3 = center + val2 - pulse.ListenerOrigin; float magnitude = ((Vector3)(ref val3)).magnitude; if (!float.IsFinite(magnitude) || magnitude < 0.001f) { return false; } direction = val3 / magnitude; range = Math.Min(magnitude + ((Vector3)(ref extents)).magnitude * 2f + 0.02f, _settings.WorldRange + ((Vector3)(ref extents)).magnitude * 2f); if (float.IsFinite(range)) { return range > 0f; } return false; } private bool FindReturn(Vector3 origin, Vector3 direction, float range, Transform? rigRoot, SoundEmitterSurface? ignoredOwner, out RaycastHit selected) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) selected = default(RaycastHit); int num = Physics.RaycastNonAlloc(origin, direction, _hits, range, -5, (QueryTriggerInteraction)1); if (num == 0 || num >= ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length) { return false; } float num2 = float.PositiveInfinity; bool flag = false; for (int i = 0; i < num; i++) { RaycastHit val = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (!((Object)(object)collider == (Object)null) && !(((RaycastHit)(ref val)).distance >= num2)) { ColliderFlags colliderFlags = GetColliderFlags(collider, rigRoot); if (!colliderFlags.Local && (colliderFlags.Player || ignoredOwner == null || !ignoredOwner.IsOwnCollider(collider))) { num2 = ((RaycastHit)(ref val)).distance; selected = val; flag = true; } } } if (!flag) { return false; } if (GetColliderFlags(((RaycastHit)(ref selected)).collider, rigRoot).Player) { return false; } return true; } private void AddReturn(ref Pulse pulse, RaycastHit selected, float nearest, float now) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(45f, Mathf.Max(pulse.Range, nearest) / 1.25f); bool flag = pulse.Sonar || pulse.Lidar; float num2 = (flag ? now : ((pulse.Clap ? now : pulse.Time) + nearest / num)); float num3 = Mathf.Clamp(_settings.DotLifetime, 0.15f, 8f); if (pulse.Clap) { num3 = Mathf.Max(2.5f, num3); } if (pulse.Automatic) { num3 = Math.Min(num3, 0.85f); } if (pulse.Sonar) { num3 = Math.Min(num3, 0.35f); } if (now >= num2 + num3) { return; } SurfaceCell surfaceCell = default(SurfaceCell); if (pulse.Deduplicate) { if (!Finite(((RaycastHit)(ref selected)).point) || !Finite(((RaycastHit)(ref selected)).normal)) { return; } surfaceCell = new SurfaceCell(((Object)((RaycastHit)(ref selected)).collider).GetInstanceID(), ((RaycastHit)(ref selected)).point, ((RaycastHit)(ref selected)).normal, pulse.Automatic ? 0.09f : 0.04f, !pulse.Automatic); if (_surfaceCells.TryGetValue(surfaceCell, out var value)) { ref Dot reference = ref _dots[value]; if (!reference.Clap || pulse.Clap) { reference.Birth = ((reference.Birth <= now) ? Math.Min(num2, now) : Math.Min(reference.Birth, num2)); if (flag) { reference.FadeInStart = Math.Min(reference.FadeInStart, now - 0.025f); } reference.Lifetime = num3; reference.Strength = Math.Max(reference.Strength, ReturnStrength(pulse, nearest)); reference.Color = (Color)(pulse.Clap ? new Color(0.65f, 0.98f, 1f, 1f) : ColorFor(pulse.Kind)); reference.Clap = pulse.Clap; } return; } } int num4; if (_dotCount < _dots.Length) { num4 = _dotCount++; } else { num4 = _overwriteCursor++ % _dots.Length; if (_overwriteCursor >= _dots.Length) { _overwriteCursor = 0; } if (pulse.Automatic && num2 > now + 0.1f && _dots[num4].Birth <= now) { return; } RemoveCell(num4); } _dots[num4] = new Dot { Position = ((RaycastHit)(ref selected)).point + ((RaycastHit)(ref selected)).normal * 0.007f, Birth = num2, FadeInStart = (flag ? (num2 - 0.025f) : num2), Lifetime = num3, Strength = ReturnStrength(pulse, nearest), Color = (Color)(pulse.Clap ? new Color(0.65f, 0.98f, 1f, 1f) : ColorFor(pulse.Kind)), Indexed = pulse.Deduplicate, Cell = surfaceCell, Clap = pulse.Clap }; if (pulse.Deduplicate) { _surfaceCells[surfaceCell] = num4; } } private static float ReturnStrength(Pulse pulse, float distance) { return pulse.Strength * Mathf.Lerp(1f, pulse.Clap ? 0.7f : 0.35f, distance / pulse.Range); } private ColliderFlags GetColliderFlags(Collider collider, Transform? rigRoot) { int instanceID = ((Object)collider).GetInstanceID(); if (_colliderFlags.TryGetValue(instanceID, out var value) && (Object)(object)value.Collider == (Object)(object)collider) { return value; } Transform transform = ((Component)collider).transform; bool flag = (Object)(object)rigRoot != (Object)null && ((Object)(object)transform == (Object)(object)rigRoot || transform.IsChildOf(rigRoot)); value = new ColliderFlags { Collider = collider, Local = flag, Player = (!flag && _players.IsPlayerTransform(transform)) }; if (_colliderFlags.Count < 512) { _colliderFlags[instanceID] = value; } return value; } private bool HasRecentNearbySound(Vector3 origin, float now, Collider? owner) { //IL_0041: 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) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) RecentSound[] recentSounds = _recentSounds; for (int i = 0; i < recentSounds.Length; i++) { RecentSound recentSound = recentSounds[i]; if (recentSound.Valid && (Object)(object)recentSound.Owner == (Object)(object)owner && now >= recentSound.Time && now - recentSound.Time < 0.18f) { Vector3 val = origin - recentSound.Origin; if (((Vector3)(ref val)).sqrMagnitude < 0.5625f) { return true; } } } return false; } private int NextPulseIndex(bool allowAutomatic) { int num = ClapPulseIndex(); if (num >= 0) { return num; } bool flag = false; for (int i = 0; i < _pulseCount; i++) { if (_pulses[i].Kind == EchoKind.Manual && !_pulses[i].Sonar && !_pulses[i].Lidar) { flag = true; } } for (int j = 0; j < _pulseCount; j++) { int num2 = (_pulseCursor + j) % _pulseCount; if (!((_pulses[num2].Sonar || _pulses[num2].Lidar) && flag) && (allowAutomatic || !_pulses[num2].Automatic)) { return num2; } } return -1; } private void Draw(float now, Transform head) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0065: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_0162: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) int num = 0; float num2 = Mathf.Clamp(_settings.DotSize, 0.002f, 0.2f); float num3 = (float.IsFinite(_settings.DotBrightness) ? Mathf.Clamp(_settings.DotBrightness, 0.25f, 3f) : 1.8f); Vector3 val = head.right * num2; Vector3 val2 = head.up * num2; for (int i = 0; i < _dotCount; i++) { ref Dot reference = ref _dots[i]; float num4 = now - reference.Birth; if (num4 < 0f) { continue; } float num5 = Mathf.Clamp01(1f - num4 / reference.Lifetime); float num6 = reference.Strength * num5 * num5 * Mathf.Clamp01((now - reference.FadeInStart) / 0.025f); if (!(num6 < 0.006f)) { int num7 = num++ * 5; Color color = reference.Color; color.r *= num3; color.g *= num3; color.b *= num3; color.a = num6; ((Il2CppArrayBase<Vector3>)(object)_vertices)[num7] = reference.Position; ((Il2CppArrayBase<Color>)(object)_colors)[num7] = color; color.a = 0f; ((Il2CppArrayBase<Vector3>)(object)_vertices)[num7 + 1] = reference.Position + val2; ((Il2CppArrayBase<Vector3>)(object)_vertices)[num7 + 2] = reference.Position + val; ((Il2CppArrayBase<Vector3>)(object)_vertices)[num7 + 3] = reference.Position - val2; ((Il2CppArrayBase<Vector3>)(object)_vertices)[num7 + 4] = reference.Position - val; for (int j = 1; j <= 4; j++) { ((Il2CppArrayBase<Color>)(object)_colors)[num7 + j] = color; } } } if (num != 0) { int num8 = num * 5; _mesh.Clear(); _mesh.indexFormat = (IndexFormat)(num8 > 65535); _mesh.SetVertices(_vertices, 0, num8); _mesh.SetColors(_colors, 0, num8); _mesh.SetUVs(0, _uvs, 0, num8); _mesh.SetTriangles(_indices, 0, num * 12, 0, true, 0); Graphics.DrawMesh(_mesh, Matrix4x4.identity, _material, 0, (Camera)null, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null); } } private void EnsureCapacity(int capacity) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (_dots.Length != capacity) { for (int i = capacity; i < _dotCount; i++) { RemoveCell(i); } Array.Resize(ref _dots, capacity); _dotCount = Math.Min(_dotCount, capacity); _overwriteCursor = 0; } if (_uploadCapacity >= capacity) { return; } _uploadCapacity = capacity; _vertices = new Il2CppStructArray<Vector3>((long)(capacity * 5)); _colors = new Il2CppStructArray<Color>((long)(capacity * 5)); _uvs = new Il2CppStructArray<Vector2>((long)(capacity * 5)); _indices = new Il2CppStructArray<int>((long)(capacity * 12)); for (int j = 0; j < capacity; j++) { int num = j * 5; for (int k = 0; k < 5; k++) { ((Il2CppArrayBase<Vector2>)(object)_uvs)[num + k] = new Vector2(0.5f, 0.5f); } for (int l = 0; l < 4; l++) { int num2 = j * 12 + l * 3; ((Il2CppArrayBase<int>)(object)_indices)[num2] = num; ((Il2CppArrayBase<int>)(object)_indices)[num2 + 1] = num + l + 1; ((Il2CppArrayBase<int>)(object)_indices)[num2 + 2] = num + (l + 1) % 4 + 1; } } } private void ExpireDots(float now) { int num = 0; while (num < _dotCount) { if (now >= _dots[num].Birth + _dots[num].Lifetime) { RemoveCell(num); _dots[num] = _dots[--_dotCount]; if (num < _dotCount && _dots[num].Indexed) { _surfaceCells[_dots[num].Cell] = num; } } else { num++; } } } private void RemoveCell(int slot) { if (_dots[slot].Indexed) { _surfaceCells.Remove(_dots[slot].Cell); } } private void PrunePulses(float now) { for (int num = _pulseCount - 1; num >= 0; num--) { if (((_pulses[num].Sonar || _pulses[num].Lidar) && now < _pulses[num].Time) || now - _pulses[num].Time > (_pulses[num].Clap ? 3f : (_pulses[num].Sonar ? 0.12f : (_pulses[num].Lidar ? 0.25f : 1.25f)))) { RemovePulse(num); } } } private int ClapPulseIndex() { for (int i = 0; i < _pulseCount; i++) { if (_pulses[i].Clap) { return i; } } return -1; } private static int ReverseLowBits(int value, int bits) { int num = 0; for (int i = 0; i < bits; i++) { num = (num << 1) | (value & 1); value >>= 1; } return num; } private void RemovePulse(int index) { _pulses[index] = _pulses[--_pulseCount]; if (_pulseCursor >= _pulseCount) { _pulseCursor = 0; } } private void EnsureAssets(float now) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown if (Ready || now < _nextShaderAttempt || _shaderAttempts >= 6) { return; } _shaderAttempts++; _nextShaderAttempt = now + 3f; DestroyAssets(); try { Shader val = null; string[] shaderNames = ShaderNames; for (int i = 0; i < shaderNames.Length; i++) { Shader val2 = Shader.Find(shaderNames[i]); if ((Object)(object)val2 != (Object)null && val2.isSupported) { val = val2; break; } } if ((Object)(object)val == (Object)null) { if (_shaderAttempts == 1 || _shaderAttempts == 6) { _warning($"Echolocation: no supported depth-tested vertex-color shader (attempt {_shaderAttempts}/{6})."); } return; } _material = new Material(val) { hideFlags = (HideFlags)61, renderQueue = 3001 }; if (_material.HasProperty(