Decompiled source of Spectate v1.5.10
Spectate.dll
Decompiled 10 minutes 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.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading.Tasks; using AIGraph; using Agents; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Utils.Collections; using CellMenu; using CullingSystem; using Enemies; using GameData; using Globals; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using Player; using SNetwork; using Spectate.Config; using Spectate.Patches; using Spectate.Patches.Compat; using Spectate.UI; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Spectate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Spectate")] [assembly: AssemblyTitle("Spectate")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace Spectate { public class AgentTarget { public readonly PlayerAgent Agent; public Transform Transform => ((Component)Agent).transform; public FPSCamera? FPSCamera => Agent.FPSCamera; public FirstPersonItemHolder? FPHolder => Agent.FPItemHolder; public PlayerLocomotion Locomotion => Agent.Locomotion; public PLOC_State LocomotionStateEnum => Locomotion.m_currentStateEnum; public bool IsDowned => (int)LocomotionStateEnum == 7; public PlayerSyncModelData PlayerModel => Agent.PlayerSyncModel; public SNet_Player SAgent => Agent.Owner; public bool IsBot => SAgent.IsBot; public bool IsLocal => SAgent.IsLocal; public Dam_PlayerDamageBase Damage => Agent.Damage; public float Health => ((Dam_SyncedDamageBase)Damage).Health / ((Dam_SyncedDamageBase)Damage).HealthMax; public float HealthPercent => Health * 100f; public float Infection => Damage.Infection; public float InfectionPercent => Infection * 100f; public PlayerInventoryBase? Inventory => Agent.Inventory; public InventorySlot? ActiveItemSlot { get { //IL_0014: Unknown result type (might be due to invalid IL or missing references) PlayerInventoryBase? inventory = Inventory; if (inventory == null) { return null; } return inventory.WieldedSlot; } } public AIG_CourseNode? CourseNode { get { if (IsCaptured) { PouncerTracker? instance = PouncerTracker.Instance; if (instance != null && instance.TryGetCapturingPouncer(Agent, out PouncerBehaviour capturingPouncer)) { object obj; if (capturingPouncer == null) { obj = null; } else { EnemyAI ai = ((EnemyBehaviour)capturingPouncer).m_ai; if (ai == null) { obj = null; } else { EnemyAgent enemyAgent = ai.m_enemyAgent; obj = ((enemyAgent != null) ? ((Agent)enemyAgent).CourseNode : null); } } if (obj == null) { obj = ((Agent)Agent).CourseNode; } return (AIG_CourseNode?)obj; } } return ((Agent)Agent).CourseNode; } } public PlayerBackpack? Backpack => PlayerBackpackManager.GetBackpack(Agent.Owner); public PlayerAmmoStorage? AmmoStorage { get { PlayerBackpack? backpack = Backpack; if (backpack == null) { return null; } return backpack.AmmoStorage; } } public bool HasClipData { get { if (IsLocal) { return true; } if (PlayerManager.GetLocalPlayerAgent().Owner.IsMaster && IsBot) { return true; } return false; } } public bool IsCaptured { get { if ((Object)(object)PouncerTracker.Instance != (Object)null) { return PouncerTracker.Instance.IsCaptured(Agent); } return false; } } public static bool CanSpectate(PlayerAgent agent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 bool num = (int)agent.Locomotion.m_currentStateEnum == 7; bool flag = (Object)(object)PouncerTracker.Instance != (Object)null && PouncerTracker.Instance.IsCaptured(agent); if (num) { return !flag; } return false; } public AgentTarget(PlayerAgent agent) { Agent = agent; } public void SetRigActive(bool active) { Util.SetTargetActiveIfDiff(((Component)Agent.PlayerSyncModel).gameObject, active); } public void SetHostHiddenRigActive(bool active) { PlayerSyncModelData playerSyncModel = Agent.PlayerSyncModel; if (((Il2CppArrayBase<GameObject>)(object)playerSyncModel.m_gfxHead).Count == 0 || ((Il2CppArrayBase<GameObject>)(object)playerSyncModel.m_gfxArms).Count == 0) { Util.FindAndSortGfxParts(((Component)playerSyncModel).gameObject, out GameObject[] gfxHead, out GameObject[] gfxArms, out GameObject[] gfxTorso, out GameObject[] gfxLegs); playerSyncModel.m_gfxHead = Il2CppReferenceArray<GameObject>.op_Implicit(gfxHead); playerSyncModel.m_gfxArms = Il2CppReferenceArray<GameObject>.op_Implicit(gfxArms); playerSyncModel.m_gfxTorso = Il2CppReferenceArray<GameObject>.op_Implicit(gfxTorso); playerSyncModel.m_gfxLegs = Il2CppReferenceArray<GameObject>.op_Implicit(gfxLegs); } playerSyncModel.SetHeadVisible(active, active); playerSyncModel.SetArmsVisible(active, active); } public void SetRigTorsoLegsActive(bool active) { PlayerSyncModelData playerSyncModel = Agent.PlayerSyncModel; playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, active, active); playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, active, active); } public static bool operator ==(AgentTarget? a, AgentTarget? b) { if ((object)a == b) { return true; } if ((object)a == null) { if ((object)b != null) { return (Object)(object)b.Agent == (Object)null; } return true; } if ((object)b == null) { return (Object)(object)a.Agent == (Object)null; } return (Object)(object)a.Agent == (Object)(object)b.Agent; } public static bool operator !=(AgentTarget? a, AgentTarget? b) { return !(a == b); } public override bool Equals(object? other) { if (other is AgentTarget agentTarget) { return this == agentTarget; } return false; } public override int GetHashCode() { return ((Object)Agent).GetHashCode(); } } public static class Events { public static event Action? OnSessionEnd; public static event Action? OnSessionStart; public static event Action? OnAnyPlayerDeath; public static event Action? OnCheckpointReload; internal static void RaiseSessionEnd() { Events.OnSessionEnd?.Invoke(); } internal static void RaiseSessionStart() { Events.OnSessionStart?.Invoke(); } internal static void RaiseAnyPlayerDeath() { Events.OnAnyPlayerDeath?.Invoke(); } internal static void RaiseCheckpointReload() { Events.OnCheckpointReload?.Invoke(); } } public class InputHelper { public static int GetAlphaNumKeyDown() { int result = -1; for (int i = 0; i < 10; i++) { if (Input.GetKeyDown((KeyCode)(48 + i))) { result = i; break; } } return result; } public static bool OnlyModifies(KeyCode mod, KeyCode altMod = 0, KeyCode nonMod = 0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Invalid comparison between Unknown and I4 //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Invalid comparison between Unknown and I4 //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 bool num = Input.GetKey(mod) || Input.GetKey(altMod) || Input.GetKeyDown(nonMod); bool flag = false; if ((int)mod != 304 && (int)mod != 303 && (int)altMod != 304 && (int)altMod != 303) { flag |= Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); } if ((int)mod != 306 && (int)mod != 305 && (int)altMod != 306 && (int)altMod != 305) { flag |= Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); } if ((int)mod != 308 && (int)mod != 307 && (int)altMod != 308 && (int)altMod != 307) { flag |= Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); } if (num) { return !flag; } return false; } public static Vector2 GetMouseDelta() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Vector2(InputMapper.GetAxis.Invoke((InputAction)3, (eFocusState)0), InputMapper.GetAxis.Invoke((InputAction)4, (eFocusState)0)); } } internal static class Logger { private static ManualLogSource _mLogSource; public static bool Ready => _mLogSource != null; public static void Setup() { _mLogSource = Logger.CreateLogSource("io.takina.gtfo.Spectate"); } public static void SetupFromInit(ManualLogSource logSource) { _mLogSource = logSource; } private static string Format(object data) { return data.ToString(); } public static void Debug(object msg) { if (ConfigMgr.Debug) { _mLogSource.LogInfo((object)("[DEBUG] " + Format(msg))); } else { _mLogSource.LogDebug((object)Format(msg)); } } public static void Info(object msg) { _mLogSource.LogInfo((object)Format(msg)); } public static void Warn(object msg) { _mLogSource.LogWarning((object)Format(msg)); } public static void Error(object msg) { _mLogSource.LogError((object)Format(msg)); } public static void Fatal(object msg) { _mLogSource.LogFatal((object)Format(msg)); } } [BepInPlugin("io.takina.gtfo.Spectate", "Spectate", "1.5.10")] public class Plugin : BasePlugin { public const string NAME = "Spectate"; public const string GUID = "io.takina.gtfo.Spectate"; public const string VERSION = "1.5.10"; public static GameObject? PluginObject; public event Action? OnManagersSetup; public override void Load() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown Logger.Setup(); Logger.Info("Spectate [io.takina.gtfo.Spectate @ 1.5.10]"); Harmony val = new Harmony("io.takina.gtfo.Spectate"); ConfigMgr.Process(); ClassInjector.RegisterTypeInIl2Cpp<SpectateCam>(); ClassInjector.RegisterTypeInIl2Cpp<SpectateUI>(); ClassInjector.RegisterTypeInIl2Cpp<SpectateConfigUpdater>(); ClassInjector.RegisterTypeInIl2Cpp<PouncerTracker>(); ClassInjector.RegisterTypeInIl2Cpp<PouncerTrackingDart>(); ClassInjector.RegisterTypeInIl2Cpp<Wm>(); OnManagersSetup += Initialize; Global.OnAllManagersSetup += Action.op_Implicit(this.OnManagersSetup); Logger.Info("Patching..."); ApplyPatch<EventPatch>(val); ApplyPatch<UIPatch>(val); ApplyPatch<CameraPatch>(val); ApplyPatch<AnimationPatch>(val); ApplyPatch<PouncerPatch>(val); CompatPatcher.PatchAll(val); Logger.Info("Finished Patching"); } private static void ApplyPatch<T>(Harmony h) { h.PatchAll(typeof(T)); } private void Initialize() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Logger.Debug("Initializing Spectate GameObject's..."); PluginObject = new GameObject("io.takina.gtfo.Spectate"); Object.DontDestroyOnLoad((Object)(object)PluginObject); SpectateUI spectateUI = PluginObject.AddComponent<SpectateUI>(); PluginObject.AddComponent<SpectateCam>(); PluginObject.AddComponent<SpectateConfigUpdater>(); PluginObject.AddComponent<PouncerTracker>(); PluginObject.AddComponent<Wm>(); spectateUI.ReplicateUI(); } public override bool Unload() { ConfigMgr.WriteConfigIfDirty(); return true; } } public class PouncerTracker : MonoBehaviour { private const float CleanupDelay = 10f; private float _timeUntilCleanup; public static PouncerTracker? Instance { get; private set; } public bool IsLocalPlayerSnatched { get; private set; } private List<PouncerBehaviour> ActivePouncers { get; } = new List<PouncerBehaviour>(); public PouncerTracker(IntPtr ptr) : base(ptr) { } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } else if ((Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)this); } } private void Update() { if (_timeUntilCleanup > 0f) { _timeUntilCleanup -= Time.deltaTime; if (_timeUntilCleanup <= 0f) { CleanupPouncers(); _timeUntilCleanup = 10f; } } } public void RegisterPouncer(PouncerBehaviour pouncer) { if (!ActivePouncers.Contains(pouncer)) { ActivePouncers.Add(pouncer); ((Component)pouncer).gameObject.AddComponent<PouncerTrackingDart>(); IsLocalPlayerSnatched = true; } } public void UnregisterPouncer(GameObject pouncer) { foreach (PouncerBehaviour activePouncer in ActivePouncers) { if ((Object)(object)((Component)activePouncer).gameObject == (Object)(object)pouncer || ((Il2CppObjectBase)((Component)activePouncer).gameObject).Pointer == ((Il2CppObjectBase)pouncer).Pointer) { ActivePouncers.Remove(activePouncer); break; } } } public bool IsCaptured(PlayerAgent agent) { foreach (PouncerBehaviour activePouncer in ActivePouncers) { if (!((Object)(object)activePouncer == (Object)null) && !((Object)(object)activePouncer.CapturedPlayer == (Object)null) && ((Il2CppObjectBase)activePouncer.CapturedPlayer).Pointer == ((Il2CppObjectBase)agent).Pointer) { return true; } } return false; } public bool TryGetCapturingPouncer(PlayerAgent agent, out PouncerBehaviour? capturingPouncer) { foreach (PouncerBehaviour activePouncer in ActivePouncers) { if (!((Object)(object)activePouncer == (Object)null) && !((Object)(object)activePouncer.CapturedPlayer == (Object)null) && ((Il2CppObjectBase)activePouncer.CapturedPlayer).Pointer == ((Il2CppObjectBase)agent).Pointer) { capturingPouncer = activePouncer; return true; } } capturingPouncer = null; return false; } private void CleanupPouncers() { ActivePouncers.RemoveAll((PouncerBehaviour p) => (Object)(object)p == (Object)null || !((Component)p).gameObject.activeInHierarchy); } } public class PouncerTrackingDart : MonoBehaviour { public PouncerTrackingDart(IntPtr ptr) : base(ptr) { } private void OnDestroy() { if ((Object)(object)PouncerTracker.Instance != (Object)null) { PouncerTracker.Instance.UnregisterPouncer(((Component)this).gameObject); } } } public class SpectateCam : MonoBehaviour { private bool _wasActive; private int _lastTargetPlayerIdx = -1; private bool _freecam = ConfigMgr.DefaultFreecamView; private bool _freecamFollow = ConfigMgr.AutoTransitionToFollowView; private float _freeLookReturnTimer; private PouncerBehaviour? _lastPouncer; public const float DownToSpectateDelay = 1f; private float _pitch = ConfigMgr.CameraPitchAngleDeg; private float _yaw; private float _pitchTarget = ConfigMgr.CameraPitchAngleDeg; private float _yawTarget; private float _eyeY; private float _eyeYTarget; private Vector3 _eyeXZ = Vector3.zero; private Vector3 _eyeXZTarget = Vector3.zero; private Vector3 _camPosComputed = Vector3.zero; public const float DefaultCameraYPositionLerpGain = 11f; public const float DefaultCameraXZPositionLerpGain = 15f; public const float DefaultCameraLerpGain = 6f; public const float DefaultOrbitCenterVerticalOffset = 0.325f; public const float DefaultPitchAngleDeg = -18.75f; public const float DefaultDistanceFromEye = 0.625f; public const float DefaultScrollSensitivity = 0.5f; public const float DefaultFreecamSensitivity = 1f; public const float OrbitCenterVerticalOffsetMin = -1f; public const float OrbitCenterVerticalOffsetMax = 5f; public const float DistanceMin = 0.1f; public const float DistanceMax = 5f; public const float DistanceOffsetPouncer = 1.3f; public const float PitchAngleDegMin = -89f; public const float PitchAngleDegMax = 89f; private AgentTarget? _self; private AgentTarget? _target; public static SpectateCam? Instance { get; set; } public bool SelfReady { get { if (_self != null) { return (Object)(object)_self.FPSCamera != (Object)null; } return false; } } public bool TargetReady => _target != null; public bool Active { get; private set; } public bool Freecam => _freecam; public C_Node? LastLocalCullNode { get; private set; } public Vector3 DiegeticCamDir { get; private set; } = Vector3.forward; public Vector3 DiegeticPlayerRigScale { get; private set; } = Vector3.one; public Vector3 CameraPos { get { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!Active) { AgentTarget? self = _self; Vector3? obj; if ((object)self == null) { obj = null; } else { FPSCamera? fPSCamera = self.FPSCamera; obj = ((fPSCamera != null) ? new Vector3?(fPSCamera.Position) : null); } return (Vector3)(((??)obj) ?? Vector3.zero); } return _camPosComputed; } } public AgentTarget? Self { get { if (_self == null) { _self = new AgentTarget(PlayerManager.GetLocalPlayerAgent()); } return _self; } } public AgentTarget? Target => _target; public bool CanSpectate { get { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); bool flag = (Object)(object)localPlayerAgent != (Object)null && AgentTarget.CanSpectate(localPlayerAgent); return ConfigMgr.DevEnables(eDevOpts.AllowSpectatingAnytime) || flag; } } public event Action? OnActive; public SpectateCam(IntPtr ptr) : base(ptr) { }//IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; Object.DontDestroyOnLoad((Object)(object)this); Events.OnSessionStart += delegate { Load(); }; Events.OnSessionEnd += delegate { Unload(); }; Events.OnAnyPlayerDeath += delegate { if (ConfigMgr.PreferSpectateAlive && (_target == null || _target.IsDowned)) { TrySetAnyNonLocalTarget(); } }; Events.OnCheckpointReload += delegate { if (Active) { Detach(); } Unload(); }; } public bool Load() { PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent == (Object)null) { Logger.Error("SpectateCam: Failed to load - local player agent is null"); return false; } _self = new AgentTarget(localPlayerAgent); return (Object)(object)_self.FPSCamera != (Object)null; } public bool Unload() { SetActive(active: false); _self = null; _target = null; return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetTarget(PlayerAgent agent) { _target = new AgentTarget(agent); } public void TryAttachDelayed(float delay) { ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(TryAttachDelayedCoroutine(delay))); } private IEnumerator TryAttachDelayedCoroutine(float delay) { yield return (object)new WaitForSeconds(delay); if (!Attach()) { Logger.Warn("SpectateCam: TryAttachDelayed failed to attach after delay"); } } public bool Attach() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (Active) { return true; } if (!SelfReady && !Load()) { Logger.Error("SpectateCam: Attach failed - self not ready and cannot be loaded"); return false; } if (!CanSpectate) { return false; } if (!TargetReady && !TrySetAnyNonLocalTarget()) { Logger.Warn("SpectateCam: Attach failed - no valid target available"); return false; } DiegeticCamDir = _self.FPSCamera.Forward; DiegeticPlayerRigScale = ((Component)_self.PlayerModel).gameObject.transform.localScale; AgentTarget? self = _self; object lastLocalCullNode; if ((object)self == null) { lastLocalCullNode = null; } else { AIG_CourseNode? courseNode = self.CourseNode; lastLocalCullNode = ((courseNode != null) ? courseNode.m_cullNode : null); } LastLocalCullNode = (C_Node?)lastLocalCullNode; ((Component)_self.PlayerModel).gameObject.transform.localScale = Vector3.one; GuiManager.PlayerLayer.ApplyMovementSway(Vector3.zero); GuiManager.CrosshairLayer.ShowPrecisionDot(); SpectateUI.Instance?.UpdateForAttach(); SetRelatedActive(spectateActive: true); UpdateCull(); SetActive(active: true); return true; } public bool Detach() { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return true; } if (!SelfReady && !Load()) { Logger.Error("SpectateCam: Detach failed - self not ready and cannot be loaded"); Logger.Info("SpectateCam: Detach falling back to Unload"); Unload(); return false; } SetActive(active: false); SetRelatedActive(spectateActive: false); RevertCull(); SpectateUI.Instance?.UpdateForDetach(); CrosshairGuiLayer crosshairLayer = GuiManager.CrosshairLayer; if (crosshairLayer != null) { FirstPersonItemHolder? fPHolder = _self.FPHolder; float? obj; if (fPHolder == null) { obj = null; } else { ItemEquippable wieldedItem = fPHolder.WieldedItem; obj = ((wieldedItem != null) ? new float?(wieldedItem.HipFireCrosshairSize) : null); } crosshairLayer.ShowSpreadCircle(obj ?? 40f); } PlayerGuiLayer playerLayer = GuiManager.PlayerLayer; if (playerLayer != null) { PUI_LocalPlayerStatus playerStatus = playerLayer.m_playerStatus; if (playerStatus != null) { playerStatus.ResetDamageAnimation(); } } ((Component)_self.PlayerModel).gameObject.transform.localScale = DiegeticPlayerRigScale; return true; } private void SetActive(bool active) { if (active && !_wasActive) { this.OnActive?.Invoke(); } _wasActive = Active; Active = active; if (!Active) { _yaw = 0f; _pitch = ConfigMgr.CameraPitchAngleDeg; _freeLookReturnTimer = 0f; } } internal void SetRelatedActive(bool spectateActive) { if (!SelfReady) { Logger.Error("SpectateCam: SetRelatedActive failed - self not ready"); return; } if (ConfigMgr.ShowPlayerBodyWhenSpectating) { _self.SetHostHiddenRigActive(spectateActive); if (!Self.IsDowned && !spectateActive) { _self.SetRigTorsoLegsActive(active: true); } else { _self.SetRigTorsoLegsActive(spectateActive); } } else { _self.SetRigActive(!spectateActive); } _self.Agent.DeadDebugMode = spectateActive; _self.PlayerModel.GhostEnabled = spectateActive; Util.SetTargetActiveIfDiff((Behaviour?)(object)_self.Inventory, !spectateActive); PlayerInventoryBase? inventory = _self.Inventory; Util.SetTargetActiveIfDiff((inventory != null) ? ((Component)inventory.m_flashlight).gameObject : null, !spectateActive); FirstPersonItemHolder? fPHolder = _self.FPHolder; Util.SetTargetActiveIfDiff((fPHolder != null) ? ((Component)fPHolder).gameObject : null, !spectateActive); FirstPersonItemHolder? fPHolder2 = _self.FPHolder; if (fPHolder2 != null) { PlayerFPSBody fPSArms = fPHolder2.FPSArms; if (fPSArms != null) { fPSArms.SetVisible(!spectateActive && !_self.IsDowned); } } FPSCamera fPSCamera = _self.FPSCamera; if ((Object)(object)fPSCamera != (Object)null) { fPSCamera.MouseLookEnabled = !spectateActive; fPSCamera.PlayerAgentRotationEnabled = !spectateActive; } } private void Update() { if (!((Behaviour)this).enabled || !((Component)this).gameObject.activeInHierarchy) { return; } ProcessInput(); UpdateTransitions(); if (Active) { if (!TargetReady || !SelfReady) { Detach(); return; } UpdateLerp(_freecam); UpdateCamera(); UpdateCull(); } } private void UpdateTransitions() { if (SelfReady) { if (Active && !_self.IsDowned && !ConfigMgr.DevEnables(eDevOpts.AllowSpectatingAnytime)) { Detach(); } else if (Active && ConfigMgr.AutoTransitionToFollowView && _freeLookReturnTimer >= 0f) { _freeLookReturnTimer -= Time.deltaTime; } } } private void ProcessInput() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Invalid comparison between Unknown and I4 //IL_01c9: Unknown result type (might be due to invalid IL or missing references) if (!InputMapper.Current.FocusStateFilterPass((eFocusState)4)) { return; } if (CanSpectate && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleSpectate))) { if (Active) { if (!Detach()) { Logger.Warn("SpectateCam: Failed to detach SpecCam"); } } else if (!Attach()) { Logger.Warn("SpectateCam: Failed to attach SpecCam"); } } if (!Active) { return; } if (Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleFreecam))) { if (_freecam) { _freecam = false; OnFree2Follow(); } else { _freecam = true; OnFollow2Free(); } } if (_freecam && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleAutoFollow))) { ConfigMgr.AutoTransitionToFollowView = !ConfigMgr.AutoTransitionToFollowView; SpectateUI.Instance?.MarkUIDirty(); } Vector2 mouseDelta = InputHelper.GetMouseDelta(); if (_freecam && mouseDelta != Vector2.zero) { AdjustYaw(mouseDelta.x * ConfigMgr.FreecamSensitivity); AdjustPitch(mouseDelta.y * ConfigMgr.FreecamSensitivity); if (ConfigMgr.AutoTransitionToFollowView) { _freecamFollow = false; _freeLookReturnTimer = ConfigMgr.AutoTransitionDelay; } } if (_freecam) { if (Input.GetKey((KeyCode)273)) { AdjustPitch(ConfigMgr.FreecamSensitivity); } if (Input.GetKey((KeyCode)274)) { AdjustPitch(0f - ConfigMgr.FreecamSensitivity); } if (Input.GetKey((KeyCode)276)) { AdjustYaw(0f - ConfigMgr.FreecamSensitivity); } if (Input.GetKey((KeyCode)275)) { AdjustYaw(ConfigMgr.FreecamSensitivity); } } if (Input.GetKeyDown((KeyCode)323)) { TrySetNextTarget(); } if (Input.GetKeyDown((KeyCode)324)) { TrySetPreviousTarget(); } if ((int)FocusStateManager.Current.m_currentState != 6) { int alphaNumKeyDown = InputHelper.GetAlphaNumKeyDown(); if (alphaNumKeyDown > 0) { TrySetTargetByIdx(alphaNumKeyDown - 1, overridePreferAlive: true); } } float num = Input.mouseScrollDelta.y * ConfigMgr.ScrollSensitivity; if (InputMapper.Current.FocusStateFilterPass((eFocusState)6) || !(Mathf.Abs(num) > 0f)) { return; } if (InputHelper.OnlyModifies((KeyCode)304, (KeyCode)303, (KeyCode)0)) { if (_freecam) { SpectateUI.Instance?.WarnFreecamNoAdjustPitch(); } else { ConfigMgr.CameraPitchAngleDeg -= 0.5f * num; } } else if (InputHelper.OnlyModifies((KeyCode)306, (KeyCode)305, (KeyCode)0)) { ConfigMgr.CameraOrbitVerticalOffset = Mathf.Clamp(ConfigMgr.CameraOrbitVerticalOffset + 0.05f * num, -1f, 5f); } else { ConfigMgr.CameraDistance = Mathf.Clamp(ConfigMgr.CameraDistance - 0.05f * num, 0.1f, 5f); } } private void UpdateCamera() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b2: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (!SelfReady || !TargetReady) { Logger.Error("SpectateCam: UpdateCamera failed - target or self not ready"); return; } if (ConfigMgr.AutoTransitionToFollowView && _freecam) { if (_freeLookReturnTimer < 0.001f) { _freecamFollow = true; } if (_freecamFollow) { UpdateYawPitchWithFollowView(instant: false); } } SetEye(GetTargetOrbitCenter()); Vector3 val = _eyeXZ + Vector3.up * _eyeY; Vector3 forward = ((Agent)_target.Agent).Forward; Vector3 val2 = ((Vector3)(ref forward)).normalized; if (_freecam) { val2 = Quaternion.Euler(0f, _yaw, 0f) * Vector3.forward; } float num = (float)Math.PI / 180f * (_freecam ? _pitch : ConfigMgr.CameraPitchAngleDeg); Vector3 val3 = val2 + Vector3.up * Mathf.Tan(num); ((Vector3)(ref val3)).Normalize(); float num2 = ConfigMgr.CameraDistance; if (_target.IsCaptured) { num2 = Mathf.Clamp(num2 + 1.3f, 0.1f, 5f); } _camPosComputed = val - val3 * num2; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val, -val3, ref val4, num2, LayerManager.MASK_WORLD)) { _camPosComputed = val4.m_Point + val3 * 0.1f; } _self.FPSCamera.OverridePositionAndRotation(_camPosComputed, Quaternion.LookRotation(val3)); _self.FPSCamera.OverrideFieldOfView((float)CellSettingsManager.GetIntValue((eCellSettingID)52)); } private void UpdateLerp(bool freecamEnabled) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) _eyeXZ = Vector3.Lerp(_eyeXZ, _eyeXZTarget, Time.deltaTime * ConfigMgr.CameraXZLerpGain); _eyeY = Mathf.Lerp(_eyeY, _eyeYTarget, Time.deltaTime * ConfigMgr.CameraYLerpGain); if (freecamEnabled) { _yaw = Mathf.LerpAngle(_yaw, _yawTarget, Time.deltaTime * ConfigMgr.FreecamLerpGain); float num = _yawTarget - _yaw; _yaw = Mathf.Repeat(_yaw, 360f); _yawTarget = _yaw + num; _pitch = Mathf.LerpAngle(_pitch, _pitchTarget, Time.deltaTime * ConfigMgr.FreecamLerpGain); } } private void UpdateCull() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!SelfReady || !TargetReady) { Logger.Error("SpectateCam: UpdateCull failed - target or self not ready"); return; } Vector3 val = GetTargetOrbitCenter(); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 64f, LayerManager.MASK_WORLD)) { val = val2.m_Point; } CameraManager.CullingPosition = val; CameraManager.CullingDirection = _self.FPSCamera.Forward; _self.Agent.m_movingCuller.UpdatePosition(((Agent)_self.Agent).m_dimensionIndex, val); C_Node currentNode = _self.Agent.m_movingCuller.CurrentNode; AIG_CourseNode? courseNode = _target.CourseNode; C_Node val3 = ((courseNode != null) ? courseNode.m_cullNode : null); if (val3 != null) { if (((Il2CppObjectBase)currentNode).Pointer != ((Il2CppObjectBase)val3).Pointer) { _self.Agent.m_movingCuller.SetCurrentNode(val3); } } else { Logger.Warn("SpectateCam: UpdateCull - failed to sync cull nodes, target node is null"); } } private void RevertCull() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0055: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!SelfReady) { Logger.Error("SpectateCam: RevertCull failed - self is not ready"); return; } Vector3 val = ((Agent)_self.Agent).Position; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 64f, LayerManager.MASK_WORLD)) { val = val2.m_Point; } CameraManager.CullingPosition = val; CameraManager.CullingDirection = _self.FPSCamera.Forward; _self.Agent.m_movingCuller.UpdatePosition(((Agent)_self.Agent).m_dimensionIndex, val); C_Node currentNode = _self.Agent.m_movingCuller.CurrentNode; if (LastLocalCullNode != null) { IntPtr? intPtr = ((currentNode != null) ? new IntPtr?(((Il2CppObjectBase)currentNode).Pointer) : null); C_Node? lastLocalCullNode = LastLocalCullNode; if (intPtr != ((lastLocalCullNode != null) ? new IntPtr?(((Il2CppObjectBase)lastLocalCullNode).Pointer) : null)) { _self.Agent.m_movingCuller.SetCurrentNode(LastLocalCullNode); } } else { Logger.Warn("SpectateCam: RevertCull - failed to sync cull nodes self or target node is null"); } } public void ClearTarget() { _target = null; _lastTargetPlayerIdx = -1; } private bool TrySetAnyNonLocalTarget() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) SNet_PlayerSlotManager slots = SNet.Slots; List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null); if (val == null || val.Count == 0) { return false; } float num = float.MaxValue; _lastTargetPlayerIdx = -1; for (int i = 0; i < val.Count; i++) { if (SimulateSetTargetIdx(i, out PlayerAgent agent)) { float num2 = Vector3.Distance(((Agent)agent).Position, ((Agent)_self.Agent).Position); if (num2 < num) { num = num2; _lastTargetPlayerIdx = i; } } } if (_lastTargetPlayerIdx != -1) { return TrySetTargetByIdx(_lastTargetPlayerIdx); } return false; } private bool TrySetNextTarget() { SNet_PlayerSlotManager slots = SNet.Slots; int num = ((slots == null) ? null : slots.SlottedPlayers?.Count) ?? (-1); if (num <= 0) { return false; } for (int i = 1; i <= num; i++) { int playerIdx = (_lastTargetPlayerIdx + i) % num; if (TrySetTargetByIdx(playerIdx)) { return true; } } return false; } private bool TrySetPreviousTarget() { SNet_PlayerSlotManager slots = SNet.Slots; int num = ((slots == null) ? null : slots.SlottedPlayers?.Count) ?? (-1); if (num <= 0) { return false; } for (int i = 1; i <= num; i++) { int playerIdx = (_lastTargetPlayerIdx - i + num) % num; if (TrySetTargetByIdx(playerIdx)) { return true; } } return false; } private bool SimulateSetTargetIdx(int playerIdx, [NotNullWhen(true)] out PlayerAgent? agent, bool overridePreferAlive = false) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Invalid comparison between Unknown and I4 agent = null; SNet_PlayerSlotManager slots = SNet.Slots; List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null); if (val == null || val.Count == 0) { return false; } if (playerIdx >= 0 && playerIdx < val.Count) { if (val[playerIdx].IsLocal) { return false; } SNet_Player obj = val[playerIdx]; object obj2; if (obj == null) { obj2 = null; } else { SNet_IPlayerAgent playerAgent = obj.PlayerAgent; obj2 = ((playerAgent != null) ? ((Il2CppObjectBase)playerAgent).Cast<PlayerAgent>() : null); } agent = (PlayerAgent?)obj2; if ((Object)(object)agent == (Object)null) { return false; } if (!overridePreferAlive && ConfigMgr.PreferSpectateAlive && (int)agent.Locomotion.m_currentStateEnum == 7) { return false; } return true; } return false; } private bool TrySetTargetByIdx(int playerIdx, bool overridePreferAlive = false) { //IL_0092: 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_0067: Invalid comparison between Unknown and I4 SNet_PlayerSlotManager slots = SNet.Slots; List<SNet_Player> val = ((slots != null) ? slots.SlottedPlayers : null); if (val == null || val.Count == 0) { return false; } if (playerIdx >= 0 && playerIdx < val.Count) { if (val[playerIdx].IsLocal) { return false; } PlayerAgent val2 = ((Il2CppObjectBase)val[playerIdx].PlayerAgent).Cast<PlayerAgent>(); if (!overridePreferAlive && ConfigMgr.PreferSpectateAlive && (int)val2.Locomotion.m_currentStateEnum == 7) { return false; } SetTarget(val2); bool flag = playerIdx != _lastTargetPlayerIdx; if ((ConfigMgr.NoPosLerpOnSwitchTarget && flag) || !_freecam) { SetEye(GetTargetOrbitCenter(), instant: true); } _lastTargetPlayerIdx = playerIdx; return true; } return false; } private Vector3 GetTargetOrbitCenter() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) Vector3 result = Vector3.zero; PlayerAgent agent; if (_target != null) { agent = _target.Agent; if (_target.IsCaptured) { if (!((Object)(object)_lastPouncer == (Object)null)) { PlayerAgent capturedPlayer = _lastPouncer.CapturedPlayer; if (!(((capturedPlayer != null) ? ((Il2CppObjectBase)capturedPlayer).Pointer : IntPtr.Zero) != ((Il2CppObjectBase)agent).Pointer)) { goto IL_0083; } } PouncerTracker? instance = PouncerTracker.Instance; if (instance != null && instance.TryGetCapturingPouncer(agent, out PouncerBehaviour capturingPouncer)) { _lastPouncer = capturingPouncer; } goto IL_0083; } result = _target.Agent.m_eyePosition; } goto IL_00bd; IL_0083: result = (((Object)(object)_lastPouncer == (Object)null) ? agent.m_eyePosition : ((Component)_lastPouncer).transform.position); goto IL_00bd; IL_00bd: result.y += ConfigMgr.CameraOrbitVerticalOffset; return result; } private void OnFollow2Free() { if (!TargetReady) { Logger.Error("SpectateCam: OnTransitionToFreecam failed - target not ready"); return; } UpdateYawPitchWithFollowView(instant: true); SpectateUI.Instance?.MarkUIDirty(); } private void OnFree2Follow() { if (!TargetReady) { Logger.Error("SpectateCam: OnTransitionToFollow failed - target not ready"); return; } UpdateYawPitchWithFollowView(instant: true); SpectateUI.Instance?.MarkUIDirty(); } private void UpdateYawPitchWithFollowView(bool instant) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) SetYaw(Vector3.SignedAngle(Vector3.forward, ((Agent)_target.Agent).Forward, Vector3.up), instant); SetPitch(ConfigMgr.CameraPitchAngleDeg, instant); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void AdjustPitch(float deltaPitch, bool instant = false) { SetPitch(_pitchTarget + deltaPitch, instant); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void AdjustYaw(float deltaYaw, bool instant = false) { SetYaw(_yawTarget + deltaYaw, instant); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetPitch(float pitch, bool instant = false) { pitch = Mathf.Clamp(pitch, -89f, 89f); _pitchTarget = pitch; if (instant) { _pitch = pitch; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetYaw(float yaw, bool instant = false) { _yawTarget = yaw; if (instant) { _yaw = yaw; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetEyeXZ(Vector3 eyeXZ, bool instant = false) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) eyeXZ.y = 0f; _eyeXZTarget = eyeXZ; if (instant) { _eyeXZ = eyeXZ; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetEyeY(float eyeY, bool instant = false) { _eyeYTarget = eyeY; if (instant) { _eyeY = eyeY; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SetEye(Vector3 pos, bool instant = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) SetEyeXZ(pos, instant); SetEyeY(pos.y, instant); } } public class SpectateConfigUpdater : MonoBehaviour { public const float UpdateIntervalSeconds = 5f; private Coroutine _configUpdateCoroutine; public SpectateConfigUpdater(IntPtr ptr) : base(ptr) { } private void Awake() { _configUpdateCoroutine = ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(ConfigUpdateCoroutine())); } private IEnumerator ConfigUpdateCoroutine() { while (true) { yield return (object)new WaitForSeconds(5f); ConfigMgr.WriteConfigIfDirty(); } } private void OnApplicationQuit() { ConfigMgr.WriteConfigIfDirty(); } } public static class Util { public const float GOOD_ENOUGH_DEG_EPS = 0.2f; public static bool GoodEnoughDeg(float a, float b) { return NearlyEqual(a, b, 0.2f); } public static bool NearlyEqual(float a, float b, float eps = 0.0001f) { return Mathf.Abs(a - b) < eps; } public static bool SetTargetActiveIfDiff(GameObject? obj, bool active) { if ((Object)(object)obj == (Object)null) { return false; } if (obj.activeSelf != active) { obj.SetActive(active); } return active; } public static void SetTargetActiveIfDiff(Behaviour? beh, bool active) { if (!((Object)(object)beh == (Object)null) && beh.enabled != active) { beh.enabled = active; } } public static void FindAndSortGfxParts(GameObject root, out GameObject[] gfxHead, out GameObject[] gfxArms, out GameObject[] gfxTorso, out GameObject[] gfxLegs, bool includeInactive = true) { //IL_0035: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected I4, but got Unknown PlayerGfxPart[] array = Il2CppArrayBase<PlayerGfxPart>.op_Implicit(root.GetComponentsInChildren<PlayerGfxPart>(includeInactive)); List<GameObject> list = new List<GameObject>(); List<GameObject> list2 = new List<GameObject>(); List<GameObject> list3 = new List<GameObject>(); List<GameObject> list4 = new List<GameObject>(); PlayerGfxPart[] array2 = array; foreach (PlayerGfxPart val in array2) { PlayerGFXType type = val.m_type; switch ((int)type) { case 0: list.Add(((Component)val).gameObject); break; case 2: case 3: list2.Add(((Component)val).gameObject); break; case 1: case 4: list3.Add(((Component)val).gameObject); break; case 5: list4.Add(((Component)val).gameObject); break; } } gfxHead = list.ToArray(); gfxArms = list2.ToArray(); gfxTorso = list3.ToArray(); gfxLegs = list4.ToArray(); } } } namespace Spectate.UI { public enum eSpectateUIComp { SpectateTarget, Title, ViewMode, Menu } public enum eSpectateMenuItem { HideMenu, ShowMenu, EnterSpectate, ExitSpectate, ToggleFreecam, EnableFreecamAutoTransition, DisableFreecamAutoTransition, SwitchPlayer, SelectPlayer, AdjustDistance, AdjustOrbitCenterHeight, AdjustFollowPitch } public enum eSpectateUIState { FPDowned, FPNotDowned, HideMenu, ShowMenu } public struct MenuKeybindEntry { private string _keyName; private bool _isAssociated; private SpectateInputAction _associatedAction; public MenuKeybindEntry(string keyName) { _isAssociated = false; _associatedAction = SpectateInputAction.None; _keyName = keyName; } public MenuKeybindEntry(SpectateInputAction action) { _isAssociated = true; _associatedAction = action; _keyName = ""; } public override string ToString() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (_isAssociated) { return CellSettingGlobals.GetLocalizedKeyCode(ConfigMgr.GetKeybind(_associatedAction)); } return _keyName; } } public class SpectateUI : MonoBehaviour { private bool _wasUIActive; private bool _isUIDirty = true; private eSpectateUIState _uiState = eSpectateUIState.FPNotDowned; private eSpectateUIState _uiStatePrev = eSpectateUIState.FPNotDowned; private eSpectateUIState _uiStateRendered = eSpectateUIState.ShowMenu; private PlayerAgent? _lastRenderedTarget; private readonly List<GameObject> _uiRoots = new List<GameObject>(); private readonly Dictionary<eSpectateUIComp, bool> _uiCompState = new Dictionary<eSpectateUIComp, bool>(); private bool _wantToRevertPUIStatus; private const float MenuCenterOffsetX = 300f; private const float MenuLeftPadding = 50f; private const float MenuElementWidth = 250f; private const float MenuCenterDivideSpacing = 5f; private const int MaxMenuItems = 10; private const float MenuItemSpacing = 27f; private const float MenuOptionHeight = 22f; private const float MenuKeybindHeight = 16f; private static readonly Vector3 HeadBeaconAlignOffset = new Vector3(0f, 0.3f, 0f); private const float SpectateInvOffsetY = -20f; private const string SpecTargetTextColor = "FFFFFF"; private const string StateHighlightColor = "04B065"; private GameObject? _navMarkerTrackTarget; private NavMarker? _navMarker; private TextMeshPro? _specTargetTmp; private GameObject? _menuObj; private TextMeshPro? _menuTitleTmp; private TextMeshPro? _menuViewModeTmp; private GameObject? _menuListObj; private readonly List<(TextMeshPro?, TextMeshPro?)> _menuItemsTmp = new List<(TextMeshPro, TextMeshPro)>(10); private SpriteRenderer? _menuBackground; private PUI_Inventory? _spectateInv; private string _specTargetStr = ""; private readonly string _menuTitleStr = "SPECTATE"; private string _menuViewModeStr = ""; private readonly List<(string, string)> _menuItemsStr = new List<(string, string)>(); private readonly Dictionary<eSpectateMenuItem, (string, MenuKeybindEntry)> _menuItems = new Dictionary<eSpectateMenuItem, (string, MenuKeybindEntry)> { [eSpectateMenuItem.ShowMenu] = ("Show Menu", new MenuKeybindEntry(SpectateInputAction.ToggleMenu)), [eSpectateMenuItem.HideMenu] = ("Hide Menu", new MenuKeybindEntry(SpectateInputAction.ToggleMenu)), [eSpectateMenuItem.EnterSpectate] = ("Enter Spectate", new MenuKeybindEntry(SpectateInputAction.ToggleSpectate)), [eSpectateMenuItem.ExitSpectate] = ("Exit Spectate", new MenuKeybindEntry(SpectateInputAction.ToggleSpectate)), [eSpectateMenuItem.ToggleFreecam] = ("Toggle Free-Look", new MenuKeybindEntry(SpectateInputAction.ToggleFreecam)), [eSpectateMenuItem.EnableFreecamAutoTransition] = ("Enable Auto-Follow", new MenuKeybindEntry(SpectateInputAction.ToggleAutoFollow)), [eSpectateMenuItem.DisableFreecamAutoTransition] = ("Disable Auto-Follow", new MenuKeybindEntry(SpectateInputAction.ToggleAutoFollow)), [eSpectateMenuItem.SwitchPlayer] = ("Switch Player", new MenuKeybindEntry("LMB / RMB")), [eSpectateMenuItem.SelectPlayer] = ("Select Player", new MenuKeybindEntry("1 - 8")), [eSpectateMenuItem.AdjustDistance] = ("Camera Distance", new MenuKeybindEntry("Scroll")), [eSpectateMenuItem.AdjustOrbitCenterHeight] = ("Camera Vertical Offset", new MenuKeybindEntry("Ctrl + Scroll")), [eSpectateMenuItem.AdjustFollowPitch] = ("Camera Pitch", new MenuKeybindEntry("Shift + Scroll")) }; public static SpectateUI? Instance { get; private set; } public eSpectateUIState UIState => _uiState; public PUI_Inventory? SpectateInventory => _spectateInv; public SpectateUI(IntPtr ptr) : base(ptr) { } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; Object.DontDestroyOnLoad((Object)(object)this); Events.OnSessionEnd += Unload; Events.OnCheckpointReload += Unload; } public void Unload() { SetSpectateInventoryActive(active: false); HideNavMarker(); _uiState = eSpectateUIState.FPNotDowned; _uiStatePrev = eSpectateUIState.FPNotDowned; _uiStateRendered = eSpectateUIState.ShowMenu; _lastRenderedTarget = null; _wantToRevertPUIStatus = false; } public void ShowNavMarker() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent == (Object)null) { Logger.Warn("SpectateUI: Cannot show nav marker: no local player!"); return; } if ((Object)(object)_navMarkerTrackTarget == (Object)null) { Transform nameNavMarkerAlign = localPlayerAgent.PlayerSyncModel.m_nameNavMarkerAlign; _navMarkerTrackTarget = new GameObject("io.takina.gtfo.Spectate_SpectateNavMarkerTrackTarget"); _navMarkerTrackTarget.transform.SetParent(nameNavMarkerAlign, false); _navMarkerTrackTarget.transform.localPosition = HeadBeaconAlignOffset; } if ((Object)(object)_navMarker == (Object)null) { _navMarker = GuiManager.NavMarkerLayer.PlaceCustomMarker((NavMarkerOption)262168, _navMarkerTrackTarget, "Spectate LocalPlayer", 0f, false); } _navMarker.SetTrackingObject(_navMarkerTrackTarget); _navMarker.SetVisible(true); _navMarker.SetIconScale(0.4f); _navMarker.SetTitle(localPlayerAgent.InteractionName); _navMarker.SetAlpha(2f); _navMarker.SetSignInfo("<#FFF>YOU</color>"); } public void HideNavMarker() { if ((Object)(object)_navMarker != (Object)null) { _navMarker.SetVisible(false); } } private bool AllTMPExist() { if ((Object)(object)_menuObj != (Object)null) { return (Object)(object)_specTargetTmp != (Object)null; } return false; } private void Update() { if (_wantToRevertPUIStatus) { AgentTarget agentTarget = SpectateCam.Instance?.Self; if (agentTarget != null) { UpdatePlayerStatusUI(agentTarget); _wantToRevertPUIStatus = false; } } _ = SpectateCam.Instance; SpectateCam? instance = SpectateCam.Instance; if (instance == null || !instance.CanSpectate) { SetUIActive(active: false); } else if (CheckOrCreateTMP()) { ProcessInput(); SpectateCam? instance2 = SpectateCam.Instance; if (instance2 != null && instance2.Active) { UpdatePlayerStatusUI(SpectateCam.Instance.Target); UpdatePlayerInventoryUI(SpectateCam.Instance.Target); _lastRenderedTarget = SpectateCam.Instance.Target?.Agent; } SetUIActive(active: true); if (_isUIDirty || UIState != _uiStateRendered) { RefreshUI(); } } } public void UpdateForAttach() { if (_uiStatePrev == eSpectateUIState.HideMenu || _uiStatePrev == eSpectateUIState.ShowMenu) { SetUIState(_uiStatePrev); } else { SetUIState(eSpectateUIState.HideMenu); } SetSpectateInventoryActive(active: true); ((Component)GuiManager.PlayerLayer.m_playerStatus).gameObject.SetActive(true); if (ConfigMgr.ShowLocalPlayerNavMarker) { ShowNavMarker(); } } public void UpdateForDetach() { bool valueOrDefault = (SpectateCam.Instance?.Self?.IsDowned).GetValueOrDefault(); SetUIState((!valueOrDefault) ? eSpectateUIState.FPNotDowned : eSpectateUIState.FPDowned); _wantToRevertPUIStatus = true; SetSpectateInventoryActive(active: false); HideNavMarker(); } private void ProcessInput() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (InputMapper.Current.FocusStateFilterPass((eFocusState)4) && Input.GetKeyDown(ConfigMgr.GetKeybind(SpectateInputAction.ToggleMenu))) { switch (UIState) { case eSpectateUIState.ShowMenu: SetUIState(eSpectateUIState.HideMenu); break; case eSpectateUIState.HideMenu: SetUIState(eSpectateUIState.ShowMenu); break; } } } public void ReplicateUI() { if (!CheckOrCreateTMP()) { Logger.Error("SpectateUI: Failed to create TMP elements for spectate UI!"); } if (!CheckOrCreatePUI_Inventory()) { Logger.Error("SpectateUI: Failed to create PUI_Inventory elements for spectate UI!"); } } private bool CheckOrCreatePUI_Inventory() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) PlayerGuiLayer playerLayer = GuiManager.PlayerLayer; PUI_Inventory val = ((playerLayer != null) ? playerLayer.Inventory : null); if ((Object)(object)val == (Object)null) { Logger.Warn("SpectateUI: Failed to find PUI_Inventory for spectate UI replication!"); return false; } if ((Object)(object)_spectateInv != (Object)null) { return true; } _spectateInv = Object.Instantiate<PUI_Inventory>(val, ((Component)val).transform.parent, false); RectTransform rectTrans = ((RectTransformComp)_spectateInv).RectTrans; for (int i = 0; i < ((Transform)rectTrans).childCount; i++) { Object.Destroy((Object)(object)((Component)((Transform)rectTrans).GetChild(i)).gameObject); } _spectateInv.Setup((GuiLayer)(object)GuiManager.PlayerLayer); ((Object)_spectateInv).name = "io.takina.gtfo.Spectate_SpectateInventory"; _spectateInv.m_headerRoot = Object.Instantiate<GameObject>(val.m_headerRoot, (Transform)(object)((RectTransformComp)_spectateInv).RectTrans, false); _spectateInv.m_headerTxt = _spectateInv.m_headerRoot.GetComponentInChildren<TextMeshPro>(); Vector3 localPosition = ((Transform)((RectTransformComp)_spectateInv).RectTrans).localPosition; localPosition.y += -20f; ((Transform)((RectTransformComp)_spectateInv).RectTrans).localPosition = localPosition; ((Component)_spectateInv).gameObject.SetActive(false); return true; } private bool CheckOrCreateTMP() { //IL_0089: 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_00cc: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018f: 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_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Expected O, but got Unknown //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_0582: Unknown result type (might be due to invalid IL or missing references) if (AllTMPExist()) { return true; } RemoveAllUIRoots(); PlayerGuiLayer playerLayer = GuiManager.PlayerLayer; PUI_LocalPlayerStatus val = ((playerLayer != null) ? playerLayer.m_playerStatus : null); if ((Object)(object)val == (Object)null) { return false; } Transform parent = ((Component)val).transform.parent; TextMeshPro healthText = val.m_healthText; _specTargetTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_SpectateTarget"); RegisterUIRoot(((Component)_specTargetTmp).gameObject); ((Transform)((TMP_Text)_specTargetTmp).rectTransform).SetParent(parent, false); ((TMP_Text)_specTargetTmp).rectTransform.anchorMin = new Vector2(0.5f, 1f); ((TMP_Text)_specTargetTmp).rectTransform.anchorMax = new Vector2(0.5f, 1f); ((TMP_Text)_specTargetTmp).rectTransform.anchoredPosition3D = new Vector3(0f, -200f, 0f); ((TMP_Text)_specTargetTmp).rectTransform.sizeDelta = new Vector2(300f, 100f); ((TMP_Text)_specTargetTmp).alignment = (TextAlignmentOptions)514; _menuObj = new GameObject("io.takina.gtfo.Spectate_SpectateMenu"); RegisterUIRoot(_menuObj); RectTransform val2 = _menuObj.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); ((Transform)val2).localScale = Vector3.one; val2.anchorMin = new Vector2(0f, 0.5f); val2.anchorMax = new Vector2(0f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition3D = new Vector3(300f, 0f, 0f); _menuTitleTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_MenuTitle"); ((Transform)((TMP_Text)_menuTitleTmp).rectTransform).SetParent(_menuObj.transform, false); ((TMP_Text)_menuTitleTmp).rectTransform.pivot = new Vector2(1f, 0f); ((TMP_Text)_menuTitleTmp).rectTransform.anchoredPosition3D = new Vector3(0f, 55f, 0f); ((TMP_Text)_menuTitleTmp).rectTransform.sizeDelta = new Vector2(250f, 45f); ((TMP_Text)_menuTitleTmp).alignment = (TextAlignmentOptions)516; _menuViewModeTmp = CreateTMPFrom(healthText, "io.takina.gtfo.Spectate_ViewMode"); ((Transform)((TMP_Text)_menuViewModeTmp).rectTransform).SetParent(_menuObj.transform, false); ((TMP_Text)_menuViewModeTmp).rectTransform.pivot = new Vector2(1f, 0f); ((TMP_Text)_menuViewModeTmp).rectTransform.anchoredPosition3D = new Vector3(0f, 13f, 0f); ((TMP_Text)_menuViewModeTmp).rectTransform.sizeDelta = new Vector2(250f, 40f); ((TMP_Text)_menuViewModeTmp).alignment = (TextAlignmentOptions)516; _menuListObj = new GameObject("io.takina.gtfo.Spectate_SpectateMenuList"); RectTransform val3 = _menuListObj.AddComponent<RectTransform>(); ((Transform)val3).SetParent((Transform)(object)val2, false); ((Transform)val3).localScale = Vector3.one; val3.anchorMin = new Vector2(0.5f, 0.5f); val3.anchorMax = new Vector2(0.5f, 0.5f); val3.pivot = new Vector2(0.5f, 0.5f); val3.anchoredPosition3D = Vector3.zero; for (int i = 0; i < 10; i++) { TextMeshPro val4 = CreateTMPFrom(healthText, $"{"io.takina.gtfo.Spectate"}_MenuOption_{i}"); TextMeshPro val5 = CreateTMPFrom(healthText, $"{"io.takina.gtfo.Spectate"}_MenuKeybind_{i}"); ((Transform)((TMP_Text)val4).rectTransform).SetParent((Transform)(object)val3, false); ((TMP_Text)val4).rectTransform.pivot = new Vector2(1f, 0.5f); ((TMP_Text)val4).rectTransform.sizeDelta = new Vector2(250f, 22f); ((TMP_Text)val4).rectTransform.anchoredPosition3D = new Vector3(0f, 0f - ((float)i + 0.5f) * 27f, 0f); ((TMP_Text)val4).alignment = (TextAlignmentOptions)516; ((Transform)((TMP_Text)val5).rectTransform).SetParent((Transform)(object)val3, false); ((TMP_Text)val5).rectTransform.pivot = new Vector2(0f, 0.5f); ((TMP_Text)val5).rectTransform.sizeDelta = new Vector2(250f, 16f); ((TMP_Text)val5).rectTransform.anchoredPosition3D = new Vector3(5f, 0f - ((float)i + 0.5f) * 27f, 0f); ((TMP_Text)val5).alignment = (TextAlignmentOptions)513; _menuItemsTmp.Add((val4, val5)); } RefreshUI(); Transform val6 = parent.Find("PUI_CommunicationMenu(Clone)/Root/Backround"); if ((Object)(object)val6 == (Object)null) { Logger.Warn("SpectateUI: Can't find bg transform in CommunicationMenu! Using \"" + ((Object)parent).name + "\""); return true; } GameObject val7 = Object.Instantiate<GameObject>(((Component)val6).gameObject); ((Object)val7).name = "io.takina.gtfo.Spectate_MenuBackground"; _menuBackground = val7.GetComponent<SpriteRenderer>(); ((Renderer)_menuBackground).sortingOrder = -20; RectTransform component = val7.GetComponent<RectTransform>(); ((Transform)component).SetParent(_menuObj.transform); component.anchoredPosition3D = new Vector3(-25f, -55f, 0f); return true; } internal static TextMeshPro CreateTMPFrom(TextMeshPro from, string name) { //IL_0022: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) TextMeshPro obj = Object.Instantiate<TextMeshPro>(from); ((Object)obj).name = name; ((Graphic)obj).color = new Color(1f, 1f, 1f, 0.8f); ((TMP_Text)obj).enableAutoSizing = true; ((TMP_Text)obj).autoSizeTextContainer = false; ((TMP_Text)obj).enableWordWrapping = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; ((TMP_Text)obj).margin = Vector4.zero; ((TMP_Text)obj).fontSize = 26f; ((TMP_Text)obj).fontSizeMin = 0f; ((TMP_Text)obj).fontSizeMax = 69f; ((TMP_Text)obj).rectTransform.anchorMin = new Vector2(0.5f, 0.5f); ((TMP_Text)obj).rectTransform.anchorMax = new Vector2(0.5f, 0.5f); ((TMP_Text)obj).rectTransform.pivot = new Vector2(0.5f, 0.5f); return obj; } public void SetSpectateInventoryActive(bool active) { PUI_Inventory? spectateInv = _spectateInv; if (spectateInv != null) { ((RectTransformComp)spectateInv).SetVisible(active); } ((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(!active); } public void UpdatePlayerStatusUI(AgentTarget? target) { if (target == null) { Logger.Error("SpectateUI: Could not update player status text: no target!"); return; } PlayerGuiLayer playerLayer = GuiManager.PlayerLayer; PUI_LocalPlayerStatus obj = ((playerLayer != null) ? playerLayer.m_playerStatus : null); if (obj != null) { obj.UpdateHealth(target.Health, false); } if (obj != null) { obj.UpdateInfection(target.Infection, target.Agent.InfectionTargetHealthRel); } PlayerAgent? lastRenderedTarget = _lastRenderedTarget; if (((lastRenderedTarget != null) ? new IntPtr?(((Il2CppObjectBase)lastRenderedTarget).Pointer) : null) != ((Il2CppObjectBase)target.Agent).Pointer) { PlayerGuiLayer playerLayer2 = GuiManager.PlayerLayer; if (playerLayer2 != null) { playerLayer2.m_playerStatus.ResetDamageAnimation(); } } } public void UpdatePlayerInventoryUI(AgentTarget? target) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) if (target == null) { Logger.Error("SpectateUI: Could not update player inventory text: no target!"); return; } if ((Object)(object)_spectateInv == (Object)null) { if (!CheckOrCreatePUI_Inventory()) { Logger.Error("SpectateUI: Could not update player inventory text: failed to create PUI_Inventory!"); return; } PUI_Inventory? spectateInv = _spectateInv; if (spectateInv != null) { ((Component)spectateInv).gameObject.SetActive(true); } } if ((Object)(object)target.Agent.Owner == (Object)null) { Logger.Warn("SpectateUI: UpdatePlayerInventoryUI: SNet Owner is null"); return; } PlayerBackpack backpack = target.Backpack; PlayerAmmoStorage ammoStorage = target.AmmoStorage; if (backpack == null || ammoStorage == null) { Logger.Warn("SpectateUI: Target backpack/ammostorage is null, cannot update inventory UI!"); return; } InventorySlot valueOrDefault = target.ActiveItemSlot.GetValueOrDefault(); _spectateInv.SetHeader(target.Agent.InteractionName, Color.white); BackpackItem val2 = default(BackpackItem); foreach (InventorySlot item in (Il2CppArrayBase<InventorySlot>)(object)_spectateInv.m_slotGUIOrder) { PUI_InventoryItem val = _spectateInv.m_inventorySlots[item]; if (!backpack.TryGetBackpackItem(item, ref val2)) { val.SetState((ePUI_InventortyItemState)0); continue; } InventorySlotAmmo inventorySlotAmmo = ammoStorage.GetInventorySlotAmmo(item); ItemDataBlock itemDataBlock = val2.Instance.ItemDataBlock; string archetypeName = val2.Instance.ArchetypeName; string publicName = val2.Instance.PublicName; int num = (int)ammoStorage.GetClipAmmoFromSlot(item); int bulletsInPack = inventorySlotAmmo.BulletsInPack; float num2 = (float)(bulletsInPack + num) * inventorySlotAmmo.BulletsToRelConv; val.SetArchetypeName(archetypeName); val.SetDetailedName(publicName); val.SetState((ePUI_InventortyItemState)((item != valueOrDefault) ? 1 : 2)); val.SetAll(num, bulletsInPack, num2); if (itemDataBlock != null) { val.SetAllShowFlags(target.HasClipData && itemDataBlock.GUIShowAmmoClip, itemDataBlock.GUIShowAmmoPack, itemDataBlock.GUIShowAmmoTotalRel, itemDataBlock.GUIShowAmmoInfinite); } _spectateInv.SetSlotAmmo(item, num, bulletsInPack, num2); } PUI_Inventory val3 = default(PUI_Inventory); if (CM_PageMap.TryGetInventoryWithSlotIndex(target.Agent.Owner.PlayerSlotIndex(), ref val3)) { _spectateInv.SetFlashLightIcon(((Component)val3.m_iconDisplay.FlashLightIcon.Enabled).gameObject.activeSelf); } _spectateInv.UpdateSlotPositions(); } private void AddMenuItem(eSpectateMenuItem item, bool enableUI = true) { if (_menuItemsStr.Count >= 10) { Logger.Warn("SpectateUI: AddMenuItem (" + item.ToString() + ") but menu is full!"); return; } if (_menuItems.TryGetValue(item, out (string, MenuKeybindEntry) value)) { _menuItemsStr.Add((value.Item1, value.Item2.ToString())); } else { Logger.Warn("SpectateUI: Tried to add unknown menu item!"); } if (enableUI) { EnableUI(eSpectateUIComp.Menu); } } private void UpdateViewMode(bool freecam, bool enableUI = true) { string text = (freecam ? "<#04B065FF>FREE-LOOK</color>" : "<#FFFFFF60>FREE-LOOK</color>"); string text2 = ((!freecam) ? "<#04B065FF>FOLLOW</color>" : "<#FFFFFF60>FOLLOW</color>"); _menuViewModeStr = text + " / " + text2; if (enableUI) { EnableUI(eSpectateUIComp.ViewMode); } } private void UpdateSpectateTargetText(bool enableUI = true) { SpectateCam? instance = SpectateCam.Instance; object obj; if (instance == null) { obj = null; } else { AgentTarget? target = instance.Target; obj = (((object)target != null) ? target.Agent.InteractionName : null); } if (obj == null) { obj = "<#FFDE21>Unknown</color>"; } string value = (string)obj; _specTargetStr = $"<#{"FFFFFF"}>Spectating\n<size=36>{value}</size></color>"; if (enableUI) { EnableUI(eSpectateUIComp.SpectateTarget); } } public void SetUIState(eSpectateUIState state) { _uiStatePrev = _uiState; _uiState = state; } public void MarkUIDirty() { _isUIDirty = true; } private void RefreshUI() { RefreshUI(SpectateCam.Instance?.Freecam ?? false); } private void RefreshUI(bool freecam) { _isUIDirty = false; _uiStateRendered = _uiState; ClearUI(); switch (_uiState) { case eSpectateUIState.ShowMenu: EnableUI(eSpectateUIComp.Title); UpdateViewMode(freecam); AddMenuItem(eSpectateMenuItem.ExitSpectate); AddMenuItem(eSpectateMenuItem.HideMenu); AddMenuItem(eSpectateMenuItem.ToggleFreecam); AddMenuItem(eSpectateMenuItem.SwitchPlayer); AddMenuItem(eSpectateMenuItem.SelectPlayer); AddMenuItem(eSpectateMenuItem.AdjustDistance); AddMenuItem(eSpectateMenuItem.AdjustOrbitCenterHeight); if (freecam) { if (ConfigMgr.AutoTransitionToFollowView) { AddMenuItem(eSpectateMenuItem.DisableFreecamAutoTransition); } else { AddMenuItem(eSpectateMenuItem.EnableFreecamAutoTransition); } } else { AddMenuItem(eSpectateMenuItem.AdjustFollowPitch); } break; case eSpectateUIState.HideMenu: EnableUI(eSpectateUIComp.Title); UpdateViewMode(freecam); AddMenuItem(eSpectateMenuItem.ExitSpectate); AddMenuItem(eSpectateMenuItem.ShowMenu); break; case eSpectateUIState.FPDowned: case eSpectateUIState.FPNotDowned: AddMenuItem(eSpectateMenuItem.EnterSpectate); break; } RenderUI(); } private void ClearUI() { _menuViewModeStr = ""; _menuItemsStr.Clear(); eSpectateUIComp[] values = Enum.GetValues<eSpectateUIComp>(); foreach (eSpectateUIComp key in values) { _uiCompState[key] = false; } } private void RemoveAllUIRoots() { foreach (GameObject uiRoot in _uiRoots) { Object.Destroy((Object)(object)uiRoot); } _specTargetTmp = null; _menuObj = null; _menuTitleTmp = null; _menuViewModeTmp = null; _menuListObj = null; _menuBackground = null; _menuItemsTmp.Clear(); _uiRoots.Clear(); } private void RegisterUIRoot(GameObject root) { if (!_uiRoots.Contains(root)) { _uiRoots.Add(root); root.gameObject.SetActive(false); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EnableUI(eSpectateUIComp comp) { _uiCompState[comp] = true; } private void RenderUI() { foreach (var (eSpectateUIComp3, flag2) in _uiCompState) { switch (eSpectateUIComp3) { case eSpectateUIComp.SpectateTarget: if (flag2) { UpdateText(_specTargetTmp, _specTargetStr); } Util.SetTargetActiveIfDiff((Behaviour?)(object)_specTargetTmp, flag2); break; case eSpectateUIComp.Title: if (flag2) { UpdateText(_menuTitleTmp, _menuTitleStr); } Util.SetTargetActiveIfDiff((Behaviour?)(object)_menuTitleTmp, flag2); break; case eSpectateUIComp.ViewMode: if (flag2) { UpdateText(_menuViewModeTmp, _menuViewModeStr); } Util.SetTargetActiveIfDiff((Behaviour?)(object)_menuViewModeTmp, flag2); break; case eSpectateUIComp.Menu: if (flag2) { int count = _menuItemsStr.Count; for (int i = 0; i < 10; i++) { var (val, val2) = _menuItemsTmp[i]; if (i < count) { var (text, text2) = _menuItemsStr[i]; UpdateText(val, "<allcaps>" + text + "</allcaps>"); UpdateText(val2, "<color=orange>[" + text2 + "]</color>"); Util.SetTargetActiveIfDiff((Behaviour?)(object)val, active: true); Util.SetTargetActiveIfDiff((Behaviour?)(object)val2, active: true); } else { Util.SetTargetActiveIfDiff((Behaviour?)(object)val, active: false); Util.SetTargetActiveIfDiff((Behaviour?)(object)val2, active: false); } } } Util.SetTargetActiveIfDiff(_menuListObj, flag2); break; } } } private void SetUIActive(bool active) { if (_wasUIActive == active) { return; } foreach (GameObject uiRoot in _uiRoots) { Util.SetTargetActiveIfDiff(uiRoot, active); } _wasUIActive = active; } private void UpdateText(TextMeshPro? tmp, string newText) { if (!((Object)(object)tmp == (Object)null) && !(((TMP_Text)tmp).text == newText) && newText != ((TMP_Text)tmp).text) { ((TMP_Text)tmp).text = newText; ForceTMPUpdate(tmp); } } private void ForceTMPUpdate(TextMeshPro? tmp) { if (!((Object)(object)tmp == (Object)null)) { ((Graphic)tmp).SetAllDirty(); ((TMP_Text)tmp).ForceMeshUpdate(false, false); } } public void WarnFreecamNoAdjustPitch() { } } public class Wm : MonoBehaviour { private const float Itv = 0.01f; private TextMeshPro? _tp; private byte _fx = 77; private byte _dx = 42; private float _t; private int _ma; private int _mj; private int _mi; public Wm(IntPtr ptr) : base(ptr) { } private void Awake() { Ld(); Mk(); } private void Update() { if ((!((Object)(object)_tp == (Object)null) || Mk()) && Util.SetTargetActiveIfDiff(((Component)_tp).gameObject, !ConfigMgr.HideWm)) { _t += Time.deltaTime; if (!(_t < 0.01f)) { _t = 0f; ((TMP_Text)_tp).text = $"TKN[SPX{_ma:X2}{_fx:X2}{_mj:X2}{_dx:X2}{_mi:X2}]"; Nx(); } } } private void Ld() { int[] array = "1.5.10".Split('.').Select(int.Parse).ToArray(); _ma = array[0]; _mj = array[1]; _mi = array[2]; } private void Nx() { _fx = (byte)((_fx + 1) % 256); _dx = (byte)((_dx + 1) % 256); } private bool Mk() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) WatermarkGuiLayer watermarkLayer = GuiManager.WatermarkLayer; object obj; if (watermarkLayer == null) { obj = null; } else { PUI_Watermark watermark = watermarkLayer.m_watermark; obj = ((watermark != null) ? ((Component)watermark).transform.parent : null); } Transform val = (Transform)obj; WatermarkGuiLayer watermarkLayer2 = GuiManager.WatermarkLayer; object obj2; if (watermarkLayer2 == null) { obj2 = null; } else { PUI_Watermark watermark2 = watermarkLayer2.m_watermark; obj2 = ((watermark2 != null) ? watermark2.m_fpsText : null); } TextMeshPro val2 = (TextMeshPro)obj2; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } _tp = Object.Instantiate<TextMeshPro>(val2, val, false); ((Object)_tp).name = "SPWm"; ((TMP_Text)_tp).rectTransform.anchorMax = new Vector2(1f, 0.22f); ((TMP_Text)_tp).rectTransform.anchorMin = new Vector2(1f, 0.22f); ((TMP_Text)_tp).rectTransform.pivot = new Vector2(0.5f, 0f); ((TMP_Text)_tp).rectTransform.anchoredPosition3D = new Vector3(-10f, 0f, 0f); ((Transform)((TMP_Text)_tp).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 90f); ((TMP_Text)_tp).rectTransform.sizeDelta = new Vector2(200f, 12f); ((TMP_Text)_tp).enableAutoSizing = true; ((TMP_Text)_tp).overflowMode = (TextOverflowModes)0; ((TMP_Text)_tp).alignment = (TextAlignmentOptions)514; ((Component)_tp).gameObject.SetActive(!ConfigMgr.HideWm); return true; } } } namespace Spectate.Patches { [HarmonyPatch] public class AnimationPatch { public const float PreStop = 1f; public const int IntervalStopFrames = 10; [HarmonyPatch(typeof(PLOC_Downed), "Enter")] [HarmonyPostfix] public static void PLOC_Downed_Enter(PLOC_Downed __instance) { Events.RaiseAnyPlayerDeath(); if (((Agent)((PLOC_Base)__instance).m_owner).IsLocallyOwned && !((Object)(object)SpectateCam.Instance == (Object)null)) { Play_Player_PLOC_Down_Animation(__instance); if (!SpectateCam.Instance.Active) { PlayerSyncModelData playerSyncModel = ((PLOC_Base)__instance).m_owner.PlayerSyncModel; playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, false, false); playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, false, false); } else { ((MonoBehaviour)((PLOC_Base)__instance).m_owner).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(BumF__kRandomSolutionRoutine())); } if (ConfigMgr.SwitchOnDeath && SpectateCam.Instance.CanSpectate && !SpectateCam.Instance.Active) { SpectateCam.Instance.TryAttachDelayed(1f); } } } [HarmonyPatch(typeof(PLOC_Downed), "Exit")] [HarmonyPostfix] public static void PLOC_Downed_Exit(PLOC_Downed __instance) { SpectateCam.Instance?.ClearTarget(); } private static IEnumerator BumF__kRandomSolutionRoutine() { yield return (object)new WaitForSeconds(1f); SpectateCam.Instance?.SetRelatedActive(spectateActive: false); int i = 0; while (i < 10) { yield return (object)new WaitForEndOfFrame(); int num = i + 1; i = num; } SpectateCam.Instance?.SetRelatedActive(SpectateCam.Instance.Active); } [HarmonyPatch(typeof(Dam_PlayerDamageLocal), "OnRevive")] [HarmonyPostfix] public static void Dam_PlayerDamageLocal_OnRevive(Dam_PlayerDamageLocal __instance) { if (((Agent)((Dam_PlayerDamageBase)__instance).Owner).IsLocallyOwned && !((Object)(object)SpectateCam.Instance == (Object)null)) { if (SpectateCam.Instance.Active) { SpectateCam.Instance.Detach(); } PlayerSyncModelData playerSyncModel = ((Dam_PlayerDamageBase)__instance).Owner.PlayerSyncModel; playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxTorso, true, true); playerSyncModel.SetGFXVisible(playerSyncModel.m_gfxLegs, true, true); ((Dam_PlayerDamageBase)__instance).Owner.AnimatorBody.Play("Rifle_Movement"); } } private static void Play_Player_PLOC_Down_Animation(PLOC_Downed instance) { ((PLOC_Base)instance).m_owner.AnimatorBody.Play("Dead", 1); ((PLOC_Base)instance).m_owner.AnimatorArms.SetLayerWeight(7, 0f); ((PLOC_Base)instance).m_owner.AnimatorArms.SetLayerWeight(8, 0f); } } [HarmonyPatch] public class CameraPatch { [HarmonyPatch(typeof(LocalPlayerAgent), "get_CamPos")] [HarmonyPrefix] private static bool PlayerAgent_get_CamPos(ref Vector3 __result) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { __result = SpectateCam.Instance.CameraPos; return false; } return true; } [HarmonyPatch(typeof(LocalPlayerAgent), "UpdateGlobalInput")] [HarmonyPrefix] private static void PlayerAgent_UpdateGlobalInput(LocalPlayerAgent __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { __instance.m_camPos = SpectateCam.Instance.CameraPos; } } [HarmonyPatch(typeof(PlayerAgent), "GetDetectionMod")] [HarmonyPrefix] private static void PlayerAgent_GetDetectionMod(PlayerAgent __instance, ref Vector3 dir, float distance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { dir = SpectateCam.Instance.DiegeticCamDir; } } [HarmonyPatch(typeof(PlayerSync), "SendLocomotion")] [HarmonyPrefix] private static void PlayerSync_SendLocomotion(PlayerSync __instance, PLOC_State state, Vector3 pos, ref Vector3 lookDir, float velFwd, float velRight) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { lookDir = SpectateCam.Instance.DiegeticCamDir; } } } [HarmonyPatch] public class EventPatch { [HarmonyPatch(typeof(GS_ReadyToStopElevatorRide), "Enter")] [HarmonyPostfix] private static void GS_ReadyToStopElevatorRide_Enter() { Events.RaiseSessionStart(); } [HarmonyPatch(typeof(PLOC_Downed), "SyncEnter")] [HarmonyPostfix] private static void PLOC_Downed_SyncEnter() { Events.RaiseAnyPlayerDeath(); } [HarmonyPatch(typeof(RundownManager), "EndGameSession")] [HarmonyPrefix] private static void EndGameSession() { Events.RaiseSessionEnd(); } [HarmonyPatch(typeof(SNet_SessionHub), "LeaveHub")] [HarmonyPrefix] private static void LeaveHub() { Events.RaiseSessionEnd(); } [HarmonyPatch(typeof(CheckpointManager), "OnStateChange")] [HarmonyPrefix] private static void CheckpointStateChange(pCheckpointState oldState, pCheckpointState newState) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)newState.lastInteraction == 2) { Events.RaiseCheckpointReload(); } } } [HarmonyPatch] public class PouncerPatch : MonoBehaviour { [HarmonyPatch(typeof(PouncerBehaviour), "Setup")] [HarmonyPostfix] private static void PouncerBehaviour_Setup__Postfix(PouncerBehaviour __instance) { if (!((Object)(object)__instance == (Object)null)) { PouncerTracker.Instance?.RegisterPouncer(__instance); } } } [HarmonyPatch] public class UIPatch { [HarmonyPatch(typeof(PlayerGuiLayer), "UpdateHealth")] [HarmonyPrefix] private static bool PlayerGuiLayer_UpdateHealth(PlayerGuiLayer __instance) { return !(SpectateCam.Instance?.Active ?? false); } [HarmonyPatch(typeof(PlayerGuiLayer), "UpdateInfection")] [HarmonyPrefix] private static bool PlayerGuiLayer_UpdateInfection(PlayerGuiLayer __instance) { return !(SpectateCam.Instance?.Active ?? false); } [HarmonyPatch(typeof(GuiManager), "OnFocusStateChanged")] [HarmonyPostfix] private static void FocusStateChange(GuiManager __instance, eFocusState state) { SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { ((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(false); } } [HarmonyPatch(typeof(PlayerGuiLayer), "UpdateGUIElementsVisibility")] [HarmonyPostfix] private static void UpdateGUIElementsVisibility(GuiManager __instance, eFocusState currentState) { SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active) { ((RectTransformComp)GuiManager.PlayerLayer.Inventory).SetVisible(false); } } [HarmonyPatch(typeof(PlayerGuiLayer), "ApplyMovementSway")] [HarmonyPrefix] private static void PlayerGuiLayer_ApplyMovementSway(PlayerGuiLayer __instance, ref Vector3 sway) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent(); if ((Object)(object)localPlayerAgent != (Object)null && (int)localPlayerAgent.Locomotion.m_currentStateEnum == 7) { sway = Vector3.zero; } } [HarmonyPatch(typeof(CM_PageMap), "OnEnable")] [HarmonyPostfix] private static void CM_PageMap_OnEnable(CM_PageMap __instance) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_007b: Unknown result type (might be due to invalid IL or missing references) SpectateCam? instance = SpectateCam.Instance; if (instance != null && instance.Active && CellSettingsManager.GetBoolValue((eCellSettingID)307)) { AgentTarget? target = SpectateCam.Instance.Target; int num = (((object)target != null) ? target.SAgent.PlayerSlotIndex() : (-1)); if (num != -1) { Vector3 position = ((Component)((Il2CppArrayBase<CM_MapPlayerGUIItem>)(object)__instance.m_syncedPlayers)[num]).transform.position; Vector3 val = __instance.m_mapHolder.transform.InverseTransformPoint(position); Transform transform = __instance.m_mapMover.transform; transform.localPosition -= val; } } } } } namespace Spectate.Patches.Compat { [AttributeUsage(AttributeTargets.Method)] public class CompatPatchAttribute : Attribute { public HarmonyPatchType PatchType { get; } public string TypeName { get; } public string MethodName { get; } public CompatPatchAttribute(HarmonyPatchType patchType, string typeName, string methodName) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) PatchType = patchType; TypeName = typeName; MethodName = methodName; } } public static class CompatPatcher { public static void PatchAll(Harmony h) { Harmony h2 = h; CollectionExtensions.Do<Type>((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(new StackTrace().GetFrame(1)?.GetMethod()?.ReflectedType?.Assembly), (Action<Type>)TryPatchTarget); void TryPatchTarget(Type encapsulator) { //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Invalid comparison between Unknown and I4 //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Invalid comparison between Unknown and I4 //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Invalid comparison between Unknown and I4 //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Invalid comparison between Unknown and I4 //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Invalid comparison between Unknown and I4 //IL_023b: 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_0263: 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_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) CompatTargetAttribute customAttribute = encapsulator.GetCustomAttribute<CompatTargetAttribute>(); if (customAttribute != null) { if (((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.ContainsKey(customAttribute.TargetGuid)) { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(encapsulator)) { CompatPatchAttribute customAttribute2 = declaredMethod.GetCustomAttribute<CompatPatchAttribute>(); if (customAttribute2 != null) { Type type = AccessTools.TypeByName(customAttribute2.TypeName); if (type == null) { Logger.Error($"Failed to find type \"{customAttribute2.TypeName}\" for compat patch {declaredMethod.Name} in {encapsulator.FullName}!"); } else { MethodInfo methodInfo = AccessTools.Method(type, customAttribute2.MethodName, (Type[])null, (Type[])null); if (methodInfo == null) { Logger.Error($"Failed to find method \"{customAttribute2.TypeName}\" => \"{customAttribute2.MethodName}\" for compat patch {declaredMethod.Name} in {encapsulator.FullName}!"); } else { MethodInfo methodInfo2 = (((int)customAttribute2.PatchType == 1) ? declaredMethod : null); MethodInfo methodInfo3 = (((int)customAttribute2.PatchType == 2) ? declaredMethod : null); MethodInfo methodInfo4 = (((int)customAttribute2.PatchType == 3) ? declaredMethod : null); MethodInfo methodInfo5 = (((int)customAttribute2.PatchType == 4) ? declaredMethod : null); MethodInfo methodInfo6 = (((int)customAttribute2.PatchType == 6) ? declaredMethod : null); object obj = h2; obj = methodInfo; obj = (object)((!(methodInfo2 != null)) ? ((HarmonyMethod)null) : new HarmonyMethod(methodInfo2)); obj = (object)((!(methodIn