using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using CoilHead;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Input;
using Il2CppSLZ.Marrow.Utilities;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LabFusion.Data;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.SDK.Metadata;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(CoilHeadMod), "Coilhead mod", "1.2.4", "MannequinMod", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MannequinMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.4.0")]
[assembly: AssemblyInformationalVersion("1.2.4")]
[assembly: AssemblyProduct("MannequinMod")]
[assembly: AssemblyTitle("MannequinMod")]
[assembly: AssemblyVersion("1.2.4.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 CoilHead
{
public sealed class CoilHeadMod : MelonMod
{
private readonly WatchTimer _timer = new WatchTimer();
private readonly ModSettings _settings = new ModSettings();
private readonly PoseLock _pose = new PoseLock(null, delegate(string message)
{
MelonLogger.Warning(message);
});
private readonly List<NetworkPlayer> _watchers = new List<NetworkPlayer>();
private readonly List<AIBrain> _npcWatchers = new List<AIBrain>();
private readonly NpcWatcherScanner _npcScanner = new NpcWatcherScanner();
private ObserverMode _mode;
private readonly WatcherOutline _outline = new WatcherOutline();
private readonly WatcherScanner _scanner = new WatcherScanner();
private readonly DisableGesture _gesture = new DisableGesture();
private readonly CountdownHud _hud = new CountdownHud();
private readonly RemoteFreeze _remote = new RemoteFreeze();
private bool _showHud = true;
private bool _showHighlights = true;
private float _nextVisualRetry;
private float _nextHudRetry;
private static readonly Color Gold = new Color(1f, 0.9f, 0.08f);
private static readonly Color Mint = new Color(0.2f, 1f, 0.72f);
private Page? _menuRoot;
private BoolElement? _toggle;
private FunctionElement? _status;
private RigManager? _rig;
private Transform? _avatar;
private bool _enabled;
private bool _poseHookReady;
private float _nextStatus;
private int _freezeSegmentSeconds = 20;
public override void OnInitializeMelon()
{
_settings.Load();
_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
SightQuery.ViewAngle = _settings.ViewAngle;
((MelonBase)this).LoggerInstance.Msg("Coilhead mod 1.2.4 loaded. Live gaze, saved settings, pose-only freezing; no native rig detours.");
}
private void Menu()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: 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_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_023a: Unknown result type (might be due to invalid IL or missing references)
if (Page.Root == null || _menuRoot == Page.Root)
{
return;
}
Page val = Page.Root.CreatePage("Coilhead mod", Gold, 0, true);
_status = val.CreateFunction("OFF / COILHEAD", Color.gray, (Action)delegate
{
});
((Element)_status).SetTooltip("Gold: frozen. Mint: cooldown, free to move. White: ready.");
_toggle = val.CreateBool("Enable Coilhead", Gold, _enabled, (Action<bool>)SetEnabled);
((Element)_toggle).SetTooltip("Combined look time qualifies each freeze. Looking away releases immediately; the countdown continues. No new freeze in its final 5 seconds.");
val.CreateEnum("Who can freeze you", Gold, (Enum)_mode, (Action<Enum>)delegate(Enum value)
{
Reset();
_mode = (ObserverMode)(object)value;
});
val.CreateFunction("Emergency release / disable", Color.red, (Action)delegate
{
SetEnabled(value: false);
});
Page obj = val.CreatePage("Settings", Mint, 0, true);
((Element)obj.CreateFloat("Look time before freezing", Color.white, _settings.LookSeconds, 0.25f, 0f, 10f, (Action<float>)delegate(float value)
{
Reset();
_settings.LookSeconds = value;
_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
})).SetTooltip("Seconds of combined looks needed before each freeze. Pauses while unseen. Default 2.5s; 0 freezes instantly.");
obj.CreateInt("Freeze duration (seconds)", Color.white, _settings.FreezeSeconds, 1, 1, 120, (Action<int>)delegate(int value)
{
Reset();
_settings.FreezeSeconds = value;
_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
});
obj.CreateInt("Cooldown (seconds)", Color.white, _settings.CooldownSeconds, 1, 0, 120, (Action<int>)delegate(int value)
{
Reset();
_settings.CooldownSeconds = value;
_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
});
((Element)obj.CreateInt("View cone (degrees)", Color.white, _settings.ViewAngle, 5, 20, 100, (Action<int>)delegate(int value)
{
Reset();
_settings.ViewAngle = value;
SightQuery.ViewAngle = _settings.ViewAngle;
})).SetTooltip("Full cone around headset forward. Lower values require a more direct look. Default: 60 degrees.");
obj.CreateEnum("Outline color", _settings.Color, (Enum)_settings.ColorChoice, (Action<Enum>)delegate(Enum value)
{
_settings.ColorChoice = (OutlineColor)(object)value;
});
Page obj2 = val.CreatePage("Display & highlights", Mint, 0, true);
obj2.CreateBool("VR countdown", Color.white, _showHud, (Action<bool>)delegate(bool value)
{
_showHud = value;
if (!value)
{
_hud.Hide();
}
});
obj2.CreateBool("Watcher outlines", Gold, _showHighlights, (Action<bool>)delegate(bool value)
{
_showHighlights = value;
if (!value)
{
_outline.Clear();
}
});
_menuRoot = Page.Root;
}
private void SetEnabled(bool value)
{
_enabled = false;
Reset();
_enabled = value;
if (_toggle != null)
{
_toggle.Value = value;
}
((MelonBase)this).LoggerInstance.Msg(value ? $"Coilhead enabled. Look time {_settings.LookSeconds}s; freeze {_settings.FreezeSeconds}s; cooldown {_settings.CooldownSeconds}s." : "Coilhead disabled; released.");
}
public override void OnUpdate()
{
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_022e: Expected O, but got Unknown
//IL_0262: Unknown result type (might be due to invalid IL or missing references)
//IL_026f: Expected O, but got Unknown
//IL_06de: Unknown result type (might be due to invalid IL or missing references)
//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_enabled)
{
XRApi xr = MarrowGame.xr;
XRController val = ((xr != null) ? xr.LeftController : null);
XRController val2 = ((xr != null) ? xr.RightController : null);
bool flag = val != null && val2 != null && (Object)(object)Player.LeftController != (Object)null && (Object)(object)Player.RightController != (Object)null && ((Behaviour)Player.LeftController).isActiveAndEnabled && ((Behaviour)Player.RightController).isActiveAndEnabled;
if (_gesture.Tick(flag, flag ? val.Trigger : 0f, flag ? val2.Trigger : 0f, flag && val.BButton, flag && val2.BButton, Time.realtimeSinceStartupAsDouble))
{
SetEnabled(value: false);
}
}
Menu();
RigManager rigManager = Player.RigManager;
if ((Object)(object)_rig != (Object)(object)rigManager)
{
goto IL_0107;
}
if ((Object)(object)rigManager != (Object)null)
{
Transform? avatar = _avatar;
Avatar avatar2 = rigManager.avatar;
if ((Object)(object)avatar != (Object)(object)((avatar2 != null) ? ((Component)avatar2).transform : null))
{
goto IL_0107;
}
}
goto IL_013f;
IL_0107:
Reset();
_rig = rigManager;
_avatar = (((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.avatar != (Object)null) ? ((Component)rigManager.avatar).transform : null);
goto IL_013f;
IL_013f:
bool flag2 = _enabled && (_mode != ObserverMode.Players || NetworkInfo.HasServer) && (Object)(object)_rig != (Object)null && (Object)(object)_rig.physicsRig != (Object)null && (Object)(object)_avatar != (Object)null && (Object)(object)Player.Head != (Object)null && ((Object)(object)_rig.health == (Object)null || _rig.health.curr_Health > 0f);
if (flag2)
{
if (NetworkInfo.HasServer && !_poseHookReady)
{
((MelonBase)this).LoggerInstance.Msg("Installing managed Fusion outgoing-pose hook.");
((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(RigPose), "ReadSkeleton", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PoseLock), "AfterReadSkeleton", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(NetworkPlayer), "OnReceivePose", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PlayerGaze), "OnReceivePose", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
_poseHookReady = true;
}
_pose.Track(_rig);
}
else
{
_pose.StopTracking();
}
if (flag2 && NetworkInfo.HasServer && _mode != ObserverMode.NPCs)
{
_scanner.Scan(Time.unscaledTime, _rig, _watchers);
}
else
{
_watchers.Clear();
_scanner.Clear();
}
if (flag2 && _mode != ObserverMode.Players)
{
_npcScanner.Scan(Time.unscaledTime, _rig, _npcWatchers);
}
else
{
_npcWatchers.Clear();
_npcScanner.Clear();
}
int num = _watchers.Count + _npcWatchers.Count;
bool frozen = _timer.Frozen;
bool flag3 = _timer.Tick(flag2, num > 0, Time.realtimeSinceStartupAsDouble);
if (flag3)
{
if (!frozen)
{
_freezeSegmentSeconds = Math.Clamp((int)Math.Ceiling(_timer.FreezeRemaining), 1, 120);
}
if (!_pose.Active)
{
_pose.Capture(_rig, _timer.FreezeRemaining);
}
_pose.Renew();
}
else if (frozen || _pose.Active)
{
_pose.StopTracking();
}
else
{
_pose.Release();
}
if (flag3 != frozen)
{
((MelonBase)this).LoggerInstance.Msg(flag3 ? $"Frozen: {_watchers.Count} player(s), {_npcWatchers.Count} NPC(s)." : ("Released: " + ((num == 0) ? "unseen" : "freeze limit") + "; pose callbacks cleared."));
}
_remote.Publish(flag2 && NetworkInfo.HasServer, _pose.Active, _freezeSegmentSeconds);
_remote.Update(_rig);
if (Time.unscaledTime >= _nextStatus)
{
_nextStatus = Time.unscaledTime + 0.2f;
if (_status != null)
{
((Element)_status).ElementName = ((!_enabled) ? "OFF / COILHEAD" : ((!flag2) ? "WAITING / PLAYER OR LOBBY" : (_pose.Active ? $"FROZEN / {_timer.FreezeRemaining:F1}s / {num} watching" : ((_timer.CooldownRemaining > 0.0) ? $"FREE TO MOVE / {_timer.CooldownRemaining:F1}s" : (_timer.CountdownActive ? $"FREE / COUNTDOWN {_timer.FreezeRemaining:F1}s" : ((_timer.LookElapsed > 0.0 || num > 0) ? $"LOOK TIME / {_timer.LookElapsed:F2} / {_timer.LookSeconds:F2}s" : "READY / UNSEEN"))))));
((Element)_status).ElementColor = ((!_enabled) ? Color.gray : (_pose.Active ? Gold : ((_timer.CooldownRemaining > 0.0) ? Mint : Color.white)));
}
}
}
catch (Exception ex)
{
Fail(ex);
}
}
public override void OnFixedUpdate()
{
try
{
if (_enabled && _timer.Frozen)
{
_pose.Hold();
}
else
{
_pose.Release();
}
_remote.HoldFixed();
}
catch (Exception ex)
{
Fail(ex);
}
}
public override void OnLateUpdate()
{
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_enabled && _timer.Frozen)
{
_pose.HoldVisual();
}
else
{
_pose.Release();
}
}
catch (Exception ex)
{
Fail(ex);
}
if (Time.unscaledTime >= _nextHudRetry)
{
try
{
_hud.Tick(Time.unscaledTime, _enabled && _showHud, _timer, _watchers.Count + _npcWatchers.Count);
}
catch (Exception ex2)
{
_nextHudRetry = Time.unscaledTime + 2f;
_hud.Hide();
((MelonBase)this).LoggerInstance.Warning("Coilhead HUD retry in 2s: " + ex2.Message);
}
}
if (Time.unscaledTime < _nextVisualRetry)
{
return;
}
try
{
if (_enabled && _showHighlights)
{
_outline.Draw(_watchers, _npcWatchers, Player.Head, _settings.Color);
}
}
catch (Exception ex3)
{
_nextVisualRetry = Time.unscaledTime + 10f;
((MelonBase)this).LoggerInstance.Warning("Coilhead visual retry in 10s: " + ex3.Message);
}
}
private void Fail(Exception ex)
{
_enabled = false;
try
{
Reset();
if (_toggle != null)
{
_toggle.Value = false;
}
}
catch (Exception ex2)
{
((MelonBase)this).LoggerInstance.Error((object)ex2);
}
((MelonBase)this).LoggerInstance.Error("Coilhead disabled and released after an error: " + ex);
}
private void Reset()
{
_pose.StopTracking();
_timer.Reset();
_gesture.Reset();
_scanner.Clear();
_watchers.Clear();
_npcScanner.Clear();
_npcWatchers.Clear();
_outline.Clear();
_hud.Hide();
_nextVisualRetry = (_nextHudRetry = 0f);
_remote.Publish(enabled: false, frozen: false);
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
Reset();
_remote.ResetPeers();
_rig = null;
_avatar = null;
}
public override void OnDeinitializeMelon()
{
Reset();
_remote.ResetPeers();
_outline.Dispose();
_hud.Dispose();
}
}
internal sealed class CountdownHud : IDisposable
{
private GameObject? _root;
private Canvas? _canvas;
private Text? _number;
private Material? _material;
private Font? _font;
private int _layer = -1;
private int _lastSecond = -1;
internal void Tick(float now, bool visible, WatchTimer timer, int watchers)
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
CountdownReading countdownReading = CountdownReading.Read(visible, timer);
if (!countdownReading.Visible)
{
Hide();
return;
}
Camera val = HeadsetView.Camera();
if ((Object)(object)val == (Object)null)
{
Hide();
return;
}
if ((Object)(object)_root == (Object)null)
{
Build();
}
_canvas.worldCamera = val;
Transform transform = _root.transform;
if ((Object)(object)transform.parent != (Object)(object)((Component)val).transform)
{
transform.SetParent(((Component)val).transform, false);
}
float num = Math.Max(1.15f, val.nearClipPlane + 0.3f);
Vector3 localPosition = CornerPosition(val, num);
transform.localPosition = localPosition;
transform.localRotation = Quaternion.identity;
float num2 = num * 0.00085f;
transform.localScale = new Vector3(num2, num2, num2);
int num3 = HeadsetView.VisibleLayer(val.cullingMask);
if (num3 < 0)
{
Hide();
return;
}
if (_layer != num3)
{
foreach (Transform componentsInChild in _root.GetComponentsInChildren<Transform>(true))
{
((Component)componentsInChild).gameObject.layer = num3;
}
_layer = num3;
}
if (_lastSecond != countdownReading.Seconds)
{
_number.text = countdownReading.Seconds.ToString();
((Graphic)_number).color = ((countdownReading.Seconds <= 3) ? new Color(1f, 0.78f, 0.28f, 1f) : new Color(1f, 0.96f, 0.78f, 1f));
_lastSecond = countdownReading.Seconds;
}
if (!_root.activeSelf)
{
_root.SetActive(true);
}
}
private static Vector3 CornerPosition(Camera camera, float distance)
{
//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_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: 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_0072: 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_007a: Unknown result type (might be due to invalid IL or missing references)
try
{
Matrix4x4 stereoProjectionMatrix = camera.GetStereoProjectionMatrix((StereoscopicEye)0);
Matrix4x4 stereoProjectionMatrix2 = camera.GetStereoProjectionMatrix((StereoscopicEye)1);
return CountdownPlacement.Position(distance, ((Matrix4x4)(ref stereoProjectionMatrix))[0, 0], ((Matrix4x4)(ref stereoProjectionMatrix))[0, 2], ((Matrix4x4)(ref stereoProjectionMatrix))[1, 1], ((Matrix4x4)(ref stereoProjectionMatrix))[1, 2], ((Matrix4x4)(ref stereoProjectionMatrix2))[0, 0], ((Matrix4x4)(ref stereoProjectionMatrix2))[0, 2], ((Matrix4x4)(ref stereoProjectionMatrix2))[1, 1], ((Matrix4x4)(ref stereoProjectionMatrix2))[1, 2]);
}
catch
{
return new Vector3(distance * 0.48f, (0f - distance) * 0.38f, distance);
}
}
private void Build()
{
//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_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Expected O, but got Unknown
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
Dispose();
try
{
try
{
_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
}
catch
{
_font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
}
if ((Object)(object)_font == (Object)null)
{
_font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
}
if ((Object)(object)_font == (Object)null)
{
throw new InvalidOperationException("Countdown font unavailable");
}
_material = new Material(Graphic.defaultGraphicMaterial)
{
hideFlags = (HideFlags)61,
renderQueue = 5000
};
_material.SetInt("unity_GUIZTestMode", 8);
_root = new GameObject("Mannequin.VR.Countdown", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
((Object)_root).hideFlags = (HideFlags)61;
_root.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)_root);
_canvas = _root.AddComponent<Canvas>();
_canvas.renderMode = (RenderMode)2;
_canvas.sortingOrder = 32700;
_root.GetComponent<RectTransform>().sizeDelta = new Vector2(110f, 80f);
GameObject val = new GameObject("Seconds", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
RectTransform component = val.GetComponent<RectTransform>();
((Transform)component).SetParent(_root.transform, false);
Vector2 val2 = (component.pivot = new Vector2(0.5f, 0.5f));
Vector2 anchorMin = (component.anchorMax = val2);
component.anchorMin = anchorMin;
component.sizeDelta = new Vector2(110f, 80f);
_number = val.AddComponent<Text>();
_number.font = _font;
_number.fontSize = 56;
_number.fontStyle = (FontStyle)1;
((Graphic)_number).material = _material;
_number.alignment = (TextAnchor)4;
((Graphic)_number).raycastTarget = false;
_number.supportRichText = false;
Shadow obj2 = val.AddComponent<Shadow>();
obj2.effectColor = new Color(0f, 0f, 0f, 0.85f);
obj2.effectDistance = new Vector2(1.5f, -1.5f);
}
catch
{
Dispose();
throw;
}
}
internal void Hide()
{
if ((Object)(object)_root != (Object)null && _root.activeSelf)
{
_root.SetActive(false);
}
_lastSecond = -1;
}
public void Dispose()
{
Hide();
if ((Object)(object)_root != (Object)null)
{
Object.Destroy((Object)(object)_root);
}
if ((Object)(object)_material != (Object)null)
{
Object.Destroy((Object)(object)_material);
}
_root = null;
_canvas = null;
_number = null;
_material = null;
_layer = -1;
}
}
internal static class CountdownPlacement
{
internal static Vector3 Position(float distance, float lx, float lcx, float ly, float lcy, float rx, float rcx, float ry, float rcy)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
float num = Math.Min((1f + lcx) / lx, (1f + rcx) / rx);
float num2 = Math.Min((1f - lcy) / ly, (1f - rcy) / ry);
if (!float.IsFinite(num) || !float.IsFinite(num2) || num <= 0f || num2 <= 0f)
{
return new Vector3(distance * 0.48f, (0f - distance) * 0.38f, distance);
}
return new Vector3(distance * Math.Min(num * 0.64f, 0.72f), (0f - distance) * Math.Min(num2 * 0.58f, 0.65f), distance);
}
}
internal readonly record struct CountdownReading(bool Visible, int Seconds, float Fraction)
{
internal static CountdownReading Read(bool enabled, WatchTimer timer)
{
if (!enabled || !timer.CountdownActive || timer.FreezeRemaining <= 0.0)
{
return default(CountdownReading);
}
double freezeRemaining = timer.FreezeRemaining;
return new CountdownReading(Visible: true, (int)Math.Ceiling(freezeRemaining), (float)Math.Clamp(freezeRemaining / timer.FreezeSeconds, 0.0, 1.0));
}
}
internal sealed class DisableGesture
{
private enum Phase
{
Neutral,
Ready,
Gathering,
Held
}
private Phase _phase;
private bool _leftDown;
private bool _rightDown;
private bool _firstTap;
private double? _neutralSince;
private double _pressStarted;
private double _firstReleased;
private double _last = double.NegativeInfinity;
public bool Tick(bool available, float leftTrigger, float rightTrigger, bool y, bool b, double now)
{
if (!available || !double.IsFinite(now) || !float.IsFinite(leftTrigger) || !float.IsFinite(rightTrigger))
{
Reset();
return false;
}
if (now < _last || (double.IsFinite(_last) && now - _last > 0.5))
{
Reset();
}
_last = now;
_leftDown = leftTrigger >= (_leftDown ? 0.55f : 0.8f);
_rightDown = rightTrigger >= (_rightDown ? 0.55f : 0.8f);
bool flag = leftTrigger < 0.55f && rightTrigger < 0.55f && !y && !b;
bool flag2 = _leftDown && _rightDown && y && b;
if (_firstTap && now - _firstReleased > 0.65)
{
_firstTap = false;
}
if (_phase == Phase.Neutral)
{
_neutralSince = (flag ? new double?(_neutralSince ?? now) : ((double?)null));
if (_neutralSince.HasValue && now - _neutralSince.Value >= 0.04)
{
_phase = Phase.Ready;
}
return false;
}
if (_phase == Phase.Ready)
{
if (!_leftDown && !_rightDown && !y && !b)
{
return false;
}
_pressStarted = now;
_phase = Phase.Gathering;
}
if (_phase == Phase.Gathering)
{
if (now - _pressStarted > 0.2 || flag)
{
CancelTap();
return false;
}
if (!flag2)
{
return false;
}
if (_firstTap)
{
Reset();
return true;
}
_phase = Phase.Held;
}
if (_phase == Phase.Held)
{
if (now - _pressStarted > 0.4)
{
CancelTap();
return false;
}
if (flag)
{
_firstTap = true;
_firstReleased = now;
_neutralSince = now;
_phase = Phase.Neutral;
}
}
return false;
}
private void CancelTap()
{
_phase = Phase.Neutral;
_firstTap = false;
_neutralSince = null;
}
public void Reset()
{
CancelTap();
_leftDown = (_rightDown = false);
_pressStarted = (_firstReleased = 0.0);
_last = double.NegativeInfinity;
}
}
internal static class EchoMeshSpace
{
internal static bool TryGetDrawMatrix(Renderer renderer, SkinnedMeshRenderer? skin, Mesh snapshot, out Matrix4x4 matrix)
{
//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_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: 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_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: 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_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: 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_01ab: 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);
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;
}
Bounds bounds = snapshot.bounds;
if (!Usable(bounds))
{
return false;
}
Vector3 extents = ((Bounds)(ref bounds)).extents;
Vector3 value = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(((Bounds)(ref bounds)).center);
Vector3 value2 = default(Vector3);
((Vector3)(ref value2))..ctor(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);
if (!Finite(value) || !Finite(value2))
{
return false;
}
return ((Vector3)(ref value2)).sqrMagnitude <= 10000f;
}
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 static class HeadsetView
{
internal static Camera? Camera()
{
//IL_0071: 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)
OpenControllerRig controllerRig = Player.ControllerRig;
Il2CppReferenceArray<Camera> val = ((controllerRig != null) ? controllerRig.cameras : null);
if (val != null)
{
for (int i = 0; i < ((Il2CppArrayBase<Camera>)(object)val).Length; i++)
{
if ((Object)(object)((Il2CppArrayBase<Camera>)(object)val)[i] != (Object)null && ((Behaviour)((Il2CppArrayBase<Camera>)(object)val)[i]).isActiveAndEnabled && (int)((Il2CppArrayBase<Camera>)(object)val)[i].stereoTargetEye != 0)
{
return ((Il2CppArrayBase<Camera>)(object)val)[i];
}
}
}
Camera main = Camera.main;
if (!((Object)(object)main != (Object)null) || !((Behaviour)main).isActiveAndEnabled || (int)main.stereoTargetEye == 0)
{
return null;
}
return main;
}
internal static int VisibleLayer(int mask)
{
if ((mask & 0x20) != 0)
{
return 5;
}
for (int i = 0; i < 32; i++)
{
if ((mask & (1 << i)) != 0)
{
return i;
}
}
return -1;
}
}
internal enum OutlineColor
{
Yellow,
White,
Cyan,
Green,
Blue,
Purple,
Pink,
Red
}
internal sealed class ModSettings
{
private MelonPreferences_Category _category;
private MelonPreferences_Entry<int> _freeze;
private MelonPreferences_Entry<int> _cooldown;
private MelonPreferences_Entry<int> _angle;
private MelonPreferences_Entry<float> _lookTime;
private MelonPreferences_Entry<OutlineColor> _color;
internal int FreezeSeconds
{
get
{
return Math.Clamp(_freeze.Value, 1, 120);
}
set
{
_freeze.Value = Math.Clamp(value, 1, 120);
Save();
}
}
internal int CooldownSeconds
{
get
{
return Math.Clamp(_cooldown.Value, 0, 120);
}
set
{
_cooldown.Value = Math.Clamp(value, 0, 120);
Save();
}
}
internal int ViewAngle
{
get
{
return Math.Clamp(_angle.Value, 20, 100);
}
set
{
_angle.Value = Math.Clamp(value, 20, 100);
Save();
}
}
internal float LookSeconds
{
get
{
return ClampLookTime(_lookTime.Value);
}
set
{
_lookTime.Value = ClampLookTime(value);
Save();
}
}
internal OutlineColor ColorChoice
{
get
{
if (!Enum.IsDefined(typeof(OutlineColor), _color.Value))
{
return OutlineColor.Yellow;
}
return _color.Value;
}
set
{
_color.Value = value;
Save();
}
}
internal Color Color => (Color)(ColorChoice switch
{
OutlineColor.White => new Color(1f, 1f, 1f),
OutlineColor.Cyan => new Color(0f, 1f, 1f),
OutlineColor.Green => new Color(0.2f, 1f, 0.15f),
OutlineColor.Blue => new Color(0.2f, 0.45f, 1f),
OutlineColor.Purple => new Color(0.65f, 0.25f, 1f),
OutlineColor.Pink => new Color(1f, 0.25f, 0.65f),
OutlineColor.Red => new Color(1f, 0.15f, 0.08f),
_ => new Color(1f, 0.9f, 0.02f),
});
private static float ClampLookTime(float value)
{
if (!float.IsFinite(value))
{
return 2.5f;
}
return Math.Clamp(value, 0f, 10f);
}
internal void Load()
{
_category = MelonPreferences.CreateCategory("MannequinMod");
_freeze = _category.CreateEntry<int>("FreezeSeconds", 20, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_cooldown = _category.CreateEntry<int>("CooldownSeconds", 20, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_angle = _category.CreateEntry<int>("ViewAngleDegrees", 60, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_lookTime = _category.CreateEntry<float>("LookSeconds", 2.5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
_color = _category.CreateEntry<OutlineColor>("OutlineColor", OutlineColor.Yellow, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
}
private void Save()
{
_category.SaveToFile(false);
}
}
internal enum ObserverMode
{
Players,
NPCs,
Both
}
internal sealed class NpcWatcherScanner
{
private sealed class Observer
{
internal AIBrain Brain;
internal bool Watching;
internal float NextCheck;
internal float LastCheck;
}
private readonly List<Observer> _npcs = new List<Observer>();
private readonly Dictionary<int, Observer> _previous = new Dictionary<int, Observer>();
private readonly SightQuery _sight = new SightQuery();
private int _cursor;
private float _nextRoster;
internal void Scan(float now, RigManager local, List<AIBrain> watchers)
{
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: Unknown result type (might be due to invalid IL or missing references)
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0302: Unknown result type (might be due to invalid IL or missing references)
//IL_0307: Unknown result type (might be due to invalid IL or missing references)
//IL_0311: Unknown result type (might be due to invalid IL or missing references)
//IL_0318: Unknown result type (might be due to invalid IL or missing references)
//IL_031d: Unknown result type (might be due to invalid IL or missing references)
if (now >= _nextRoster)
{
_nextRoster = now + 2f;
_previous.Clear();
foreach (Observer npc in _npcs)
{
if ((Object)(object)npc.Brain != (Object)null)
{
_previous[((Object)npc.Brain).GetInstanceID()] = npc;
}
}
_npcs.Clear();
foreach (AIBrain item in Object.FindObjectsOfType<AIBrain>())
{
if (Alive(item))
{
_npcs.Add(_previous.TryGetValue(((Object)item).GetInstanceID(), out Observer value) ? value : new Observer
{
Brain = item
});
}
}
_previous.Clear();
}
Vector3 position = ((Rig)local.physicsRig).m_head.position;
Vector3 position2 = ((Rig)local.physicsRig).m_pelvis.position;
Vector3 point = Vector3.Lerp(position, position2, 0.55f);
int num = 0;
for (int i = 0; i < _npcs.Count; i++)
{
if (num >= 4)
{
break;
}
if (_cursor >= _npcs.Count)
{
_cursor = 0;
}
Observer observer = _npcs[_cursor++];
if (!(now < observer.NextCheck))
{
num++;
observer.NextCheck = now + 0.05f;
observer.LastCheck = now;
observer.Watching = false;
AIBrain brain = observer.Brain;
if (Alive(brain))
{
Transform eyeTran = brain.behaviour.eyeTran;
Transform transform = ((Component)brain.puppetMaster).transform;
Transform targetRoot = brain.puppetMaster.targetRoot;
observer.Watching = _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, position, targetRoot) || _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, point, targetRoot) || _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, position2, targetRoot);
}
}
}
watchers.Clear();
foreach (Observer npc2 in _npcs)
{
if (!npc2.Watching || now < npc2.LastCheck || now - npc2.LastCheck > 0.35f || !Alive(npc2.Brain))
{
npc2.Watching = false;
continue;
}
Transform eyeTran2 = npc2.Brain.behaviour.eyeTran;
if (!SightQuery.InCone(eyeTran2.position, eyeTran2.forward, position) && !SightQuery.InCone(eyeTran2.position, eyeTran2.forward, point) && !SightQuery.InCone(eyeTran2.position, eyeTran2.forward, position2))
{
npc2.Watching = false;
}
else
{
watchers.Add(npc2.Brain);
}
}
}
private static bool Alive(AIBrain? brain)
{
if ((Object)(object)brain != (Object)null && ((Component)brain).gameObject.activeInHierarchy && !brain.isDead && (Object)(object)brain.puppetMaster != (Object)null && brain.puppetMaster.isAlive && (Object)(object)brain.behaviour != (Object)null)
{
return (Object)(object)brain.behaviour.eyeTran != (Object)null;
}
return false;
}
internal void Clear()
{
_npcs.Clear();
_previous.Clear();
_cursor = 0;
_nextRoster = 0f;
}
}
internal static class PlayerGaze
{
private sealed class Receipt
{
internal double At;
}
private static readonly ConditionalWeakTable<NetworkPlayer, Receipt> Receipts = new ConditionalWeakTable<NetworkPlayer, Receipt>();
internal static void OnReceivePose(NetworkPlayer __instance)
{
Received(__instance, Time.realtimeSinceStartupAsDouble);
}
internal static void Received(NetworkPlayer player, double now)
{
Receipts.GetValue(player, (NetworkPlayer _) => new Receipt()).At = now;
}
internal static bool TryRead(NetworkPlayer player, double now, out Vector3 eye, out Vector3 forward)
{
//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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: 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_00d1: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: 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)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: 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_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
eye = (forward = Vector3.zero);
if (!Receipts.TryGetValue(player, out Receipt value) || !double.IsFinite(now) || !double.IsFinite(value.At) || now < value.At || now - value.At > 0.35)
{
return false;
}
RigPose rigPose = player.RigPose;
RigRefs rigRefs = player.RigRefs;
Transform val = ((rigRefs != null) ? rigRefs.Headset : null);
if (!player.ReceivedPose || rigPose == null || (Object)(object)val == (Object)null || rigPose.TrackedPoints == null || rigPose.TrackedPoints.Length < 1 || rigPose.TrackedPoints[0] == null)
{
return false;
}
SerializedLocalTransform val2 = rigPose.TrackedPoints[0];
Transform parent = val.parent;
eye = (((Object)(object)parent != (Object)null) ? parent.TransformPoint(val2.position) : val2.position);
Quaternion val3 = (((Object)(object)parent != (Object)null) ? parent.rotation : Quaternion.identity);
Transform val4 = player.RigSkeleton?.TrackedPlayspace;
if ((Object)(object)val4 != (Object)null)
{
val3 = rigPose.TrackedPlayspaceExpanded * Quaternion.Inverse(val4.rotation) * val3;
}
forward = val3 * val2.rotation * Vector3.forward;
return true;
}
}
internal sealed class PlayerSilhouetteRenderer : IDisposable
{
private sealed class CachedMesh
{
internal Renderer Renderer;
internal Mesh Source;
internal Mesh Mesh;
internal Transform AvatarRoot;
internal Transform? RootBone;
internal Vector3 BakedScale;
internal bool HasSnapshot;
internal int Vertices;
internal Il2CppStructArray<Color>? White;
internal float NextBake;
internal float LastSeen;
internal float ScanTime = float.NegativeInfinity;
internal Matrix4x4 ScanMatrix;
internal bool HasScanMatrix;
}
private const int MaxMeshVertices = 120000;
private const int MaxCachedVertices = 1000000;
private readonly Dictionary<int, CachedMesh> _meshes = new Dictionary<int, CachedMesh>();
private readonly List<int> _expired = new List<int>();
private readonly Action<string> _warning;
private Material? _material;
private MaterialPropertyBlock? _block;
private Mesh? _voiceMarker;
private int _bakes;
private int _draws;
private int _attempts;
private int _bakeVertices;
private int _cachedVertices;
private float _now;
private float _nextAttempt;
private float _nextCleanup;
private float _nextWarning;
private bool _disposed;
internal bool Ready
{
get
{
if (!_disposed)
{
return (Object)(object)_material != (Object)null;
}
return false;
}
}
internal PlayerSilhouetteRenderer(Action<string> warning)
{
_warning = warning;
}
internal void BeginFrame(float now)
{
_now = now;
_bakes = 1;
_draws = 96;
_bakeVertices = 120000;
if (_disposed)
{
return;
}
EnsureMaterial();
if (now < _nextCleanup)
{
return;
}
_nextCleanup = now + 0.5f;
_expired.Clear();
foreach (KeyValuePair<int, CachedMesh> mesh in _meshes)
{
if ((Object)(object)mesh.Value.Renderer == (Object)null || now - mesh.Value.LastSeen > 12f)
{
_expired.Add(mesh.Key);
}
}
foreach (int item in _expired)
{
Remove(item);
}
}
internal void Draw(float now, SilhouetteTarget target, bool visible, float alpha, int layer, Color color, bool forceRed = false, float scanTime = float.NaN, float voiceGlow = 0f)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: 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_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: 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_01c1: 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)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_032e: Unknown result type (might be due to invalid IL or missing references)
//IL_0333: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Expected O, but got Unknown
//IL_04df: Unknown result type (might be due to invalid IL or missing references)
//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
//IL_055c: Unknown result type (might be due to invalid IL or missing references)
//IL_055e: Unknown result type (might be due to invalid IL or missing references)
//IL_0505: Unknown result type (might be due to invalid IL or missing references)
//IL_050a: Unknown result type (might be due to invalid IL or missing references)
//IL_047a: Unknown result type (might be due to invalid IL or missing references)
//IL_047c: Unknown result type (might be due to invalid IL or missing references)
//IL_044f: Unknown result type (might be due to invalid IL or missing references)
//IL_058c: Unknown result type (might be due to invalid IL or missing references)
if (_disposed || (Object)(object)_material == (Object)null || !target.Alive || alpha < 0.01f)
{
return;
}
Color val = color;
if (voiceGlow > 0f)
{
float num = Mathf.Clamp01(voiceGlow);
val = Color.Lerp(val, new Color(1f, 1f, 0.95f, alpha), num * 0.6f);
}
_block.Clear();
_block.SetColor("_Color", val);
int num2 = Math.Min(target.Renderers.Length, 8);
int num3 = 0;
int num4 = 64;
int num5 = ((num2 > 0) ? (target.NextMesh % num2) : 0);
for (int i = 0; i < num2; i++)
{
if (num4 <= 0)
{
break;
}
if (_draws <= 0)
{
break;
}
int num6 = (num5 + i) % num2;
Renderer val2 = target.Renderers[num6];
try
{
if ((Object)(object)val2 == (Object)null || !val2.enabled || !((Component)val2).gameObject.activeInHierarchy || ((Object)(object)((Component)val2).transform != (Object)(object)target.AvatarRoot && !((Component)val2).transform.IsChildOf(target.AvatarRoot)))
{
continue;
}
SkinnedMeshRenderer val3 = ((Il2CppObjectBase)val2).TryCast<SkinnedMeshRenderer>();
object obj;
if (!((Object)(object)val3 != (Object)null))
{
MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
obj = ((component != null) ? component.sharedMesh : null);
}
else
{
obj = val3.sharedMesh;
}
Mesh val4 = (Mesh)obj;
if ((Object)(object)val4 == (Object)null || val4.vertexCount == 0 || val4.vertexCount > 120000)
{
continue;
}
int vertexCount = val4.vertexCount;
int instanceID = ((Object)val2).GetInstanceID();
Transform val5 = (((Object)(object)val3 != (Object)null) ? val3.rootBone : null);
Vector3 val6 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform.lossyScale : Vector3.one);
if (!EchoMeshSpace.SameScale(val6, val6))
{
continue;
}
if (_meshes.TryGetValue(instanceID, out CachedMesh value) && ((Object)(object)value.Renderer != (Object)(object)val2 || (Object)(object)value.Source != (Object)(object)val4 || (Object)(object)value.AvatarRoot != (Object)(object)target.AvatarRoot || (Object)(object)value.RootBone != (Object)(object)val5 || value.Vertices != vertexCount))
{
Remove(instanceID);
value = null;
}
if (value != null)
{
goto IL_02f4;
}
if (_bakes <= 0 || vertexCount > _bakeVertices)
{
continue;
}
while (_meshes.Count >= 128 || _cachedVertices + vertexCount > 1000000)
{
EvictOldest();
}
value = new CachedMesh
{
Renderer = val2,
Source = val4,
AvatarRoot = target.AvatarRoot,
RootBone = val5,
Vertices = vertexCount,
Mesh = new Mesh
{
name = "CoilHead.WatcherSilhouette",
hideFlags = (HideFlags)61
}
};
_meshes[instanceID] = value;
_cachedVertices += vertexCount;
goto IL_02f4;
IL_02f4:
value.LastSeen = now;
bool flag = float.IsFinite(scanTime);
bool flag2 = flag && scanTime > value.ScanTime;
bool flag3 = (Object)(object)val3 != (Object)null && value.HasSnapshot && !EchoMeshSpace.SameScale(value.BakedScale, val6);
if ((!flag || flag2) && (now >= value.NextBake || flag3) && _bakes > 0 && vertexCount <= _bakeVertices)
{
_bakes--;
_bakeVertices -= vertexCount;
target.NextMesh = (num6 + 1) % num2;
value.HasSnapshot = false;
value.NextBake = now + 0.2f;
if ((Object)(object)val3 != (Object)null)
{
val3.BakeMesh(value.Mesh, true);
}
else
{
Object.Destroy((Object)(object)value.Mesh);
value.Mesh = Object.Instantiate<Mesh>(val4);
((Object)value.Mesh).hideFlags = (HideFlags)61;
}
value.Mesh.RecalculateBounds();
int vertexCount2 = value.Mesh.vertexCount;
if (value.White == null || ((Il2CppArrayBase<Color>)(object)value.White).Length != vertexCount2)
{
value.White = new Il2CppStructArray<Color>((long)vertexCount2);
for (int j = 0; j < vertexCount2; j++)
{
((Il2CppArrayBase<Color>)(object)value.White)[j] = Color.white;
}
}
value.Mesh.SetColors(value.White);
value.BakedScale = val6;
value.HasSnapshot = true;
value.NextBake = (((Object)(object)val3 != (Object)null) ? (now + ((vertexCount > 120000) ? 0.35f : 0.2f)) : float.PositiveInfinity);
}
Matrix4x4 matrix;
if (value.HasSnapshot && value.Mesh.vertexCount != 0 && (flag || !((Object)(object)val3 != (Object)null) || EchoMeshSpace.SameScale(value.BakedScale, val6)))
{
if (flag && !flag2 && value.HasScanMatrix)
{
matrix = value.ScanMatrix;
goto IL_054d;
}
if (EchoMeshSpace.TryGetDrawMatrix(val2, val3, value.Mesh, out matrix))
{
goto IL_054d;
}
if (now >= _nextWarning)
{
_nextWarning = now + 10f;
_warning("Skipped an invalid or oversized watcher mesh snapshot.");
}
}
goto end_IL_00d2;
IL_054d:
if (flag2)
{
value.ScanTime = scanTime;
value.ScanMatrix = matrix;
value.HasScanMatrix = true;
}
int draws = _draws;
for (int k = 0; k < value.Mesh.subMeshCount; k++)
{
if (num4 <= 0)
{
break;
}
if (_draws <= 0)
{
break;
}
Graphics.DrawMesh(value.Mesh, matrix, _material, layer, (Camera)null, k, _block, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null);
_draws--;
num4--;
}
if (_draws < draws)
{
num3++;
}
end_IL_00d2:;
}
catch (Exception ex)
{
if (now >= _nextWarning)
{
_nextWarning = now + 10f;
_warning("Player echo mesh: " + ex.Message);
}
}
}
}
private void EnsureMaterial()
{
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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_00a8: Expected O, but got Unknown
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Expected O, but got Unknown
if ((Object)(object)_material != (Object)null || _now < _nextAttempt)
{
return;
}
_attempts++;
_nextAttempt = _now + ((_attempts >= 6) ? 10f : 2f);
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 = 5000
};
if (text == "Hidden/Internal-Colored" && (!val2.HasProperty("_ZTest") || !val2.HasProperty("_ZWrite")))
{
Object.Destroy((Object)(object)val2);
continue;
}
if (val2.HasProperty("_Color"))
{
val2.SetColor("_Color", Color.white);
}
if (val2.HasProperty("_MainTex"))
{
val2.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
}
Set(val2, "_ZTest", 8);
Set(val2, "_ZWrite", 0);
Set(val2, "_Cull", 0);
Set(val2, "_SrcBlend", 5);
Set(val2, "_DstBlend", 10);
_material = val2;
_block = new MaterialPropertyBlock();
return;
}
if (_attempts == 1 || _attempts == 6)
{
_warning("Player echo highlight shader unavailable.");
}
}
private void EvictOldest()
{
int key = 0;
float num = float.PositiveInfinity;
foreach (KeyValuePair<int, CachedMesh> mesh in _meshes)
{
if (mesh.Value.LastSeen < num)
{
num = mesh.Value.LastSeen;
key = mesh.Key;
}
}
Remove(key);
}
private void Remove(int key)
{
if (_meshes.TryGetValue(key, out CachedMesh value))
{
if ((Object)(object)value.Mesh != (Object)null)
{
Object.Destroy((Object)(object)value.Mesh);
}
_cachedVertices -= value.Vertices;
_meshes.Remove(key);
}
}
internal void Reset()
{
foreach (CachedMesh value in _meshes.Values)
{
if ((Object)(object)value.Mesh != (Object)null)
{
Object.Destroy((Object)(object)value.Mesh);
}
}
_meshes.Clear();
_cachedVertices = 0;
_attempts = 0;
_nextAttempt = 0f;
_nextCleanup = 0f;
if ((Object)(object)_voiceMarker != (Object)null)
{
Object.Destroy((Object)(object)_voiceMarker);
}
_voiceMarker = null;
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Reset();
if ((Object)(object)_material != (Object)null)
{
Object.Destroy((Object)(object)_material);
}
_material = null;
_block = null;
}
}
private static void Set(Material material, string name, int value)
{
if (material.HasProperty(name))
{
material.SetInt(name, value);
}
}
}
internal sealed class PoseLock
{
private record struct Body(Rigidbody Value, Vector3 Position, Quaternion Rotation);
private record struct Bone(Transform Value, Vector3 Position, Quaternion Rotation, Vector3 LocalPosition, Quaternion LocalRotation);
private readonly List<Body> _historyBodies = new List<Body>();
private readonly List<Body> _bodies = new List<Body>();
private readonly List<Bone> _historyBones = new List<Bone>();
private readonly List<Bone> _bones = new List<Bone>();
private readonly HashSet<int> _bodyIds = new HashSet<int>();
private readonly Func<double> _clock;
private readonly Action<string>? _warning;
private readonly bool _localOwner;
private double _started;
private double _leaseUntil;
private double _hardDeadline;
private double _historyTime = double.NegativeInfinity;
private RigManager? _rig;
private Action? _lateCallback;
private UnityAction? _renderCallback;
private RigSkeleton? _skeleton;
private RigPose? _historyPose;
private RigPose? _networkPose;
internal static PoseLock? Current { get; private set; }
public bool Active { get; private set; }
internal PoseLock(Func<double>? clock = null, Action<string>? warning = null, bool localOwner = true)
{
_clock = clock ?? ((Func<double>)(() => Time.realtimeSinceStartupAsDouble));
_warning = warning;
_localOwner = localOwner;
}
internal void Track(RigManager rig)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected O, but got Unknown
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Expected O, but got Unknown
if ((Object)(object)_rig == (Object)(object)rig)
{
return;
}
StopTracking();
_rig = rig;
try
{
_bodyIds.Clear();
Enumerator<Rigidbody> enumerator = rig.physicsRig.selfRbs.GetEnumerator();
while (enumerator.MoveNext())
{
Rigidbody current = enumerator.Current;
AddBody(current);
}
AddBody(rig.physicsRig.rbFeet);
AddBody(rig.physicsRig.rbKnee);
foreach (Transform componentsInChild in ((Component)rig.avatar).GetComponentsInChildren<Transform>(true))
{
if ((Object)(object)componentsInChild != (Object)null)
{
_historyBones.Add(ReadBone(componentsInChild));
}
}
if (_localOwner)
{
_skeleton = new RigSkeleton(rig);
_historyPose = new RigPose();
}
_lateCallback = Action.op_Implicit((Action)AfterRigLateUpdate);
_renderCallback = UnityAction.op_Implicit((Action)BeforeRender);
rig.OnPostLateUpdate += _lateCallback;
Application.onBeforeRender += _renderCallback;
Record();
}
catch
{
StopTracking();
throw;
}
}
private void AddBody(Rigidbody? rb)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)rb != (Object)null && _bodyIds.Add(((Object)rb).GetInstanceID()))
{
_historyBodies.Add(new Body(rb, rb.position, rb.rotation));
}
}
private static Bone ReadBone(Transform bone)
{
//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_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
return new Bone(bone, bone.position, bone.rotation, bone.localPosition, bone.localRotation);
}
private void Record()
{
//IL_0042: 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)
if (Active || (Object)(object)_rig == (Object)null)
{
return;
}
for (int i = 0; i < _historyBodies.Count; i++)
{
Rigidbody value = _historyBodies[i].Value;
if ((Object)(object)value != (Object)null)
{
_historyBodies[i] = new Body(value, value.position, value.rotation);
}
}
for (int j = 0; j < _historyBones.Count; j++)
{
if ((Object)(object)_historyBones[j].Value != (Object)null)
{
_historyBones[j] = ReadBone(_historyBones[j].Value);
}
}
if (_localOwner)
{
_historyPose.ReadSkeleton(_skeleton);
}
_historyTime = _clock();
}
public void Capture(RigManager rig, double duration = 20.0)
{
//IL_004e: 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)
//IL_0067: 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_0130: 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_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: 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_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: 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_0167: Unknown result type (might be due to invalid IL or missing references)
if (Active)
{
return;
}
Release();
Track(rig);
double num = _clock();
if (!double.IsFinite(num))
{
return;
}
try
{
Vector3 val;
int num2;
if (_historyBodies.Count > 0)
{
val = _historyBodies[0].Value.position - _historyBodies[0].Position;
num2 = ((((Vector3)(ref val)).sqrMagnitude > 4f) ? 1 : 0);
}
else
{
num2 = 0;
}
bool flag = (byte)num2 != 0;
if (num < _historyTime || num - _historyTime > 0.2 || flag)
{
Record();
}
foreach (Body historyBody in _historyBodies)
{
if ((Object)(object)historyBody.Value != (Object)null)
{
_bodies.Add(historyBody);
}
}
_bones.AddRange(_historyBones);
_networkPose = _historyPose;
if (_networkPose != null)
{
val = (_networkPose.PelvisPose.Velocity = (_networkPose.PelvisPose.AngularVelocity = Vector3.zero));
_networkPose.LeftController.ThumbstickAxis = Vector2.zero;
_networkPose.RightController.ThumbstickAxis = Vector2.zero;
}
_started = num;
_hardDeadline = num + Math.Clamp(double.IsFinite(duration) ? duration : 20.0, 1.0, 120.0);
_leaseUntil = num + 0.35;
Active = true;
if (_localOwner)
{
Current = this;
}
HoldVisual();
}
catch
{
Release();
throw;
}
}
public void Renew()
{
double num = _clock();
if (Active)
{
if (!double.IsFinite(num) || num < _started || num >= _hardDeadline)
{
Release();
}
else
{
_leaseUntil = Math.Min(num + 0.35, _hardDeadline);
}
}
}
private bool CanHold()
{
if (!Active)
{
return false;
}
double num = _clock();
if (!double.IsFinite(num) || num < _started || num >= _leaseUntil || num >= _hardDeadline)
{
Release();
return false;
}
return true;
}
public void Hold()
{
//IL_006a: 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_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: 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_0057: Unknown result type (might be due to invalid IL or missing references)
if (!CanHold())
{
return;
}
foreach (Body body in _bodies)
{
if (!((Object)(object)body.Value == (Object)null))
{
if (!body.Value.isKinematic)
{
body.Value.velocity = Vector3.zero;
body.Value.angularVelocity = Vector3.zero;
}
body.Value.position = body.Position;
body.Value.rotation = body.Rotation;
((Component)body.Value).transform.SetPositionAndRotation(body.Position, body.Rotation);
}
}
}
public void HoldVisual()
{
//IL_0046: 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)
if (!CanHold())
{
return;
}
Hold();
if (!Active)
{
return;
}
foreach (Bone bone in _bones)
{
if ((Object)(object)bone.Value != (Object)null)
{
bone.Value.SetPositionAndRotation(bone.Position, bone.Rotation);
}
}
}
public void Release()
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: 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_00f4: 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)
bool active = Active;
Active = false;
if (Current == this)
{
Current = null;
}
_networkPose = null;
_leaseUntil = (_hardDeadline = 0.0);
int num = 0;
foreach (Bone bone in _bones)
{
try
{
if ((Object)(object)bone.Value != (Object)null)
{
bone.Value.localPosition = bone.LocalPosition;
bone.Value.localRotation = bone.LocalRotation;
}
}
catch
{
num++;
}
}
foreach (Body body in _bodies)
{
try
{
if ((Object)(object)body.Value != (Object)null && !body.Value.isKinematic)
{
Rigidbody value = body.Value;
Vector3 velocity = (body.Value.angularVelocity = Vector3.zero);
value.velocity = velocity;
body.Value.WakeUp();
}
}
catch
{
num++;
}
}
_bodies.Clear();
_bones.Clear();
if (active)
{
_historyTime = double.NegativeInfinity;
}
if (active && num > 0)
{
Warn($"Mannequin released; {num} unavailable rig parts skipped. No native movement locks were set.");
}
}
internal void StopTracking()
{
Release();
try
{
if ((Object)(object)_rig != (Object)null && (Delegate)(object)_lateCallback != (Delegate)null)
{
RigManager? rig = _rig;
rig.OnPostLateUpdate -= _lateCallback;
}
}
catch (Exception ex)
{
Warn("Mannequin late callback cleanup: " + ex.Message);
}
try
{
if ((Delegate)(object)_renderCallback != (Delegate)null)
{
Application.onBeforeRender -= _renderCallback;
}
}
catch (Exception ex2)
{
Warn("Mannequin render callback cleanup: " + ex2.Message);
}
_lateCallback = null;
_renderCallback = null;
_rig = null;
_historyPose = null;
_skeleton = null;
_historyBodies.Clear();
_historyBones.Clear();
_historyTime = double.NegativeInfinity;
}
private void Warn(string message)
{
try
{
_warning?.Invoke(message);
}
catch
{
}
}
private void AfterRigLateUpdate()
{
try
{
if (!((Object)(object)_rig == (Object)null))
{
if (CanHold())
{
HoldVisual();
return;
}
Release();
Record();
}
}
catch (Exception ex)
{
Release();
Warn(ex.Message);
}
}
private void BeforeRender()
{
try
{
HoldVisual();
}
catch (Exception ex)
{
Release();
Warn(ex.Message);
}
}
internal static void AfterReadSkeleton(RigPose __instance, RigSkeleton skeleton)
{
PoseLock current = Current;
if (current != null && current.CanHold() && !((Object)(object)current._rig == (Object)null) && current._networkPose != null && !((Object)(object)((Component)skeleton.PhysicsPelvis).transform != (Object)(object)((Rig)current._rig.physicsRig).m_pelvis))
{
RigPose networkPose = current._networkPose;
for (int i = 1; i < 3; i++)
{
__instance.TrackedPoints[i] = networkPose.TrackedPoints[i];
}
networkPose.PelvisPose.CopyTo(__instance.PelvisPose);
__instance.LeftController = networkPose.LeftController;
__instance.RightController = networkPose.RightController;
__instance.CrouchTarget = networkPose.CrouchTarget;
__instance.FeetOffset = networkPose.FeetOffset;
}
}
}
internal sealed class RemoteFreeze
{
private sealed class Peer
{
internal readonly RemoteFreezeLease Lease = new RemoteFreezeLease();
internal readonly PoseLock Pose = new PoseLock(null, delegate(string message)
{
MelonLogger.Warning(message);
}, localOwner: false);
internal RigManager Rig;
internal Transform Avatar;
internal bool Warned;
}
private const string Key = "MannequinMod.Pose.v1";
private readonly Dictionary<NetworkPlayer, Peer> _peers = new Dictionary<NetworkPlayer, Peer>();
private readonly HashSet<NetworkPlayer> _seen = new HashSet<NetworkPlayer>();
private readonly List<NetworkPlayer> _remove = new List<NetworkPlayer>();
private string _token = "";
private string _sent = "";
private long _sequence;
private bool _wasFrozen;
private double _nextSend;
internal void Publish(bool enabled, bool frozen, int duration = 20)
{
PlayerMetadata metadata = LocalPlayer.Metadata;
NetworkMetadata val = ((metadata != null) ? metadata.Metadata : null);
if (val == null)
{
return;
}
double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
if (!enabled || !NetworkInfo.HasServer)
{
if (_sent.Length != 0 && val.TryRemoveMetadata("MannequinMod.Pose.v1"))
{
_sent = "";
}
_wasFrozen = false;
return;
}
if (frozen && !_wasFrozen)
{
_token = Guid.NewGuid().ToString("N");
_sequence = 0L;
_nextSend = 0.0;
}
if (!frozen || !_wasFrozen || !(realtimeSinceStartupAsDouble < _nextSend))
{
string text = (frozen ? $"F|{_token}|{++_sequence}|{Math.Clamp(duration, 1, 120)}" : "R");
if (text != _sent && val.TrySetMetadata("MannequinMod.Pose.v1", text))
{
_sent = text;
_nextSend = realtimeSinceStartupAsDouble + 0.4;
}
_wasFrozen = frozen;
}
}
internal void Update(RigManager? localRig = null)
{
if (!NetworkInfo.HasServer)
{
ResetPeers();
return;
}
_seen.Clear();
double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
string text = default(string);
foreach (NetworkPlayer player in NetworkPlayer.Players)
{
try
{
if (player.PlayerID == null || player.PlayerID.IsMe || !player.PlayerID.IsValid || !player.HasRig || player.ForceHide)
{
continue;
}
RigRefs rigRefs = player.RigRefs;
RigManager val = ((rigRefs != null) ? rigRefs.RigManager : null);
if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)localRig || (Object)(object)val.avatar == (Object)null || ((Object)(object)val.health != (Object)null && val.health.curr_Health <= 0f))
{
continue;
}
PlayerMetadata metadata = player.PlayerID.Metadata;
NetworkMetadata val2 = ((metadata != null) ? metadata.Metadata : null);
_seen.Add(player);
if (val2 == null || !val2.TryGetMetadata("MannequinMod.Pose.v1", ref text) || (text != "R" && !text.StartsWith("F|", StringComparison.Ordinal)))
{
if (_peers.TryGetValue(player, out Peer value))
{
value.Lease.Observe(null, realtimeSinceStartupAsDouble);
value.Pose.StopTracking();
}
continue;
}
if (!_peers.TryGetValue(player, out Peer value2))
{
value2 = (_peers[player] = new Peer());
}
Transform transform = ((Component)val.avatar).transform;
if ((Object)(object)value2.Rig != (Object)(object)val || (Object)(object)value2.Avatar != (Object)(object)transform)
{
if ((Object)(object)value2.Rig != (Object)null)
{
value2.Lease.Observe(null, realtimeSinceStartupAsDouble);
}
value2.Pose.StopTracking();
value2.Rig = val;
value2.Avatar = transform;
}
value2.Pose.Track(val);
if (value2.Lease.Observe(text, realtimeSinceStartupAsDouble))
{
if (!value2.Pose.Active)
{
value2.Pose.Capture(val, value2.Lease.Duration);
}
value2.Pose.Renew();
}
else
{
value2.Pose.Release();
}
}
catch (Exception ex)
{
if (_peers.TryGetValue(player, out Peer value3))
{
value3.Lease.Observe(null, realtimeSinceStartupAsDouble);
value3.Pose.StopTracking();
if (!value3.Warned)
{
value3.Warned = true;
MelonLogger.Warning("Mannequin remote pose released: " + ex.Message);
}
}
}
}
_remove.Clear();
foreach (KeyValuePair<NetworkPlayer, Peer> peer2 in _peers)
{
if (!_seen.Contains(peer2.Key))
{
_remove.Add(peer2.Key);
}
}
foreach (NetworkPlayer item in _remove)
{
Retire(_peers[item].Pose);
_peers.Remove(item);
}
}
private void Retire(PoseLock pose)
{
pose.StopTracking();
}
internal void HoldFixed()
{
foreach (Peer value in _peers.Values)
{
try
{
value.Pose.Hold();
}
catch
{
value.Lease.Observe(null, Time.realtimeSinceStartupAsDouble);
value.Pose.Release();
}
}
}
internal void ResetPeers()
{
foreach (Peer value in _peers.Values)
{
Retire(value.Pose);
}
_peers.Clear();
}
}
internal sealed class RemoteFreezeLease
{
private string _token = "";
private long _sequence = -1L;
private double _lastHeartbeat;
private double _deadline;
private bool _expired;
private string? _wire;
internal int Duration { get; private set; } = 20;
internal bool Observe(string? value, double now)
{
if (!double.IsFinite(now) || value == null || value.Length > 90 || !value.StartsWith("F|", StringComparison.Ordinal))
{
_expired = true;
return false;
}
if (value == _wire)
{
if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
{
_expired = true;
}
return !_expired;
}
string[] array = value.Split('|');
int result = 20;
if ((array.Length != 3 && array.Length != 4) || !Guid.TryParseExact(array[1], "N", out var _) || !long.TryParse(array[2], out var result3) || result3 < 0 || (array.Length == 4 && (!int.TryParse(array[3], out result) || result < 1 || result > 120)))
{
_expired = true;
return false;
}
_wire = value;
if (array[1] != _token)
{
_token = array[1];
_sequence = result3;
_lastHeartbeat = now;
Duration = result;
_deadline = now + (double)result;
_expired = false;
}
else
{
if (result != Duration)
{
_expired = true;
}
if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
{
_expired = true;
}
if (!_expired && result3 > _sequence)
{
_sequence = result3;
_lastHeartbeat = now;
}
}
if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
{
_expired = true;
}
return !_expired;
}
}
internal sealed class SightQuery
{
private readonly Il2CppStructArray<RaycastHit> _hits = new Il2CppStructArray<RaycastHit>(64L);
private static int _viewAngle = 60;
private static float _cosine = 0.8660254f;
internal static int ViewAngle
{
get
{
return _viewAngle;
}
set
{
_viewAngle = Math.Clamp(value, 20, 100);
_cosine = (float)Math.Cos((double)_viewAngle * Math.PI / 360.0);
}
}
internal static bool InCone(Vector3 eye, Vector3 forward, Vector3 point)
{
//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_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_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = point - eye;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
float sqrMagnitude2 = ((Vector3)(ref forward)).sqrMagnitude;
if (float.IsFinite(sqrMagnitude) && float.IsFinite(sqrMagnitude2) && sqrMagnitude2 > 1E-06f && sqrMagnitude >= 1E-06f && sqrMagnitude <= 10000f)
{
return Vector3.Dot(forward / Mathf.Sqrt(sqrMagnitude2), val / Mathf.Sqrt(sqrMagnitude)) >= _cosine;
}
return false;
}
internal bool Visible(Vector3 eye, Vector3 forward, Transform observer, Transform target, Vector3 point, Transform? otherObserverRoot = null)
{
//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_0002: 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_000f: 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_0015: 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_0024: 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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (!InCone(eye, forward, point))
{
return false;
}
Vector3 val = point - eye;
float num = Mathf.Sqrt(((Vector3)(ref val)).sqrMagnitude);
int num2 = Physics.RaycastNonAlloc(eye, val / num, _hits, num, -1, (QueryTriggerInteraction)1);
if (num2 >= ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length)
{
return false;
}
for (int i = 0; i < num2; i++)
{
RaycastHit val2 = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i];
Collider collider = ((RaycastHit)(ref val2)).collider;
if (!((Object)(object)collider == (Object)null))
{
Transform transform = ((Component)collider).transform;
if (!Within(transform, observer) && !Within(transform, target) && !Within(transform, otherObserverRoot))
{
return false;
}
}
}
return true;
}
private static bool Within(Transform t, Transform? root)
{
if ((Object)(object)root != (Object)null)
{
if (!((Object)(object)t == (Object)(object)root))
{
return t.IsChildOf(root);
}
return true;
}
return false;
}
}
internal sealed class SilhouetteTarget
{
internal Transform Root;
internal Transform AvatarRoot;
internal Renderer[] Renderers = Array.Empty<Renderer>();
internal int NextMesh;
internal float NextRefresh;
internal float LastSeen;
internal bool Alive
{
get
{
if ((Object)(object)Root != (Object)null && (Object)(object)AvatarRoot != (Object)null)
{
return ((Component)Root).gameObject.activeInHierarchy;
}
return false;
}
}
}
internal sealed class WatcherOutline : IDisposable
{
private readonly PlayerSilhouetteRenderer _renderer = new PlayerSilhouetteRenderer(delegate(string message)
{
MelonLogger.Warning(message);
});
private readonly Dictionary<int, SilhouetteTarget> _targets = new Dictionary<int, SilhouetteTarget>();
private readonly List<int> _expired = new List<int>();
private readonly List<Renderer> _candidates = new List<Renderer>();
private float _nextCleanup;
private int _start;
public void Draw(List<NetworkPlayer> watchers, List<AIBrain> npcs, Transform? eye, Color color)
{
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
int num = watchers.Count + npcs.Count;
if ((Object)(object)eye == (Object)null || num == 0)
{
return;
}
Camera val = HeadsetView.Camera();
if ((Object)(object)val == (Object)null)
{
return;
}
int num2 = HeadsetView.VisibleLayer(val.cullingMask);
if (num2 < 0)
{
return;
}
float unscaledTime = Time.unscaledTime;
_renderer.BeginFrame(unscaledTime);
int num3 = 1;
if (_start >= num)
{
_start = 0;
}
int num4 = _start++;
for (int i = 0; i < num; i++)
{
int num5 = (num4 + i) % num;
Transform transform;
Transform val3;
if (num5 < watchers.Count)
{
NetworkPlayer val2 = watchers[num5];
if (!val2.HasRig)
{
continue;
}
RigRefs rigRefs = val2.RigRefs;
if ((Object)(object)((rigRefs != null) ? rigRefs.RigManager : null) == (Object)null)
{
continue;
}
RigManager rigManager = val2.RigRefs.RigManager;
if ((Object)(object)rigManager.avatar == (Object)null)
{
continue;
}
transform = ((Component)rigManager).transform;
val3 = ((Component)rigManager.avatar).transform;
}
else
{
AIBrain val4 = npcs[num5 - watchers.Count];
if ((Object)(object)val4 == (Object)null || val4.isDead || (Object)(object)val4.puppetMaster == (Object)null)
{
continue;
}
transform = ((Component)val4.puppetMaster).transform;
val3 = val4.puppetMaster.targetRoot;
if ((Object)(object)val3 == (Object)null)
{
continue;
}
}
int instanceID = ((Object)val3).GetInstanceID();
if (!_targets.TryGetValue(instanceID, out SilhouetteTarget value) || (Object)(object)value.AvatarRoot != (Object)(object)val3)
{
if (num3 == 0)
{
continue;
}
value = new SilhouetteTarget
{
Root = transform,
AvatarRoot = val3
};
_targets[instanceID] = value;
}
value.LastSeen = unscaledTime;
if (unscaledTime >= value.NextRefresh && num3 > 0)
{
num3--;
value.NextRefresh = unscaledTime + 3f;
_candidates.Clear();
foreach (Renderer componentsInChild in ((Component)val3).GetComponentsInChildren<Renderer>(false))
{
if ((Object)(object)componentsInChild != (Object)null && componentsInChild.enabled)
{
_candidates.Add(componentsInChild);
}
}
_candidates.Sort(delegate(Renderer a, Renderer b)
{
//IL_0001: 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_0009: 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_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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)
Bounds bounds = b.bounds;
Vector3 size = ((Bounds)(ref bounds)).size;
float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
bounds = a.bounds;
size = ((Bounds)(ref bounds)).size;
return sqrMagnitude.CompareTo(((Vector3)(ref size)).sqrMagnitude);
});
int num6 = Math.Min(8, _candidates.Count);
value.Renderers = (Renderer[])(object)new Renderer[num6];
for (int num7 = 0; num7 < num6; num7++)
{
value.Renderers[num7] = _candidates[num7];
}
}
_renderer.Draw(unscaledTime, value, visible: true, 1f, num2, color);
}
if (!(unscaledTime >= _nextCleanup))
{
return;
}
_nextCleanup = unscaledTime + 2f;
_expired.Clear();
foreach (KeyValuePair<int, SilhouetteTarget> target in _targets)
{
if (!target.Value.Alive || unscaledTime - target.Value.LastSeen > 12f)
{
_expired.Add(target.Key);
}
}
foreach (int item in _expired)
{
_targets.Remove(item);
}
}
public void Clear()
{
_renderer.Reset();
_targets.Clear();
_start = 0;
}
public void Dispose()
{
Clear();
_renderer.Dispose();
}
}
internal sealed class WatcherScanner
{
private sealed class Observer
{
internal NetworkPlayer Player;
internal bool Watching;
internal float NextCheck;
internal float LastCheck;
}
private readonly List<Observer> _players = new List<Observer>();
private readonly Dictionary<NetworkPlayer, Observer> _previous = new Dictionary<NetworkPlayer, Observer>();
private readonly SightQuery _sight = new SightQuery();
private int _cursor;
private float _nextRoster;
internal void Scan(float now, RigManager local, List<NetworkPlayer> watchers)
{
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
//IL_03af: Unknown result type (might be due to invalid IL or missing references)
//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: 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_0283: Unknown result type (might be due to invalid IL or missing references)
//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
//IL_0292: Unknown result type (might be due to invalid IL or missing references)
//IL_0294: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Unknown result type (might be due to invalid IL or missing references)
if (now >= _nextRoster)
{
_nextRoster = now + 0.25f;
_previous.Clear();
foreach (Observer player3 in _players)
{
_previous[player3.Player] = player3;
}
_players.Clear();
foreach (NetworkPlayer player4 in NetworkPlayer.Players)
{
if (player4.PlayerID != null && !player4.PlayerID.IsMe && player4.PlayerID.IsValid)
{
_players.Add(_previous.TryGetValue(player4, out Observer value) ? value : new Observer
{
Player = player4
});
}
}
_previous.Clear();
}
Vector3 position = ((Rig)local.physicsRig).m_head.position;
Vector3 position2 = ((Rig)local.physicsRig).m_pelvis.position;
Vector3 point = Vector3.Lerp(position, position2, 0.55f);
Transform transform = ((Component)local).transform;
int num = 0;
for (int i = 0; i < _players.Count; i++)
{
if (num >= 8)
{
break;
}
if (_cursor >= _players.Count)
{
_cursor = 0;
}
Observer observer = _players[_cursor++];
if (now < observer.NextCheck)
{
continue;
}
num++;
observer.NextCheck = now + 0.05f;
observer.LastCheck = now;
observer.Watching = false;
NetworkPlayer player = observer.Player;
if (player.PlayerID.IsValid && player.HasRig && !player.ForceHide)
{
RigRefs rigRefs = player.RigRefs;
RigManager val = ((rigRefs != null) ? rigRefs.RigManager : null);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)local) && !((Object)(object)rigRefs.Headset == (Object)null) && !((Object)(object)val.avatar == (Object)null) && (!((Object)(object)val.health != (Object)null) || !(val.health.curr_Health <= 0f)) && PlayerGaze.TryRead(player, Time.realtimeSinceStartupAsDouble, out var eye, out var forward))
{
Transform transform2 = ((Component)val).transform;
observer.Watching = _sight.Visible(eye, forward, transform2, transform, position) || _sight.Visible(eye, forward, transform2, transform, point) || _sight.Visible(eye, forward, transform2, transform, position2);
}
}
}
watchers.Clear();
foreach (Observer player5 in _players)
{
NetworkPlayer player2 = player5.Player;
if (player5.Watching && !(now < player5.LastCheck) && !(now - player5.LastCheck > 0.35f) && player2.PlayerID.IsValid && player2.HasRig && !player2.ForceHide && PlayerGaze.TryRead(player2, Time.realtimeSinceStartupAsDouble, out var eye2, out var forward2))
{
RigRefs rigRefs2 = player2.RigRefs;
object obj;
if (rigRefs2 == null)
{
obj = null;
}
else
{
RigManager rigManager = rigRefs2.RigManager;
obj = ((rigManager != null) ? rigManager.health : null);
}
if ((!((Object)obj != (Object)null) || !(player2.RigRefs.RigManager.health.curr_Health <= 0f)) && (SightQuery.InCone(eye2, forward2, position) || SightQuery.InCone(eye2, forward2, point) || SightQuery.InCone(eye2, forward2, position2)))
{
watchers.Add(player2);
continue;
}
}
player5.Watching = false;
}
}
internal void Clear()
{
_players.Clear();
_previous.Clear();
_cursor = 0;
_nextRoster = 0f;
}
}
internal sealed class WatchTimer
{
private double? _since;
private double _cooldownUntil;
private double _lastTime = double.NegativeInfinity;
private bool _watchingForLook;
public double Elapsed { get; private set; }
public double CooldownRemaining { get; private set; }
public double FreezeSeconds { get; private set; } = 20.0;
public double CooldownSeconds { get; private set; } = 20.0;
public double LookSeconds { get; private set; } = 2.5;
public double LookElapsed { get; private set; }
public bool CountdownActive => _since.HasValue;
public double FreezeRemaining
{
get
{
if (!CountdownActive)
{
return 0.0;
}
return Math.Max(0.0, FreezeSeconds - Elapsed);
}
}
public bool Frozen { get; private set; }
internal void Configure(int freeze, int cooldown, double look = 2.5)
{
Reset();
FreezeSeconds = Math.Clamp(freeze, 1, 120);
CooldownSeconds = Math.Clamp(cooldown, 0, 120);
LookSeconds = (double.IsFinite(look) ? Math.Clamp(look, 0.0, 10.0) : 2.5);
}
public bool Tick(bool enabled, bool watched, double now)
{
if (!enabled || !double.IsFinite(now))
{
Reset();
return false;
}
if (now < _lastTime)
{
Reset();
}
double delta = (double.IsFinite(_lastTime) ? (now - _lastTime) : 0.0);
_lastTime = now;
CooldownRemaining = Math.Max(0.0, _cooldownUntil - now);
if (CooldownRemaining > 0.0)
{
ResetLook();
Frozen = false;
Elapsed = 0.0;
return false;
}
if (!_since.HasValue)
{
if (!Qualifies(watched, delta))
{
Elapsed = 0.0;
return Frozen = false;
}
_since = now;
Elapsed = 0.0;
return Frozen = true;
}
Elapsed = now - _since.Value;
if (Elapsed >= FreezeSeconds)
{
_since = null;
ResetLook();
_cooldownUntil = now + CooldownSeconds;
CooldownRemaining = CooldownSeconds;
Elapsed = 0.0;
return Frozen = false;
}
if (Frozen)
{
if (watched)
{
return true;
}
ResetLook();
return Frozen = false;
}
if (FreezeRemaining <= 5.0)
{
ResetLook();
return false;
}
return Frozen = Qualifies(watched, delta);
}
private bool Qualifies(bool watched, double delta)
{
if (_watchingForLook && delta >= 0.0 && delta <= 0.35)
{
LookElapsed = Math.Min(LookSeconds, LookElapsed + delta);
}
_watchingForLook = watched;
if (!watched || LookElapsed + 1E-09 < LookSeconds)
{
return false;
}
ResetLook();
return true;
}
private void ResetLook()
{
_watchingForLook = false;
LookElapsed = 0.0;
}
public void Reset()
{
_since = null;
_cooldownUntil = 0.0;
_lastTime = double.NegativeInfinity;
double elapsed = (CooldownRemaining = 0.0);
Elapsed = elapsed;
Frozen = false;
ResetLook();
}
}
}