Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MimicReplay v0.12.6
BepInEx\plugins\MimicReplay\MimicReplay.dll
Decompiled a day 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.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace MimicReplay; [BepInPlugin("com.schetnikov.repo.mimicreplay", "MimicReplay", "0.12.6")] public class Plugin : BaseUnityPlugin { private sealed class RigidbodyState { internal bool UseGravity; internal bool IsKinematic; internal bool DetectCollisions; } private sealed class PendingNetworkSpawn { internal int ActorNumber; internal float Delay; internal float Expires; internal bool Authoritative; } private const byte NetworkSpawnEventCode = 197; private const string NetworkSpawnSignature = "MimicReplaySpawnV1"; internal static ManualLogSource Log; internal static Plugin Instance; internal ConfigEntry<bool> Enabled; internal ConfigEntry<KeyboardShortcut> SpawnKey; internal ConfigEntry<KeyboardShortcut> RemoveKey; internal ConfigEntry<int> RecordingRateHz; internal ConfigEntry<int> HistorySeconds; internal ConfigEntry<int> ReplayDelayMinSeconds; internal ConfigEntry<int> ReplayDelayMaxSeconds; internal ConfigEntry<float> PositionInterpolationSpeed; internal ConfigEntry<float> RotationInterpolationSpeed; internal ConfigEntry<bool> ShowCopiedName; internal ConfigEntry<bool> HostOnlySpawn; internal ConfigEntry<bool> VerboseLogging; internal ConfigEntry<float> VerticalOffset; internal ConfigEntry<float> TemporaryVisualDesyncDistance; internal ConfigEntry<bool> DebugTrail; internal ConfigEntry<KeyboardShortcut> DebugTrailKey; internal ConfigEntry<float> PlaybackSpeed; internal ConfigEntry<float> ChaseSpeed; internal ConfigEntry<float> VisionDistance; internal ConfigEntry<float> AttackRange; internal ConfigEntry<int> AttackDamage; internal ConfigEntry<float> AttackCooldown; internal ConfigEntry<float> TurnSpeed; internal ConfigEntry<KeyboardShortcut> SpectatorKey; internal ConfigEntry<KeyboardShortcut> NoclipKey; internal ConfigEntry<float> NoclipSpeed; internal ConfigEntry<KeyboardShortcut> AddMoneyKey; internal ConfigEntry<int> AddMoneyAmount; internal ConfigEntry<float> KnockbackForce; private readonly List<PlayerRecorder> _recorders = new List<PlayerRecorder>(); private readonly List<MimicController> _mimics = new List<MimicController>(); private float _nextPlayerScan; private float _nextSpawnAllowedTime; private float _nextDebugToggleAllowedTime; private float _nextSpectatorToggleAllowedTime; private float _nextNoclipToggleAllowedTime; private float _nextMoneyAllowedTime; private float _moneyNoticeUntil; private string _moneyNotice; private bool _previousGodMode; private GUIStyle _spectatorStyle; private GUIStyle _spectatorShadowStyle; private readonly Dictionary<Collider, bool> _noclipColliderStates = new Dictionary<Collider, bool>(); private readonly Dictionary<Rigidbody, RigidbodyState> _noclipBodyStates = new Dictionary<Rigidbody, RigidbodyState>(); private bool _networkSubscribed; private readonly List<PendingNetworkSpawn> _pendingNetworkSpawns = new List<PendingNetworkSpawn>(); private static readonly FieldInfo PlayerHealthField = typeof(PlayerAvatar).GetField("playerHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo GodModeField = typeof(PlayerHealth).GetField("godMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo AvatarPhotonViewField = typeof(PlayerAvatar).GetField("photonView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo StatGetRunCurrencyMethod = AccessTools.Method(typeof(SemiFunc), "StatGetRunCurrency", Type.EmptyTypes, (Type[])null); private static readonly MethodInfo StatSetRunCurrencyMethod = AccessTools.Method(typeof(SemiFunc), "StatSetRunCurrency", new Type[1] { typeof(int) }, (Type[])null); internal bool SpectatorMode { get; private set; } internal bool NoclipMode { get; private set; } private void Awake() { //IL_004e: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Expected O, but got Unknown //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Expected O, but got Unknown //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Expected O, but got Unknown //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Expected O, but got Unknown //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Expected O, but got Unknown //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Expected O, but got Unknown //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Expected O, but got Unknown //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_0548: Expected O, but got Unknown //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_05b7: Expected O, but got Unknown //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_05f6: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the mod"); SpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "SpawnKey", new KeyboardShortcut((KeyCode)288, (KeyCode[])(object)new KeyCode[0]), "Spawn a mimic"); RemoveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "RemoveKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[0]), "Remove all mimics"); RecordingRateHz = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RecordingRateHz", 10, new ConfigDescription("Record snapshots per second", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), new object[0])); HistorySeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "HistorySeconds", 60, new ConfigDescription("History buffer length in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 300), new object[0])); ReplayDelayMinSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ReplayDelayMinSeconds", 15, new ConfigDescription("Minimum replay delay", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 120), new object[0])); ReplayDelayMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ReplayDelayMaxSeconds", 30, new ConfigDescription("Maximum replay delay", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 120), new object[0])); PositionInterpolationSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PositionInterpolationSpeed", 2f, new ConfigDescription("Position interpolation speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), new object[0])); RotationInterpolationSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RotationInterpolationSpeed", 2f, new ConfigDescription("Rotation interpolation speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), new object[0])); ShowCopiedName = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowCopiedName", true, "Show the copied player name above mimic"); HostOnlySpawn = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HostOnlySpawn", false, "Only host spawns mimics (mimics are currently client-local)"); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log extra details"); VerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "VerticalOffset", 0f, "Manual vertical correction applied after automatic bounds alignment"); TemporaryVisualDesyncDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "TemporaryVisualDesyncDistance", 0f, new ConfigDescription("Temporary horizontal offset between visible mimic and its real collider/hitbox; set 0 to disable", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), new object[0])); DebugTrail = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugTrail", false, "Draw the recorded and replayed trajectory"); DebugTrailKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "DebugTrailKey", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[0]), "Toggle trajectory visualization"); PlaybackSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "PlaybackSpeed", 0.65f, new ConfigDescription("Replay speed multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), new object[0])); ChaseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "ChaseSpeed", 2.5f, new ConfigDescription("Movement speed while chasing", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), new object[0])); VisionDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "VisionDistance", 12f, new ConfigDescription("Player detection distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[0])); AttackRange = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "AttackRange", 1.5f, new ConfigDescription("Attack distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), new object[0])); AttackDamage = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy", "AttackDamage", 10, new ConfigDescription("Damage per attack", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), new object[0])); AttackCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "AttackCooldown", 2f, new ConfigDescription("Seconds between attacks", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), new object[0])); TurnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "TurnSpeed", 540f, new ConfigDescription("Turning speed in degrees per second", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 1080f), new object[0])); SpectatorKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Spectator", "SpectatorKey", new KeyboardShortcut((KeyCode)291, (KeyCode[])(object)new KeyCode[0]), "Toggle spectator mode"); NoclipKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Noclip", "NoclipKey", new KeyboardShortcut((KeyCode)290, (KeyCode[])(object)new KeyCode[0]), "Toggle flight and wall noclip"); NoclipSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Noclip", "NoclipSpeed", 8f, new ConfigDescription("Flight speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), new object[0])); AddMoneyKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Cheats", "AddMoneyKey", new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[0]), "Add money (host/singleplayer only)"); AddMoneyAmount = ((BaseUnityPlugin)this).Config.Bind<int>("Cheats", "AddMoneyAmount", 10000, new ConfigDescription("Dollars added per key press", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1000, 1000000), new object[0])); KnockbackForce = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "KnockbackForce", 6f, new ConfigDescription("Player knockback force", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), new object[0])); Log.LogMessage((object)"MimicReplay loaded"); Log.LogMessage((object)("Game version: " + Application.version)); Harmony.CreateAndPatchAll(typeof(EnvironmentDirectorDisconnectPatch), "com.schetnikov.repo.mimicreplay.environment"); Harmony.CreateAndPatchAll(typeof(LocalVoiceShortInputPatch), "com.schetnikov.repo.mimicreplay.voice.short"); ((MonoBehaviour)this).StartCoroutine(PeriodicUpdate()); } private IEnumerator PeriodicUpdate() { while (true) { yield return (object)new WaitForSeconds(0.25f); if (Enabled.Value) { DiscoverPlayers(); ProcessPendingNetworkSpawns(); } } } private void Update() { //IL_0026: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (Enabled.Value) { MaintainNetworkSubscription(); UpdateRecorders(); UpdateMimics(); KeyboardShortcut value = SpawnKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && Time.unscaledTime >= _nextSpawnAllowedTime) { _nextSpawnAllowedTime = Time.unscaledTime + 0.75f; SpawnMimic(); } KeyboardShortcut value2 = RemoveKey.Value; if (((KeyboardShortcut)(ref value2)).IsDown()) { RemoveAllMimics(); } KeyboardShortcut value3 = DebugTrailKey.Value; if (((KeyboardShortcut)(ref value3)).IsDown() && Time.unscaledTime >= _nextDebugToggleAllowedTime) { _nextDebugToggleAllowedTime = Time.unscaledTime + 0.75f; DebugTrail.Value = !DebugTrail.Value; Log.LogMessage((object)("DebugTrail: " + DebugTrail.Value)); } KeyboardShortcut value4 = SpectatorKey.Value; if (((KeyboardShortcut)(ref value4)).IsDown() && Time.unscaledTime >= _nextSpectatorToggleAllowedTime) { _nextSpectatorToggleAllowedTime = Time.unscaledTime + 0.75f; SetSpectatorMode(!SpectatorMode); } KeyboardShortcut value5 = NoclipKey.Value; if (((KeyboardShortcut)(ref value5)).IsDown() && Time.unscaledTime >= _nextNoclipToggleAllowedTime) { _nextNoclipToggleAllowedTime = Time.unscaledTime + 0.5f; SetNoclipMode(!NoclipMode); } KeyboardShortcut value6 = AddMoneyKey.Value; if (((KeyboardShortcut)(ref value6)).IsDown() && Time.unscaledTime >= _nextMoneyAllowedTime) { _nextMoneyAllowedTime = Time.unscaledTime + 0.75f; AddMoney(); } MaintainSpectatorMode(); MaintainNoclipMode(); } } private void OnGUI() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_008f: 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_00aa: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: 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_01f0: 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) if (Enabled.Value && (SpectatorMode || NoclipMode || !(Time.unscaledTime >= _moneyNoticeUntil))) { if (_spectatorStyle == null) { _spectatorStyle = new GUIStyle(GUI.skin.label); _spectatorStyle.alignment = (TextAnchor)4; _spectatorStyle.fontSize = 22; _spectatorStyle.fontStyle = (FontStyle)1; _spectatorStyle.normal.textColor = new Color(0.25f, 1f, 0.9f, 1f); _spectatorShadowStyle = new GUIStyle(_spectatorStyle); _spectatorShadowStyle.normal.textColor = new Color(0f, 0f, 0f, 0.9f); } string text = ((SpectatorMode && NoclipMode) ? "SPECTATOR [F10] | NOCLIP [F9]" : (SpectatorMode ? "SPECTATOR MODE [F10]" : "NOCLIP / FLIGHT [F9]")); if (!SpectatorMode && !NoclipMode) { text = _moneyNotice ?? "MONEY UPDATED"; } float num = Mathf.Min(420f, (float)Screen.width - 20f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 18f, num, 38f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x - 8f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 16f, ((Rect)(ref val)).height + 6f); Color color = GUI.color; GUI.color = new Color(0.02f, 0.06f, 0.08f, 0.78f); GUI.Box(val2, GUIContent.none); GUI.color = color; GUI.Label(new Rect(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, _spectatorShadowStyle); GUI.Label(val, text, _spectatorStyle); } } private void SetSpectatorMode(bool enabled) { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); PlayerHealth val2 = (PlayerHealth)(((Object)(object)val != (Object)null && PlayerHealthField != null) ? /*isinst with value type is only supported in some contexts*/: null); if (enabled && (Object)(object)val2 != (Object)null && GodModeField != null) { _previousGodMode = (bool)GodModeField.GetValue(val2); } SpectatorMode = enabled; if (!enabled && (Object)(object)val2 != (Object)null && GodModeField != null) { GodModeField.SetValue(val2, _previousGodMode); } Log.LogMessage((object)("Spectator mode: " + (enabled ? "ON" : "OFF"))); } private void MaintainSpectatorMode() { if (!SpectatorMode) { return; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if (!((Object)(object)val == (Object)null)) { val.EnemyVisionFreezeTimerSet(1f); val.OverrideDisableEnemyInvestigate(1f); PlayerHealth val2 = (PlayerHealth)((PlayerHealthField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null && GodModeField != null) { GodModeField.SetValue(val2, true); } } } private void SetNoclipMode(bool enabled) { if (NoclipMode != enabled) { NoclipMode = enabled; if (enabled) { CaptureAndDisableLocalPhysics(); } else { RestoreLocalPhysics(); } Log.LogMessage((object)("Noclip mode: " + (enabled ? "ON [WASD/Space/Ctrl]" : "OFF"))); } } private void CaptureAndDisableLocalPhysics() { //IL_00bf: 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) PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return; } _noclipColliderStates.Clear(); _noclipBodyStates.Clear(); Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { _noclipColliderStates[val2] = val2.enabled; val2.enabled = false; } } Rigidbody[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null)) { _noclipBodyStates[val3] = new RigidbodyState { UseGravity = val3.useGravity, IsKinematic = val3.isKinematic, DetectCollisions = val3.detectCollisions }; val3.velocity = Vector3.zero; val3.angularVelocity = Vector3.zero; val3.useGravity = false; val3.detectCollisions = false; val3.isKinematic = true; } } } private void MaintainNoclipMode() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0093: 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_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_00a6: 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_00a9: 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_00b9: 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_00bc: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00d4: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) if (!NoclipMode) { return; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return; } if (_noclipColliderStates.Count == 0 && _noclipBodyStates.Count == 0) { CaptureAndDisableLocalPhysics(); } Camera main = Camera.main; Vector3 val2 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : ((Component)val).transform.forward); Vector3 val3 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.right : ((Component)val).transform.right); Vector3 val4 = Vector3.zero; if (Input.GetKey((KeyCode)119)) { val4 += val2; } if (Input.GetKey((KeyCode)115)) { val4 -= val2; } if (Input.GetKey((KeyCode)100)) { val4 += val3; } if (Input.GetKey((KeyCode)97)) { val4 -= val3; } if (Input.GetKey((KeyCode)32)) { val4 += Vector3.up; } if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)99)) { val4 -= Vector3.up; } Rigidbody[] array = _noclipBodyStates.Keys.ToArray(); foreach (Rigidbody val5 in array) { if (!((Object)(object)val5 == (Object)null)) { val5.velocity = Vector3.zero; val5.angularVelocity = Vector3.zero; } } if (!(((Vector3)(ref val4)).sqrMagnitude < 0.001f)) { float num = NoclipSpeed.Value * (Input.GetKey((KeyCode)304) ? 2f : 1f); Vector3 val6 = ((Vector3)(ref val4)).normalized * num * Time.unscaledDeltaTime; Transform val7 = (((Object)(object)val.playerTransform != (Object)null) ? val.playerTransform : ((Component)val).transform); val7.position += val6; } } private void RestoreLocalPhysics() { //IL_00c8: 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) foreach (KeyValuePair<Collider, bool> noclipColliderState in _noclipColliderStates) { if ((Object)(object)noclipColliderState.Key != (Object)null) { noclipColliderState.Key.enabled = noclipColliderState.Value; } } foreach (KeyValuePair<Rigidbody, RigidbodyState> noclipBodyState in _noclipBodyStates) { if (!((Object)(object)noclipBodyState.Key == (Object)null)) { noclipBodyState.Key.useGravity = noclipBodyState.Value.UseGravity; noclipBodyState.Key.isKinematic = noclipBodyState.Value.IsKinematic; noclipBodyState.Key.detectCollisions = noclipBodyState.Value.DetectCollisions; noclipBodyState.Key.velocity = Vector3.zero; noclipBodyState.Key.angularVelocity = Vector3.zero; } } _noclipColliderStates.Clear(); _noclipBodyStates.Clear(); } private void AddMoney() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { ShowMoneyNotice("MONEY: HOST ONLY"); Log.LogWarning((object)"F5 money ignored: only the host can change run currency"); return; } if (StatGetRunCurrencyMethod == null || StatSetRunCurrencyMethod == null) { ShowMoneyNotice("MONEY API NOT FOUND"); Log.LogError((object)"Run currency API was not found"); return; } try { int num = Convert.ToInt32(StatGetRunCurrencyMethod.Invoke(null, null)); int num2 = Mathf.Max(1, Mathf.RoundToInt((float)AddMoneyAmount.Value / 1000f)); int num3 = ((num > int.MaxValue - num2) ? int.MaxValue : (num + num2)); StatSetRunCurrencyMethod.Invoke(null, new object[1] { num3 }); RefreshCurrencyUi(); int num4 = num2 * 1000; ShowMoneyNotice("+$" + num4.ToString("N0") + " [F5]"); Log.LogMessage((object)("Money added: $" + num4 + ", balance=$" + (long)num3 * 1000L)); } catch (Exception ex) { ShowMoneyNotice("MONEY ERROR — CHECK LOG"); Log.LogError((object)("Failed to add money: " + ex)); } } private void ShowMoneyNotice(string text) { _moneyNotice = text; _moneyNoticeUntil = Time.unscaledTime + 2.5f; } private static void RefreshCurrencyUi() { Type type = AccessTools.TypeByName("CurrencyUI"); if (!(type == null)) { FieldInfo fieldInfo = AccessTools.Field(type, "instance"); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(null) : null); MethodInfo methodInfo = AccessTools.Method(type, "FetchCurrency", Type.EmptyTypes, (Type[])null); if (obj != null && methodInfo != null) { methodInfo.Invoke(obj, null); } } } internal void RegisterRecorder(PlayerRecorder recorder) { _recorders.Add(recorder); } internal PlayerRecorder FindRecorderForPlayer(GameObject playerGo) { return _recorders.FirstOrDefault((PlayerRecorder r) => (Object)(object)r.TargetPlayer == (Object)(object)playerGo); } internal void RegisterMimic(MimicController mimic) { _mimics.Add(mimic); } internal void RemoveMimic(MimicController mimic) { _mimics.Remove(mimic); } internal void RemoveAllMimics() { MimicController[] array = _mimics.ToArray(); MimicController[] array2 = array; foreach (MimicController mimicController in array2) { mimicController.Dispose(); } _mimics.Clear(); } private void DiscoverPlayers() { if (Time.unscaledTime < _nextPlayerScan) { return; } _nextPlayerScan = Time.unscaledTime + 1f; PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>(); foreach (PlayerAvatar val in array) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && FindRecorderForPlayer(((Component)val).gameObject) == null) { RegisterRecorder(new PlayerRecorder(val, this)); if (VerboseLogging.Value) { Log.LogInfo((object)("Recording player: " + ((Object)((Component)val).gameObject).name)); } } } _recorders.RemoveAll((PlayerRecorder r) => (Object)(object)r.TargetPlayer == (Object)null); } private void UpdateRecorders() { foreach (PlayerRecorder item in _recorders.ToList()) { item.Tick(); } } private void UpdateMimics() { foreach (MimicController item in _mimics.ToList()) { item.Tick(); } } internal void SpawnMimic() { //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) if (!Enabled.Value) { return; } if (HostOnlySpawn.Value && !IsHost()) { Log.LogWarning((object)"F7 ignored: HostOnlySpawn is enabled and this client is not the host"); return; } PlayerRecorder playerRecorder = FindRandomMimicSource(); if (playerRecorder == null) { Log.LogWarning((object)"No active player has enough recorded history to spawn a mimic yet"); return; } _ = playerRecorder.TargetPlayer; PlayerSnapshot playerSnapshot = playerRecorder.History[0]; PlayerSnapshot playerSnapshot2 = playerRecorder.History[playerRecorder.History.Count - 1]; float num = playerSnapshot2.Timestamp - playerSnapshot.Timestamp; if (num < (float)ReplayDelayMinSeconds.Value) { Log.LogWarning((object)("Not enough recorded history. Available: " + num.ToString("F1") + "s, required: " + ReplayDelayMinSeconds.Value + "s")); return; } float num2 = Mathf.Min((float)ReplayDelayMaxSeconds.Value, num); float num3 = Mathf.Min((float)ReplayDelayMinSeconds.Value, num2); float num4 = Random.Range(num3, num2); PhotonView val = (PhotonView)((AvatarPhotonViewField != null) ? /*isinst with value type is only supported in some contexts*/: null); if (PhotonNetwork.InRoom && (Object)(object)val != (Object)null && val.Owner != null) { object[] array = new object[3] { "MimicReplaySpawnV1", val.OwnerActorNr, num4 }; RaiseEventOptions val2 = new RaiseEventOptions(); val2.Receivers = (ReceiverGroup)1; val2.CachingOption = (EventCaching)0; RaiseEventOptions val3 = val2; bool flag = PhotonNetwork.RaiseEvent((byte)197, (object)array, val3, SendOptions.SendReliable); Log.LogMessage((object)("Network mimic spawn sent=" + flag + " sourceActor=" + val.OwnerActorNr + " delay=" + num4.ToString("F2"))); } else { SpawnMimicForRecorder(playerRecorder, num4, "local", authoritative: true); } } private void SpawnMimicForRecorder(PlayerRecorder recorder, float selectedDelay, string origin, bool authoritative) { if (recorder == null || (Object)(object)recorder.TargetPlayer == (Object)null || recorder.History.Count < 2) { return; } GameObject targetPlayer = recorder.TargetPlayer; PlayerSnapshot playerSnapshot = recorder.History[0]; PlayerSnapshot playerSnapshot2 = recorder.History[recorder.History.Count - 1]; ManualLogSource log = Log; object[] array = new object[14] { "Mimic spawn origin=", origin, " source=", ((Object)targetPlayer).name, " id=", ((Object)targetPlayer).GetInstanceID(), " snapshots=", recorder.History.Count, " oldest=", null, null, null, null, null }; float timestamp = playerSnapshot.Timestamp; array[9] = timestamp.ToString("F3"); array[10] = " newest="; float timestamp2 = playerSnapshot2.Timestamp; array[11] = timestamp2.ToString("F3"); array[12] = " delay="; array[13] = selectedDelay.ToString("F3"); log.LogMessage((object)string.Concat(array)); try { MimicController item = new MimicController(targetPlayer, recorder, selectedDelay, this, authoritative); _mimics.Add(item); Log.LogMessage((object)("Spawned mimic for " + ((Object)targetPlayer).name)); } catch (Exception ex) { Log.LogError((object)("Failed to create mimic: " + ex)); } } private void OnNetworkEvent(EventData eventData) { if (eventData != null && eventData.Code == 197 && eventData.CustomData is object[] array && array.Length >= 3 && array[0] is string && !((string)array[0] != "MimicReplaySpawnV1")) { int num = Convert.ToInt32(array[1]); float num2 = Convert.ToSingle(array[2]); bool authoritative = PhotonNetwork.LocalPlayer != null && eventData.Sender == PhotonNetwork.LocalPlayer.ActorNumber; PlayerRecorder playerRecorder = FindRecorderForActor(num); if (playerRecorder != null && playerRecorder.History.Count >= 2) { float num3 = playerRecorder.History[playerRecorder.History.Count - 1].Timestamp - playerRecorder.History[0].Timestamp; SpawnMimicForRecorder(playerRecorder, Mathf.Min(num2, num3), "network actor=" + num, authoritative); return; } _pendingNetworkSpawns.Add(new PendingNetworkSpawn { ActorNumber = num, Delay = num2, Expires = Time.unscaledTime + 15f, Authoritative = authoritative }); Log.LogInfo((object)("Network mimic spawn queued sourceActor=" + num)); } } private void MaintainNetworkSubscription() { LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient; bool flag = PhotonNetwork.InRoom && networkingClient != null; if (flag && !_networkSubscribed) { networkingClient.EventReceived += OnNetworkEvent; _networkSubscribed = true; Log.LogInfo((object)"MimicReplay network listener enabled after room join"); } else if (!flag && _networkSubscribed) { if (networkingClient != null) { networkingClient.EventReceived -= OnNetworkEvent; } _networkSubscribed = false; Log.LogInfo((object)"MimicReplay network listener disabled outside room"); } } private PlayerRecorder FindRecorderForActor(int actorNumber) { foreach (PlayerRecorder recorder in _recorders) { if (recorder != null && !((Object)(object)recorder.Avatar == (Object)null)) { PhotonView val = (PhotonView)((AvatarPhotonViewField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null && val.OwnerActorNr == actorNumber) { return recorder; } } } return null; } private void ProcessPendingNetworkSpawns() { for (int num = _pendingNetworkSpawns.Count - 1; num >= 0; num--) { PendingNetworkSpawn pendingNetworkSpawn = _pendingNetworkSpawns[num]; if (Time.unscaledTime >= pendingNetworkSpawn.Expires) { Log.LogWarning((object)("Network mimic spawn expired sourceActor=" + pendingNetworkSpawn.ActorNumber)); _pendingNetworkSpawns.RemoveAt(num); } else { PlayerRecorder playerRecorder = FindRecorderForActor(pendingNetworkSpawn.ActorNumber); if (playerRecorder != null && playerRecorder.History.Count >= 2) { float num2 = playerRecorder.History[playerRecorder.History.Count - 1].Timestamp - playerRecorder.History[0].Timestamp; if (!(num2 < Mathf.Min((float)ReplayDelayMinSeconds.Value, pendingNetworkSpawn.Delay))) { SpawnMimicForRecorder(playerRecorder, Mathf.Min(pendingNetworkSpawn.Delay, num2), "queued network actor=" + pendingNetworkSpawn.ActorNumber, pendingNetworkSpawn.Authoritative); _pendingNetworkSpawns.RemoveAt(num); } } } } } private PlayerRecorder FindRandomMimicSource() { List<PlayerRecorder> list = new List<PlayerRecorder>(); foreach (PlayerRecorder recorder in _recorders) { if (recorder != null && !((Object)(object)recorder.Avatar == (Object)null) && !((Object)(object)recorder.TargetPlayer == (Object)null) && recorder.TargetPlayer.activeInHierarchy && recorder.History.Count >= 2) { PlayerSnapshot playerSnapshot = recorder.History[0]; PlayerSnapshot playerSnapshot2 = recorder.History[recorder.History.Count - 1]; if (playerSnapshot2.Timestamp - playerSnapshot.Timestamp >= (float)ReplayDelayMinSeconds.Value) { list.Add(recorder); } } } if (list.Count == 0) { return null; } PlayerRecorder playerRecorder = list[Random.Range(0, list.Count)]; Log.LogMessage((object)("Random mimic source selected index=" + list.IndexOf(playerRecorder) + "/" + list.Count + " object=" + ((Object)playerRecorder.TargetPlayer).name + " avatarId=" + ((Object)playerRecorder.Avatar).GetInstanceID())); return playerRecorder; } private bool IsHost() { return SemiFunc.IsMasterClientOrSingleplayer(); } private void OnDestroy() { if (_networkSubscribed && PhotonNetwork.NetworkingClient != null) { PhotonNetwork.NetworkingClient.EventReceived -= OnNetworkEvent; } _networkSubscribed = false; if (NoclipMode) { SetNoclipMode(enabled: false); } if (SpectatorMode) { SetSpectatorMode(enabled: false); } RemoveAllMimics(); } } [HarmonyPatch(typeof(EnvironmentDirector), "AmbientLightLogic")] internal static class EnvironmentDirectorDisconnectPatch { private static Exception Finalizer(Exception __exception) { if (__exception is NullReferenceException && !PhotonNetwork.IsConnected) { return null; } return __exception; } } [HarmonyPatch] internal static class LocalVoiceInputPatch { private static IEnumerable<MethodBase> TargetMethods() { Type type = AccessTools.TypeByName("Photon.Voice.LocalVoiceAudioFloat"); if (!(type == null)) { MethodInfo push = AccessTools.Method(type, "PushData", new Type[1] { typeof(float[]) }, (Type[])null); MethodInfo pushAsync = AccessTools.Method(type, "PushDataAsync", new Type[1] { typeof(float[]) }, (Type[])null); if (push != null) { yield return push; } if (pushAsync != null) { yield return pushAsync; } } } private static void Prefix(float[] __0) { VoicePhraseCapture.AcceptLocalFrame(__0); } } [HarmonyPatch] internal static class LocalVoiceShortInputPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Photon.Voice.LocalVoiceFramed`1"); if (type == null) { return null; } Type type2 = type.MakeGenericType(typeof(short)); return AccessTools.Method(type2, "PushDataAsync", new Type[1] { typeof(short[]) }, (Type[])null); } private static void Prefix(short[] __0) { VoicePhraseCapture.AcceptLocalShortFrame(__0); } } [HarmonyPatch] internal static class WindowsMicrophoneInputPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Photon.Voice.Windows.WindowsAudioInPusher"); if (!(type != null)) { return null; } return AccessTools.Method(type, "push", (Type[])null, (Type[])null); } private static void Prefix(object __instance, IntPtr __0, int __1) { Type type = __instance.GetType(); MethodInfo methodInfo = AccessTools.PropertyGetter(type, "Channels"); MethodInfo methodInfo2 = AccessTools.PropertyGetter(type, "SamplingRate"); int channels = ((!(methodInfo != null)) ? 1 : ((int)methodInfo.Invoke(__instance, null))); int sampleRate = ((methodInfo2 != null) ? ((int)methodInfo2.Invoke(__instance, null)) : 48000); VoicePhraseCapture.AcceptLocalPcm16(__0, __1, channels, sampleRate); } } [HarmonyPatch] internal static class UnityMicrophoneReaderPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Photon.Voice.Unity.MicWrapper"); if (!(type != null)) { return null; } return AccessTools.Method(type, "Read", (Type[])null, (Type[])null); } private static void Postfix(float[] __0, bool __result) { if (__result) { VoicePhraseCapture.AcceptLocalFrame(__0); } } } [HarmonyPatch] internal static class UnityMicrophonePusherPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Photon.Voice.Unity.MicWrapperPusherOnAudioFilterRead"); if (!(type != null)) { return null; } return AccessTools.Method(type, "OnAudioFilterRead", (Type[])null, (Type[])null); } private static void Prefix(float[] __0) { VoicePhraseCapture.AcceptLocalFrame(__0); } } public static class MeshFactory { public static Mesh CreateCubeMesh() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0024: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Mesh val = new Mesh(); val.vertices = (Vector3[])(object)new Vector3[8] { new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(0.5f, 0.5f, -0.5f), new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0.5f, 0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }; val.triangles = new int[36] { 0, 2, 1, 0, 3, 2, 2, 3, 4, 2, 4, 5, 1, 2, 5, 1, 5, 6, 0, 7, 4, 0, 4, 3, 5, 4, 7, 5, 7, 6, 0, 1, 6, 0, 6, 7 }; val.RecalculateNormals(); return val; } } internal sealed class MimicAppearanceResult { internal bool Success; internal string Error; internal Animator Animator; internal Transform FacingTransform; } internal static class MimicAppearance { internal static MimicAppearanceResult Create(PlayerAvatar avatar, Transform destination) { //IL_006f: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) MimicAppearanceResult mimicAppearanceResult = new MimicAppearanceResult(); if ((Object)(object)avatar == (Object)null) { mimicAppearanceResult.Error = "PlayerAvatar is null"; return mimicAppearanceResult; } GameObject val = FindVisualRoot(avatar); if ((Object)(object)val == (Object)null) { mimicAppearanceResult.Error = "playerAvatarVisuals was not found"; return mimicAppearanceResult; } GameObject val2 = Object.Instantiate<GameObject>(val); ((Object)val2).name = ((Object)val).name + "_MimicClone"; val2.transform.SetParent(destination, false); val2.transform.localPosition = val.transform.localPosition; val2.transform.localRotation = val.transform.localRotation; val2.transform.localScale = val.transform.localScale; SetLayerRecursively(val2, 0); Transform val3 = null; Transform[] componentsInChildren = val2.GetComponentsInChildren<Transform>(true); foreach (Transform val4 in componentsInChildren) { if (((Object)val4).name == "ANIM BOT") { val3 = val4; break; } } List<string> list = new List<string>(); Component[] componentsInChildren2 = val2.GetComponentsInChildren<Component>(true); foreach (Component val5 in componentsInChildren2) { if (!((Object)(object)val5 == (Object)null) && !(val5 is Transform) && !(val5 is Renderer) && !(val5 is Animator) && !(val5 is MeshFilter) && (val5 is Camera || val5 is AudioListener || val5 is Collider || val5 is Rigidbody || val5 is MonoBehaviour)) { list.Add(((object)val5).GetType().FullName); Behaviour val6 = (Behaviour)(object)((val5 is Behaviour) ? val5 : null); if ((Object)(object)val6 != (Object)null) { val6.enabled = false; } Object.Destroy((Object)(object)val5); } } Renderer[] componentsInChildren3 = val2.GetComponentsInChildren<Renderer>(true); foreach (Renderer val7 in componentsInChildren3) { if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val7).transform != (Object)(object)val3 && !((Component)val7).transform.IsChildOf(val3)) { val7.enabled = false; continue; } val7.enabled = true; val7.shadowCastingMode = (ShadowCastingMode)1; val7.receiveShadows = true; Material[] sharedMaterials = val7.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int l = 0; l < sharedMaterials.Length; l++) { array[l] = (((Object)(object)sharedMaterials[l] != (Object)null) ? new Material(sharedMaterials[l]) : ((Material)null)); } val7.materials = array; } Renderer[] componentsInChildren4 = val2.GetComponentsInChildren<Renderer>(true); SkinnedMeshRenderer[] componentsInChildren5 = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true); Animator componentInChildren = val2.GetComponentInChildren<Animator>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.applyRootMotion = false; componentInChildren.cullingMode = (AnimatorCullingMode)0; } mimicAppearanceResult.Animator = componentInChildren; mimicAppearanceResult.FacingTransform = (((Object)(object)val3 != (Object)null) ? val3 : (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).transform : val2.transform)); Plugin.Log.LogMessage((object)("Mimic appearance source=" + ((Object)((Component)avatar).gameObject).name + " visualPath=" + GetPath(val.transform) + " renderers=" + componentsInChildren4.Length + " skinnedRenderers=" + componentsInChildren5.Length + " animator=" + ((Object)(object)componentInChildren != (Object)null) + " disabled=[" + string.Join(",", list.ToArray()) + "]")); if (componentsInChildren4.Length == 0) { mimicAppearanceResult.Error = "visual root contains no Renderer"; return mimicAppearanceResult; } mimicAppearanceResult.Success = true; return mimicAppearanceResult; } private static void SetLayerRecursively(GameObject root, int layer) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown root.layer = layer; foreach (Transform item in root.transform) { Transform val = item; SetLayerRecursively(((Component)val).gameObject, layer); } } private static GameObject FindVisualRoot(PlayerAvatar avatar) { FieldInfo field = typeof(PlayerAvatar).GetField("playerAvatarVisuals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value = field.GetValue(avatar); Component val = (Component)((value is Component) ? value : null); if ((Object)(object)val != (Object)null) { return val.gameObject; } } Renderer[] componentsInChildren = ((Component)avatar).GetComponentsInChildren<Renderer>(true); if (componentsInChildren.Length == 0) { return null; } Transform val2 = ((Component)componentsInChildren[0]).transform; while ((Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)((Component)avatar).transform) { val2 = val2.parent; } return ((Component)val2).gameObject; } internal static Bounds GetCombinedBounds(GameObject root) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); List<Renderer> list = new List<Renderer>(); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (val.enabled && ((Component)val).gameObject.activeInHierarchy) { list.Add(val); } } if (list.Count == 0) { list.AddRange(componentsInChildren); } Bounds bounds = list[0].bounds; for (int j = 1; j < list.Count; j++) { ((Bounds)(ref bounds)).Encapsulate(list[j].bounds); } return bounds; } private static string GetPath(Transform transform) { string text = ((Object)transform).name; while ((Object)(object)transform.parent != (Object)null) { transform = transform.parent; text = ((Object)transform).name + "/" + text; } return text; } } public class MimicController { private enum MimicMode { Replay, Chase, Attack, StuckRecovery } private readonly GameObject _mimicObject; private readonly GameObject _visualContainer; private readonly Plugin _plugin; private readonly bool _authoritative; private readonly PlayerRecorder _recorder; private readonly Animator _animator; private readonly Transform _visualFacing; private readonly AudioSource _voiceSource; private readonly CapsuleCollider _capsule; private readonly NavMeshAgent _agent; private readonly EnemyNavMeshAgent _enemyNavigation; private List<PlayerSnapshot> _segment; private float _sourceStartTime; private float _sourceEndTime; private bool _reversePlayback; private float _localStartTime; private float _nextVerboseLogTime; private float _nextVisionCheck; private float _lastSeenTime; private float _nextAttackTime; private float _attackStateUntil; private float _nextRepathTime; private float _nextDoorCheck; private float _nextStuckCheck; private float _stuckSince; private Vector3 _recoveryStartPosition; private int _recoveryAttempts; private float _lastInteractionTimestamp = -1f; private Vector3 _lastProgressPosition; private Vector3 _retreatDirection; private Vector3 _retreatDestination; private Vector3 _lastMovementPosition; private Vector3 _lastReplayPosition; private float _nextVoiceTime; private Vector3 _lastPathDestination; private bool _hasPathDestination; private PlayerAvatar _chaseTarget; private MimicMode _mode; private LineRenderer _recordedTrail; private LineRenderer _replayTrail; private bool _wasJumping; private bool _wasSprinting; private bool _chaseCrouching; private bool _chaseCrawling; private GameObject _fakeHeldObject; private int _fakeHeldSourceId; private static readonly FieldInfo PlayerHealthField = typeof(PlayerAvatar).GetField("playerHealth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerCrouchingField = typeof(PlayerAvatar).GetField("isCrouching", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerCrawlingField = typeof(PlayerAvatar).GetField("isCrawling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo DoorOpenMethod = typeof(PhysGrabHinge).GetMethod("OpenImpulse", BindingFlags.Instance | BindingFlags.NonPublic); public MimicController(GameObject source, PlayerRecorder recorder, float selectedDelay, Plugin plugin, bool authoritative) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00cc: 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_0217: 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_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022e: 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) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: 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_0281: 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_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028a: 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_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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_0368: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0559: 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_0565: Unknown result type (might be due to invalid IL or missing references) //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: 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_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0301: 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_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: 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_01d4: 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_01ef: Unknown result type (might be due to invalid IL or missing references) _plugin = plugin; _authoritative = authoritative; _recorder = recorder; _segment = new List<PlayerSnapshot>(recorder.History.Items); PlayerSnapshot playerSnapshot = _segment[_segment.Count - 1]; _sourceStartTime = playerSnapshot.Timestamp - selectedDelay; _sourceEndTime = playerSnapshot.Timestamp; TrimToReplayWindow(); _mimicObject = new GameObject("MimicReplay_Mimic"); _visualContainer = new GameObject("Visual"); _visualContainer.transform.SetParent(_mimicObject.transform, false); PlayerSnapshot playerSnapshot2 = _segment[0]; _mimicObject.transform.position = playerSnapshot2.Position; _mimicObject.transform.rotation = playerSnapshot2.Rotation; MimicAppearanceResult mimicAppearanceResult = MimicAppearance.Create(source.GetComponent<PlayerAvatar>(), _visualContainer.transform); if (!mimicAppearanceResult.Success) { Object.Destroy((Object)(object)_mimicObject); throw new InvalidOperationException("Mimic visual clone failed: " + mimicAppearanceResult.Error); } _animator = mimicAppearanceResult.Animator; _visualFacing = mimicAppearanceResult.FacingTransform; if ((Object)(object)mimicAppearanceResult.FacingTransform != (Object)null) { Vector3 forward = mimicAppearanceResult.FacingTransform.forward; forward.y = 0f; Vector3 val = playerSnapshot2.Rotation * Vector3.forward; val.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude > 0.001f && ((Vector3)(ref val)).sqrMagnitude > 0.001f) { Quaternion val2 = Quaternion.FromToRotation(((Vector3)(ref forward)).normalized, ((Vector3)(ref val)).normalized); _visualContainer.transform.rotation = val2 * _visualContainer.transform.rotation; ManualLogSource log = Plugin.Log; float y = ((Quaternion)(ref val2)).eulerAngles.y; log.LogInfo((object)("Mimic visual facing calibrated yaw=" + y.ToString("F1"))); } } Bounds combinedBounds = MimicAppearance.GetCombinedBounds(_visualContainer); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(((Bounds)(ref combinedBounds)).center.x, ((Bounds)(ref combinedBounds)).min.y, ((Bounds)(ref combinedBounds)).center.z); Vector3 val4 = playerSnapshot2.Position + Vector3.up * _plugin.VerticalOffset.Value; Transform transform = _visualContainer.transform; transform.position += val4 - val3; if (_plugin.TemporaryVisualDesyncDistance.Value > 0.01f) { float num = Random.Range(0f, (float)Math.PI * 2f); Vector3 val5 = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * _plugin.TemporaryVisualDesyncDistance.Value; Transform transform2 = _visualContainer.transform; transform2.position += val5; Plugin.Log.LogWarning((object)("Temporary visual desync enabled: visible body offset=" + ((Vector3)(ref val5)).ToString("F2") + " while collider/hitbox remains on mimic root")); } _capsule = _mimicObject.AddComponent<CapsuleCollider>(); _capsule.radius = 0.36f; _capsule.height = playerSnapshot2.CapsuleHeight; _capsule.center = Vector3.up * (_capsule.height * 0.5f); ((Collider)_capsule).isTrigger = false; Rigidbody val6 = _mimicObject.AddComponent<Rigidbody>(); val6.isKinematic = true; val6.useGravity = false; _agent = _mimicObject.AddComponent<NavMeshAgent>(); ((Behaviour)_agent).enabled = false; _agent.radius = 0.36f; _agent.height = 1.8f; _agent.speed = _plugin.ChaseSpeed.Value; _agent.acceleration = 12f; _agent.angularSpeed = _plugin.TurnSpeed.Value; _agent.stoppingDistance = Mathf.Max(0.2f, _plugin.AttackRange.Value * 0.75f); _agent.autoRepath = true; _agent.autoTraverseOffMeshLink = true; _agent.updateRotation = false; _agent.autoBraking = true; _agent.obstacleAvoidanceType = (ObstacleAvoidanceType)4; _agent.avoidancePriority = Random.Range(25, 60); _enemyNavigation = _mimicObject.AddComponent<EnemyNavMeshAgent>(); ((Behaviour)_enemyNavigation).enabled = false; _voiceSource = _mimicObject.AddComponent<AudioSource>(); _voiceSource.playOnAwake = false; _voiceSource.loop = false; _voiceSource.spatialBlend = 1f; _voiceSource.minDistance = 2f; _voiceSource.maxDistance = 18f; _voiceSource.rolloffMode = (AudioRolloffMode)1; _nextVoiceTime = Time.time + Random.Range(6f, 14f); _localStartTime = Time.time; _lastProgressPosition = playerSnapshot2.Position; _lastMovementPosition = playerSnapshot2.Position; _lastReplayPosition = playerSnapshot2.Position; BuildTrails(); LogMode("created", null); } private void TrimToReplayWindow() { while (_segment.Count > 2 && _segment[1].Timestamp < _sourceStartTime) { _segment.RemoveAt(0); } } public void Tick() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_mimicObject == (Object)null) && _segment.Count >= 2) { UpdateVision(); if (_mode == MimicMode.Replay) { TickReplay(); } else if (_mode == MimicMode.Chase) { TickChase(); } else if (_mode == MimicMode.Attack) { TickAttack(); } else { TickStuckRecovery(); } TickVoiceReplay(); UpdateReplayTrail(_mimicObject.transform.position); if (_plugin.VerboseLogging.Value && Time.unscaledTime >= _nextVerboseLogTime) { _nextVerboseLogTime = Time.unscaledTime + 1f; LogPath("periodic"); } } } private void TickReplay() { //IL_00d1: 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_00df: 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_00fa: 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) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0186: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_chaseTarget != (Object)null) { EnterChase("target detected"); return; } float num = _sourceEndTime - _sourceStartTime; if (num <= 0f) { return; } float num2 = (Time.time - _localStartTime) * _plugin.PlaybackSpeed.Value; if (num2 >= num) { ChooseNextRoute(); num = _sourceEndTime - _sourceStartTime; num2 = 0f; } float num3 = (_reversePlayback ? (_sourceEndTime - num2) : (_sourceStartTime + num2)); FindNeighbours(num3, out var previous, out var next); float num4 = next.Timestamp - previous.Timestamp; float num5 = ((num4 > 0.0001f) ? Mathf.Clamp01((num3 - previous.Timestamp) / num4) : 0f); _mimicObject.transform.position = Vector3.Lerp(previous.Position, next.Position, num5); Vector3 direction = _mimicObject.transform.position - _lastReplayPosition; direction.y = 0f; _lastReplayPosition = _mimicObject.transform.position; if (((Vector3)(ref direction)).sqrMagnitude > 4E-06f) { UpdateFacing(direction); } else { Quaternion val = Quaternion.Slerp(previous.Rotation, next.Rotation, num5); if (_reversePlayback) { val *= Quaternion.Euler(0f, 180f, 0f); } _mimicObject.transform.rotation = val; } ApplyCapsule(previous.CapsuleHeight); UpdateFakeHeldObject(previous, next, num5); if (next.InteractStarted && next.Timestamp != _lastInteractionTimestamp) { _lastInteractionTimestamp = next.Timestamp; TryOpenNearbyDoor("recorded interaction"); } UpdateAnimation(previous, next, num4); } private void EnterChase(string reason) { //IL_001a: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_009d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_chaseTarget == (Object)null)) { NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(_mimicObject.transform.position, ref val, 0.75f, -1)) { EnterStuckRecovery(reason + "; replay endpoint is not on NavMesh"); return; } ((Behaviour)_agent).enabled = true; ((Behaviour)_enemyNavigation).enabled = true; _agent.Warp(((NavMeshHit)(ref val)).position); ApplyCapsule(1.8f); _lastProgressPosition = _mimicObject.transform.position; _lastMovementPosition = _mimicObject.transform.position; _nextStuckCheck = Time.time + 0.75f; Transition(MimicMode.Chase, reason); Repath("enter chase"); } } private void TickChase() { //IL_003d: 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_006f: 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) if ((Object)(object)_chaseTarget == (Object)null) { EnterReplay("target lost"); return; } Transform targetTransform = GetTargetTransform(_chaseTarget); UpdateChasePosture(_chaseTarget); float num = Vector3.Distance(_mimicObject.transform.position, targetTransform.position); if (num <= _plugin.AttackRange.Value) { Transition(MimicMode.Attack, "target entered attack range"); BeginAttack(targetTransform.position); return; } if (Time.time >= _nextRepathTime) { Repath("interval"); } if (Time.time >= _nextDoorCheck) { TryOpenNearbyDoor("chase proximity"); } UpdateFacing(GetNavigationFacingDirection()); CheckStuck(num); UpdateChaseAnimation(); } private void TickAttack() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_chaseTarget != (Object)null) { UpdateChasePosture(_chaseTarget); } if (Time.time < _attackStateUntil) { if (((Behaviour)_agent).enabled && _agent.isOnNavMesh) { _agent.speed = _plugin.ChaseSpeed.Value; UpdateFacing(GetNavigationFacingDirection()); } } else if ((Object)(object)_chaseTarget == (Object)null) { EnterReplay("attack retreat complete; target lost"); } else { Transition(MimicMode.Chase, "attack retreat complete"); Repath("after attack"); } } private void BeginAttack(Vector3 targetPosition) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_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_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_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_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: 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) if ((Object)(object)_chaseTarget == (Object)null) { return; } PlayerAvatar chaseTarget = _chaseTarget; if (_authoritative && (!_plugin.SpectatorMode || !((Object)(object)chaseTarget == (Object)(object)SemiFunc.PlayerAvatarLocal())) && Time.time >= _nextAttackTime) { PlayerHealth val = (PlayerHealth)((PlayerHealthField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null) { _nextAttackTime = Time.time + _plugin.AttackCooldown.Value; val.Hurt(_plugin.AttackDamage.Value, false, -1, false); Vector3 val2 = targetPosition - _mimicObject.transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = _mimicObject.transform.forward; } chaseTarget.ForceImpulse(((Vector3)(ref val2)).normalized * _plugin.KnockbackForce.Value + Vector3.up * (_plugin.KnockbackForce.Value * 0.3f)); _retreatDirection = -((Vector3)(ref val2)).normalized; _retreatDestination = _mimicObject.transform.position + _retreatDirection * 4f; NavMeshHit val3 = default(NavMeshHit); if (NavMesh.SamplePosition(_retreatDestination, ref val3, 2f, -1)) { _retreatDestination = ((NavMeshHit)(ref val3)).position; } if (((Behaviour)_agent).enabled && _agent.isOnNavMesh) { _agent.SetDestination(_retreatDestination); } _attackStateUntil = Time.time + Random.Range(3f, 5f); Plugin.Log.LogMessage((object)("Mimic attack target=" + ((Object)((Component)chaseTarget).gameObject).name + " retreatUntil=" + _attackStateUntil.ToString("F2"))); return; } } _attackStateUntil = Time.time + 0.25f; } private void TickStuckRecovery() { //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_004a: 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_00c0: 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) if ((Object)(object)_chaseTarget == (Object)null) { EnterReplay("stuck recovery has no target"); return; } float num = Vector3.Distance(_recoveryStartPosition, _mimicObject.transform.position); if (num >= 0.2f) { _lastProgressPosition = _mimicObject.transform.position; _nextStuckCheck = Time.time + 0.75f; Transition(MimicMode.Chase, "stock navigation restored progress after attempts=" + _recoveryAttempts); return; } if (Time.time >= _nextDoorCheck) { TryOpenNearbyDoor("stuck recovery"); } if (!(Time.time < _nextRepathTime)) { NavMeshHit val = default(NavMeshHit); if (!((Behaviour)_agent).enabled && NavMesh.SamplePosition(_mimicObject.transform.position, ref val, 0.75f, -1)) { ((Behaviour)_agent).enabled = true; ((Behaviour)_enemyNavigation).enabled = true; _agent.Warp(((NavMeshHit)(ref val)).position); } if (((Behaviour)_agent).enabled && _agent.isOnNavMesh) { _enemyNavigation.ResetPath(); Repath("stuck recovery"); _recoveryAttempts++; } _nextRepathTime = Time.time + 0.5f; } } private void Repath(string reason) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00ca: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Invalid comparison between Unknown and I4 //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) _nextRepathTime = Time.time + 0.3f; if ((Object)(object)_chaseTarget == (Object)null || !((Behaviour)_agent).enabled || !_agent.isOnNavMesh) { return; } Vector3 position = GetTargetTransform(_chaseTarget).position; NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(position, ref val, 1.5f, -1)) { Plugin.Log.LogWarning((object)("Mimic path target is outside NavMesh: " + ((Vector3)(ref position)).ToString("F2"))); } else { if (_hasPathDestination && Vector3.Distance(_lastPathDestination, ((NavMeshHit)(ref val)).position) < 0.2f && _agent.hasPath && (int)_agent.pathStatus != 2) { return; } NavMeshPath val2 = new NavMeshPath(); if (!NavMesh.CalculatePath(_mimicObject.transform.position, ((NavMeshHit)(ref val)).position, -1, val2) || (int)val2.status == 2 || val2.corners.Length < 2) { Plugin.Log.LogWarning((object)string.Concat("Mimic path rejected reason=", reason, " status=", val2.status, " corners=", val2.corners.Length, " target=", ((Object)((Component)_chaseTarget).gameObject).name)); return; } _agent.speed = _plugin.ChaseSpeed.Value; _enemyNavigation.SetDestination(((NavMeshHit)(ref val)).position); bool flag = _agent.hasPath || _agent.pathPending; if (flag) { _lastPathDestination = ((NavMeshHit)(ref val)).position; _hasPathDestination = true; } Plugin.Log.LogInfo((object)string.Concat("Mimic repath reason=", reason, " accepted=", flag, " calculatedStatus=", val2.status, " calculatedCorners=", val2.corners.Length, " target=", ((Object)((Component)_chaseTarget).gameObject).name)); LogPath(reason); } } private void CheckStuck(float targetDistance) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_00dc: 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_00fc: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _nextStuckCheck || targetDistance < _plugin.AttackRange.Value * 1.2f) { return; } _nextStuckCheck = Time.time + 0.75f; float num = Vector3.Distance(_lastProgressPosition, _mimicObject.transform.position); if (num < 0.12f) { if (_stuckSince <= 0f) { _stuckSince = Time.time; } if (Time.time - _stuckSince >= 2.25f) { string text = FindBlockingObjectName(); object[] array = new object[8] { "no progress for ", (Time.time - _stuckSince).ToString("F1"), "s; obstacle=", text, "; path=", _agent.pathStatus, "; desiredSpeed=", null }; Vector3 desiredVelocity = _agent.desiredVelocity; array[7] = ((Vector3)(ref desiredVelocity)).magnitude.ToString("F2"); EnterStuckRecovery(string.Concat(array)); } } else { _stuckSince = 0f; _lastProgressPosition = _mimicObject.transform.position; } } private void EnterStuckRecovery(string reason) { //IL_000c: 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) _recoveryStartPosition = _mimicObject.transform.position; _recoveryAttempts = 0; _stuckSince = 0f; if (((Behaviour)_agent).enabled && _agent.isOnNavMesh) { _enemyNavigation.ResetPath(); } _nextRepathTime = Time.time + 0.1f; Transition(MimicMode.StuckRecovery, reason); } private string FindBlockingObjectName() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_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_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 desiredVelocity = _agent.desiredVelocity; if (((Vector3)(ref desiredVelocity)).sqrMagnitude < 0.01f) { return "path/no desired velocity"; } RaycastHit val = default(RaycastHit); if (Physics.Raycast(_mimicObject.transform.position + Vector3.up * 0.8f, ((Vector3)(ref desiredVelocity)).normalized, ref val, 0.8f, -5, (QueryTriggerInteraction)1)) { return ((Object)((Component)((RaycastHit)(ref val)).collider).gameObject).name; } return "unknown"; } private void TryOpenNearbyDoor(string reason) { //IL_0056: 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) _nextDoorCheck = Time.time + 0.5f; if (!_authoritative || DoorOpenMethod == null) { return; } PhysGrabHinge val = null; float num = 1.8f; PhysGrabHinge[] array = Object.FindObjectsOfType<PhysGrabHinge>(); foreach (PhysGrabHinge val2 in array) { if (!((Object)(object)val2 == (Object)null)) { float num2 = Vector3.Distance(_mimicObject.transform.position, ((Component)val2).transform.position); if (num2 < num) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null) { return; } try { PhysGrabObject componentInParent = ((Component)val).GetComponentInParent<PhysGrabObject>(); if ((Object)(object)componentInParent != (Object)null) { componentInParent.EnemyInteractTimeSet(); } DoorOpenMethod.Invoke(val, null); Plugin.Log.LogInfo((object)("Mimic door detected=" + ((Object)((Component)val).gameObject).name + " distance=" + num.ToString("F2") + " action=PhysGrabHinge.OpenImpulse reason=" + reason)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Mimic door open failed object=" + ((Object)((Component)val).gameObject).name + " error=" + ex.GetBaseException().Message)); } } private void EnterReplay(string reason) { //IL_005b: 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) if (((Behaviour)_agent).enabled) { if (_agent.isOnNavMesh) { _agent.ResetPath(); } ((Behaviour)_agent).enabled = false; } ((Behaviour)_enemyNavigation).enabled = false; _hasPathDestination = false; _localStartTime = Time.time; _lastReplayPosition = _mimicObject.transform.position; Transition(MimicMode.Replay, reason); } private void Transition(MimicMode next, string reason) { if (_mode != next || !(reason != "created")) { MimicMode mode = _mode; _mode = next; Plugin.Log.LogMessage((object)string.Concat("Mimic mode ", mode, " -> ", next, " reason=", reason, " target=", TargetName())); } } private void LogMode(string reason, PlayerAvatar target) { Plugin.Log.LogMessage((object)string.Concat("Mimic mode=", _mode, " reason=", reason, " target=", ((Object)(object)target != (Object)null) ? ((Object)((Component)target).gameObject).name : "none")); } private void LogPath(string reason) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) string text = "agent-disabled"; int num = 0; if ((Object)(object)_agent != (Object)null && ((Behaviour)_agent).enabled && _agent.isOnNavMesh) { text = (_agent.pathPending ? "Pending" : ((object)_agent.pathStatus).ToString()); if (!_agent.pathPending && _agent.hasPath) { num = _agent.path.corners.Length; } } Plugin.Log.LogInfo((object)string.Concat("Mimic debug mode=", _mode, " target=", TargetName(), " pathStatus=", text, " corners=", num, " reason=", reason)); } private string TargetName() { if (!((Object)(object)_chaseTarget != (Object)null)) { return "none"; } return ((Object)((Component)_chaseTarget).gameObject).name; } private static Transform GetTargetTransform(PlayerAvatar avatar) { if (!((Object)(object)avatar.playerTransform != (Object)null)) { return ((Component)avatar).transform; } return avatar.playerTransform; } private void ApplyCapsule(float height) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) height = Mathf.Clamp(height, 0.65f, 1.8f); _capsule.height = height; _capsule.center = Vector3.up * (height * 0.5f); _agent.height = height; } private void UpdateChasePosture(PlayerAvatar target) { bool flag = ReadAvatarBool(PlayerCrawlingField, target); bool flag2 = flag || ReadAvatarBool(PlayerCrouchingField, target); float num = (flag ? 0.65f : (flag2 ? 1.05f : 1.8f)); if (_chaseCrouching != flag2 || _chaseCrawling != flag || !(Mathf.Abs(_capsule.height - num) < 0.01f)) { _chaseCrouching = flag2; _chaseCrawling = flag; ApplyCapsule(num); if (_plugin.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("Mimic chase posture=" + (flag ? "crawl" : (flag2 ? "crouch" : "stand")) + " target=" + (((Object)(object)target != (Object)null) ? ((Object)((Component)target).gameObject).name : "none") + " capsule=" + num.ToString("F2"))); } } } private static bool ReadAvatarBool(FieldInfo field, PlayerAvatar avatar) { if (field == null || (Object)(object)avatar == (Object)null) { return false; } try { return Convert.ToBoolean(field.GetValue(avatar)); } catch { return false; } } private void UpdateVision() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00a5: 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_00ae: 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_00c4: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _nextVisionCheck) { return; } _nextVisionCheck = Time.time + 0.2f; PlayerAvatar chaseTarget = _chaseTarget; PlayerAvatar val = null; float num = _plugin.VisionDistance.Value; PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>(); foreach (PlayerAvatar val2 in array) { if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeInHierarchy && (!_plugin.SpectatorMode || !((Object)(object)val2 == (Object)(object)SemiFunc.PlayerAvatarLocal()))) { Transform targetTransform = GetTargetTransform(val2); Vector3 val3 = _mimicObject.transform.position + Vector3.up; float num2 = Vector3.Distance(val3, targetTransform.position + Vector3.up); if (!(num2 >= num) && HasLineOfSight(val3, targetTransform, ((Component)val2).transform)) { num = num2; val = val2; } } } if ((Object)(object)val != (Object)null) { _chaseTarget = val; _lastSeenTime = Time.time; } else if ((Object)(object)chaseTarget != (Object)null && Time.time - _lastSeenTime <= 5f) { _chaseTarget = chaseTarget; } else { _chaseTarget = null; } } private static bool HasLineOfSight(Vector3 origin, Transform target, Transform root) { //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_000b: 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_0011: 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_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) Vector3 val = target.position + Vector3.up; Vector3 val2 = val - origin; RaycastHit val3 = default(RaycastHit); if (!Physics.Raycast(origin, ((Vector3)(ref val2)).normalized, ref val3, ((Vector3)(ref val2)).magnitude, -5, (QueryTriggerInteraction)1)) { return true; } if (!((Object)(object)((RaycastHit)(ref val3)).transform == (Object)(object)root) && !((RaycastHit)(ref val3)).transform.IsChildOf(root) && !((Object)(object)((RaycastHit)(ref val3)).transform == (Object)(object)target)) { return ((RaycastHit)(ref val3)).transform.IsChildOf(target); } return true; } private void UpdateFacing(Vector3 direction) { //IL_001d: 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) //IL_002c: 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_007d: 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) //IL_0061: 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_00d2: 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) direction.y = 0f; if (!(((Vector3)(ref direction)).sqrMagnitude < 0.0025f)) { Quaternion val = Quaternion.LookRotation(((Vector3)(ref direction)).normalized, Vector3.up); Vector3 forward = _mimicObject.transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.001f || Vector3.Dot(((Vector3)(ref forward)).normalized, ((Vector3)(ref direction)).normalized) < 0.2f) { _mimicObject.transform.rotation = val; return; } float num = 1f - Mathf.Exp((0f - Mathf.Max(2f, _plugin.TurnSpeed.Value / 90f)) * Time.deltaTime); _mimicObject.transform.rotation = Quaternion.Slerp(_mimicObject.transform.rotation, val, num); } } private Vector3 GetNavigationFacingDirection() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_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_0049: 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_0082: Unknown result type (might be due to invalid IL or missing references) //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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_015c: 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_00ef: 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) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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) if ((Object)(object)_agent == (Object)null || !((Behaviour)_agent).enabled || !_agent.isOnNavMesh) { return Vector3.zero; } Vector3 result = _mimicObject.transform.position - _lastMovementPosition; result.y = 0f; _lastMovementPosition = _mimicObject.transform.position; if (((Vector3)(ref result)).sqrMagnitude > 4E-06f) { return result; } Vector3 result2 = _agent.steeringTarget - _mimicObject.transform.position; result2.y = 0f; if (((Vector3)(ref result2)).sqrMagnitude > 0.01f) { return result2; } if (_agent.hasPath && !_agent.pathPending) { Vector3[] corners = _agent.path.corners; for (int i = 0; i < corners.Length; i++) { Vector3 result3 = corners[i] - _mimicObject.transform.position; result3.y = 0f; if (((Vector3)(ref result3)).sqrMagnitude > 0.04f) { return result3; } } } Vector3 velocity = _agent.velocity; velocity.y = 0f; if (((Vector3)(ref velocity)).sqrMagnitude > 0.01f) { return velocity; } return Vector3.zero; } private void TickVoiceReplay() { if ((Object)(object)_voiceSource == (Object)null || _voiceSource.isPlaying || Time.time < _nextVoiceTime) { return; } _nextVoiceTime = Time.time + Random.Range(8f, 20f); VoicePhraseCapture voiceCapture = _recorder.VoiceCapture; if ((Object)(object)voiceCapture == (Object)null) { return; } if (!voiceCapture.TryGetRandomPhrase(out var samples, out var channels, out var sampleRate)) { _nextVoiceTime = Time.time + 1f; return; } if ((Object)(object)_voiceSource.clip != (Object)null) { Object.Destroy((Object)(object)_voiceSource.clip); } int num = samples.Length / Math.Max(1, channels); float num2 = 0f; for (int i = 0; i < samples.Length; i++) { num2 = Mathf.Max(num2, Mathf.Abs(samples[i])); } if (num2 > 0.0001f) { float num3 = Mathf.Min(5f, 0.88f / num2); for (int j = 0; j < samples.Length; j++) { samples[j] = Mathf.Clamp(samples[j] * num3, -1f, 1f); } } AudioClip val = AudioClip.Create("MimicPhrase_" + voiceCapture.OwnerName, num, channels, sampleRate, false); val.SetData(samples, 0); _voiceSource.clip = val; _voiceSource.pitch = Random.Range(0.96f, 1.04f); _voiceSource.volume = 1f; _voiceSource.Play(); Plugin.Log.LogInfo((object)("Mimic voice phrase player=" + voiceCapture.OwnerName + " duration=" + val.length.ToString("F2") + "s")); } private void UpdateChaseAnimation() { //IL_0015: 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 (!((Object)(object)_animator == (Object)null)) { Vector3 velocity = _agent.velocity; float magnitude = ((Vector3)(ref velocity)).magnitude; _animator.SetBool("Moving", magnitude > 0.12f); _animator.SetBool("Sprinting", magnitude > 3.2f); _animator.SetBool("Crouching", _chaseCrouching); _animator.SetBool("Crawling", _chaseCrawling); _animator.speed = ((magnitude > 0.12f) ? Mathf.Clamp(magnitude / 1.8f, 0.65f, 1.8f) : 1f); } } private void UpdateAnimation(PlayerSnapshot previous, PlayerSnapshot next, float span) { //IL_0018: 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_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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_003c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_animator == (Object)null) && !(span <= 0.0001f)) { Vector3 val = Vector3.Lerp(previous.Velocity, next.Velocity, 0.5f); if (_reversePlayback) { val = -val; } Vector2 val2 = new Vector2(val.x, val.z); float magnitude = ((Vector2)(ref val2)).magnitude; bool flag = next.JumpStarted || (!next.IsGrounded && val.y > 0.25f); bool flag2 = !next.IsGrounded && val.y < -0.25f; bool flag3 = magnitude > 3.2f; _animator.SetBool("Moving", magnitude > 0.12f); _animator.SetBool("Sprinting", flag3); _animator.SetBool("Jumping", flag); _animator.SetBool("Falling", flag2); _animator.SetBool("Crouching", previous.IsCrouching); _animator.SetBool("Crawling", previous.IsCrawling); _animator.speed = ((magnitude > 0.12f) ? Mathf.Clamp(magnitude / 1.8f, 0.65f, 1.8f) : 1f); if (flag && !_wasJumping) { _animator.SetTrigger("JumpingImpulse"); } if (flag3 && !_wasSprinting) { _animator.SetTrigger("SprintingImpulse"); } _wasJumping = flag; _wasSprinting = flag3; } } private void UpdateFakeHeldObject(PlayerSnapshot previous, PlayerSnapshot next, float t) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) PlayerSnapshot playerSnapshot = ((t < 0.5f) ? previous : next); GameObject heldObjectSource = playerSnapshot.HeldObjectSource; if ((Object)(object)heldObjectSource == (Object)null) { ClearFakeHeldObject(); return; } int instanceID = ((Object)heldObjectSource).GetInstanceID(); if ((Object)(object)_fakeHeldObject == (Object)null || instanceID != _fakeHeldSourceId) { ClearFakeHeldObject(); _fakeHeldObject = CreateVisualOnlyHeldObject(heldObjectSource); _fakeHeldSourceId = instanceID; if ((Object)(object)_fakeHeldObject != (Object)null) { _fakeHeldObject.transform.SetParent(_mimicObject.transform, false); Plugin.Log.LogInfo((object)("Mimic fake held visual created source=" + ((Object)heldObjectSource).name + " renderers=" + _fakeHeldObject.GetComponentsInChildren<Renderer>(true).Length)); } } if (!((Object)(object)_fakeHeldObject == (Object)null)) { bool flag = (Object)(object)previous.HeldObjectSource != (Object)null && (Object)(object)next.HeldObjectSource != (Object)null && ((Object)previous.HeldObjectSource).GetInstanceID() == ((Object)next.HeldObjectSource).GetInstanceID(); _fakeHeldObject.transform.localPosition = (flag ? Vector3.Lerp(previous.HeldLocalPosition, next.HeldLocalPosition, t) : playerSnapshot.HeldLocalPosition); _fakeHeldObject.transform.localRotation = (flag ? Quaternion.Slerp(previous.HeldLocalRotation, next.HeldLocalRotation, t) : playerSnapshot.HeldLocalRotation); } } private static GameObject CreateVisualOnlyHeldObject(GameObject source) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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) //IL_01b1: 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) GameObject val = new GameObject("FakeHeld_" + ((Object)source).name); Renderer[] componentsInChildren = source.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (!val2.ena