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.29
MimicReplay.dll
Decompiled 2 months 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: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace MimicReplay; [BepInPlugin("com.schetnikov.repo.mimicreplay", "MimicReplay", "0.12.29")] public class Plugin : BaseUnityPlugin { private sealed class RigidbodyState { internal bool UseGravity; internal bool IsKinematic; internal bool DetectCollisions; } private sealed class PendingNetworkSpawn { internal int MimicId; internal int ActorNumber; internal float Delay; internal float Expires; internal bool Authoritative; } private const byte NetworkSpawnEventCode = 197; private const byte NetworkStateEventCode = 198; private const string NetworkSpawnSignature = "MimicReplaySpawnV1"; private const string NetworkStateSignature = "MimicReplayStateV1"; 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<KeyboardShortcut> SpawnMostValuableKey; internal ConfigEntry<float> KnockbackForce; internal ConfigEntry<int> MimicHealth; internal ConfigEntry<bool> AutoSpawnEnabled; internal ConfigEntry<KeyboardShortcut> AutoSpawnToggleKey; internal ConfigEntry<int> AutoSpawnMaxMimics; internal ConfigEntry<float> AutoSpawnIntervalMin; internal ConfigEntry<float> AutoSpawnIntervalMax; internal ConfigEntry<float> AutoSpawnGrowthSeconds; internal ConfigEntry<float> AutoSpawnMinDistance; internal ConfigEntry<float> AutoSpawnMaxDistance; 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 _nextValuableSpawnAllowedTime; private float _moneyNoticeUntil; private string _moneyNotice; private bool _autoSpawnWasInLevel; private float _autoSpawnLevelStarted; private float _nextAutoSpawnTime; private float _nextAutoSpawnToggleAllowedTime; 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 Transform _noclipMovementRoot; private Vector3 _noclipTargetPosition; private int _nextNetworkMimicId; private GameObject _grabProxyPrefab; private object _grabProxyPrefabRef; private readonly Dictionary<int, MimicGrabProxy> _grabProxies = new Dictionary<int, MimicGrabProxy>(); 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_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Expected O, but got Unknown //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Expected O, but got Unknown //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Expected O, but got Unknown //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Expected O, but got Unknown //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Expected O, but got Unknown //IL_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_0560: Unknown result type (might be due to invalid IL or missing references) //IL_056a: Expected O, but got Unknown //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Expected O, but got Unknown //IL_061c: Unknown result type (might be due to invalid IL or missing references) //IL_0660: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Expected O, but got Unknown //IL_0698: Unknown result type (might be due to invalid IL or missing references) //IL_06a2: Expected O, but got Unknown //IL_06e4: Unknown result type (might be due to invalid IL or missing references) //IL_071d: Unknown result type (might be due to invalid IL or missing references) //IL_0727: Expected O, but got Unknown //IL_075c: Unknown result type (might be due to invalid IL or missing references) //IL_0766: Expected O, but got Unknown //IL_079b: Unknown result type (might be due to invalid IL or missing references) //IL_07a5: Expected O, but got Unknown //IL_07da: Unknown result type (might be due to invalid IL or missing references) //IL_07e4: Expected O, but got Unknown //IL_0819: Unknown result type (might be due to invalid IL or missing references) //IL_0823: Expected O, but got Unknown //IL_0858: Unknown result type (might be due to invalid IL or missing references) //IL_0862: 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", 4.2f, new ConfigDescription("Movement speed while chasing", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), new object[0])); if (ChaseSpeed.Value <= 2.51f) { ChaseSpeed.Value = 4.2f; } 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", 18f, new ConfigDescription("Flight speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), new object[0])); if (NoclipSpeed.Value <= 8.01f) { NoclipSpeed.Value = 18f; } 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])); SpawnMostValuableKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Cheats", "SpawnMostValuableKey", new KeyboardShortcut((KeyCode)282, (KeyCode[])(object)new KeyCode[0]), "Spawn the most valuable object available in the current level (host/singleplayer only)"); KnockbackForce = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy", "KnockbackForce", 6f, new ConfigDescription("Player knockback force", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), new object[0])); MimicHealth = ((BaseUnityPlugin)this).Config.Bind<int>("Enemy", "MimicHealth", 100, new ConfigDescription("Damage required to kill a mimic", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), new object[0])); AutoSpawnEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("AutoSpawn", "Enabled", true, "Periodically spawn mimics during levels (host only)"); AutoSpawnToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("AutoSpawn", "ToggleKey", new KeyboardShortcut((KeyCode)284, (KeyCode[])(object)new KeyCode[0]), "Toggle automatic mimic spawning"); AutoSpawnMaxMimics = ((BaseUnityPlugin)this).Config.Bind<int>("AutoSpawn", "MaximumMimics", 7, new ConfigDescription("Maximum automatic mimic population", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[0])); AutoSpawnIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSpawn", "IntervalMinSeconds", 35f, new ConfigDescription("Minimum time between automatic spawn attempts", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[0])); AutoSpawnIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSpawn", "IntervalMaxSeconds", 70f, new ConfigDescription("Maximum time between automatic spawn attempts", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 600f), new object[0])); AutoSpawnGrowthSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSpawn", "PopulationGrowthSeconds", 120f, new ConfigDescription("Seconds before the allowed population grows by one", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 600f), new object[0])); AutoSpawnMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSpawn", "MinimumPlayerDistance", 4f, new ConfigDescription("Minimum spawn distance from a player", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), new object[0])); AutoSpawnMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSpawn", "MaximumPlayerDistance", 16f, new ConfigDescription("Maximum spawn distance from a player", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 50f), 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"); Harmony.CreateAndPatchAll(typeof(MimicHurtColliderPatch), "com.schetnikov.repo.mimicreplay.damage"); RegisterGrabProxyPrefab(); ((MonoBehaviour)this).StartCoroutine(PeriodicUpdate()); } private IEnumerator PeriodicUpdate() { while (true) { yield return (object)new WaitForSeconds(0.25f); if (Enabled.Value) { DiscoverPlayers(); ProcessPendingNetworkSpawns(); TickAutoSpawn(); } } } 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_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_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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) if (!Enabled.Value) { return; } 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 = AutoSpawnToggleKey.Value; if (((KeyboardShortcut)(ref value3)).IsDown() && Time.unscaledTime >= _nextAutoSpawnToggleAllowedTime) { _nextAutoSpawnToggleAllowedTime = Time.unscaledTime + 0.5f; AutoSpawnEnabled.Value = !AutoSpawnEnabled.Value; ((BaseUnityPlugin)this).Config.Save(); if (AutoSpawnEnabled.Value) { ScheduleNextAutoSpawn(5f, 10f); } Log.LogMessage((object)("Automatic mimic spawning: " + (AutoSpawnEnabled.Value ? "ON" : "OFF"))); } KeyboardShortcut value4 = DebugTrailKey.Value; if (((KeyboardShortcut)(ref value4)).IsDown() && Time.unscaledTime >= _nextDebugToggleAllowedTime) { _nextDebugToggleAllowedTime = Time.unscaledTime + 0.75f; DebugTrail.Value = !DebugTrail.Value; Log.LogMessage((object)("DebugTrail: " + DebugTrail.Value)); } KeyboardShortcut value5 = SpectatorKey.Value; if (((KeyboardShortcut)(ref value5)).IsDown() && Time.unscaledTime >= _nextSpectatorToggleAllowedTime) { _nextSpectatorToggleAllowedTime = Time.unscaledTime + 0.75f; SetSpectatorMode(!SpectatorMode); } KeyboardShortcut value6 = NoclipKey.Value; if (((KeyboardShortcut)(ref value6)).IsDown() && Time.unscaledTime >= _nextNoclipToggleAllowedTime) { _nextNoclipToggleAllowedTime = Time.unscaledTime + 0.2f; SetNoclipMode(!NoclipMode); } KeyboardShortcut value7 = AddMoneyKey.Value; if (((KeyboardShortcut)(ref value7)).IsDown() && Time.unscaledTime >= _nextMoneyAllowedTime) { _nextMoneyAllowedTime = Time.unscaledTime + 0.75f; AddMoney(); } KeyboardShortcut value8 = SpawnMostValuableKey.Value; if (((KeyboardShortcut)(ref value8)).IsDown() && Time.unscaledTime >= _nextValuableSpawnAllowedTime) { _nextValuableSpawnAllowedTime = Time.unscaledTime + 1f; SpawnMostValuable(); } MaintainSpectatorMode(); } private void LateUpdate() { if (Enabled.Value && NoclipMode) { MaintainNoclipMode(); } if (!Enabled.Value) { return; } MimicController[] array = _mimics.ToArray(); foreach (MimicController mimicController in array) { if (mimicController != null && mimicController.IsAlive) { mimicController.LateTick(); } } } private void OnGUI() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0072: 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_008d: Expected O, but got Unknown //IL_00ac: 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_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_029c: 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_0313: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) if (!Enabled.Value) { return; } 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); } if (SpectatorMode || NoclipMode || Time.unscaledTime < _moneyNoticeUntil) { 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); } string text2 = "AUTO MIMICS: " + (AutoSpawnEnabled.Value ? "ON" : "OFF") + " [F3]"; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(18f, 18f, 300f, 32f); Color textColor = _spectatorStyle.normal.textColor; _spectatorStyle.normal.textColor = (AutoSpawnEnabled.Value ? new Color(0.3f, 1f, 0.4f, 1f) : new Color(1f, 0.3f, 0.3f, 1f)); _spectatorStyle.alignment = (TextAnchor)3; _spectatorShadowStyle.alignment = (TextAnchor)3; GUI.Label(new Rect(((Rect)(ref val3)).x + 2f, ((Rect)(ref val3)).y + 2f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text2, _spectatorShadowStyle); GUI.Label(val3, text2, _spectatorStyle); _spectatorStyle.normal.textColor = textColor; _spectatorStyle.alignment = (TextAnchor)4; _spectatorShadowStyle.alignment = (TextAnchor)4; } 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_00a0: 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_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return; } _noclipColliderStates.Clear(); _noclipBodyStates.Clear(); _noclipMovementRoot = (((Object)(object)val.playerTransform != (Object)null) ? val.playerTransform : ((Component)val).transform); List<Component> list = new List<Component>(); list.Add((Component)(object)val); List<Component> list2 = list; Type type = AccessTools.TypeByName("PlayerController"); Component val2 = (Component)((type != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null) { list2.Add(val2); _noclipMovementRoot = val2.transform; } _noclipTargetPosition = _noclipMovementRoot.position; foreach (Component item in list2) { Collider[] componentsInChildren = item.GetComponentsInChildren<Collider>(true); foreach (Collider val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && !_noclipColliderStates.ContainsKey(val3)) { _noclipColliderStates[val3] = val3.enabled; val3.enabled = false; } } Rigidbody[] componentsInChildren2 = item.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody val4 in componentsInChildren2) { if (!((Object)(object)val4 == (Object)null) && !_noclipBodyStates.ContainsKey(val4)) { _noclipBodyStates[val4] = new RigidbodyState { UseGravity = val4.useGravity, IsKinematic = val4.isKinematic, DetectCollisions = val4.detectCollisions }; val4.velocity = Vector3.zero; val4.angularVelocity = Vector3.zero; val4.useGravity = false; val4.detectCollisions = false; val4.isKinematic = true; } } } Log.LogInfo((object)("Noclip captured controller=" + (((Object)(object)val2 != (Object)null) ? ((Object)val2.gameObject).name : "not found") + " colliders=" + _noclipColliderStates.Count + " rigidbodies=" + _noclipBodyStates.Count)); } 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: 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_0192: 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_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: 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; } } float num = NoclipSpeed.Value * (Input.GetKey((KeyCode)304) ? 2f : 1f); Vector3 val6 = ((((Vector3)(ref val4)).sqrMagnitude >= 0.001f) ? (((Vector3)(ref val4)).normalized * num * Time.unscaledDeltaTime) : Vector3.zero); Transform val7 = (((Object)(object)_noclipMovementRoot != (Object)null) ? _noclipMovementRoot : (((Object)(object)val.playerTransform != (Object)null) ? val.playerTransform : ((Component)val).transform)); _noclipTargetPosition += val6; val7.position = _noclipTargetPosition; } 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(); _noclipMovementRoot = null; } 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 SpawnMostValuable() { //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_025f: 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_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0279: 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_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: 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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMasterClientOrSingleplayer()) { ShowMoneyNotice("VALUABLE: HOST ONLY"); return; } ValuableDirector instance = ValuableDirector.instance; PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null) { ShowMoneyNotice("VALUABLES NOT READY"); return; } try { PrefabRef val2 = null; float num = float.MinValue; BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; string[] array = new string[7] { "tinyValuables", "smallValuables", "mediumValuables", "bigValuables", "wideValuables", "tallValuables", "veryTallValuables" }; foreach (string name in array) { FieldInfo field = typeof(ValuableDirector).GetField(name, bindingAttr); IEnumerable enumerable = ((field != null) ? (field.GetValue(instance) as IEnumerable) : null); if (enumerable == null) { continue; } foreach (object item in enumerable) { PrefabRef val3 = (PrefabRef)((item is PrefabRef) ? item : null); GameObject val4 = ((PrefabRef<GameObject>)(object)val3)?.Prefab; ValuableObject val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponentInChildren<ValuableObject>(true) : null); if (!((Object)(object)val5 == (Object)null)) { FieldInfo field2 = typeof(ValuableObject).GetField("dollarValueOverride", bindingAttr); int num2 = ((field2 != null) ? Convert.ToInt32(field2.GetValue(val5)) : 0); float num3 = ((num2 > 0) ? ((float)num2) : (((Object)(object)val5.valuePreset != (Object)null) ? val5.valuePreset.valueMax : 0f)); if (!(num3 <= num)) { num = num3; val2 = val3; } } } } if (val2 == null || (Object)(object)((PrefabRef<GameObject>)(object)val2).Prefab == (Object)null) { ShowMoneyNotice("NO VALUABLE PREFAB"); return; } Transform val6 = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : (((Object)(object)val.playerTransform != (Object)null) ? val.playerTransform : ((Component)val).transform)); Vector3 forward = val6.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = ((Component)val).transform.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 val7 = val6.position + forward * 2.2f; RaycastHit val8 = default(RaycastHit); if (Physics.Raycast(val7 + Vector3.up * 1.5f, Vector3.down, ref val8, 4f, -5, (QueryTriggerInteraction)1)) { val7 = ((RaycastHit)(ref val8)).point + Vector3.up * 0.35f; } GameObject val9; if (PhotonNetwork.InRoom) { val9 = PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)val2).ResourcePath, val7, Quaternion.identity, (byte)0, (object[])null); } else { val9 = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)val2).Prefab, val7, Quaternion.identity); val9.SetActive(true); } if ((Object)(object)val9 == (Object)null) { throw new InvalidOperationException("valuable spawn returned null"); } ShowMoneyNotice("SPAWNED: " + ((PrefabRef<GameObject>)(object)val2).PrefabName + " [F1]"); Log.LogMessage((object)("Spawned most valuable prefab=" + ((PrefabRef<GameObject>)(object)val2).PrefabName + " maxValue=" + num.ToString("F0") + " path=" + ((PrefabRef<GameObject>)(object)val2).ResourcePath)); } catch (Exception ex) { ShowMoneyNotice("VALUABLE SPAWN ERROR"); Log.LogError((object)("Failed to spawn most valuable: " + 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()) { if (item != null && item.IsAlive) { item.Tick(); } } _mimics.RemoveAll((MimicController mimic) => mimic == null || !mimic.IsAlive); } internal void SpawnMimic() { 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) { SendNetworkSpawn(val.OwnerActorNr, num4, "manual"); } else { SpawnMimicForRecorder(playerRecorder, num4, "local", authoritative: true); } } private void SendNetworkSpawn(int actorNumber, float delay, string reason) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0); int num2 = num * 100000 + ++_nextNetworkMimicId % 100000; object[] array = new object[4] { "MimicReplaySpawnV1", actorNumber, delay, num2 }; RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)1; val.CachingOption = (EventCaching)0; RaiseEventOptions val2 = val; bool flag = PhotonNetwork.RaiseEvent((byte)197, (object)array, val2, SendOptions.SendReliable); Log.LogMessage((object)("Network mimic spawn sent=" + flag + " sourceActor=" + actorNumber + " delay=" + delay.ToString("F2") + " reason=" + reason)); } private void TickAutoSpawn() { if (!SemiFunc.RunIsLevel()) { if (_autoSpawnWasInLevel) { RemoveAllMimics(); } _autoSpawnWasInLevel = false; } else if (!_autoSpawnWasInLevel) { _autoSpawnWasInLevel = true; _autoSpawnLevelStarted = Time.time; ScheduleNextAutoSpawn(25f, 40f); Log.LogInfo((object)"Mimic auto-spawn armed for this level"); } else { if (!AutoSpawnEnabled.Value || !SemiFunc.IsMasterClientOrSingleplayer() || Time.time < _nextAutoSpawnTime) { return; } float num = Mathf.Max(0f, Time.time - _autoSpawnLevelStarted); int num2 = Mathf.Clamp(1 + Mathf.FloorToInt(num / Mathf.Max(30f, AutoSpawnGrowthSeconds.Value)), 1, AutoSpawnMaxMimics.Value); if (_mimics.Count >= num2) { ScheduleNextAutoSpawn(AutoSpawnIntervalMin.Value, AutoSpawnIntervalMax.Value); return; } if (!TryFindAutoSpawnRoute(out var selectedRecorder, out var selectedDelay, out var selectedPoint)) { _nextAutoSpawnTime = Time.time + 10f; if (VerboseLogging.Value) { Log.LogInfo((object)"Auto-spawn postponed: no recent visible free route point"); } return; } 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) { SendNetworkSpawn(val.OwnerActorNr, selectedDelay, "automatic cap=" + num2); } else { SpawnMimicForRecorder(selectedRecorder, selectedDelay, "automatic singleplayer", authoritative: true, ++_nextNetworkMimicId); } Log.LogMessage((object)("Automatic mimic selected route point=" + ((Vector3)(ref selectedPoint)).ToString("F2") + " population=" + (_mimics.Count + 1) + "/" + num2)); ScheduleNextAutoSpawn(AutoSpawnIntervalMin.Value, AutoSpawnIntervalMax.Value); } } private void ScheduleNextAutoSpawn(float minimum, float maximum) { minimum = Mathf.Max(1f, minimum); maximum = Mathf.Max(minimum, maximum); _nextAutoSpawnTime = Time.time + Random.Range(minimum, maximum); } private bool TryFindAutoSpawnRoute(out PlayerRecorder selectedRecorder, out float selectedDelay, out Vector3 selectedPoint) { //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_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_00ba: 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) selectedRecorder = null; selectedDelay = 0f; selectedPoint = Vector3.zero; List<Tuple<PlayerRecorder, float, Vector3>> list = new List<Tuple<PlayerRecorder, float, Vector3>>(); foreach (PlayerRecorder recorder in _recorders) { if (recorder == null || (Object)(object)recorder.Avatar == (Object)null || recorder.History.Count < 2) { continue; } IList<PlayerSnapshot> items = recorder.History.Items; PlayerSnapshot playerSnapshot = items[items.Count - 1]; for (int i = 0; i < items.Count; i += 3) { PlayerSnapshot playerSnapshot2 = items[i]; float num = playerSnapshot.Timestamp - playerSnapshot2.Timestamp; if (!(num < (float)ReplayDelayMinSeconds.Value) && !(num > (float)ReplayDelayMaxSeconds.Value) && IsValidAutoSpawnPoint(playerSnapshot2.Position, out var _)) { list.Add(Tuple.Create<PlayerRecorder, float, Vector3>(recorder, num, playerSnapshot2.Position)); } } } if (list.Count == 0) { return false; } Tuple<PlayerRecorder, float, Vector3> tuple = list[Random.Range(0, list.Count)]; selectedRecorder = tuple.Item1; selectedDelay = tuple.Item2; selectedPoint = tuple.Item3; return true; } private bool IsValidAutoSpawnPoint(Vector3 point, out PlayerAvatar observer) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_0152: 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_015c: 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_0160: Unknown result type (might be due to invalid IL or missing references) observer = null; float num = Mathf.Min(AutoSpawnMinDistance.Value, AutoSpawnMaxDistance.Value); float num2 = Mathf.Max(AutoSpawnMinDistance.Value, AutoSpawnMaxDistance.Value); PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>(); RaycastHit val5 = default(RaycastHit); NavMeshHit val7 = default(NavMeshHit); foreach (PlayerAvatar val in array) { if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } Transform val2 = (((Object)(object)val.playerTransform != (Object)null) ? val.playerTransform : ((Component)val).transform); float num3 = Vector3.Distance(val2.position, point); if (num3 < num || num3 > num2) { continue; } Vector3 val3 = val2.position + Vector3.up * 0.9f; Vector3 val4 = point + Vector3.up * 0.9f; if (Physics.Linecast(val3, val4, ref val5, -5, (QueryTriggerInteraction)1)) { PlayerAvatar val6 = (((Object)(object)((RaycastHit)(ref val5)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val5)).collider).GetComponentInParent<PlayerAvatar>() : null); if ((Object)(object)val6 != (Object)(object)val) { continue; } } if (NavMesh.SamplePosition(point, ref val7, 1f, -1)) { Vector3 val8 = ((NavMeshHit)(ref val7)).position + Vector3.up * 0.38f; Vector3 val9 = ((NavMeshHit)(ref val7)).position + Vector3.up * 1.45f; if (!Physics.CheckCapsule(val8, val9, 0.32f, -5, (QueryTriggerInteraction)1)) { observer = val; return true; } } } return false; } private void SpawnMimicForRecorder(PlayerRecorder recorder, float selectedDelay, string origin, bool authoritative, int mimicId = 0) { //IL_0158: 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) 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 { if (mimicId == 0) { mimicId = ++_nextNetworkMimicId; } MimicController mimicController = new MimicController(targetPlayer, recorder, selectedDelay, this, authoritative, mimicId); _mimics.Add(mimicController); if (authoritative) { SpawnGrabProxy(mimicId, mimicController.WorldPosition, mimicController.WorldRotation); } 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) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (eventData == null) { return; } object[] array = eventData.CustomData as object[]; if (eventData.Code == 198) { if (array != null && array.Length >= 4 && array[0] is string && !((string)array[0] != "MimicReplayStateV1")) { int stateMimicId = Convert.ToInt32(array[1]); _mimics.FirstOrDefault((MimicController item) => item != null && item.NetworkId == stateMimicId)?.ApplyNetworkState((Vector3)array[2], (Quaternion)array[3]); } } else if (eventData.Code == 197 && array != null && array.Length >= 3 && array[0] is string && !((string)array[0] != "MimicReplaySpawnV1")) { int num = Convert.ToInt32(array[1]); float num2 = Convert.ToSingle(array[2]); int mimicId = ((array.Length >= 4) ? Convert.ToInt32(array[3]) : (++_nextNetworkMimicId)); 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, mimicId); return; } _pendingNetworkSpawns.Add(new PendingNetworkSpawn { MimicId = mimicId, 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, pendingNetworkSpawn.MimicId); _pendingNetworkSpawns.RemoveAt(num); } } } } } internal void SendMimicState(int mimicId, Vector3 position, Quaternion rotation) { //IL_0022: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0042: 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_004f: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom) { object[] array = new object[4] { "MimicReplayStateV1", mimicId, position, rotation }; RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)0; val.CachingOption = (EventCaching)0; PhotonNetwork.RaiseEvent((byte)198, (object)array, val, SendOptions.SendUnreliable); } } internal MimicController FindMimicByNetworkId(int mimicId) { return _mimics.FirstOrDefault((MimicController mimic) => mimic != null && mimic.NetworkId == mimicId); } internal void RegisterGrabProxy(int mimicId, MimicGrabProxy proxy) { if (mimicId != 0 && (Object)(object)proxy != (Object)null) { _grabProxies[mimicId] = proxy; } } internal void KnockDownGrabProxy(int mimicId, Vector3 force) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (_grabProxies.TryGetValue(mimicId, out var value) && (Object)(object)value != (Object)null) { value.KnockDown(force); } } private void RegisterGrabProxyPrefab() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) try { _grabProxyPrefab = new GameObject("MimicReplay_GrabProxy"); _grabProxyPrefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_grabProxyPrefab); CapsuleCollider val = _grabProxyPrefab.AddComponent<CapsuleCollider>(); val.radius = 0.42f; val.height = 1.8f; val.center = Vector3.up * 0.9f; Rigidbody val2 = _grabProxyPrefab.AddComponent<Rigidbody>(); val2.mass = 18f; val2.drag = 0.25f; val2.angularDrag = 1.5f; val2.collisionDetectionMode = (CollisionDetectionMode)2; PhotonView val3 = _grabProxyPrefab.AddComponent<PhotonView>(); PhysGrabObject val4 = _grabProxyPrefab.AddComponent<PhysGrabObject>(); val4.rb = val2; BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeof(PhysGrabObject).GetField("isEnemy", bindingAttr); FieldInfo field2 = typeof(PhysGrabObject).GetField("isNonValuable", bindingAttr); if (field != null) { field.SetValue(val4, true); } if (field2 != null) { field2.SetValue(val4, true); } _grabProxyPrefab.AddComponent<MimicGrabProxy>(); val3.ObservedComponents = new List<Component> { (Component)(object)val4 }; val3.Synchronization = (ViewSynchronization)3; Type type = ResolveREPOLibNetworkPrefabsType(); MethodInfo methodInfo = ((type != null) ? type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "RegisterNetworkPrefab" && method.GetParameters().Length == 2) : null); if (methodInfo == null) { throw new MissingMethodException("REPOLib NetworkPrefabs.RegisterNetworkPrefab was not found"); } _grabProxyPrefabRef = methodInfo.Invoke(null, new object[2] { "MimicReplay/GrabProxy", _grabProxyPrefab }); if (_grabProxyPrefabRef == null) { throw new InvalidOperationException("REPOLib rejected MimicReplay/GrabProxy"); } Log.LogInfo((object)"Registered network PhysGrabObject proxy for mimics"); } catch (Exception ex) { Log.LogError((object)("Mimic grab proxy registration failed: " + ex.GetBaseException().Message)); _grabProxyPrefabRef = null; } } private void SpawnGrabProxy(int mimicId, Vector3 position, Quaternion rotation) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) if (_grabProxyPrefabRef == null) { SpawnLocalGrabProxy(mimicId, position, rotation); return; } try { Type type = ResolveREPOLibNetworkPrefabsType(); if (type == null) { throw new TypeLoadException("REPOLib.Modules.NetworkPrefabs was not found in loaded assemblies"); } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "SpawnNetworkPrefab" && method.GetParameters().Length == 5); if (methodInfo == null) { throw new MissingMethodException("REPOLib NetworkPrefabs.SpawnNetworkPrefab was not found"); } object? obj = methodInfo.Invoke(null, new object[5] { _grabProxyPrefabRef, position, rotation, (byte)0, new object[1] { mimicId } }); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("REPOLib returned no grab proxy instance"); } val.SetActive(true); MimicGrabProxy component = val.GetComponent<MimicGrabProxy>(); if ((Object)(object)component != (Object)null) { component.Bind(mimicId); } } catch (Exception ex) { Log.LogError((object)("Mimic grab proxy spawn failed: " + ex.GetBaseException().Message)); } } private static Type ResolveREPOLibNetworkPrefabsType() { Type type = Type.GetType("REPOLib.Modules.NetworkPrefabs, REPOLib", throwOnError: false) ?? AccessTools.TypeByName("REPOLib.Modules.NetworkPrefabs"); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (string.Equals(assembly.GetName().Name, "REPOLib", StringComparison.OrdinalIgnoreCase)) { type = assembly.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false); if (type != null) { return type; } } } return null; } private void SpawnLocalGrabProxy(int mimicId, Vector3 position, Quaternion rotation) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_grabProxyPrefab == (Object)null) { return; } try { GameObject val = Object.Instantiate<GameObject>(_grabProxyPrefab, position, rotation); ((Object)val).name = "MimicReplay_GrabProxy_Local_" + mimicId; val.SetActive(true); MimicGrabProxy component = val.GetComponent<MimicGrabProxy>(); if ((Object)(object)component != (Object)null) { component.Bind(mimicId); RegisterGrabProxy(mimicId, component); Log.LogWarning((object)"Using local mimic physics proxy because REPOLib network registration is unavailable"); } } catch (Exception ex) { Log.LogError((object)("Mimic local grab proxy spawn failed: " + ex.GetBaseException().Message)); } } 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(HurtCollider), "CanHit")] internal static class MimicHurtColliderPatch { private static readonly FieldInfo EnemyDamageField = AccessTools.Field(typeof(HurtCollider), "enemyDamage"); private static readonly FieldInfo EnemyKillField = AccessTools.Field(typeof(HurtCollider), "enemyKill"); private static readonly FieldInfo EnemyHitForceField = AccessTools.Field(typeof(HurtCollider), "enemyHitForce"); private static bool Prefix(HurtCollider __instance, GameObject hitObject, Vector3 hitPosition, ref bool __result) { //IL_0084: 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) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hitObject == (Object)null) { return true; } MimicDamageReceiver componentInParent = hitObject.GetComponentInParent<MimicDamageReceiver>(); if ((Object)(object)componentInParent == (Object)null) { return true; } int num = ((EnemyDamageField != null) ? Convert.ToInt32(EnemyDamageField.GetValue(__instance)) : 0); bool flag = EnemyKillField != null && Convert.ToBoolean(EnemyKillField.GetValue(__instance)); float force = ((EnemyHitForceField != null) ? Convert.ToSingle(EnemyHitForceField.GetValue(__instance)) : 0f); Vector3 val = hitPosition - ((Component)__instance).transform.position; if (((Vector3)(ref val)).sqrMagnitude < 0.001f) { val = ((Component)__instance).transform.forward; } componentInParent.ReceiveWeaponHit(flag ? int.MaxValue : Mathf.Max(1, num), ((Vector3)(ref val)).normalized, force); __result = false; return false; } } [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_0076: 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_00a2: 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.SetActive(true); 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; } } Transform val5 = FindClonedMeshRoot(avatar, val.transform, val2.transform); if ((Object)(object)val5 != (Object)null) { ActivateHierarchy(val5, val2.transform); } else if ((Object)(object)val3 != (Object)null) { ActivateHierarchy(val3, val2.transform); } List<string> list = new List<string>(); HashSet<Renderer> hashSet = new HashSet<Renderer>(); MonoBehaviour[] componentsInChildren2 = val2.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val6 in componentsInChildren2) { if (!((Object)(object)val6 == (Object)null) && ((object)val6).GetType().Name.IndexOf("Cosmetic", StringComparison.OrdinalIgnoreCase) >= 0) { Renderer[] componentsInChildren3 = ((Component)val6).GetComponentsInChildren<Renderer>(true); foreach (Renderer item in componentsInChildren3) { hashSet.Add(item); } } } Component[] componentsInChildren4 = val2.GetComponentsInChildren<Component>(true); foreach (Component val7 in componentsInChildren4) { if (!((Object)(object)val7 == (Object)null) && !(val7 is Transform) && !(val7 is Renderer) && !(val7 is Animator) && !(val7 is MeshFilter) && (val7 is Camera || val7 is AudioListener || val7 is Collider || val7 is Rigidbody || val7 is MonoBehaviour)) { list.Add(((object)val7).GetType().FullName); Behaviour val8 = (Behaviour)(object)((val7 is Behaviour) ? val7 : null); if ((Object)(object)val8 != (Object)null) { val8.enabled = false; } Object.Destroy((Object)(object)val7); } } Renderer[] componentsInChildren5 = val2.GetComponentsInChildren<Renderer>(true); foreach (Renderer val9 in componentsInChildren5) { Transform val10 = (((Object)(object)val5 != (Object)null) ? val5 : val3); if (!((Object)(object)val10 == (Object)null) && !((Object)(object)((Component)val9).transform == (Object)(object)val10) && !((Component)val9).transform.IsChildOf(val10) && !hashSet.Contains(val9)) { val9.enabled = false; continue; } val9.shadowCastingMode = (ShadowCastingMode)1; val9.receiveShadows = true; } Renderer[] componentsInChildren6 = val2.GetComponentsInChildren<Renderer>(true); SkinnedMeshRenderer[] componentsInChildren7 = 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)); if (Plugin.Instance.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("Mimic appearance source=" + ((Object)((Component)avatar).gameObject).name + " visualPath=" + GetPath(val.transform) + " renderers=" + componentsInChildren6.Length + " skinnedRenderers=" + componentsInChildren7.Length + " animator=" + ((Object)(object)componentInChildren != (Object)null) + " disabled=[" + string.Join(",", list.ToArray()) + "]")); } int num = 0; Renderer[] array = componentsInChildren6; foreach (Renderer val11 in array) { if ((Object)(object)val11 != (Object)null && val11.enabled && ((Component)val11).gameObject.activeInHierarchy) { num++; } } if (num == 0) { Object.Destroy((Object)(object)val2); mimicAppearanceResult.Error = "visual root has no active Renderer (player appearance is not ready)"; return mimicAppearanceResult; } mimicAppearanceResult.Success = true; return mimicAppearanceResult; } private static void ActivateHierarchy(Transform child, Transform root) { Transform val = child; while ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(true); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } } private static Transform FindClonedMeshRoot(PlayerAvatar avatar, Transform visualRoot, Transform clonedRoot) { FieldInfo field = typeof(PlayerAvatar).GetField("playerAvatarVisuals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Component val = (Component)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { return null; } FieldInfo field2 = ((object)val).GetType().GetField("meshParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); GameObject val2 = (GameObject)((field2 != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null) { return null; } string relativePath = GetRelativePath(visualRoot, val2.transform); if (!string.IsNullOrEmpty(relativePath)) { return clonedRoot.Find(relativePath); } return clonedRoot; } private static string GetRelativePath(Transform root, Transform child) { List<string> list = new List<string>(); Transform val = child; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } if ((Object)(object)val != (Object)(object)root) { return null; } list.Reverse(); return string.Join("/", list.ToArray()); } 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 NavMeshAgent _agent; private 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 LineRenderer[] _navigationRays; private float _nextObstacleRepath; private bool _wasJumping; private bool _wasSprinting; private bool _chaseCrouching; private bool _chaseCrawling; private GameObject _fakeHeldObject; private int _fakeHeldSourceId; private int _health; private Vector3 _externalOffset; private bool _disposed; private float _nextNetworkStateTime; private Vector3 _networkPosition; private Quaternion _networkRotation; private Vector3 _networkVelocity; private Vector3 _networkSmoothVelocity; private float _lastNetworkStateTime; private bool _hasNetworkState; private bool _grabPhysicsActive; private Transform _mouthTransform; private Quaternion _mouthRestRotation; private readonly float[] _mouthSamples = new float[64]; private float _tumbledUntil; private float _replayIdleSince; 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); private static readonly FieldInfo DoorClosedField = typeof(PhysGrabHinge).GetField("closed", BindingFlags.Instance | BindingFlags.NonPublic); private readonly Dictionary<int, float> _doorOpenCooldowns = new Dictionary<int, float>(); internal int NetworkId { get; private set; } internal Vector3 WorldPosition { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_mimicObject != (Object)null)) { return Vector3.zero; } return _mimicObject.transform.position; } } internal Quaternion WorldRotation { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_mimicObject != (Object)null)) { return Quaternion.identity; } return _mimicObject.transform.rotation; } } internal bool CanBeGrabbed { get { if (!(Time.time < _tumbledUntil)) { return _grabPhysicsActive; } return true; } } internal bool IsAlive { get { if (!_disposed) { return (Object)(object)_mimicObject != (Object)null; } return false; } } public MimicController(GameObject source, PlayerRecorder recorder, float selectedDelay, Plugin plugin, bool authoritative, int networkId) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00ec: 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_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: 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_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021d: 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_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) _plugin = plugin; _authoritative = authoritative; NetworkId = networkId; _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; _health = _plugin.MimicHealth.Value; MimicDamageReceiver mimicDamageReceiver = _mimicObject.AddComponent<MimicDamageReceiver>(); mimicDamageReceiver.Initialize(this); int num = ResolveEnemyHitLayer(); if (num >= 0) { _mimicObject.layer = num; } 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; ResolveMouthTransform(); _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 num2 = Random.Range(0f, (float)Math.PI * 2f); Vector3 val5 = new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * _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; _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; CreateNavigationRays(); _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() { if ((Object)(object)_mimicObject == (Object)null || _segment.Count < 2) { return; } if (_grabPhysicsActive) { TickVoiceReplay(); SendNetworkStateIfNeeded(); return; } if (!_authoritative && PhotonNetwork.InRoom) { TickNetworkReplica(); TickVoiceReplay(); return; } UpdateVision(); if (_mode == MimicMode.Replay) { TickReplay(); } else if (_mode == MimicMode.Chase) { TickChase(); } else if (_mode == MimicMode.Attack) { TickAttack(); } else { TickStuckRecovery(); } TickVoiceReplay(); SendNetworkStateIfNeeded(); if (_plugin.VerboseLogging.Value && Time.unscaledTime >= _nextVerboseLogTime) { _nextVerboseLogTime = Time.unscaledTime + 1f; LogPath("periodic"); } } private void SendNetworkStateIfNeeded() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (_authoritative && PhotonNetwork.InRoom && !(Time.unscaledTime < _nextNetworkStateTime)) { _nextNetworkStateTime = Time.unscaledTime + 0.1f; _plugin.SendMimicState(NetworkId, _mimicObject.transform.position, _mimicObject.transform.rotation); } } internal void ApplyGrabPose(Vector3 position, Quaternion rotation, bool active) { //IL_0099: Unknown result type (might