using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Ashley.MeshSplitter")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")] [assembly: IgnoresAccessChecksTo("DemiLib")] [assembly: IgnoresAccessChecksTo("DOTween")] [assembly: IgnoresAccessChecksTo("DOTweenPro")] [assembly: IgnoresAccessChecksTo("HBAO.Runtime")] [assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")] [assembly: IgnoresAccessChecksTo("LightVolume.Runtime")] [assembly: IgnoresAccessChecksTo("Mono.Security")] [assembly: IgnoresAccessChecksTo("Newtonsoft.Json")] [assembly: IgnoresAccessChecksTo("Photon3Unity3D")] [assembly: IgnoresAccessChecksTo("PhotonChat")] [assembly: IgnoresAccessChecksTo("PhotonRealtime")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Demos")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")] [assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")] [assembly: IgnoresAccessChecksTo("PhotonVoice.API")] [assembly: IgnoresAccessChecksTo("PhotonVoice")] [assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")] [assembly: IgnoresAccessChecksTo("pworld")] [assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")] [assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")] [assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")] [assembly: IgnoresAccessChecksTo("Sirenix.Serialization")] [assembly: IgnoresAccessChecksTo("Sirenix.Utilities")] [assembly: IgnoresAccessChecksTo("Tayx.Graphy")] [assembly: IgnoresAccessChecksTo("unity-websocket-sharp")] [assembly: IgnoresAccessChecksTo("Unity.Addressables")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Cinemachine")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.RebindingUI")] [assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.004")] [assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")] [assembly: IgnoresAccessChecksTo("Unity.Localization")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Center.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode.Common.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.Rendering.LightTransport.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime.Shared")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.GPUDriven.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.2D.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")] [assembly: IgnoresAccessChecksTo("Unity.ResourceManager")] [assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication.PlayerAccounts")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.Multiplayer")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Wire.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Splines")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.UnifiedRayTracing.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.AccessibilityModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AdaptivePerformanceModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AMDModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AndroidJNIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AnimationModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AssetBundleModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.AudioModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClothModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClusterInputModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ClusterRendererModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ContentLoadModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.CoreModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.CrashReportingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.DirectorModule")] [assembly: IgnoresAccessChecksTo("UnityEngine")] [assembly: IgnoresAccessChecksTo("UnityEngine.DSPGraphModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GameCenterModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GraphicsStateCollectionSerializerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.GridModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyCoreModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.HotReloadModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.IdentifiersModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ImageConversionModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.IMGUIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputForUIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputLegacyModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InputModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.InsightsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.JSONSerializeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.LocalizationModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.MarshallingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.MultiplayerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ParticleSystemModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PerformanceReportingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.Physics2DModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsBackendPhysXModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.PropertiesModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.RenderAs2DModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ScreenCaptureModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ShaderRuntimeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.ShaderVariantAnalyticsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SharedInternalsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpriteMaskModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpriteShapeModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.StreamingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SubstanceModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SubsystemsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TerrainModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TerrainPhysicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreFontEngineModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreTextEngineModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TextRenderingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TilemapModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.TLSModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.UIElementsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UIModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UmbraModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsCommonModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityConnectModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityConsentModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityCurlModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityTestProtocolModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAssetBundleModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAudioModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestTextureModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestWWWModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VectorGraphicsModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VehiclesModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VFXModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VideoModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VirtualTexturingModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.VRModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.WindModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.XRModule")] [assembly: IgnoresAccessChecksTo("UnityUIExtensions")] [assembly: IgnoresAccessChecksTo("websocket-sharp")] [assembly: IgnoresAccessChecksTo("Whinarn.UnityMeshSimplifier.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.AutoLOD")] [assembly: IgnoresAccessChecksTo("Zorro.ControllerSupport")] [assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.JiggleBones")] [assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")] [assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")] [assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PeakSpectatorMode { internal sealed class BetterPlayerDistanceIntegration { private const string BpdGuid = "com.AiAe.betterplayerdistance"; private const string BpdPluginTypeName = "BetterPlayerDistance.Plugin"; private const string OverlayFieldName = "Overlay"; private const string CanvasFieldName = "_canvas"; private bool _detected; private string _detectedVersion; private FieldInfo _overlayField; private FieldInfo _canvasField; private bool _suppressed; private bool _savedCanvasEnabled = true; internal bool IsLoaded => _detected; internal string DetectedVersion => _detectedVersion; internal void TryDetect() { try { if (!Chainloader.PluginInfos.TryGetValue("com.AiAe.betterplayerdistance", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { L10n.LogDebug("BetterPlayerDistance not detected; skipping BPD2 compatibility (quiet fallback logging).", "BetterPlayerDistance 未检测到,跳过 BPD2 兼容(无噪音降级日志)。"); return; } _detectedVersion = ((value.Metadata != null && value.Metadata.Version != null) ? value.Metadata.Version.ToString() : "(unknown)"); Type type = AccessTools.TypeByName("BetterPlayerDistance.Plugin"); if (type == null) { L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but type BetterPlayerDistance.Plugin was not found.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但找不到类型 BetterPlayerDistance.Plugin。"); return; } _overlayField = AccessTools.Field(type, "Overlay"); if (_overlayField == null) { L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but field BetterPlayerDistance.Plugin.Overlay was not found.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但找不到字段 BetterPlayerDistance.Plugin.Overlay。"); return; } Type fieldType = _overlayField.FieldType; _canvasField = AccessTools.Field(fieldType, "_canvas"); if (_canvasField == null) { L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but field _canvas was not found in OverlayManager.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但 OverlayManager 中找不到 _canvas 字段。"); return; } _detected = true; L10n.LogInfo("BetterPlayerDistance v" + _detectedVersion + " detected; BPD2 compatibility enabled (Canvas.enabled switching mode).", "BetterPlayerDistance v" + _detectedVersion + " 已检测到,BPD2 兼容启用(Canvas.enabled 切换模式)。"); } catch (Exception ex) { _detected = false; L10n.LogWarning("BetterPlayerDistance compatibility detection failed: " + ex.GetType().Name + ": " + ex.Message, "BetterPlayerDistance 兼容检测失败:" + ex.GetType().Name + ": " + ex.Message); } } private Canvas ResolveCanvas() { if (!_detected || _overlayField == null || _canvasField == null) { return null; } try { object value = _overlayField.GetValue(null); if (value == null) { return null; } object? value2 = _canvasField.GetValue(value); return (Canvas)((value2 is Canvas) ? value2 : null); } catch (Exception ex) { L10n.LogDebug("[BPD2 Compat] ResolveCanvas exception: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] ResolveCanvas 异常:" + ex.GetType().Name + ": " + ex.Message); return null; } } internal void Suppress() { if (!_detected || _suppressed || !Configuration.EnableBetterPlayerDistanceIntegration) { return; } Canvas val = ResolveCanvas(); if ((Object)(object)val == (Object)null) { L10n.LogDebug("[BPD2 Compat] Canvas is missing during Suppress (BPD2 may not be initialized yet); skipping.", "[BPD2兼容] Suppress 时 Canvas 不存在(BPD2 可能尚未初始化),跳过。"); return; } try { _savedCanvasEnabled = ((Behaviour)val).enabled; if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; } _suppressed = true; L10n.LogInfo($"[BPD2 Compat] Temporarily disabled BPD2 Canvas (saved enabled={_savedCanvasEnabled})", $"[BPD2兼容] 已临时关闭 BPD2 Canvas(暂存 enabled={_savedCanvasEnabled})"); } catch (Exception ex) { L10n.LogWarning("[BPD2 Compat] Suppress failed: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] Suppress 失败:" + ex.GetType().Name + ": " + ex.Message); } } internal void Restore() { if (!_detected || !_suppressed) { return; } Canvas val = ResolveCanvas(); if ((Object)(object)val == (Object)null) { _suppressed = false; L10n.LogDebug("[BPD2 Compat] Canvas is already missing during Restore (scene reload?); marking as reset.", "[BPD2兼容] Restore 时 Canvas 已不存在(Scene 重载?),标记复位。"); return; } try { ((Behaviour)val).enabled = _savedCanvasEnabled; _suppressed = false; L10n.LogInfo($"[BPD2 Compat] Restored BPD2 Canvas.enabled={_savedCanvasEnabled}", $"[BPD2兼容] 已恢复 BPD2 Canvas.enabled={_savedCanvasEnabled}"); } catch (Exception ex) { L10n.LogWarning("[BPD2 Compat] Restore failed: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] Restore 失败:" + ex.GetType().Name + ": " + ex.Message); } } } internal static class CharacterState { internal static bool IsAliveSpectatorTarget(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((Component)character).gameObject == (Object)null || !((Component)character).gameObject.activeInHierarchy || character.isBot) { return false; } if (!Configuration.DebugMode && (Object)(object)character == (Object)(object)Character.localCharacter) { return false; } return !IsDead(character); } internal static bool IsDead(Character character) { try { return (Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || character.data.dead; } catch { return true; } } } internal enum SpectatorArrowStyle { RoundedGlass, OutlineGlass } internal static class Configuration { internal static ConfigEntry ToggleKey; internal static ConfigEntry ResetKey; internal static ConfigEntry PreviousPlayerKey; internal static ConfigEntry NextPlayerKey; internal static ConfigEntry ToggleOverlayKey; internal static ConfigEntry PeakTrailsToggleKey; internal static ConfigEntry ForcedDeathKey; internal static ConfigEntry NormalSpeed; internal static ConfigEntry FastSpeed; internal static ConfigEntry TurnSpeed; internal static ConfigEntry AltSlowSpeedMultiplier; internal static ConfigEntry MoveDamping; internal static ConfigEntry TurnDamping; internal static ConfigEntry TelescopeKey; internal static ConfigEntry TelescopeMultiplier; internal static ConfigEntry EnableSoftFollow; internal static ConfigEntry SoftFollowMaxDistance; internal static ConfigEntry NameFontSize; internal static ConfigEntry HeightFontSize; internal static ConfigEntry OverlayOpacity; internal static ConfigEntry LabelTextOpacity; internal static ConfigEntry HeadArrowStyle; internal static ConfigEntry ShowFullPeakStatsExInfo; internal static ConfigEntry SpectatorTeammateStaminaDistance; internal static ConfigEntry OverlayCycleKey; internal static ConfigEntry LogLang; internal const float MaxPeakHeightMeters = 1920f; internal static readonly bool DebugMode = true; internal static readonly bool ShowOverlay = true; internal static readonly bool ShowXraySilhouette = true; internal static readonly bool HideHudInFreeCamera = true; internal static readonly bool EnablePeakTrailsCompatibility = true; internal static readonly bool EnablePeakStatsExCompatibility = true; internal static readonly bool ForcePeakStatsExInventoryInFreeCamera = true; internal static readonly bool EnableForcedDeath = true; internal static readonly bool ShowXrayDetailLayer = true; internal static readonly bool EnableSummitRosterCompatibility = true; internal static readonly bool MoveSummitRosterRight = true; internal static readonly bool ShowSummitRosterFocusArrow = true; internal static readonly bool EnableGhostSpectatorIntegration = true; internal static readonly bool EnableBetterPlayerDistanceIntegration = true; internal const KeyCode ResetZoomKey = (KeyCode)325; internal const float ForcedDeathHoldSeconds = 3f; internal const float TelescopeTransitionSpeed = 8f; internal const float LabelTextOffsetY = 0f; internal const float LabelArrowOffsetY = -38f; internal const float LabelScreenPadding = 48f; internal const float LabelDistanceScreenPadding = 36f; internal const float LabelCameraForwardOffset = 0.4f; internal const float FloatAmplitude = 7f; internal const float FloatSpeed = 1.15f; internal const float OverlayFadeSpeed = 5f; internal const float XrayOpacity = 0.34f; internal const float XrayDetailOpacity = 0.16f; internal const float XrayOcclusionCheckInterval = 0.12f; internal static void Initialize(ConfigFile config) { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Expected O, but got Unknown //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Expected O, but got Unknown //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Expected O, but got Unknown //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Expected O, but got Unknown //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Expected O, but got Unknown //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Expected O, but got Unknown //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Invalid comparison between Unknown and I4 //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Invalid comparison between Unknown and I4 LogLang = config.Bind("0. General 常规", "Log Language 日志语言", LogLanguage.Auto, "Language used for the mod's console/log messages. Auto follows the in-game language.\n模组控制台/日志信息使用的语言。Auto 表示跟随游戏内语言。"); ToggleKey = config.Bind("1. Hotkeys 热键", "Spectator Toggle 观战开关", (KeyCode)284, "Toggle the free spectator camera on/off.\n开启或关闭自由观战相机。"); ResetKey = config.Bind("1. Hotkeys 热键", "Reset Near Self 重置到自己附近", (KeyCode)285, "Reset the free camera near the local player.\n将自由相机重置到本地玩家附近。"); PreviousPlayerKey = config.Bind("1. Hotkeys 热键", "Previous Player 上一个玩家", (KeyCode)113, "Snap the free camera near the previous other player.\n将自由相机快速切换到上一个其他玩家附近。"); NextPlayerKey = config.Bind("1. Hotkeys 热键", "Next Player 下一个玩家", (KeyCode)101, "Snap the free camera near the next other player.\n将自由相机快速切换到下一个其他玩家附近。"); ToggleOverlayKey = config.Bind("1. Hotkeys 热键", "Temporarily Hide Labels 临时隐藏标记", (KeyCode)102, "Smoothly show/hide player names and altitude in free camera.\n自由相机模式下平滑显示或隐藏玩家名称和海拔。"); OverlayCycleKey = config.Bind("1. Hotkeys 热键", "Cycle Label Mode 标记显示模式循环", (KeyCode)99, "3-step cycle in free camera: name + arrow -> name only -> hide all -> back to name + arrow.\n自由相机下 3 段循环:名称+箭头 → 仅名称 → 全部隐藏 → 回到名称+箭头。"); PeakTrailsToggleKey = config.Bind("1. Hotkeys 热键", "PEAKTrails Toggle PEAKTrails轨迹开关", (KeyCode)114, "Toggle PEAKTrails player trails while in free camera.\n自由相机模式下切换 PEAKTrails 玩家轨迹显示或隐藏。"); TelescopeKey = config.Bind("1. Hotkeys 热键", "Telescope Key 望远镜按键", (KeyCode)120, "Hold to smoothly zoom in the free camera; release to smoothly restore the current scroll zoom.\n按住后平滑放大自由相机视角,松开后平滑恢复到当前滚轮缩放。"); ForcedDeathKey = config.Bind("1. Hotkeys 热键", "Forced Death Key (Alt+) 强制死亡主按键(Alt+)", (KeyCode)284, "Hold together with Alt to trigger forced death.\n配合 Alt 长按触发强制死亡。"); NormalSpeed = config.Bind("2. Camera 相机", "Normal Speed 普通速度", 12f, new ConfigDescription("Free camera normal move speed.\n自由相机普通移动速度。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 80f), Array.Empty())); FastSpeed = config.Bind("2. Camera 相机", "Shift Speed shift速度", 60f, new ConfigDescription("Move speed while holding Shift.\n按住 Shift 时的移动速度。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 200f), Array.Empty())); TurnSpeed = config.Bind("2. Camera 相机", "Turn Speed 转向速度", 50f, new ConfigDescription("Free camera mouse turn speed.\n自由相机鼠标转向速度。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 80f), Array.Empty())); AltSlowSpeedMultiplier = config.Bind("2. Camera 相机", "Alt Slow Multiplier Alt慢速倍率", 0.33f, new ConfigDescription("Move speed multiplier while holding Alt in F3 free camera; 0.33 = 33%.\nF3 自由相机模式下按住 Alt 时的移动速度倍率,0.33 表示 33%。", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty())); MoveDamping = config.Bind("2. Camera 相机", "Move Damping 移动阻尼", 3f, new ConfigDescription("Free camera move damping; higher stops faster.\n自由相机移动阻尼,数值越高停下越快。", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); TurnDamping = config.Bind("2. Camera 相机", "Turn Damping 转向阻尼", 5f, new ConfigDescription("Free camera turn damping; higher turns more steadily.\n自由相机转向阻尼,数值越高转向越稳。", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 20f), Array.Empty())); TelescopeMultiplier = config.Bind("2. Camera 相机", "Telescope Multiplier 望远镜倍率", 5f, new ConfigDescription("Zoom multiplier while holding the telescope key.\n按住望远镜按键时的放大倍率。", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 30f), Array.Empty())); EnableSoftFollow = config.Bind("2. Camera 相机", "Soft Follow After Switch 切换后镜头软跟随玩家", true, "After switching to a player, auto soft-follow once the transition ends: the camera moves with the player; exits when you press any move key (WASD/Space/Ctrl/Q/E) or the camera goes beyond the set distance.\n切换玩家后过渡结束自动进入软跟随:相机随玩家一起移动;按任意位移键 (WASD/Space/Ctrl/Q/E) 或相机距目标超过设定距离时退出跟随。"); SoftFollowMaxDistance = config.Bind("2. Camera 相机", "Soft Follow Max Distance 软跟随最大距离", 20f, new ConfigDescription("Auto-exit soft follow when the camera is farther than this many meters from the target.\n软跟随状态下相机距离目标超过此米数时自动退出。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); SpectatorTeammateStaminaDistance = config.Bind("2. Camera 相机", "Free Camera Teammate Stamina Distance 自由相机队友体力条距离", 9999f, new ConfigDescription("Temporarily override the PeakStatsEx teammate stamina bar display distance while in free camera.\n自由相机模式下临时覆盖 PeakStatsEx 队友体力条显示距离。", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 10000f), Array.Empty())); ShowFullPeakStatsExInfo = config.Bind("2. Camera 相机", "Show Full PeakStatsEx Info 自由相机显示完整peakstatsex信息", false, "When enabled, F3 free camera no longer hides PeakStatsEx top stats (timer, height, fog/lava, etc.); when disabled it stays minimal.\n开启后,F3 自由相机模式下不再隐藏 PeakStatsEx 的计时、高度、雾/岩浆等顶部统计信息;关闭时保持精简显示。"); NameFontSize = config.Bind("3. Display 显示", "Name Font Size 名字字号", 12f, new ConfigDescription("Player name font size.\n玩家名称字号。", (AcceptableValueBase)(object)new AcceptableValueRange(9f, 60f), Array.Empty())); HeightFontSize = config.Bind("3. Display 显示", "World Altitude Font Size 世界海拔字号", 13f, new ConfigDescription("World altitude font size.\n世界海拔字号。", (AcceptableValueBase)(object)new AcceptableValueRange(9f, 60f), Array.Empty())); OverlayOpacity = config.Bind("3. Display 显示", "Marker Opacity 标记透明度", 0.7f, new ConfigDescription("Opacity of the overhead arrow marker; label text is controlled separately by \"Label Text Opacity\" and the two are not multiplied together.\n头顶箭头标记的不透明度;文字另由“标签文字透明度”独立控制,两者互不相乘。", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LabelTextOpacity = config.Bind("3. Display 显示", "Label Text Opacity 标签文字透明度", 0.8f, new ConfigDescription("Opacity of the overhead label text (including its shadow); independent from \"Marker Opacity\" (arrow) and applied absolutely.\n头顶标签文字(含文字阴影)的不透明度;与“标记透明度”(箭头)相互独立、绝对生效。", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); HeadArrowStyle = config.Bind("3. Display 显示", "Head Arrow Style 头顶箭头样式", SpectatorArrowStyle.RoundedGlass, "RoundedGlass = rounded thick glass-filled arrow; OutlineGlass = outlined glass-filled arrow.\nRoundedGlass 为圆角粗箭头玻璃填充;OutlineGlass 为线框箭头玻璃填充。"); if ((int)PreviousPlayerKey.Value == 91) { PreviousPlayerKey.Value = (KeyCode)113; } if ((int)NextPlayerKey.Value == 93) { NextPlayerKey.Value = (KeyCode)101; } if (Mathf.Approximately(TelescopeMultiplier.Value, 10f)) { TelescopeMultiplier.Value = 5f; } } } internal sealed class ForceDeathController { private readonly MethodInfo _dieMethod = AccessTools.Method(typeof(Character), "Die", (Type[])null, (Type[])null); private GameObject _root; private CanvasGroup _group; private TextMeshProUGUI _text; private float _holdTime; private bool _triggered; internal void Update() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!Configuration.EnableForcedDeath) { ResetState(); return; } if (Plugin.GsIntegration != null && Plugin.GsIntegration.IsActive) { ResetState(); return; } bool num = IsHoldingCombo(); Character localCharacter = Character.localCharacter; if (!num || (Object)(object)localCharacter == (Object)null || CharacterState.IsDead(localCharacter)) { ResetState(); return; } EnsureUi(); _holdTime += Time.unscaledDeltaTime; float num2 = Mathf.Max(1f, 3f); float num3 = Mathf.Clamp01(_holdTime / num2); _group.alpha = Mathf.MoveTowards(_group.alpha, 1f, Time.unscaledDeltaTime * 8f); ((TMP_Text)_text).text = L10n.Game($"Warning: keep holding Alt+{Configuration.ForcedDeathKey.Value} to force death\n{num3 * num2:0.0}/{num2:0.0}s", $"警告:继续按住 Alt+{Configuration.ForcedDeathKey.Value} 将强制死亡\n{num3 * num2:0.0}/{num2:0.0}s"); if (!_triggered && _holdTime >= num2) { _triggered = true; ForceDie(); ResetState(); } } internal void Dispose() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private bool IsHoldingCombo() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)) { return Input.GetKey(Configuration.ForcedDeathKey.Value); } return false; } private void ForceDie() { try { if (_dieMethod != null) { _dieMethod.Invoke(null, null); } } catch (Exception ex) { L10n.LogWarning("Alt+F3 forced death failed: " + ex.Message, "Alt+F3 强制死亡失败:" + ex.Message); } } private void ResetState() { _holdTime = 0f; _triggered = false; if ((Object)(object)_group != (Object)null) { _group.alpha = Mathf.MoveTowards(_group.alpha, 0f, Time.unscaledDeltaTime * 8f); } } private void EnsureUi() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root != (Object)null)) { _root = new GameObject("PeakSpectatorForceDeathWarning"); Object.DontDestroyOnLoad((Object)(object)_root); _root.layer = 5; Canvas obj = _root.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 1200; CanvasScaler obj2 = _root.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); _group = _root.AddComponent(); _group.alpha = 0f; _group.blocksRaycasts = false; _group.interactable = false; GameObject val = new GameObject("Panel"); val.layer = 5; val.transform.SetParent(_root.transform, false); RectTransform obj3 = val.AddComponent(); obj3.anchorMin = new Vector2(0.5f, 0.82f); obj3.anchorMax = new Vector2(0.5f, 0.82f); obj3.pivot = new Vector2(0.5f, 0.5f); obj3.sizeDelta = new Vector2(720f, 120f); Image obj4 = val.AddComponent(); ((Graphic)obj4).color = new Color(0.12f, 0.02f, 0.02f, 0.78f); ((Graphic)obj4).raycastTarget = false; GameObject val2 = new GameObject("Text"); val2.layer = 5; val2.transform.SetParent(val.transform, false); RectTransform obj5 = val2.AddComponent(); obj5.anchorMin = Vector2.zero; obj5.anchorMax = Vector2.one; obj5.offsetMin = new Vector2(20f, 10f); obj5.offsetMax = new Vector2(-20f, -10f); _text = val2.AddComponent(); ((TMP_Text)_text).alignment = (TextAlignmentOptions)514; ((TMP_Text)_text).fontSize = 28f; ((Graphic)_text).color = new Color(1f, 0.78f, 0.58f, 1f); ((Graphic)_text).raycastTarget = false; ((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0; } } } internal sealed class GhostSpectatorIntegration { private const string GhostSpectatorGuid = "SisyphusMD.GhostSpectator"; private bool _detected; private ConfigEntry _spectatorEnabledEntry; private string _detectedVersion; internal bool IsLoaded => _detected; internal string DetectedVersion => _detectedVersion; internal bool IsActive { get { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!_detected || _spectatorEnabledEntry == null) { return false; } if (!Configuration.EnableGhostSpectatorIntegration) { return false; } if (!_spectatorEnabledEntry.Value) { return false; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) { return false; } if (!localCharacter.data.fullyPassedOut) { return false; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "Airport") { return false; } return true; } } internal bool IsCharacterPermaSpectator(Character character) { if (!_detected || (Object)(object)character == (Object)null) { return false; } try { if ((Object)(object)character == (Object)(object)Character.localCharacter) { return IsActive; } CharacterRefs refs = character.refs; if (refs == null) { return false; } PhotonView view = refs.view; if ((Object)(object)view == (Object)null) { return false; } Player owner = view.Owner; if (owner == null) { return false; } IDictionary customProperties = (IDictionary)owner.CustomProperties; if (customProperties == null) { return false; } if (customProperties["GhostSpectator.IsSpectator"] is bool result) { return result; } } catch (Exception ex) { L10n.LogDebug("IsCharacterPermaSpectator exception: " + ex.GetType().Name + ": " + ex.Message, "IsCharacterPermaSpectator 异常:" + ex.GetType().Name + ": " + ex.Message); } return false; } internal void TryDetect() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown try { if (!Chainloader.PluginInfos.TryGetValue("SisyphusMD.GhostSpectator", out var value) || value == null || (Object)(object)value.Instance == (Object)null) { L10n.LogDebug("GhostSpectator not detected; running in standalone mode (quiet fallback logging).", "GhostSpectator 未检测到,运行在独立模式(无噪音降级日志)。"); return; } _detectedVersion = ((value.Metadata != null && value.Metadata.Version != null) ? value.Metadata.Version.ToString() : "(unknown)"); ConfigFile config = value.Instance.Config; if (config == null) { L10n.LogWarning("GhostSpectator v" + _detectedVersion + " loaded, but its Config is inaccessible; compatibility mode cannot be enabled.", "GhostSpectator v" + _detectedVersion + " 已加载,但其 Config 不可访问,兼容模式无法启用。"); return; } ConfigDefinition val = new ConfigDefinition("Spectator", "Enabled"); ConfigEntry val2 = default(ConfigEntry); if (!config.TryGetEntry(val, ref val2) || val2 == null) { L10n.LogWarning("GhostSpectator v" + _detectedVersion + " loaded, but the Spectator/Enabled config entry was not found. The version may be incompatible.", "GhostSpectator v" + _detectedVersion + " 已加载,但未找到 Spectator/Enabled 配置项。可能是版本不兼容。"); return; } _spectatorEnabledEntry = val2; _detected = true; L10n.LogInfo($"GhostSpectator v{_detectedVersion} detected; compatibility mode enabled. Current SpectatorEnabled value={_spectatorEnabledEntry.Value}.", $"GhostSpectator v{_detectedVersion} 已检测到,兼容模式启用。SpectatorEnabled 当前值={_spectatorEnabledEntry.Value}。"); } catch (Exception ex) { _detected = false; _spectatorEnabledEntry = null; L10n.LogWarning("GhostSpectator compatibility detection failed: " + ex.GetType().Name + ": " + ex.Message + ". Running in standalone mode.", "GhostSpectator 兼容检测失败:" + ex.GetType().Name + ": " + ex.Message + "。运行在独立模式。"); } } } internal enum LogLanguage { Auto, English, Chinese } internal static class L10n { internal static bool GameIsChinese { get { //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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 Language cURRENT_LANGUAGE = LocalizedText.CURRENT_LANGUAGE; if ((int)cURRENT_LANGUAGE != 9) { return (int)cURRENT_LANGUAGE == 10; } return true; } } internal static bool UseChineseForLogs => ((Configuration.LogLang != null) ? Configuration.LogLang.Value : LogLanguage.Auto) switch { LogLanguage.English => false, LogLanguage.Chinese => true, _ => GameIsChinese, }; internal static string Game(string en, string zh) { if (!GameIsChinese) { return en; } return zh; } internal static void LogInfo(string en, string zh) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)(UseChineseForLogs ? zh : en)); } } internal static void LogWarning(string en, string zh) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)(UseChineseForLogs ? zh : en)); } } internal static void LogError(string en, string zh) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)(UseChineseForLogs ? zh : en)); } } internal static void LogDebug(string en, string zh) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)(UseChineseForLogs ? zh : en)); } } } internal sealed class PeakStatsExCompatibility { private struct InventoryOverrideState { internal RuntimeOverrideToken SlotsToken; internal PeakStatsExInfoOverrideState InfoState; } private struct PeakStatsExInfoOverrideState { internal RuntimeOverrideToken DisplayTimerToken; internal RuntimeOverrideToken DisplayHeightToken; internal RuntimeOverrideToken DisplayLevelToken; internal RuntimeOverrideToken DisplayBiomesToken; internal RuntimeOverrideToken DisplayDayNightCountdownToken; internal RuntimeOverrideToken DisplayFogToken; internal RuntimeOverrideToken DisplayLavaToken; internal RuntimeOverrideToken DisplayTerrainRandomiserSeedToken; internal RuntimeOverrideToken DisplayTerrainCustomiserSeedToken; internal RuntimeOverrideToken ShowStaminaInfoToken; internal RuntimeOverrideToken StaminaInfoShowAfflictionCountdownToken; } private sealed class ConfigValue { private readonly object _entry; private readonly PropertyInfo _valueProperty; private readonly FieldInfo _typedValueField; internal bool IsValid { get { if (_entry != null) { return _valueProperty != null; } return false; } } internal object EntryObject => _entry; internal ConfigValue(object entry) { _entry = entry; if (_entry != null) { _valueProperty = _entry.GetType().GetProperty("Value"); _typedValueField = AccessTools.Field(_entry.GetType(), "_typedValue"); } } internal T Get(T fallback) { if (_entry == null) { return fallback; } object obj = ((_typedValueField != null) ? _typedValueField.GetValue(_entry) : _valueProperty?.GetValue(_entry, null)); if (obj is T) { return (T)obj; } return fallback; } internal void Set(T value) { if (_entry != null) { if (_typedValueField != null) { _typedValueField.SetValue(_entry, value); } else if (_entry is ConfigEntry val) { val.Value = value; } else { _valueProperty?.SetValue(_entry, value, null); } } } } private readonly Harmony _harmony; private readonly RuntimeOverrideManager _overrides = new RuntimeOverrideManager(); private ConfigValue _proximityDistance; private ConfigValue _displayTimer; private ConfigValue _displayHeight; private ConfigValue _displayLevel; private ConfigValue _displayBiomes; private ConfigValue _displayDayNightCountdown; private ConfigValue _displayFog; private ConfigValue _displayLava; private ConfigValue _displayTerrainRandomiserSeed; private ConfigValue _displayTerrainCustomiserSeed; private ConfigValue _showInventorySlots; private ConfigValue _showStaminaInfo; private ConfigValue _staminaInfoShowAfflictionCountdown; private FieldInfo _staminaBarsField; private PropertyInfo _observedCharacterProperty; private FieldInfo _isEnabledField; private FieldInfo _animateDisableCoroutineField; private object _lastProximityManager; private bool _initialized; private bool _initAttempted; private bool _loggedMissing; private bool _fullInfoOverrideActive; private PeakStatsExInfoOverrideState _fullInfoState; private bool _wasSpectatorActive; private float _clearInventoryUntil; internal PeakStatsExCompatibility(Harmony harmony) { _harmony = harmony; } internal void Update(bool spectatorActive) { if (!Configuration.EnablePeakStatsExCompatibility) { Restore(); _wasSpectatorActive = spectatorActive; return; } EnsureInitialized(); if (!spectatorActive) { if (_wasSpectatorActive) { _clearInventoryUntil = Time.time + 1.5f; } Restore(); ClearResidualInventoryIfNeeded(); _wasSpectatorActive = false; } else { _wasSpectatorActive = true; UpdateFullPeakStatsExInfoOverride(); } } internal void Restore() { _overrides.ReleaseAll(); _fullInfoOverrideActive = false; _fullInfoState = default(PeakStatsExInfoOverrideState); } private void EnsureInitialized() { if (_initialized || _initAttempted) { return; } Type type = AccessTools.TypeByName("PeakStatsEx.PluginConfig"); if (type == null) { _initAttempted = true; LogMissingOnce(); return; } _proximityDistance = CreateConfigValue(type, "TeammateStaminaBarProximity"); if (_proximityDistance == null) { _initAttempted = true; LogMissingOnce(); return; } _displayTimer = CreateConfigValue(type, "DisplayTimer"); _displayHeight = CreateConfigValue(type, "DisplayHeight"); _displayLevel = CreateConfigValue(type, "DisplayLevel"); _displayBiomes = CreateConfigValue(type, "DisplayBiomes"); _displayDayNightCountdown = CreateConfigValue(type, "DisplayDayNightCountdown"); _displayFog = CreateConfigValue(type, "DisplayFog"); _displayLava = CreateConfigValue(type, "DisplayLava"); _displayTerrainRandomiserSeed = CreateConfigValue(type, "DisplayTerrainRandomiserSeed"); _displayTerrainCustomiserSeed = CreateConfigValue(type, "DisplayTerrainCustomiserSeed"); _showInventorySlots = CreateConfigValue(type, "ShowInventorySlots"); _showStaminaInfo = CreateConfigValue(type, "ShowStaminaInfo"); _staminaInfoShowAfflictionCountdown = CreateConfigValue(type, "StaminaInfoShowAfflictionCountdown"); Type type2 = AccessTools.TypeByName("PeakStatsEx.MonoBehaviours.ProximityStaminaManager"); _staminaBarsField = ((type2 != null) ? AccessTools.Field(type2, "staminaBars") : null); Type type3 = AccessTools.TypeByName("PeakStatsEx.MonoBehaviours.CharacterStaminaBar"); _observedCharacterProperty = ((type3 != null) ? AccessTools.Property(type3, "ObservedCharacter") : null); _isEnabledField = ((type3 != null) ? AccessTools.Field(type3, "isEnabled") : null); _animateDisableCoroutineField = ((type3 != null) ? AccessTools.Field(type3, "animateDisableCoroutine") : null); TryPatchPeakStatsEx(); _initialized = true; L10n.LogInfo("PeakStatsEx free-camera stamina bar distance compatibility enabled.", "已启用 PeakStatsEx 自由相机体力条距离兼容。"); } private void TryPatchPeakStatsEx() { PatchMethod("PeakStatsEx.MonoBehaviours.ProximityStaminaManager", "Update", "ProximityManagerUpdatePrefix", "ProximityManagerUpdatePostfix"); PatchMethod("PeakStatsEx.MonoBehaviours.TimerHeightStats", "Update", "TimerHeightStatsUpdatePrefix", "TimerHeightStatsUpdatePostfix"); PatchMethod("PeakStatsEx.MonoBehaviours.MapStats", "Update", "MapStatsUpdatePrefix", "MapStatsUpdatePostfix"); PatchMethod("PeakStatsEx.MonoBehaviours.CharacterStaminaBar", "Update", "CharacterStaminaBarUpdatePrefix", "CharacterStaminaBarUpdatePostfix"); PatchMethod("StaminaBar", "Update", "StaminaBarUpdatePrefix", "StaminaBarUpdatePostfix"); } private void PatchMethod(string typeName, string methodName, string prefixName, string postfixName) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_007a: Expected O, but got Unknown Type type = AccessTools.TypeByName(typeName); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, methodName, (Type[])null, (Type[])null) : null); MethodInfo methodInfo2 = AccessTools.Method(typeof(PeakStatsExCompatibility), prefixName, (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(PeakStatsExCompatibility), postfixName, (Type[])null, (Type[])null); if (methodInfo != null && methodInfo2 != null && methodInfo3 != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private bool ShouldOverrideDistance() { if (Configuration.EnablePeakStatsExCompatibility && Plugin.CameraController != null && Plugin.CameraController.IsActive) { return _proximityDistance != null; } return false; } private bool ShouldHidePeakStatsExExtras() { if (Configuration.EnablePeakStatsExCompatibility && !Configuration.ShowFullPeakStatsExInfo.Value) { return SpectatorHudManager.ShouldHideHud(); } return false; } private bool ShouldShowFullPeakStatsExInfo() { if (Configuration.EnablePeakStatsExCompatibility && Configuration.ShowFullPeakStatsExInfo.Value && Plugin.CameraController != null) { return Plugin.CameraController.IsActive; } return false; } private bool ShouldForceInventoryInFreeCamera() { if (Configuration.EnablePeakStatsExCompatibility && Configuration.ForcePeakStatsExInventoryInFreeCamera && Plugin.CameraController != null) { return Plugin.CameraController.IsActive; } return false; } private void UpdateFullPeakStatsExInfoOverride() { if (ShouldShowFullPeakStatsExInfo()) { if (!_fullInfoOverrideActive) { _fullInfoState = BeginFullPeakStatsExInfoOverride(); _fullInfoOverrideActive = true; } } else if (_fullInfoOverrideActive) { EndPeakStatsExInfoOverride(_fullInfoState); _fullInfoState = default(PeakStatsExInfoOverrideState); _fullInfoOverrideActive = false; } } private RuntimeOverrideToken BeginTemporaryDistanceOverride() { if (_proximityDistance == null) { return RuntimeOverrideToken.Inactive; } return _overrides.Apply(GetOverrideKey(_proximityDistance), () => _proximityDistance.Get(30f), delegate(float value) { _proximityDistance.Set(value); }, Configuration.SpectatorTeammateStaminaDistance.Value); } private void EndTemporaryDistanceOverride(RuntimeOverrideToken token) { token.Release(); } private RuntimeOverrideToken BeginBoolOverride(ConfigValue entry, bool value) { if (entry == null) { return RuntimeOverrideToken.Inactive; } return _overrides.Apply(GetOverrideKey(entry), () => entry.Get(fallback: true), delegate(bool current) { entry.Set(current); }, value); } private void EndBoolOverride(RuntimeOverrideToken token) { token.Release(); } private InventoryOverrideState BeginInventoryOverride() { InventoryOverrideState result = default(InventoryOverrideState); if (_showInventorySlots != null) { result.SlotsToken = _overrides.Apply(GetOverrideKey(_showInventorySlots), () => _showInventorySlots.Get(fallback: false), delegate(bool value) { _showInventorySlots.Set(value); }, value: true); } return result; } private void EndInventoryOverride(InventoryOverrideState state) { state.SlotsToken.Release(); EndPeakStatsExInfoOverride(state.InfoState); } private PeakStatsExInfoOverrideState BeginCompactPeakStatsExInfoOverride() { return new PeakStatsExInfoOverrideState { DisplayHeightToken = BeginBoolOverride(_displayHeight, value: false) }; } private PeakStatsExInfoOverrideState BeginFullPeakStatsExInfoOverride() { return new PeakStatsExInfoOverrideState { DisplayTimerToken = BeginBoolOverride(_displayTimer, value: true), DisplayHeightToken = BeginBoolOverride(_displayHeight, value: true), DisplayLevelToken = BeginBoolOverride(_displayLevel, value: true), DisplayBiomesToken = BeginBoolOverride(_displayBiomes, value: true), DisplayDayNightCountdownToken = BeginBoolOverride(_displayDayNightCountdown, value: true), DisplayFogToken = BeginBoolOverride(_displayFog, value: true), DisplayLavaToken = BeginBoolOverride(_displayLava, value: true), DisplayTerrainRandomiserSeedToken = BeginBoolOverride(_displayTerrainRandomiserSeed, value: true), DisplayTerrainCustomiserSeedToken = BeginBoolOverride(_displayTerrainCustomiserSeed, value: true), ShowStaminaInfoToken = BeginBoolOverride(_showStaminaInfo, value: true), StaminaInfoShowAfflictionCountdownToken = BeginBoolOverride(_staminaInfoShowAfflictionCountdown, value: true) }; } private void EndPeakStatsExInfoOverride(PeakStatsExInfoOverrideState state) { state.DisplayTimerToken.Release(); state.DisplayHeightToken.Release(); state.DisplayLevelToken.Release(); state.DisplayBiomesToken.Release(); state.DisplayDayNightCountdownToken.Release(); state.DisplayFogToken.Release(); state.DisplayLavaToken.Release(); state.DisplayTerrainRandomiserSeedToken.Release(); state.DisplayTerrainCustomiserSeedToken.Release(); state.ShowStaminaInfoToken.Release(); state.StaminaInfoShowAfflictionCountdownToken.Release(); } private static object GetOverrideKey(ConfigValue entry) { return entry?.EntryObject; } private bool TryDisableDeadStaminaBar(object characterStaminaBar) { Character observedCharacter = GetObservedCharacter(characterStaminaBar); if ((Object)(object)observedCharacter == (Object)null || !CharacterState.IsDead(observedCharacter)) { return false; } ForceDisableStaminaBar(characterStaminaBar); return true; } private void HideDeadStaminaBars(object proximityManager) { TrackProximityManager(proximityManager); if (!Configuration.EnablePeakStatsExCompatibility || proximityManager == null || _staminaBarsField == null || !(_staminaBarsField.GetValue(proximityManager) is IDictionary dictionary)) { return; } foreach (DictionaryEntry item in dictionary) { object key = item.Key; Character val = (Character)((key is Character) ? key : null); if ((Object)(object)val != (Object)null && CharacterState.IsDead(val)) { ForceDisableStaminaBar(item.Value); } } } private Character GetObservedCharacter(object characterStaminaBar) { if (characterStaminaBar == null || _observedCharacterProperty == null) { return null; } object? value = _observedCharacterProperty.GetValue(characterStaminaBar, null); return (Character)((value is Character) ? value : null); } private void ForceDisableStaminaBar(object characterStaminaBar) { if (characterStaminaBar != null) { object obj = ((characterStaminaBar is MonoBehaviour) ? characterStaminaBar : null); if (obj != null) { ((MonoBehaviour)obj).StopAllCoroutines(); } _isEnabledField?.SetValue(characterStaminaBar, false); _animateDisableCoroutineField?.SetValue(characterStaminaBar, null); Component val = (Component)((characterStaminaBar is Component) ? characterStaminaBar : null); if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null && val.gameObject.activeSelf) { val.gameObject.SetActive(false); } } } private void ClearInventorySlots(object characterStaminaBar) { if (characterStaminaBar != null) { ClearSlotList(characterStaminaBar, "inventorySlotUIs"); ClearSlotList(characterStaminaBar, "backpackSlotUIs"); ClearInventorySlot(AccessTools.Field(characterStaminaBar.GetType(), "heldItemSlot")?.GetValue(characterStaminaBar)); } } private void TrackProximityManager(object proximityManager) { if (proximityManager != null) { _lastProximityManager = proximityManager; } } private void ClearResidualInventoryIfNeeded() { if (!(Time.time > _clearInventoryUntil) && (_showInventorySlots == null || !_showInventorySlots.Get(fallback: false))) { ClearInventorySlotsFromManager(_lastProximityManager); } } private void ClearInventorySlotsFromManager(object proximityManager) { if (proximityManager == null || _staminaBarsField == null || !(_staminaBarsField.GetValue(proximityManager) is IDictionary dictionary)) { return; } foreach (DictionaryEntry item in dictionary) { ClearInventorySlots(item.Value); } } private static void ClearSlotList(object owner, string fieldName) { if (!(AccessTools.Field(owner.GetType(), fieldName)?.GetValue(owner) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { ClearInventorySlot(item); } } private static void ClearInventorySlot(object slot) { if (slot == null) { return; } MethodInfo methodInfo = AccessTools.Method(slot.GetType(), "Clear", (Type[])null, (Type[])null); if (methodInfo == null) { return; } try { methodInfo.Invoke(slot, null); } catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException || ex.InnerException is MissingReferenceException) { } catch (NullReferenceException) { } catch (MissingReferenceException) { } } private static ConfigValue CreateConfigValue(Type configType, string propertyName) { object obj = AccessTools.Property(configType, propertyName)?.GetValue(null, null); if (obj == null) { return null; } ConfigValue configValue = new ConfigValue(obj); if (!configValue.IsValid) { return null; } return configValue; } private void LogMissingOnce() { if (!_loggedMissing) { _loggedMissing = true; L10n.LogInfo("No compatible PeakStatsEx version detected (1.2.0 / 1.2.1); skipped stamina bar distance compatibility.", "未检测到可兼容的 PeakStatsEx(1.2.0 / 1.2.1),已跳过体力条距离兼容。"); } } private static void ProximityManagerUpdatePrefix(out RuntimeOverrideToken __state) { __state = RuntimeOverrideToken.Inactive; if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldOverrideDistance()) { __state = Plugin.PeakStatsEx.BeginTemporaryDistanceOverride(); } } private static void ProximityManagerUpdatePostfix(object __instance, RuntimeOverrideToken __state) { if (Plugin.PeakStatsEx != null) { Plugin.PeakStatsEx.EndTemporaryDistanceOverride(__state); Plugin.PeakStatsEx.HideDeadStaminaBars(__instance); } } private static void TimerHeightStatsUpdatePrefix(out PeakStatsExInfoOverrideState __state) { __state = default(PeakStatsExInfoOverrideState); if (Plugin.PeakStatsEx != null) { if (Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo()) { __state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride(); } else if (Plugin.PeakStatsEx.ShouldHidePeakStatsExExtras()) { __state = Plugin.PeakStatsEx.BeginCompactPeakStatsExInfoOverride(); } } } private static void TimerHeightStatsUpdatePostfix(PeakStatsExInfoOverrideState __state) { if (Plugin.PeakStatsEx != null) { Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state); } } private static void MapStatsUpdatePrefix(out PeakStatsExInfoOverrideState __state) { __state = default(PeakStatsExInfoOverrideState); if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo()) { __state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride(); } } private static void MapStatsUpdatePostfix(PeakStatsExInfoOverrideState __state) { if (Plugin.PeakStatsEx != null) { Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state); } } private static void StaminaBarUpdatePrefix(out PeakStatsExInfoOverrideState __state) { __state = default(PeakStatsExInfoOverrideState); if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo()) { __state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride(); } } private static void StaminaBarUpdatePostfix(PeakStatsExInfoOverrideState __state) { if (Plugin.PeakStatsEx != null) { Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state); } } private static bool CharacterStaminaBarUpdatePrefix(object __instance, out InventoryOverrideState __state) { __state = default(InventoryOverrideState); if (Plugin.PeakStatsEx == null) { return true; } if (Plugin.PeakStatsEx.TryDisableDeadStaminaBar(__instance)) { return false; } if (Plugin.PeakStatsEx.ShouldForceInventoryInFreeCamera()) { __state = Plugin.PeakStatsEx.BeginInventoryOverride(); } if (Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo()) { __state.InfoState = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride(); } return true; } private static void CharacterStaminaBarUpdatePostfix(InventoryOverrideState __state) { if (Plugin.PeakStatsEx != null) { Plugin.PeakStatsEx.EndInventoryOverride(__state); } } } internal sealed class PeakTrailsCompatibility { private readonly Harmony _harmony; private FieldInfo _showTrailsField; private bool _initialized; private bool _initAttempted; private bool _available; private bool _overrideVisible; private bool _loggedMissing; internal bool ShouldControlTrails { get { if (Configuration.EnablePeakTrailsCompatibility && _available && Plugin.CameraController != null) { return Plugin.CameraController.IsActive; } return false; } } internal PeakTrailsCompatibility(Harmony harmony) { _harmony = harmony; } internal void UpdateInput(bool spectatorActive) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!Configuration.EnablePeakTrailsCompatibility) { _overrideVisible = false; return; } EnsureInitialized(); if (!_available) { return; } if (!spectatorActive) { _overrideVisible = false; return; } if (Input.GetKeyDown(Configuration.PeakTrailsToggleKey.Value)) { _overrideVisible = !_overrideVisible; } ApplySpectatorTrailState(); } internal void ApplySpectatorTrailState() { SetShowTrails(_overrideVisible); } private void EnsureInitialized() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown if (_initialized || _initAttempted) { return; } Type type = AccessTools.TypeByName("PEAKTrails.Patching+PlayerVisualUpdatePatch"); if (type == null) { _initAttempted = true; LogMissingOnce(); return; } _initialized = true; _showTrailsField = AccessTools.Field(type, "ShowTrails"); MethodInfo methodInfo = AccessTools.Method(type, "UpdateLocalTrailControls", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(PeakTrailsCompatibility), "UpdateLocalTrailControlsPrefix", (Type[])null, (Type[])null); if (_showTrailsField == null || methodInfo == null || methodInfo2 == null) { _initAttempted = true; LogMissingOnce(); } else { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _available = true; L10n.LogInfo("PEAKTrails free-camera trail compatibility enabled. Use the configured key to toggle trail display in the spectator camera.", "已启用 PEAKTrails 自由相机轨迹兼容。按配置按键可在观战相机中切换轨迹显示。"); } } private void SetShowTrails(bool value) { try { _showTrailsField?.SetValue(null, value); } catch { } } private void LogMissingOnce() { if (!_loggedMissing) { _loggedMissing = true; L10n.LogInfo("No compatible PEAKTrails 1.1.3 detected; skipped trail compatibility.", "未检测到可兼容的 PEAKTrails 1.1.3,已跳过轨迹兼容。"); } } private static bool UpdateLocalTrailControlsPrefix() { if (Plugin.PeakTrails != null && Plugin.PeakTrails.ShouldControlTrails) { Plugin.PeakTrails.ApplySpectatorTrailState(); return false; } return true; } } [BepInPlugin("com.AiAe.peakspectatormode", "PeakSpectatorMode", "1.1.1")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static SpectatorCameraController CameraController; internal static SpectatorOverlay Overlay; internal static XraySilhouetteManager Xray; internal static PeakTrailsCompatibility PeakTrails; internal static PeakStatsExCompatibility PeakStatsEx; internal static SummitRosterCompatibility SummitRoster; internal static SpectatorHudManager HudManager; internal static ForceDeathController ForceDeath; internal static GhostSpectatorIntegration GsIntegration; internal static BetterPlayerDistanceIntegration BpdIntegration; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Configuration.Initialize(((BaseUnityPlugin)this).Config); _harmony = new Harmony("com.AiAe.peakspectatormode"); _harmony.PatchAll(); CameraController = new SpectatorCameraController(); Overlay = new SpectatorOverlay(); Xray = new XraySilhouetteManager(); PeakTrails = new PeakTrailsCompatibility(_harmony); PeakStatsEx = new PeakStatsExCompatibility(_harmony); SummitRoster = new SummitRosterCompatibility(_harmony); HudManager = new SpectatorHudManager(); ForceDeath = new ForceDeathController(); GsIntegration = new GhostSpectatorIntegration(); GsIntegration.TryDetect(); BpdIntegration = new BetterPlayerDistanceIntegration(); BpdIntegration.TryDetect(); L10n.LogInfo("PeakSpectatorMode v1.1.1 loaded.", "更好的观战视角 v1.1.1 已加载。"); } private void Start() { Overlay.TryInitialize(); } private void Update() { CameraController.UpdateInput(); Overlay.UpdateInput(CameraController.IsActive); PeakTrails.UpdateInput(CameraController.IsActive); PeakStatsEx.Update(CameraController.IsActive); ForceDeath.Update(); } private void LateUpdate() { CameraController.LateUpdate(); CameraController.UpdateSoftFollow(); Overlay.LateUpdate(CameraController.IsActive); Xray.LateUpdate(CameraController.IsActive); HudManager.LateUpdate(CameraController.IsActive); } private void OnDestroy() { CameraController.SetActive(active: false); BpdIntegration?.Restore(); HudManager.Restore(); PeakStatsEx.Restore(); SummitRoster?.Dispose(); ForceDeath.Dispose(); Overlay.Dispose(); Xray.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(Character))] internal static class CharacterPatches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePostfix(Character __instance) { Plugin.Overlay?.RegisterCharacter(__instance); Plugin.Xray?.RegisterCharacter(__instance); } [HarmonyPatch("OnDestroy")] [HarmonyPostfix] private static void OnDestroyPostfix(Character __instance) { Plugin.Overlay?.UnregisterCharacter(__instance); Plugin.Xray?.UnregisterCharacter(__instance); } } [HarmonyPatch(typeof(GodCam), "DoFOV")] internal static class GodCamFovPatch { [HarmonyPrefix] private static bool Prefix(GodCam __instance, Transform transform, MainCamera cam) { if (Plugin.CameraController != null) { return !Plugin.CameraController.TryOverrideGodCamFov(__instance, transform, cam); } return true; } } [HarmonyPatch(typeof(GUIManager))] internal static class GuiManagerHudPatches { [HarmonyPatch("UpdateDyingBar")] [HarmonyPrefix] [HarmonyPriority(0)] private static bool UpdateDyingBarPrefix(GUIManager __instance) { return HideAndSkipIfNeeded(__instance); } [HarmonyPatch("UpdateSpectate")] [HarmonyPrefix] [HarmonyPriority(0)] private static bool UpdateSpectatePrefix(GUIManager __instance) { return HideAndSkipIfNeeded(__instance); } [HarmonyPatch("UpdateItems")] [HarmonyPrefix] [HarmonyPriority(0)] private static bool UpdateItemsPrefix(GUIManager __instance) { return HideAndSkipIfNeeded(__instance); } [HarmonyPatch("UpdateItemPrompts")] [HarmonyPrefix] [HarmonyPriority(0)] private static bool UpdateItemPromptsPrefix(GUIManager __instance) { return HideAndSkipIfNeeded(__instance); } private static bool HideAndSkipIfNeeded(GUIManager gui) { if (!SpectatorHudManager.ShouldHideHud()) { return true; } Plugin.HudManager?.HideGuiElements(gui); return false; } } internal sealed class RuntimeOverrideManager { private interface IRuntimeOverride { int RefCount { get; } void AddRef(); void ReleaseRef(); void Restore(); } private sealed class RuntimeOverride : IRuntimeOverride { private readonly Action _setter; private readonly T _original; private int _refCount; public int RefCount => _refCount; internal RuntimeOverride(Func getter, Action setter) { _setter = setter; _original = getter(); } public void AddRef() { _refCount++; } public void ReleaseRef() { if (_refCount > 0) { _refCount--; } } internal void Set(T value) { _setter(value); } public void Restore() { _setter(_original); _refCount = 0; } } private readonly Dictionary _overrides = new Dictionary(); internal RuntimeOverrideToken Apply(object key, Func getter, Action setter, T value) { if (key == null || getter == null || setter == null) { return RuntimeOverrideToken.Inactive; } if (!_overrides.TryGetValue(key, out var value2)) { value2 = new RuntimeOverride(getter, setter); _overrides.Add(key, value2); } if (!(value2 is RuntimeOverride runtimeOverride)) { return RuntimeOverrideToken.Inactive; } runtimeOverride.AddRef(); runtimeOverride.Set(value); return new RuntimeOverrideToken(this, key, active: true); } internal void Release(RuntimeOverrideToken token) { if (token.Active && token.Key != null && _overrides.TryGetValue(token.Key, out var value)) { value.ReleaseRef(); if (value.RefCount <= 0) { value.Restore(); _overrides.Remove(token.Key); } } } internal void ReleaseAll() { foreach (IRuntimeOverride value in _overrides.Values) { value.Restore(); } _overrides.Clear(); } } internal struct RuntimeOverrideToken { internal static readonly RuntimeOverrideToken Inactive = new RuntimeOverrideToken(null, null, active: false); private readonly RuntimeOverrideManager _manager; internal object Key { get; } internal bool Active { get; } internal RuntimeOverrideToken(RuntimeOverrideManager manager, object key, bool active) { _manager = manager; Key = key; Active = active; } internal void Release() { _manager?.Release(this); } } internal sealed class SpectatorCameraController { private const float MaxCameraPitch = 89.5f; private const float MinSwitchDuration = 0.2f; private const float MaxSwitchDuration = 0.5f; private const float MaxSwitchDistance = 80f; private const float EaseEdgeRatio = 0.25f; private const float AltSlowTransitionSpeed = 10f; private readonly FieldInfo _isGodCamField = AccessTools.Field(typeof(MainCameraMovement), "isGodCam"); private readonly FieldInfo _lookDataField = AccessTools.Field(typeof(GodCam), "lookData"); private readonly FieldInfo _targetFovField = AccessTools.Field(typeof(GodCam), "targetFov"); private readonly FieldInfo _forceField = AccessTools.Field(typeof(GodCam), "force"); private readonly FieldInfo _dragField = AccessTools.Field(typeof(GodCam), "drag"); private readonly FieldInfo _lookSensField = AccessTools.Field(typeof(GodCam), "lookSens"); private readonly FieldInfo _lookDragField = AccessTools.Field(typeof(GodCam), "lookDrag"); private Character _focusedPlayer; private bool _switchTransitionActive; private Vector3 _switchStartPosition; private Vector3 _switchTargetPosition; private Quaternion _switchStartRotation; private Quaternion _switchTargetRotation; private float _switchElapsed; private float _switchDuration; private bool _hasFovState; private float _defaultFov = 70f; private float _scrollFovTarget = 70f; private bool _followActive; private Character _followTarget; private Vector3 _followTargetPosSnapshot; private float _altSlowMultiplier = 1f; internal bool IsActive { get; private set; } internal Character FollowingTarget { get { if (!_followActive || !((Object)(object)_followTarget != (Object)null) || !CharacterState.IsAliveSpectatorTarget(_followTarget)) { return null; } return _followTarget; } } internal Character FocusedPlayer { get { if (!IsActive || !((Object)(object)_focusedPlayer != (Object)null) || !CharacterState.IsAliveSpectatorTarget(_focusedPlayer)) { return null; } return _focusedPlayer; } } internal void UpdateInput() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) if (Input.GetKeyDown(Configuration.ToggleKey.Value) && !Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307)) { SetActive(!IsActive); } if (IsActive && Input.GetKeyDown((KeyCode)27)) { SetActive(active: false); } if (IsActive && Input.GetKeyDown(Configuration.ResetKey.Value)) { ResetToLocalPlayer(); } if (IsActive && Input.GetKeyDown(Configuration.PreviousPlayerKey.Value)) { CycleFocusedPlayer(-1); } if (IsActive && Input.GetKeyDown(Configuration.NextPlayerKey.Value)) { CycleFocusedPlayer(1); } if (IsActive) { ApplyGodCamSettings(); } } internal void LateUpdate() { UpdateSwitchTransition(); } internal void SetActive(bool active) { bool isActive = IsActive; MainCameraMovement instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { IsActive = false; _focusedPlayer = null; return; } IsActive = active; _isGodCamField?.SetValue(instance, active); if (active) { if (!isActive) { InitializeFovState(); } SyncGodCamState(instance); ResetCursorForCamera(); } else { _hasFovState = false; _focusedPlayer = null; _switchTransitionActive = false; _followActive = false; _followTarget = null; _altSlowMultiplier = 1f; } } private void ApplyGodCamSettings() { MainCameraMovement instance = Singleton.Instance; if (instance?.godcam != null) { float num = (Input.GetKey((KeyCode)304) ? Mathf.Max(Configuration.NormalSpeed.Value, Configuration.FastSpeed.Value / 10f) : Configuration.NormalSpeed.Value); float num2 = (IsAltHeld() ? Mathf.Clamp(Configuration.AltSlowSpeedMultiplier.Value, 0.05f, 1f) : 1f); _altSlowMultiplier = Mathf.Lerp(_altSlowMultiplier, num2, Time.unscaledDeltaTime * 10f); _forceField?.SetValue(instance.godcam, num * _altSlowMultiplier); _dragField?.SetValue(instance.godcam, Configuration.MoveDamping.Value); _lookSensField?.SetValue(instance.godcam, Configuration.TurnSpeed.Value); _lookDragField?.SetValue(instance.godcam, Configuration.TurnDamping.Value); } } private static bool IsAltHeld() { if (!Input.GetKey((KeyCode)308)) { return Input.GetKey((KeyCode)307); } return true; } internal bool TryOverrideGodCamFov(GodCam godCam, Transform cameraTransform, MainCamera mainCamera) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (!IsActive || godCam == null || (Object)(object)mainCamera == (Object)null || (Object)(object)mainCamera.cam == (Object)null) { return false; } ClampGodCamPitch(godCam, cameraTransform); EnsureFovState(mainCamera.cam); float num = Mathf.Clamp(mainCamera.cam.fieldOfView, 1f, 120f); float num2 = Mathf.Lerp(num / 70f, 1f, 0.25f); _scrollFovTarget += (0f - Input.mouseScrollDelta.y) * 2f * num2; _scrollFovTarget = Mathf.Clamp(_scrollFovTarget, 1f, 120f); if (Input.GetKeyDown((KeyCode)325)) { _scrollFovTarget = Mathf.Clamp(_defaultFov, 1f, 120f); } float num3 = _scrollFovTarget; if (Input.GetKey(Configuration.TelescopeKey.Value)) { num3 = CalculateZoomFov(_scrollFovTarget, Configuration.TelescopeMultiplier.Value); } float num4 = Mathf.Max(0.01f, 8f); mainCamera.cam.fieldOfView = Mathf.Lerp(num, num3, Time.unscaledDeltaTime * num4); _targetFovField?.SetValue(godCam, _scrollFovTarget); return true; } private void ClampGodCamPitch(GodCam godCam, Transform cameraTransform) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (_lookDataField == null || godCam == null || (Object)(object)cameraTransform == (Object)null || !(_lookDataField.GetValue(godCam) is Vector2 val)) { return; } float num = Mathf.Clamp(val.y, -89.5f, 89.5f); if (!Mathf.Approximately(num, val.y)) { val.y = num; _lookDataField.SetValue(godCam, val); Vector3 val2 = HelperFunctions.LookToDirection(new Vector3(val.x, val.y, 0f), Vector3.forward); if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { cameraTransform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized); } } } private void SyncGodCamState(MainCameraMovement movement) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (movement.godcam != null) { Vector3 val = DirectionToLook(((Component)movement).transform.forward); val.y = Mathf.Clamp(val.y, -89.5f, 89.5f); _lookDataField?.SetValue(movement.godcam, (object)new Vector2(val.x, val.y)); Camera val2 = (((Object)(object)MainCamera.instance != (Object)null) ? MainCamera.instance.cam : Camera.main); if ((Object)(object)val2 != (Object)null) { _targetFovField?.SetValue(movement.godcam, val2.fieldOfView); } ApplyGodCamSettings(); } } private void InitializeFovState() { Camera val = (((Object)(object)MainCamera.instance != (Object)null) ? MainCamera.instance.cam : Camera.main); if ((Object)(object)val == (Object)null) { _hasFovState = false; _defaultFov = 70f; _scrollFovTarget = 70f; } else { _defaultFov = Mathf.Clamp(val.fieldOfView, 1f, 120f); _scrollFovTarget = _defaultFov; _hasFovState = true; } } private void EnsureFovState(Camera cam) { if (!_hasFovState) { if ((Object)(object)cam == (Object)null) { _defaultFov = 70f; _scrollFovTarget = 70f; } else { _defaultFov = Mathf.Clamp(cam.fieldOfView, 1f, 120f); _scrollFovTarget = _defaultFov; } _hasFovState = true; } } private static float CalculateZoomFov(float baseFov, float multiplier) { baseFov = Mathf.Clamp(baseFov, 1f, 120f); multiplier = Mathf.Max(1f, multiplier); float num = baseFov * (MathF.PI / 180f); return Mathf.Clamp(2f * Mathf.Atan(Mathf.Tan(num * 0.5f) / multiplier) * 57.29578f, 1f, 120f); } internal void ResetToLocalPlayer() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) MainCameraMovement instance = Singleton.Instance; Character localCharacter = Character.localCharacter; if (!((Object)(object)instance == (Object)null) && !((Object)(object)localCharacter == (Object)null)) { Transform transform = ((Component)instance).transform; _focusedPlayer = null; _switchTransitionActive = false; _followActive = false; _followTarget = null; Vector3 characterResetPosition = GetCharacterResetPosition(localCharacter); transform.position = characterResetPosition - transform.forward * 2.4f + Vector3.up * 1.2f; SyncGodCamState(instance); } } private void CycleFocusedPlayer(int direction) { List cycleTargets = GetCycleTargets(); if (cycleTargets.Count == 0) { _focusedPlayer = null; return; } int num = cycleTargets.IndexOf(_focusedPlayer); int index = ((num >= 0) ? ((num + direction + cycleTargets.Count) % cycleTargets.Count) : ((direction <= 0) ? (cycleTargets.Count - 1) : 0)); _focusedPlayer = cycleTargets[index]; SetActive(active: true); StartCameraSwitchTransition(_focusedPlayer); } private void StartCameraSwitchTransition(Character target) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) MainCameraMovement instance = Singleton.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)target == (Object)null)) { Transform transform = ((Component)instance).transform; if (TryGetTargetCameraPose(target, transform, out var position, out var rotation)) { _switchStartPosition = transform.position; _switchStartRotation = transform.rotation; _switchTargetPosition = position; _switchTargetRotation = rotation; _switchElapsed = 0f; _switchDuration = CalculateSwitchDuration(Vector3.Distance(_switchStartPosition, _switchTargetPosition)); _switchTransitionActive = true; } } } private void UpdateSwitchTransition() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_0082: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!_switchTransitionActive || !IsActive) { return; } MainCameraMovement instance = Singleton.Instance; Character focusedPlayer = FocusedPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)focusedPlayer == (Object)null) { _switchTransitionActive = false; return; } _switchElapsed += Time.unscaledDeltaTime; float num = Mathf.Clamp01(_switchElapsed / Mathf.Max(0.01f, _switchDuration)); float num2 = TripleEase(num); Transform transform = ((Component)instance).transform; if (TryGetTargetCameraPose(focusedPlayer, transform, out var position, out var rotation)) { _switchTargetPosition = position; _switchTargetRotation = rotation; } transform.position = Vector3.LerpUnclamped(_switchStartPosition, _switchTargetPosition, num2); transform.rotation = Quaternion.Slerp(_switchStartRotation, _switchTargetRotation, num2); SyncGodCamState(instance); if (num >= 1f) { _switchTransitionActive = false; StartSoftFollow(focusedPlayer); } } private void StartSoftFollow(Character target) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null || !Configuration.EnableSoftFollow.Value) { _followActive = false; _followTarget = null; } else { _followTarget = target; _followTargetPosSnapshot = SafeGetTargetCenter(target); _followActive = true; } } internal void UpdateSoftFollow() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00bf: Unknown result type (might be due to invalid IL or missing references) if (!_followActive || !IsActive || _switchTransitionActive) { return; } if ((Object)(object)_followTarget == (Object)null || !CharacterState.IsAliveSpectatorTarget(_followTarget)) { _followActive = false; _followTarget = null; return; } MainCameraMovement instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { return; } Transform transform = ((Component)instance).transform; Vector3 val = SafeGetTargetCenter(_followTarget); float num = Vector3.Distance(transform.position, val); float num2 = Mathf.Max(1f, Configuration.SoftFollowMaxDistance.Value); if (num > num2) { _followActive = false; _followTarget = null; return; } Vector3 val2 = val - _followTargetPosSnapshot; if (((Vector3)(ref val2)).sqrMagnitude > 0f) { transform.position += val2; } _followTargetPosSnapshot = val; } private static bool HasMovementInput() { if (!Input.GetKey((KeyCode)119) && !Input.GetKey((KeyCode)97) && !Input.GetKey((KeyCode)115) && !Input.GetKey((KeyCode)100) && !Input.GetKey((KeyCode)32) && !Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)113)) { return Input.GetKey((KeyCode)101); } return true; } private static Vector3 SafeGetTargetCenter(Character target) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_003a: 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) if ((Object)(object)target == (Object)null) { return Vector3.zero; } try { return target.Center; } catch { return ((Object)(object)((Component)target).transform != (Object)null) ? ((Component)target).transform.position : Vector3.zero; } } private static float CalculateSwitchDuration(float distance) { float num = Mathf.InverseLerp(0f, 80f, Mathf.Max(0f, distance)); return Mathf.Lerp(0.2f, 0.5f, num); } private static float TripleEase(float t) { t = Mathf.Clamp01(t); float num = Mathf.Clamp(0.25f, 0.0001f, 0.4999f); float num2 = 1f / (1f - num); if (t <= num) { return num2 * t * t / (2f * num); } if (t < 1f - num) { return num2 * num / 2f + num2 * (t - num); } float num3 = num2 * num / 2f; float num4 = num2 * (1f - 2f * num); float num5 = t - (1f - num); float num6 = num2 * num5 - num2 * num5 * num5 / (2f * num); return num3 + num4 + num6; } private static bool TryGetTargetCameraPose(Character target, Transform cameraTransform, out Vector3 position, out Quaternion rotation) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; rotation = Quaternion.identity; if ((Object)(object)target == (Object)null) { return false; } Vector3 characterFocusPoint = GetCharacterFocusPoint(target); Vector3 characterBackDirection = GetCharacterBackDirection(target, cameraTransform); position = characterFocusPoint - characterBackDirection * 4f + Vector3.up * 1.4f; Vector3 val = characterFocusPoint - position; if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); return true; } rotation = (((Object)(object)cameraTransform != (Object)null) ? cameraTransform.rotation : Quaternion.identity); return true; } private static List GetCycleTargets() { List list = new List(); foreach (Character allCharacter in Character.AllCharacters) { if (CharacterState.IsAliveSpectatorTarget(allCharacter)) { list.Add(allCharacter); } } list.Sort((Character a, Character b) => GetSortKey(a).CompareTo(GetSortKey(b))); return list; } private static int GetSortKey(Character character) { try { if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null) { return ((MonoBehaviourPun)character).photonView.OwnerActorNr; } } catch { } return ((Object)character).GetInstanceID(); } private static Vector3 GetCharacterResetPosition(Character character) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) if ((Object)(object)character == (Object)null) { return Vector3.zero; } try { return character.Head; } catch { return character.Center + Vector3.up * 1.2f; } } private static Vector3 GetCharacterFocusPoint(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) try { return character.Head; } catch { return character.Center + Vector3.up * 1.2f; } } private static Vector3 GetCharacterBackDirection(Character character, Transform cameraTransform) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; try { val = character.data.lookDirection; } catch { } if (((Vector3)(ref val)).sqrMagnitude <= 0.001f && (Object)(object)cameraTransform != (Object)null) { val = cameraTransform.forward; } if (((Vector3)(ref val)).sqrMagnitude <= 0.001f) { val = Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static Vector3 DirectionToLook(Vector3 direction) { //IL_0016: 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_0020: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref direction)).sqrMagnitude <= 0.0001f) { return Vector3.zero; } Quaternion val = Quaternion.LookRotation(((Vector3)(ref direction)).normalized, Vector3.up); Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles; while (eulerAngles.x > 180f) { eulerAngles.x -= 360f; } return new Vector3(eulerAngles.y, 0f - eulerAngles.x, 0f); } private static void ResetCursorForCamera() { Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } } internal sealed class SpectatorHudManager { private readonly Dictionary _states = new Dictionary(); private bool _applied; private readonly Dictionary _canvasGroupAlphas = new Dictionary(); internal static bool ShouldHideHud() { if (Plugin.CameraController != null && Plugin.CameraController.IsActive) { return Configuration.HideHudInFreeCamera; } return false; } internal void LateUpdate(bool spectatorActive) { if (!spectatorActive || !Configuration.HideHudInFreeCamera) { Restore(); } else { Apply(); } } internal void Restore() { if (!_applied) { return; } foreach (KeyValuePair state in _states) { if ((Object)(object)state.Key != (Object)null) { state.Key.SetActive(state.Value); } } _states.Clear(); foreach (KeyValuePair canvasGroupAlpha in _canvasGroupAlphas) { if ((Object)(object)canvasGroupAlpha.Key != (Object)null) { canvasGroupAlpha.Key.alpha = canvasGroupAlpha.Value; } } _canvasGroupAlphas.Clear(); _applied = false; } private void Apply() { GUIManager instance = GUIManager.instance; if (!((Object)(object)instance == (Object)null)) { HideGuiElements(instance); } } internal void HideGuiElements(GUIManager gui) { if ((Object)(object)gui == (Object)null) { return; } _applied = true; SetHidden(((Object)(object)gui.playerNames != (Object)null) ? ((Component)gui.playerNames).gameObject : GameObject.Find("Canvas_Names")); SetHidden(((Object)(object)gui.binocularOverlay != (Object)null) ? ((Component)gui.binocularOverlay).gameObject : null); SetHidden(((Object)(object)gui.boardingPass != (Object)null) ? ((Component)gui.boardingPass).gameObject : null); SetHidden(((Object)(object)gui.ui_rope != (Object)null) ? ((Component)gui.ui_rope).gameObject : null); SetHidden(gui.emoteWheel); SetHidden(((Object)(object)gui.backpackWheel != (Object)null) ? ((Component)gui.backpackWheel).gameObject : null); SetHidden(gui.interactName); SetHidden(gui.interactPromptPrimary); SetHidden(gui.interactPromptSecondary); SetHidden(gui.interactPromptHold); SetHidden(gui.interactPromptLunge); SetHidden(((Object)(object)gui.strugglePrompt != (Object)null) ? ((Component)gui.strugglePrompt).gameObject : null); SetHidden(((Object)(object)gui.itemPromptMain != (Object)null) ? ((Component)gui.itemPromptMain).gameObject : null); SetHidden(((Object)(object)gui.itemPromptScroll != (Object)null) ? ((Component)gui.itemPromptScroll).gameObject : null); SetHidden(((Object)(object)gui.itemPromptSecondary != (Object)null) ? ((Component)gui.itemPromptSecondary).gameObject : null); SetHidden(((Object)(object)gui.itemPromptDrop != (Object)null) ? ((Component)gui.itemPromptDrop).gameObject : null); SetHidden(((Object)(object)gui.itemPromptThrow != (Object)null) ? ((Component)gui.itemPromptThrow).gameObject : null); SetHidden(gui.throwGO); SetHidden(gui.dyingBarObject); SetHidden(gui.dyingBarMushrooms); SetHidden(gui.spectatingObject); SetHidden(gui.spectatingInputs); SetHidden(gui.heroObject); SetHidden(gui.heroCanvasObject); SetHidden(gui.reticleDefault); SetHidden(gui.reticleX); SetHidden(gui.reticleClimb); SetHidden(gui.reticleClimbJump); SetHidden(gui.reticleThrow); SetHidden(gui.reticleReach); SetHidden(gui.reticleGrasp); SetHidden(gui.reticleSpike); SetHidden(gui.reticleRope); SetHidden(gui.reticleClimbTry); SetHidden(gui.reticleVine); SetHidden(gui.reticleBoost); SetHidden(gui.reticleShoot); SetHidden(gui.reticleKick); if (gui.items != null) { InventoryItemUI[] items = gui.items; foreach (InventoryItemUI val in items) { SetHidden(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); } } SetHidden(((Object)(object)gui.backpack != (Object)null) ? ((Component)gui.backpack).gameObject : null); SetHidden(((Object)(object)gui.temporaryItem != (Object)null) ? ((Component)gui.temporaryItem).gameObject : null); if (gui.friendUseItemProgressList != null) { foreach (UI_UseItemProgressFriend friendUseItemProgress in gui.friendUseItemProgressList) { SetHidden(((Object)(object)friendUseItemProgress != (Object)null) ? ((Component)friendUseItemProgress).gameObject : null); } } if (Plugin.GsIntegration != null && Plugin.GsIntegration.IsActive) { ForceCanvasGroupAlphaZero(gui.staminaCanvasGroup); ForceCanvasGroupAlphaZero(gui.mushroomsCanvasGroup); } } private void ForceCanvasGroupAlphaZero(CanvasGroup group) { if (!((Object)(object)group == (Object)null)) { if (!_canvasGroupAlphas.ContainsKey(group)) { _canvasGroupAlphas.Add(group, group.alpha); } if (group.alpha != 0f) { group.alpha = 0f; } } } private void SetHidden(GameObject go) { if (!((Object)(object)go == (Object)null)) { if (!_states.ContainsKey(go)) { _states.Add(go, go.activeSelf); } if (go.activeSelf) { go.SetActive(false); } } } } internal enum OverlayCycleState { All, NameOnly, None } internal sealed class SpectatorOverlay { private readonly Dictionary _labels = new Dictionary(); private readonly List _keyBuffer = new List(); private readonly List _fonts = new List(); private Canvas _canvas; private Transform _canvasTransform; private GameObject _labelPrefab; private TMP_FontAsset _font; private bool _initialized; private bool _runtimeOverlayVisible = true; private OverlayCycleState _cycleState; private bool _wasSpectatorActive; internal SpectatorOverlay() { SceneManager.sceneLoaded += OnSceneLoaded; } internal void Dispose() { SceneManager.sceneLoaded -= OnSceneLoaded; ClearAll(); if ((Object)(object)_canvas != (Object)null) { Object.Destroy((Object)(object)((Component)_canvas).gameObject); } } internal void TryInitialize() { if (!_initialized) { CreateCanvas(); _initialized = true; } } internal void RegisterCharacter(Character character) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)character == (Object)null) && !character.isBot) { if (!_initialized) { TryInitialize(); } int instanceID = ((Object)character).GetInstanceID(); if (!_labels.ContainsKey(instanceID)) { GameObject val = Object.Instantiate(_labelPrefab, _canvasTransform); ((Object)val).name = "SpectatorPlayerLabel"; val.GetComponent().sizeDelta = new Vector2(420f, 150f); val.SetActive(false); PlayerOverlayLabel value = new PlayerOverlayLabel(character, val, _font); _labels.Add(instanceID, value); } } } internal void UnregisterCharacter(Character character) { if (!((Object)(object)character == (Object)null)) { int instanceID = ((Object)character).GetInstanceID(); if (_labels.TryGetValue(instanceID, out var value)) { value.Destroy(); _labels.Remove(instanceID); } } } internal void UpdateInput(bool spectatorActive) { //IL_0009: 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) if (spectatorActive) { if (Input.GetKeyDown(Configuration.ToggleOverlayKey.Value)) { _runtimeOverlayVisible = !_runtimeOverlayVisible; } if (Input.GetKeyDown(Configuration.OverlayCycleKey.Value)) { _cycleState = (OverlayCycleState)((int)(_cycleState + 1) % 3); L10n.LogDebug($"[Overlay] Cycle state -> {_cycleState}", $"[Overlay] 循环状态 -> {_cycleState}"); } } } internal void LateUpdate(bool spectatorActive) { if (!_initialized) { TryInitialize(); } EnsureAllCharactersRegistered(); if (spectatorActive != _wasSpectatorActive) { if (spectatorActive) { Plugin.BpdIntegration?.Suppress(); } else { Plugin.BpdIntegration?.Restore(); _cycleState = OverlayCycleState.All; } _wasSpectatorActive = spectatorActive; } bool show = spectatorActive && Configuration.ShowOverlay && _runtimeOverlayVisible; Camera camera = GetCamera(); Character val = ((Plugin.CameraController != null) ? Plugin.CameraController.FollowingTarget : null); _keyBuffer.Clear(); _keyBuffer.AddRange(_labels.Keys); foreach (int item in _keyBuffer) { PlayerOverlayLabel playerOverlayLabel = _labels[item]; if (playerOverlayLabel.ShouldRemove()) { playerOverlayLabel.Destroy(); _labels.Remove(item); } else { bool isFollowed = (Object)(object)val != (Object)null && playerOverlayLabel.MatchesCharacter(val); playerOverlayLabel.Update(camera, show, _cycleState, isFollowed); } } } private void EnsureAllCharactersRegistered() { foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter != (Object)null && !allCharacter.isBot && !_labels.ContainsKey(((Object)allCharacter).GetInstanceID())) { RegisterCharacter(allCharacter); } } } private void CreateCanvas() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_006c: 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_0099: Expected O, but got Unknown if (!((Object)(object)_canvas != (Object)null)) { InitializeFont(); GameObject val = new GameObject("PeakSpectatorOverlayCanvas"); Object.DontDestroyOnLoad((Object)(object)val); val.layer = 5; _canvas = val.AddComponent(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 1000; CanvasScaler obj = val.AddComponent(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); val.AddComponent(); _canvasTransform = val.transform; _labelPrefab = new GameObject("SpectatorLabelPrefab"); _labelPrefab.transform.SetParent(_canvasTransform, false); _labelPrefab.layer = 5; _labelPrefab.AddComponent(); CanvasGroup obj2 = _labelPrefab.AddComponent(); obj2.blocksRaycasts = false; obj2.interactable = false; _labelPrefab.SetActive(false); } } private void InitializeFont() { _fonts.Clear(); TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val.atlasTexture != (Object)null && !string.IsNullOrEmpty(((Object)val).name)) { _fonts.Add(val); } } _fonts.Sort((TMP_FontAsset a, TMP_FontAsset b) => string.Compare(((Object)a).name, ((Object)b).name)); _font = ((IEnumerable)_fonts).FirstOrDefault((Func)((TMP_FontAsset f) => ((Object)f).name.ToLowerInvariant().Contains("daruma"))) ?? ((IEnumerable)_fonts).FirstOrDefault((Func)((TMP_FontAsset f) => ((Object)f).name.ToLowerInvariant().Contains("noto"))) ?? ((IEnumerable)_fonts).FirstOrDefault((Func)((TMP_FontAsset f) => ((Object)f).name.ToLowerInvariant().Contains("liberation"))) ?? _fonts.FirstOrDefault(); } private void ClearAll() { foreach (PlayerOverlayLabel value in _labels.Values) { value.Destroy(); } _labels.Clear(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { ClearAll(); } private static Camera GetCamera() { if ((Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null) { return MainCamera.instance.cam; } return Camera.main; } } internal sealed class PlayerOverlayLabel { private static readonly Regex ColorTagRegex = new Regex("|", RegexOptions.IgnoreCase); private const float FixedShadowSpread = 1.5f; private const float FixedShadowAlpha = 0.8f; private static readonly Color FixedShadowColor = new Color(0.267f, 0.275f, 0.216f, 1f); private static readonly Vector2[] OutlineArrowPoints = (Vector2[])(object)new Vector2[7] { new Vector2(0.37f, 0.91f), new Vector2(0.63f, 0.91f), new Vector2(0.63f, 0.52f), new Vector2(0.83f, 0.52f), new Vector2(0.5f, 0.1f), new Vector2(0.17f, 0.52f), new Vector2(0.37f, 0.52f) }; private static Sprite _roundedArrowOuterSprite; private static Sprite _roundedArrowFillSprite; private static Sprite _outlineArrowOuterSprite; private static Sprite _outlineArrowFillSprite; private readonly Character _character; private readonly GameObject _root; private readonly RectTransform _rect; private readonly CanvasGroup _group; private readonly RectTransform _textGroupRect; private readonly TextMeshProUGUI _mainText; private readonly Image _arrowOutline; private readonly Image _arrowFill; private readonly RectTransform _textSubGroupRect; private readonly CanvasGroup _textGroup; private readonly RectTransform _arrowSubGroupRect; private readonly CanvasGroup _arrowGroup; private readonly Image _followIndicator; private float _followIndicatorAlpha; private int _lastHeight = int.MinValue; private string _lastRawName; private float _lastNameFontSize = -1f; private float _lastHeightFontSize = -1f; private float _nextStyleRefresh; private Renderer[] _cachedRenderers; private float _nextRendererRefresh; private readonly List _shadows = new List(); private readonly Vector2[] _offsets = (Vector2[])(object)new Vector2[8] { new Vector2(0f, 1f), new Vector2(0f, -1f), new Vector2(-1f, 0f), new Vector2(1f, 0f), new Vector2(-1f, 1f), new Vector2(1f, 1f), new Vector2(-1f, -1f), new Vector2(1f, -1f) }; internal PlayerOverlayLabel(Character character, GameObject root, TMP_FontAsset font) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) _character = character; _root = root; _rect = root.GetComponent(); _group = root.GetComponent(); _group.alpha = 0f; _textGroupRect = CreateGroup("TextGroup", new Vector2(420f, 120f), Vector2.zero); (RectTransform, CanvasGroup) tuple = CreateSubGroup("TextSubGroup", _textGroupRect); _textSubGroupRect = tuple.Item1; _textGroup = tuple.Item2; tuple = CreateSubGroup("ArrowSubGroup", _textGroupRect); _arrowSubGroupRect = tuple.Item1; _arrowGroup = tuple.Item2; for (int i = 0; i < _offsets.Length; i++) { TextMeshProUGUI item = CreateText($"Shadow_{i}", font, _textSubGroupRect); _shadows.Add(item); } _mainText = CreateText("MainText", font, _textSubGroupRect); _arrowOutline = CreateArrowImage("ArrowOutline", _arrowSubGroupRect); _arrowFill = CreateArrowImage("ArrowFill", _arrowSubGroupRect); _followIndicator = CreateFollowIndicatorImage("FollowIndicator", _textSubGroupRect); RefreshStyle(); } internal bool ShouldRemove() { if (!((Object)(object)_character == (Object)null)) { return (Object)(object)((Component)_character).gameObject == (Object)null; } return true; } internal bool IsValid() { if ((Object)(object)_character != (Object)null && (Object)(object)((Component)_character).gameObject != (Object)null) { return ((Component)_character).gameObject.activeInHierarchy; } return false; } internal bool MatchesCharacter(Character other) { if ((Object)(object)other != (Object)null) { return (Object)(object)_character == (Object)(object)other; } return false; } internal void Update(Camera camera, bool show, OverlayCycleState cycleState, bool isFollowed) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (!show || (Object)(object)camera == (Object)null || !IsValid() || !CharacterState.IsAliveSpectatorTarget(_character)) { FadeTo(textVisible: false, arrowVisible: false); UpdateFollowIndicator(wantVisible: false); return; } if (!TryGetLabelScreenPosition(camera, out var screenPosition)) { FadeTo(textVisible: false, arrowVisible: false); UpdateFollowIndicator(wantVisible: false); return; } float num = Mathf.Sin(Time.time * 1.15f + (float)((Object)_character).GetInstanceID() * 0.031f) * 7f; if (!_root.activeSelf) { _root.SetActive(true); } _root.transform.position = screenPosition + Vector3.up * num; int heightMeters = GetHeightMeters(_character); string characterName = _character.characterName; float value = Configuration.NameFontSize.Value; float value2 = Configuration.HeightFontSize.Value; if (heightMeters != _lastHeight || characterName != _lastRawName || value != _lastNameFontSize || value2 != _lastHeightFontSize) { string text = StripColorTags(characterName); string text2 = $"{text}\n{heightMeters}m"; ((TMP_Text)_mainText).text = text2; string text3 = ColorTagRegex.Replace(text2, string.Empty); foreach (TextMeshProUGUI shadow in _shadows) { ((TMP_Text)shadow).text = text3; } _lastHeight = heightMeters; _lastRawName = characterName; _lastNameFontSize = value; _lastHeightFontSize = value2; RefreshStyle(); _nextStyleRefresh = Time.unscaledTime + 0.5f; } else if (Time.unscaledTime >= _nextStyleRefresh) { RefreshStyle(); _nextStyleRefresh = Time.unscaledTime + 0.5f; } bool flag = cycleState == OverlayCycleState.All || cycleState == OverlayCycleState.NameOnly; bool arrowVisible = cycleState == OverlayCycleState.All; FadeTo(flag, arrowVisible); UpdateFollowIndicator(isFollowed && flag); } internal void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private RectTransform CreateGroup(string name, Vector2 size, Vector2 anchoredPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = 5 }; val.transform.SetParent(_root.transform, false); RectTransform obj = val.AddComponent(); obj.sizeDelta = size; obj.anchoredPosition = anchoredPosition; return obj; } private (RectTransform, CanvasGroup) CreateSubGroup(string name, RectTransform parent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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) GameObject val = new GameObject(name); val.layer = 5; val.transform.SetParent((Transform)(object)parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; CanvasGroup val2 = val.AddComponent(); val2.alpha = 1f; val2.blocksRaycasts = false; val2.interactable = false; return (obj, val2); } private TextMeshProUGUI CreateText(string name, TMP_FontAsset font, RectTransform parent = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = 5 }; val.transform.SetParent((Transform)(object)(((Object)(object)parent != (Object)null) ? parent : _textGroupRect), false); TextMeshProUGUI val2 = val.AddComponent(); SetupTextCommon(val2, font); return val2; } private Image CreateArrowImage(string name, RectTransform parent = null) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = 5 }; val.transform.SetParent((Transform)(object)(((Object)(object)parent != (Object)null) ? parent : _textGroupRect), false); Image obj = val.AddComponent(); obj.sprite = GetArrowOuterSprite(SpectatorArrowStyle.RoundedGlass); ((Graphic)obj).raycastTarget = false; obj.preserveAspect = true; return obj; } private Image CreateFollowIndicatorImage(string name, RectTransform parent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name) { layer = 5 }; val.transform.SetParent((Transform)(object)parent, false); Image obj = val.AddComponent(); obj.sprite = GetArrowOuterSprite(SpectatorArrowStyle.RoundedGlass); ((Graphic)obj).raycastTarget = false; obj.preserveAspect = true; ((Graphic)obj).color = new Color(1f, 1f, 1f, 0f); RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0.5f, 0.5f); return obj; } private void UpdateFollowIndicator(bool wantVisible) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013b: 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_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_followIndicator == (Object)null) { return; } float num = Mathf.Max(0.5f, 5f); float num2 = (wantVisible ? 1f : 0f); _followIndicatorAlpha = Mathf.MoveTowards(_followIndicatorAlpha, num2, num * Time.unscaledDeltaTime); if (!wantVisible && _followIndicatorAlpha <= 0.0001f) { if (((Graphic)_followIndicator).color.a != 0f) { ((Graphic)_followIndicator).color = new Color(1f, 1f, 1f, 0f); } return; } ((Graphic)_followIndicator).color = new Color(1f, 1f, 1f, _followIndicatorAlpha * 0.75f); float num3 = Configuration.NameFontSize.Value * 1.05f; float num4 = num3 * 1.1875f; RectTransform rectTransform = ((Graphic)_followIndicator).rectTransform; rectTransform.sizeDelta = new Vector2(num3, num4); ((Transform)rectTransform).localEulerAngles = new Vector3(0f, 0f, 90f); Vector2 val = (Vector2)(((Object)(object)_mainText != (Object)null) ? ((TMP_Text)_mainText).GetPreferredValues() : new Vector2(80f, 40f)); float num5 = Mathf.Max(20f, val.x * 0.5f); float num6 = Mathf.Max(0f, (Configuration.NameFontSize.Value + Configuration.HeightFontSize.Value) * 0.25f) - 10f; rectTransform.anchoredPosition = new Vector2(0f - num5 - 6f - num4 * 0.5f, num6); } private void SetupTextCommon(TextMeshProUGUI text, TMP_FontAsset font) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) ((TMP_Text)text).alignment = (TextAlignmentOptions)514; ((Graphic)text).raycastTarget = false; ((TMP_Text)text).overflowMode = (TextOverflowModes)0; ((TMP_Text)text).enableWordWrapping = false; ((TMP_Text)text).richText = true; if ((Object)(object)font != (Object)null) { ((TMP_Text)text).font = font; } ((TMP_Text)text).rectTransform.anchoredPosition = Vector2.zero; } private void RefreshStyle() { //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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) Color fixedShadowColor = FixedShadowColor; fixedShadowColor.a = 0.8f; Color val = default(Color); ((Color)(ref val))..ctor(0.875f, 0.855f, 0.761f, 1f); SpectatorArrowStyle spectatorArrowStyle = ((Configuration.HeadArrowStyle != null) ? Configuration.HeadArrowStyle.Value : SpectatorArrowStyle.RoundedGlass); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0f); float num = Mathf.Max(1f, (Configuration.NameFontSize.Value + Configuration.HeightFontSize.Value) * 0.5f); float num2 = Mathf.Max(0.8f, 1.5f * num / 16f); float lineSpacing = Mathf.Clamp(140f / num - 3f, 0f, 12f); ((Graphic)_mainText).color = val; ((TMP_Text)_mainText).rectTransform.anchoredPosition = val2; ((TMP_Text)_mainText).lineSpacing = lineSpacing; Vector2 anchoredPosition = default(Vector2); ((Vector2)(ref anchoredPosition))..ctor(0f, -38f); RectTransform rectTransform = ((Graphic)_arrowOutline).rectTransform; rectTransform.sizeDelta = GetArrowOutlineSize(spectatorArrowStyle); rectTransform.anchoredPosition = anchoredPosition; Color playerColor = GetPlayerColor(_character); playerColor.a = ((spectatorArrowStyle == SpectatorArrowStyle.OutlineGlass) ? 0.98f : 0.95f); _arrowOutline.sprite = GetArrowOuterSprite(spectatorArrowStyle); ((Graphic)_arrowOutline).color = playerColor; RectTransform rectTransform2 = ((Graphic)_arrowFill).rectTransform; rectTransform2.sizeDelta = GetArrowFillSize(spectatorArrowStyle); rectTransform2.anchoredPosition = anchoredPosition; Color color = val; color.a = ((spectatorArrowStyle == SpectatorArrowStyle.OutlineGlass) ? 0.58f : 0.72f); _arrowFill.sprite = GetArrowFillSprite(spectatorArrowStyle); ((Graphic)_arrowFill).color = color; for (int i = 0; i < 8 && i < _shadows.Count; i++) { TextMeshProUGUI obj = _shadows[i]; ((Graphic)obj).color = fixedShadowColor; ((TMP_Text)obj).lineSpacing = lineSpacing; ((TMP_Text)obj).rectTransform.anchoredPosition = val2 + _offsets[i] * num2; } } private void FadeTo(bool textVisible, bool arrowVisible) { if (!((Object)(object)_root == (Object)null) && !((Object)(object)_group == (Object)null)) { bool num = textVisible || arrowVisible; if (num && !_root.activeSelf) { _root.SetActive(true); } float num2 = (num ? 1f : 0f); float num3 = Mathf.Max(0.01f, 5f); _group.alpha = Mathf.MoveTowards(_group.alpha, num2, Time.unscaledDeltaTime * num3); if ((Object)(object)_textGroup != (Object)null) { float num4 = (textVisible ? Configuration.LabelTextOpacity.Value : 0f); _textGroup.alpha = Mathf.MoveTowards(_textGroup.alpha, num4, Time.unscaledDeltaTime * num3); } if ((Object)(object)_arrowGroup != (Object)null) { float num5 = (arrowVisible ? Configuration.OverlayOpacity.Value : 0f); _arrowGroup.alpha = Mathf.MoveTowards(_arrowGroup.alpha, num5, Time.unscaledDeltaTime * num3); } if (!num && _group.alpha <= 0.001f && _root.activeSelf) { _root.SetActive(false); } } } private bool TryGetLabelScreenPosition(Camera camera, out Vector3 screenPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) screenPosition = Vector3.zero; Vector3 headPosition = GetHeadPosition(_character); Vector3 val = ((Component)camera).transform.position - headPosition; float magnitude = ((Vector3)(ref val)).magnitude; Vector3 val2 = ((magnitude > 0.01f) ? (val / magnitude) : (-((Component)camera).transform.forward)); float num = Mathf.Clamp01(Vector3.Dot(val2, Vector3.up)); Vector3 val3 = headPosition + Vector3.up * Mathf.Lerp(1.15f, 0.45f, num) + val2 * 0.4f * num; Vector3 val4 = camera.WorldToScreenPoint(val3); if (val4.z <= 0f) { return false; } float num2 = Mathf.Max(1f, (float)camera.pixelWidth); float num3 = Mathf.Max(1f, (float)camera.pixelHeight); float num4 = Mathf.InverseLerp(25f, 180f, val4.z); float num5 = 48f + 36f * num4; if (TryGetCharacterScreenBounds(camera, out var bounds)) { if (((Rect)(ref bounds)).xMax < -120f || ((Rect)(ref bounds)).xMin > num2 + 120f || ((Rect)(ref bounds)).yMax < -120f || ((Rect)(ref bounds)).yMin > num3 + 220f) { return false; } float num6 = Mathf.Clamp(Mathf.Lerp(((Rect)(ref bounds)).center.x, val4.x, 0.65f), 0f, num2); float num7 = Mathf.Max(val4.y, ((Rect)(ref bounds)).yMax + num5); if (num7 < -120f || num7 > num3 + 220f) { return false; } screenPosition = new Vector3(num6, num7, 0f); return true; } if (val4.x < -120f || val4.x > num2 + 120f || val4.y < -120f || val4.y > num3 + 220f) { return false; } screenPosition = new Vector3(val4.x, val4.y + num5, 0f); return true; } private bool TryGetCharacterScreenBounds(Camera camera, out Rect bounds) { //IL_0022: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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_0106: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) bool hasPoint = false; float minX = float.MaxValue; float minY = float.MaxValue; float maxX = float.MinValue; float maxY = float.MinValue; AddScreenPoint(camera, GetHeadPosition(_character), ref hasPoint, ref minX, ref minY, ref maxX, ref maxY); AddScreenPoint(camera, GetCenterPosition(_character), ref hasPoint, ref minX, ref minY, ref maxX, ref maxY); if ((Object)(object)_character.refs?.hip != (Object)null) { AddScreenPoint(camera, _character.refs.hip.Rig.position, ref hasPoint, ref minX, ref minY, ref maxX, ref maxY); } if (_cachedRenderers == null || Time.unscaledTime >= _nextRendererRefresh) { _cachedRenderers = ((Component)_character).GetComponentsInChildren(true); _nextRendererRefresh = Time.unscaledTime + 0.5f; } Renderer[] cachedRenderers = _cachedRenderers; foreach (Renderer val in cachedRenderers) { if (!CanUseRendererForBounds(val)) { continue; } Bounds bounds2 = val.bounds; Vector3 center = ((Bounds)(ref bounds2)).center; Vector3 extents = ((Bounds)(ref bounds2)).extents; for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { for (int l = -1; l <= 1; l += 2) { Vector3 worldPoint = center + Vector3.Scale(extents, new Vector3((float)j, (float)k, (float)l)); AddScreenPoint(camera, worldPoint, ref hasPoint, ref minX, ref minY, ref maxX, ref maxY); } } } } if (!hasPoint) { bounds = default(Rect); return false; } bounds = Rect.MinMaxRect(minX, minY, maxX, maxY); return true; } private static bool CanUseRendererForBounds(Renderer renderer) { if ((Object)(object)renderer == (Object)null || !renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy || renderer is TrailRenderer || renderer is ParticleSystemRenderer) { return false; } string name = ((Object)((Component)renderer).gameObject).name; if (!string.IsNullOrEmpty(name)) { return !name.StartsWith("PeakSpectatorXray"); } return true; } private static void AddScreenPoint(Camera camera, Vector3 worldPoint, ref bool hasPoint, ref float minX, ref float minY, ref float maxX, ref float maxY) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_004f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = camera.WorldToScreenPoint(worldPoint); if (!(val.z <= 0f)) { hasPoint = true; minX = Mathf.Min(minX, val.x); minY = Mathf.Min(minY, val.y); maxX = Mathf.Max(maxX, val.x); maxY = Mathf.Max(maxY, val.y); } } private static Vector3 GetHeadPosition(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) try { return character.Head; } catch { return GetCenterPosition(character) + Vector3.up * 0.8f; } } private static Vector3 GetCenterPosition(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) try { return character.Center; } catch { return ((Component)character).transform.position + Vector3.up * 1.2f; } } internal static int GetHeightMeters(Character character) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) float num = 0f; if ((Object)(object)character?.refs?.stats != (Object)null) { num = character.refs.stats.heightInMeters; } if (num <= 0.01f && (Object)(object)character?.refs?.hip != (Object)null) { num = character.refs.hip.Rig.position.y * CharacterStats.unitsToMeters; } num = Mathf.Clamp(num, 0f, 1920f); return Mathf.RoundToInt(num); } internal static Color GetPlayerColor(Character character) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_003e: Unknown result type (might be due to invalid IL or missing references) try { Color playerColor = character.refs.customization.PlayerColor; playerColor.a = 1f; return playerColor; } catch { return new Color(0.9f, 0.85f, 0.65f, 1f); } } private static Vector2 GetArrowOutlineSize(SpectatorArrowStyle style) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (style != SpectatorArrowStyle.OutlineGlass) { return new Vector2(30f, 36f); } return new Vector2(31f, 37f); } private static Vector2 GetArrowFillSize(SpectatorArrowStyle style) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (style != SpectatorArrowStyle.OutlineGlass) { return new Vector2(22f, 27f); } return new Vector2(31f, 37f); } internal static Sprite GetArrowOuterSprite(SpectatorArrowStyle style) { if (style == SpectatorArrowStyle.OutlineGlass) { return _outlineArrowOuterSprite ?? (_outlineArrowOuterSprite = CreateOutlineArrowSprite(fill: false)); } return _roundedArrowOuterSprite ?? (_roundedArrowOuterSprite = CreateRoundedArrowSprite(fill: false)); } private static Sprite GetArrowFillSprite(SpectatorArrowStyle style) { if (style == SpectatorArrowStyle.OutlineGlass) { return _outlineArrowFillSprite ?? (_outlineArrowFillSprite = CreateOutlineArrowSprite(fill: true)); } return _roundedArrowFillSprite ?? (_roundedArrowFillSprite = CreateRoundedArrowSprite(fill: true)); } private static Sprite CreateRoundedArrowSprite(bool fill) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) Texture2D val = new Texture2D(64, 76, (TextureFormat)4, false); ((Object)val).name = (fill ? "PeakSpectatorRoundedGlassFill" : "PeakSpectatorRoundedGlassOuter"); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color white = Color.white; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 1f, 1f, 0f); Vector2 point = default(Vector2); for (int i = 0; i < 76; i++) { for (int j = 0; j < 64; j++) { ((Vector2)(ref point))..ctor(((float)j + 0.5f) / 64f, ((float)i + 0.5f) / 76f); float num = CoverageFromSignedDistance(SignedDistanceRoundedArrow(point), 0.021875f); float num2 = (fill ? (num * GetGlassAlpha(point, 0.94f)) : num); val.SetPixel(j, i, (Color)((num2 > 0f) ? new Color(white.r, white.g, white.b, num2) : val2)); } } val.Apply(false, true); return Sprite.Create(val, new Rect(0f, 0f, 64f, 76f), new Vector2(0.5f, 0.5f), 100f); } private static Sprite CreateOutlineArrowSprite(bool fill) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(72, 86, (TextureFormat)4, false); ((Object)val).name = (fill ? "PeakSpectatorOutlineGlassFill" : "PeakSpectatorOutlineGlassOuter"); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color white = Color.white; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 1f, 1f, 0f); Vector2 point = default(Vector2); for (int i = 0; i < 86; i++) { for (int j = 0; j < 72; j++) { ((Vector2)(ref point))..ctor(((float)j + 0.5f) / 72f, ((float)i + 0.5f) / 86f); float num = SignedDistancePolygon(point, OutlineArrowPoints); float num2 = (fill ? (CoverageFromSignedDistance(num + 0.0696f, 3f / 160f) * GetGlassAlpha(point, 0.72f)) : CoverageFromSignedDistance(Mathf.Abs(num) - 0.058f, 3f / 160f)); val.SetPixel(j, i, (Color)((num2 > 0f) ? new Color(white.r, white.g, white.b, num2) : val2)); } } val.Apply(false, true); return Sprite.Create(val, new Rect(0f, 0f, 72f, 86f), new Vector2(0.5f, 0.5f), 100f); } private static float SignedDistanceRoundedArrow(Vector2 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) float num = SignedDistanceRoundedBox(point, new Vector2(0.5f, 0.66f), new Vector2(0.15f, 0.31f), 0.13f); float num2 = SignedDistanceTriangle(point, new Vector2(0.16f, 0.45f), new Vector2(0.84f, 0.45f), new Vector2(0.5f, 0.1f)) - 0.06f; return Mathf.Min(num, num2); } private static float SignedDistanceRoundedBox(Vector2 point, Vector2 center, Vector2 halfSize, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0036: 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_0042: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Vector2 val = new Vector2(Mathf.Abs(point.x - center.x), Mathf.Abs(point.y - center.y)) - halfSize + new Vector2(radius, radius); float num = Mathf.Min(Mathf.Max(val.x, val.y), 0f); Vector2 val2 = new Vector2(Mathf.Max(val.x, 0f), Mathf.Max(val.y, 0f)); return num + ((Vector2)(ref val2)).magnitude - radius; } private static float SignedDistanceTriangle(Vector2 point, Vector2 a, Vector2 b, Vector2 c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_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_0026: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(DistanceToSegment(point, a, b), Mathf.Min(DistanceToSegment(point, b, c), DistanceToSegment(point, c, a))); if (!IsInsideTriangle(point, a, b, c)) { return num; } return 0f - num; } private static bool IsInsideTriangle(Vector2 point, Vector2 a, Vector2 b, Vector2 c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) float num = Cross(point - b, a - b); float num2 = Cross(point - c, b - c); float num3 = Cross(point - a, c - a); bool flag = num < 0f || num2 < 0f || num3 < 0f; bool flag2 = num > 0f || num2 > 0f || num3 > 0f; return !(flag && flag2); } private static float SignedDistancePolygon(Vector2 point, Vector2[] points) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0028: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) bool flag = false; float num = float.MaxValue; int num2 = 0; int num3 = points.Length - 1; while (num2 < points.Length) { Vector2 val = points[num3]; Vector2 val2 = points[num2]; num = Mathf.Min(num, DistanceToSegment(point, val, val2)); if (val.y > point.y != val2.y > point.y) { float num4 = (val2.x - val.x) * (point.y - val.y) / (val2.y - val.y) + val.x; if (point.x < num4) { flag = !flag; } } num3 = num2++; } if (!flag) { return num; } return 0f - num; } private static float CoverageFromSignedDistance(float signedDistance, float feather) { return Mathf.Clamp01(0.5f - signedDistance / feather); } private static float GetGlassAlpha(Vector2 point, float strength) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0066: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Lerp(0.52f, 0.9f, Mathf.Clamp01(point.y)); float num2 = 0.16f * Mathf.Clamp01((point.y - 0.56f) / 0.32f) * (1f - Mathf.Clamp01(Mathf.Abs(point.x - 0.44f) / 0.34f)); float num3 = 0.12f * Mathf.Clamp01((0.28f - point.y) / 0.18f); return Mathf.Clamp01(strength * (num + num2 - num3)); } private static float Cross(Vector2 a, Vector2 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return a.x * b.y - a.y * b.x; } private static float DistanceToSegment(Vector2 point, Vector2 a, Vector2 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Vector2 val = b - a; float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude; if (sqrMagnitude <= 0.0001f) { return Vector2.Distance(point, a); } float num = Mathf.Clamp01(Vector2.Dot(point - a, val) / sqrMagnitude); return Vector2.Distance(point, a + val * num); } private static string StripColorTags(string text) { if (string.IsNullOrEmpty(text)) { return "Unknown"; } return ColorTagRegex.Replace(text, string.Empty); } } internal sealed class SummitRosterCompatibility { private sealed class RectState { private readonly Vector2 _anchorMin; private readonly Vector2 _anchorMax; private readonly Vector2 _pivot; private readonly Vector2 _anchoredPosition; private readonly Vector2 _sizeDelta; internal TextAlignmentOptions Alignment { get; } internal Vector2 AnchoredPosition => _anchoredPosition; internal RectState(RectTransform rect) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_002c: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_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) _anchorMin = rect.anchorMin; _anchorMax = rect.anchorMax; _pivot = rect.pivot; _anchoredPosition = rect.anchoredPosition; _sizeDelta = rect.sizeDelta; TextMeshProUGUI component = ((Component)rect).GetComponent(); Alignment = (TextAlignmentOptions)((!((Object)(object)component != (Object)null)) ? 513 : ((int)((TMP_Text)component).alignment)); } internal void Apply(RectTransform rect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = _anchorMin; rect.anchorMax = _anchorMax; rect.pivot = _pivot; rect.anchoredPosition = _anchoredPosition; rect.sizeDelta = _sizeDelta; } } private const string ProgressMapTypeName = "ProgressMap.ProgressMap"; private const string SummitRosterTypeName = "SummitRoster.SummitRoster"; private const string CanvasName = "ProgressMap"; private const string BarName = "AltitudeBar"; private const string PeakTextName = "PeakText"; private const string LabelPrefix = "Label_"; private const string TickName = "Tick"; private const string FocusArrowName = "PeakSpectatorFocusArrow"; private const float LeftOffset = 60f; private const float TextPadding = 20f; private const float MarkerWidth = 10f; private const float MarkerHeight = 5f; private const float FocusArrowScale = 0.5f; private const float FocusArrowMaxDistance = 30f; private const float FocusArrowGap = 10f; private const float OutOfBoundsAltitude = 3000f; private readonly Harmony _harmony; private readonly Dictionary _originalStates = new Dictionary(); private bool _patchAttempted; private bool _available; private bool _loggedCanvasFound; private bool _layoutAuditLogged; private int _lastProcessedFrame = -1; private int _unavailableFrames; private bool _giveUp; private Canvas _canvas; private int _canvasInstanceId; private GameObject _focusArrow; private Type _cachedSummitRosterType; private FieldInfo _characterLabelsField; private Component _cachedSummitRosterInstance; private readonly HashSet _loggedFilterIds = new HashSet(); private readonly Dictionary _labelMapCache = new Dictionary(); private bool _labelMapValid; private static readonly Vector2[] _shadowOffsets = (Vector2[])(object)new Vector2[8] { new Vector2(0f, 1f), new Vector2(0f, -1f), new Vector2(-1f, 0f), new Vector2(1f, 0f), new Vector2(-1f, 1f), new Vector2(1f, 1f), new Vector2(-1f, -1f), new Vector2(1f, -1f) }; private static readonly Color _shadowColor = new Color(0.267f, 0.275f, 0.216f, 0.8f); private const float ShadowSpread = 1.5f; private const string ShadowNamePrefix = "PeakSpec_Shadow_"; private readonly Dictionary _shadows = new Dictionary(); internal SummitRosterCompatibility(Harmony harmony) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown _harmony = harmony; Canvas.willRenderCanvases += new WillRenderCanvases(OnWillRenderCanvases); TryPatch(); } internal void LateUpdate(bool spectatorActive) { if (_giveUp) { return; } int frameCount = Time.frameCount; if (frameCount == _lastProcessedFrame) { return; } _lastProcessedFrame = frameCount; if (!Configuration.EnableSummitRosterCompatibility) { HideFocusArrow(); RestoreLayout(); ClearRuntimeBindings(); return; } EnsureAvailable(); Canvas val = FindSummitRosterCanvas(); if ((Object)(object)val != (Object)(object)_canvas) { SetCanvas(val); } if (!_available && (Object)(object)_canvas == (Object)null) { _unavailableFrames++; if (_unavailableFrames >= 3) { GiveUpPermanently(); } else { HideFocusArrow(); } return; } _unavailableFrames = 0; if ((Object)(object)_canvas == (Object)null) { HideFocusArrow(); return; } RebuildCharacterLabelsMap(); if (Configuration.MoveSummitRosterRight) { MoveLayoutRight(); } else { RestoreLayout(); } ApplyLabelVisibilityFilters(); RefreshRankedLabels(); ApplyLabelShadows(); UpdateFocusArrow(spectatorActive); } private void GiveUpPermanently() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!_giveUp) { _giveUp = true; Canvas.willRenderCanvases -= new WillRenderCanvases(OnWillRenderCanvases); HideFocusArrow(); L10n.LogInfo("Summit Roster not detected; stopped per-frame probing for this compatibility layer (zero residual overhead).", "未检测到 Summit Roster,已停止该兼容层的每帧探测(零残余开销)。"); } } private void ApplyLabelVisibilityFilters() { if ((Object)(object)_canvas == (Object)null) { return; } Dictionary characterLabelsMap = GetCharacterLabelsMap(); if (characterLabelsMap != null) { foreach (KeyValuePair item in characterLabelsMap) { Character key = item.Key; GameObject value = item.Value; if (!((Object)(object)value == (Object)null)) { RectTransform component = value.GetComponent(); if (!((Object)(object)component == (Object)null)) { bool flag = (Object)(object)key == (Object)null || (Object)(object)((Component)key).gameObject == (Object)null || !((Component)key).gameObject.activeInHierarchy; bool flag2 = !flag && Plugin.GsIntegration != null && Plugin.GsIntegration.IsLoaded && Plugin.GsIntegration.IsCharacterPermaSpectator(key); bool flag3 = !flag && IsAltitudeOutOfBounds(key); bool flag4 = flag || flag2 || flag3; if (((Component)component).gameObject.activeSelf == flag4) { ((Component)component).gameObject.SetActive(!flag4); LogFilterOnce(key, flag4, flag2, flag3, flag); } } } } return; } foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter == (Object)null) { continue; } RectTransform val = FindLabelForCharacter(allCharacter); if (!((Object)(object)val == (Object)null)) { bool flag5 = (Object)(object)((Component)allCharacter).gameObject == (Object)null || !((Component)allCharacter).gameObject.activeInHierarchy; bool flag6 = !flag5 && Plugin.GsIntegration != null && Plugin.GsIntegration.IsLoaded && Plugin.GsIntegration.IsCharacterPermaSpectator(allCharacter); bool flag7 = !flag5 && IsAltitudeOutOfBounds(allCharacter); bool flag8 = flag5 || flag6 || flag7; if (((Component)val).gameObject.activeSelf == flag8) { ((Component)val).gameObject.SetActive(!flag8); LogFilterOnce(allCharacter, flag8, flag6, flag7, flag5); } } } } private static bool IsAltitudeOutOfBounds(Character character) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return false; } try { return character.Center.y * 1.6f > 3000f; } catch { return false; } } private void LogFilterOnce(Character character, bool hidden, bool isGhostSpec, bool isOutOfBounds, bool isStale = false) { if (!((Object)(object)character == (Object)null)) { int instanceID = ((Object)character).GetInstanceID(); if (_loggedFilterIds.Add(instanceID)) { string text = GetNickname(character) ?? "?"; string text2 = (isStale ? "disabled stale Character" : (isGhostSpec ? "permanent spectator" : (isOutOfBounds ? $"altitude>{3000f:0}m fallback" : "restored"))); string text3 = (isStale ? "已禁用残留 Character" : (isGhostSpec ? "永久观察者" : (isOutOfBounds ? $"海拔>{3000f:0}m 兜底" : "已恢复"))); L10n.LogInfo("[GS Compat] Summit Roster label '" + text + "' " + (hidden ? "hidden" : "restored") + " (" + text2 + ")", "[GS兼容] Summit Roster 标签 '" + text + "' 已" + (hidden ? "隐藏" : "恢复") + "(" + text3 + ")"); } } } internal void Dispose() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Canvas.willRenderCanvases -= new WillRenderCanvases(OnWillRenderCanvases); HideFocusArrow(); RestoreLayout(); ClearRuntimeBindings(); } private void OnWillRenderCanvases() { LateUpdate(Plugin.CameraController != null && Plugin.CameraController.IsActive); } private bool EnsureAvailable() { if (!_available) { _available = FindSummitRosterType() != null; } if (_available) { TryPatch(); } return _available; } private void TryPatch() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown if (_patchAttempted || _harmony == null) { return; } Type type = FindSummitRosterType(); if (!(type == null)) { MethodInfo methodInfo = AccessTools.Method(type, "LateUpdate", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(SummitRosterCompatibility), "ProgressMapLateUpdatePostfix", (Type[])null, (Type[])null); _patchAttempted = true; if (!(methodInfo == null) && !(methodInfo2 == null)) { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static Type FindSummitRosterType() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly == null)) { Type type = assembly.GetType("ProgressMap.ProgressMap", throwOnError: false); if (type != null) { return type; } type = assembly.GetType("SummitRoster.SummitRoster", throwOnError: false); if (type != null) { return type; } } } return null; } private static void ProgressMapLateUpdatePostfix() { Plugin.SummitRoster?.LateUpdate(Plugin.CameraController != null && Plugin.CameraController.IsActive); } private Dictionary GetCharacterLabelsMap() { if (!_labelMapValid) { return null; } return _labelMapCache; } private void RebuildCharacterLabelsMap() { _labelMapCache.Clear(); _labelMapValid = false; try { if (_cachedSummitRosterType == null) { _cachedSummitRosterType = FindSummitRosterType(); } if (_cachedSummitRosterType == null) { return; } if (_characterLabelsField == null) { _characterLabelsField = AccessTools.Field(_cachedSummitRosterType, "characterLabels"); } if (_characterLabelsField == null) { return; } if ((Object)(object)_cachedSummitRosterInstance == (Object)null || (Object)(object)_cachedSummitRosterInstance.gameObject == (Object)null || !_cachedSummitRosterInstance.gameObject.activeInHierarchy || !IsInstanceForCurrentCanvas(_cachedSummitRosterInstance)) { _cachedSummitRosterInstance = FindCurrentSummitRosterInstance(); } if ((Object)(object)_cachedSummitRosterInstance == (Object)null || !(_characterLabelsField.GetValue(_cachedSummitRosterInstance) is Dictionary dictionary)) { return; } foreach (KeyValuePair item in dictionary) { if (!((Object)(object)item.Key == (Object)null) && !((Object)(object)item.Value == (Object)null) && !((Object)(object)item.Value.GetComponent() == (Object)null)) { _labelMapCache[item.Key] = item.Value; } } _labelMapValid = true; } catch { _labelMapValid = false; } } private Component FindCurrentSummitRosterInstance() { if (_cachedSummitRosterType == null) { return null; } object? obj = AccessTools.Field(_cachedSummitRosterType, "Instance")?.GetValue(null); Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null && val.gameObject.activeInHierarchy) { return val; } Object[] array = Resources.FindObjectsOfTypeAll(_cachedSummitRosterType); if (array == null) { return null; } Component val2 = null; Object[] array2 = array; foreach (Object obj2 in array2) { Component val3 = (Component)(object)((obj2 is Component) ? obj2 : null); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.gameObject == (Object)null) && val3.gameObject.activeInHierarchy) { if (IsInstanceForCurrentCanvas(val3)) { return val3; } if ((Object)(object)val2 == (Object)null) { val2 = val3; } } } return val2; } private bool IsInstanceForCurrentCanvas(Component component) { //IL_006b: 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) if ((Object)(object)component == (Object)null || (Object)(object)_canvas == (Object)null) { return false; } Canvas componentInChildren = component.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { return (Object)(object)componentInChildren == (Object)(object)_canvas; } Transform val = component.transform; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)((Component)_canvas).transform) { return true; } val = val.parent; } return component.gameObject.scene == ((Component)_canvas).gameObject.scene; } private void SetCanvas(Canvas canvas) { int num = (((Object)(object)canvas != (Object)null) ? ((Object)canvas).GetInstanceID() : 0); if (num == _canvasInstanceId) { _canvas = canvas; return; } RestoreLayout(); ClearRuntimeBindings(); _canvas = canvas; _canvasInstanceId = num; } private void ClearRuntimeBindings() { _cachedSummitRosterInstance = null; _loggedFilterIds.Clear(); _layoutAuditLogged = false; _originalStates.Clear(); _labelMapCache.Clear(); _labelMapValid = false; DestroyShadows(); if ((Object)(object)_focusArrow != (Object)null) { Object.Destroy((Object)(object)_focusArrow); _focusArrow = null; } } private void DestroyShadows() { foreach (TextMeshProUGUI[] value in _shadows.Values) { if (value == null) { continue; } TextMeshProUGUI[] array = value; foreach (TextMeshProUGUI val in array) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } _shadows.Clear(); } private Canvas FindSummitRosterCanvas() { if ((Object)(object)_canvas != (Object)null && (Object)(object)((Component)_canvas).gameObject != (Object)null && ((Component)_canvas).gameObject.activeInHierarchy) { return _canvas; } Canvas[] array = Resources.FindObjectsOfTypeAll(); foreach (Canvas val in array) { if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy && ((Object)((Component)val).gameObject).name == "ProgressMap" && (Object)(object)((Component)val).transform.Find("AltitudeBar") != (Object)null) { _available = true; if (!_loggedCanvasFound) { L10n.LogInfo("Summit Roster UI detected; runtime layout compatibility enabled.", "已检测到 Summit Roster UI,启用运行时布局兼容。"); _loggedCanvasFound = true; } return val; } } return null; } private void MoveLayoutRight() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_006e: 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_007e: Unknown result type (might be due to invalid IL or missing references) RectTransform val = FindChildRect("AltitudeBar"); float num = -60f; if ((Object)(object)val != (Object)null) { Remember(val); SetRightAnchored(val, new Vector2(-60f, val.anchoredPosition.y), val.pivot); num = val.anchoredPosition.x; } RectTransform val2 = FindChildRect("PeakText"); if ((Object)(object)val2 != (Object)null) { Remember(val2); SetRightAnchored(val2, new Vector2(num, val2.anchoredPosition.y), val2.pivot); } foreach (RectTransform item in FindLabelRects()) { MoveLabelRight(item, num); } foreach (RectTransform item2 in FindTickRects()) { MoveTickRight(item2, num); } LogLayoutAuditIfNeeded(val); } private void MoveLabelRight(RectTransform label, float barX) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0077: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) Remember(label); SetRightAnchored(label, new Vector2(barX, label.anchoredPosition.y), new Vector2(0f, 0.5f)); label.sizeDelta = new Vector2(0f, label.sizeDelta.y); RectTransform val = FindChildRect((Transform)(object)label, "Marker"); Vector2 val2 = default(Vector2); if ((Object)(object)val != (Object)null) { Remember(val); ((Vector2)(ref val2))..ctor(0f, 0.5f); val.anchorMax = val2; val.anchorMin = val2; val.pivot = new Vector2(0.5f, 1f); val.sizeDelta = new Vector2(10f, 5f); val.anchoredPosition = Vector2.zero; } TextMeshProUGUI val3 = FindLabelText(label); if ((Object)(object)val3 != (Object)null) { RectTransform rectTransform = ((TMP_Text)val3).rectTransform; Remember(rectTransform); ((Vector2)(ref val2))..ctor(0f, 0.5f); rectTransform.anchorMax = val2; rectTransform.anchorMin = val2; rectTransform.pivot = new Vector2(1f, 0.5f); rectTransform.anchoredPosition = new Vector2(-20f, 0f); ((TMP_Text)val3).alignment = (TextAlignmentOptions)516; } } private void MoveTickRight(RectTransform tick, float barX) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Remember(tick); SetRightAnchored(tick, new Vector2(barX, tick.anchoredPosition.y), new Vector2(0.5f, 0.5f)); } private void RestoreLayout() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00c6: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair originalState in _originalStates) { if (!((Object)(object)originalState.Key == (Object)null)) { Vector2 anchoredPosition = originalState.Key.anchoredPosition; Vector2 sizeDelta = originalState.Key.sizeDelta; bool num = ((Object)originalState.Key).name.StartsWith("Label_"); originalState.Value.Apply(originalState.Key); if (num) { originalState.Key.anchoredPosition = new Vector2(originalState.Value.AnchoredPosition.x, anchoredPosition.y); } TextMeshProUGUI component = ((Component)originalState.Key).GetComponent(); if ((Object)(object)component != (Object)null) { originalState.Key.sizeDelta = sizeDelta; ((TMP_Text)component).alignment = originalState.Value.Alignment; } } } _originalStates.Clear(); } private void ApplyLabelShadows() { if ((Object)(object)_canvas == (Object)null) { return; } foreach (RectTransform item in FindLabelRects()) { if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeInHierarchy) { TextMeshProUGUI val = FindLabelText(item); if (!((Object)(object)val == (Object)null)) { EnsureShadows(val); SyncShadows(val); } } } } private void EnsureShadows(TextMeshProUGUI mainText) { //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_0087: Unknown result type (might be due to invalid IL or missing references) if (!_shadows.TryGetValue(mainText, out var value) || value == null || value.Length != 8 || !((Object)(object)value[0] != (Object)null)) { RectTransform rectTransform = ((TMP_Text)mainText).rectTransform; Transform parent = ((Transform)rectTransform).parent; int siblingIndex = ((Transform)rectTransform).GetSiblingIndex(); TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[8]; for (int i = 0; i < 8; i++) { GameObject val = new GameObject("PeakSpec_Shadow_" + i, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); val.transform.SetSiblingIndex(siblingIndex); TextMeshProUGUI component = val.GetComponent(); ((Graphic)component).raycastTarget = false; ((TMP_Text)component).textWrappingMode = (TextWrappingModes)0; array[i] = component; } _shadows[mainText] = array; } } private void SyncShadows(TextMeshProUGUI mainText) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (!_shadows.TryGetValue(mainText, out var value) || value == null) { return; } RectTransform rectTransform = ((TMP_Text)mainText).rectTransform; Vector2 anchoredPosition = rectTransform.anchoredPosition; Vector2 anchorMin = rectTransform.anchorMin; Vector2 anchorMax = rectTransform.anchorMax; Vector2 pivot = rectTransform.pivot; Vector2 sizeDelta = rectTransform.sizeDelta; string text = ((TMP_Text)mainText).text; TMP_FontAsset font = ((TMP_Text)mainText).font; float fontSize = ((TMP_Text)mainText).fontSize; TextAlignmentOptions alignment = ((TMP_Text)mainText).alignment; FontStyles fontStyle = ((TMP_Text)mainText).fontStyle; for (int i = 0; i < 8; i++) { TextMeshProUGUI val = value[i]; if ((Object)(object)val == (Object)null) { continue; } if (((TMP_Text)val).text != text) { ((TMP_Text)val).text = text; if ((Object)(object)font != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)(object)font) { ((TMP_Text)val).font = font; } ((TMP_Text)val).fontSize = fontSize; ((TMP_Text)val).alignment = alignment; ((TMP_Text)val).fontStyle = fontStyle; ((Graphic)val).color = _shadowColor; RectTransform rectTransform2 = ((TMP_Text)val).rectTransform; rectTransform2.anchorMin = anchorMin; rectTransform2.anchorMax = anchorMax; rectTransform2.pivot = pivot; rectTransform2.sizeDelta = sizeDelta; } ((TMP_Text)val).rectTransform.anchoredPosition = anchoredPosition + _shadowOffsets[i] * 1.5f; } } private void UpdateFocusArrow(bool spectatorActive) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) Character val = ((spectatorActive && Configuration.ShowSummitRosterFocusArrow && Plugin.CameraController != null) ? Plugin.CameraController.FocusedPlayer : null); if ((Object)(object)val == (Object)null || (Object)(object)_canvas == (Object)null || IsFocusTooFar(val)) { HideFocusArrow(); return; } RectTransform val2 = FindLabelForCharacter(val); if ((Object)(object)val2 == (Object)null) { HideFocusArrow(); return; } TextMeshProUGUI val3 = FindLabelText(val2); if ((Object)(object)val3 == (Object)null) { HideFocusArrow(); return; } EnsureFocusArrow(val2, val3); PositionFocusArrow(val2, val3); Color playerColor = PlayerOverlayLabel.GetPlayerColor(val); playerColor.a = 0.95f; Image component = _focusArrow.GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = playerColor; } _focusArrow.SetActive(true); } private void EnsureFocusArrow(RectTransform label, TextMeshProUGUI labelText) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00d3: 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) if (!((Object)(object)_focusArrow != (Object)null) || !((Object)(object)_focusArrow.transform.parent == (Object)(object)label)) { if ((Object)(object)_focusArrow != (Object)null) { Object.Destroy((Object)(object)_focusArrow); } _focusArrow = new GameObject("PeakSpectatorFocusArrow", new Type[2] { typeof(RectTransform), typeof(Image) }); _focusArrow.transform.SetParent((Transform)(object)label, false); Image component = _focusArrow.GetComponent(); component.sprite = PlayerOverlayLabel.GetArrowOuterSprite(SpectatorArrowStyle.RoundedGlass); ((Graphic)component).raycastTarget = false; component.preserveAspect = true; float num = Mathf.Max(8f, ((TMP_Text)labelText).fontSize * 0.5f); float num2 = num * 1.1875f; RectTransform component2 = _focusArrow.GetComponent(); component2.sizeDelta = new Vector2(num, num2); ((Transform)component2).localEulerAngles = new Vector3(0f, 0f, 90f); } } private void PositionFocusArrow(RectTransform label, TextMeshProUGUI labelText) { //IL_0014: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) RectTransform component = _focusArrow.GetComponent(); RectTransform rectTransform = ((TMP_Text)labelText).rectTransform; float num = Mathf.Max(rectTransform.sizeDelta.x, ((TMP_Text)labelText).preferredWidth); float num2 = (0f - ((TMP_Text)labelText).fontSize) * 0.18f; Vector2 val = default(Vector2); if (Configuration.MoveSummitRosterRight) { ((Vector2)(ref val))..ctor(0f, 0.5f); component.anchorMax = val; component.anchorMin = val; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x - num - 10f, num2); } else { ((Vector2)(ref val))..ctor(0f, 0.5f); component.anchorMax = val; component.anchorMin = val; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x - 12f, num2); } } private void RefreshRankedLabels() { //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) List list = new List(); foreach (Character allCharacter in Character.AllCharacters) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)((Component)allCharacter).gameObject == (Object)null) && ((Component)allCharacter).gameObject.activeInHierarchy && (Plugin.GsIntegration == null || !Plugin.GsIntegration.IsCharacterPermaSpectator(allCharacter)) && !IsAltitudeOutOfBounds(allCharacter)) { list.Add(allCharacter); } } list.Sort((Character a, Character b) => GetHeightMeters(b).CompareTo(GetHeightMeters(a))); for (int num = 0; num < list.Count; num++) { Character val = list[num]; RectTransform val2 = FindLabelForCharacter(val); if ((Object)(object)val2 == (Object)null) { continue; } TextMeshProUGUI val3 = FindLabelText(val2); if (!((Object)(object)val3 == (Object)null)) { string text = GetNickname(val); if (string.IsNullOrEmpty(text)) { text = val.characterName; } if (string.IsNullOrEmpty(text)) { text = "Unknown"; } ((TMP_Text)val3).text = $"{num + 1}.{text} {Mathf.RoundToInt(GetHeightMeters(val))}m"; ((TMP_Text)val3).rectTransform.sizeDelta = ((TMP_Text)val3).GetPreferredValues() * 1.1f; } } } private static bool IsFocusTooFar(Character focused) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)Singleton.Instance != (Object)null) ? ((Component)Singleton.Instance).transform : (((Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null) ? ((Component)MainCamera.instance.cam).transform : null)); if ((Object)(object)val == (Object)null || (Object)(object)focused == (Object)null) { return true; } return Vector3.Distance(val.position, GetCharacterFocusPoint(focused)) > 30f; } private void HideFocusArrow() { if ((Object)(object)_focusArrow != (Object)null) { _focusArrow.SetActive(false); } } private RectTransform FindLabelForCharacter(Character character) { Dictionary characterLabelsMap = GetCharacterLabelsMap(); if (characterLabelsMap != null) { if ((Object)(object)character != (Object)null && characterLabelsMap.TryGetValue(character, out var value) && (Object)(object)value != (Object)null) { RectTransform component = value.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } return null; } string nickname = GetNickname(character); string playerName = (((Object)(object)character != (Object)null) ? character.characterName : null); foreach (RectTransform item in FindLabelRects()) { if (!((Object)(object)((Component)item).gameObject == (Object)null) && ((Component)item).gameObject.activeInHierarchy) { string name = ((Object)((Component)item).gameObject).name; if (MatchesLabel(name, nickname) || MatchesLabel(name, playerName)) { return item; } TextMeshProUGUI val = FindLabelText(item); if ((Object)(object)val != (Object)null && (StartsWithName(((TMP_Text)val).text, nickname) || StartsWithName(((TMP_Text)val).text, playerName))) { return item; } } } return null; } private static string GetNickname(Character character) { try { object result; if (character == null) { result = null; } else { CharacterRefs refs = character.refs; if (refs == null) { result = null; } else { PhotonView view = refs.view; if (view == null) { result = null; } else { Player owner = view.Owner; result = ((owner != null) ? owner.NickName : null); } } } return (string)result; } catch { return null; } } private static float GetHeightMeters(Character character) { try { if ((Object)(object)character?.refs?.stats != (Object)null) { return character.refs.stats.heightInMeters; } } catch { } return 0f; } private static Vector3 GetCharacterFocusPoint(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) try { return character.Head; } catch { try { return character.Center; } catch { return ((Object)(object)character != (Object)null) ? ((Component)character).transform.position : Vector3.zero; } } } private static bool MatchesLabel(string labelName, string playerName) { if (!string.IsNullOrEmpty(playerName)) { return labelName == "Label_" + playerName; } return false; } private static bool StartsWithName(string text, string playerName) { if (string.IsNullOrEmpty(playerName) || string.IsNullOrEmpty(text)) { return false; } if (text.StartsWith(playerName + " ")) { return true; } int num = text.IndexOf('.'); if (num >= 0 && num + 1 < text.Length) { return text.Substring(num + 1).StartsWith(playerName + " "); } return false; } private RectTransform FindChildRect(string name) { if (!((Object)(object)_canvas != (Object)null)) { return null; } return FindChildRect(((Component)_canvas).transform, name); } private static RectTransform FindChildRect(Transform parent, string name) { if ((Object)(object)parent == (Object)null) { return null; } Transform val = parent.Find(name); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private static TextMeshProUGUI FindLabelText(RectTransform label) { RectTransform val = FindChildRect((Transform)(object)label, "Text"); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private void LogLayoutAuditIfNeeded(RectTransform bar) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (_layoutAuditLogged || !Configuration.DebugMode || (Object)(object)bar == (Object)null) { return; } foreach (RectTransform item in FindLabelRects()) { RectTransform val = FindChildRect((Transform)(object)item, "Marker"); TextMeshProUGUI val2 = FindLabelText(item); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { _layoutAuditLogged = true; RectTransform val3 = FindFirstTickRect(); Rect rect = val.rect; float x = ((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x; rect = bar.rect; float num = x - ((Transform)bar).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x; string text; if (!((Object)(object)val3 != (Object)null)) { text = string.Empty; } else { string arg = DescribeRect(val3); rect = val3.rect; float x2 = ((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x; rect = bar.rect; text = $" Tick[{arg}] Tick center X - Bar center X={x2 - ((Transform)bar).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x:0.###}"; } string text2 = text; string text3; if (!((Object)(object)val3 != (Object)null)) { text3 = string.Empty; } else { string arg2 = DescribeRect(val3); rect = val3.rect; float x3 = ((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x; rect = bar.rect; text3 = $" Tick[{arg2}] Tick中心X-Bar中心X={x3 - ((Transform)bar).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)).x:0.###}"; } string text4 = text3; L10n.LogInfo($"Summit Roster coordinate audit: Bar[{DescribeRect(bar)}] Label[{DescribeRect(item)}] Marker[{DescribeRect(val)}] Text[{DescribeRect(((TMP_Text)val2).rectTransform)}] Marker center X - Bar center X={num:0.###}{text2}", $"SummitRoster坐标审计: Bar[{DescribeRect(bar)}] Label[{DescribeRect(item)}] Marker[{DescribeRect(val)}] Text[{DescribeRect(((TMP_Text)val2).rectTransform)}] Marker中心X-Bar中心X={num:0.###}{text4}"); break; } } } private static string DescribeRect(RectTransform rect) { //IL_0017: 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_0033: 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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { return $"anchorMin={rect.anchorMin}, anchorMax={rect.anchorMax}, pivot={rect.pivot}, size={rect.sizeDelta}, pos={rect.anchoredPosition}"; } return "null"; } private List FindLabelRects() { List list = new List(); if ((Object)(object)_canvas == (Object)null) { return list; } for (int i = 0; i < ((Component)_canvas).transform.childCount; i++) { Transform child = ((Component)_canvas).transform.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name.StartsWith("Label_")) { RectTransform component = ((Component)child).GetComponent(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } return list; } private List FindTickRects() { List list = new List(); if ((Object)(object)_canvas == (Object)null) { return list; } for (int i = 0; i < ((Component)_canvas).transform.childCount; i++) { Transform child = ((Component)_canvas).transform.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name == "Tick") { RectTransform component = ((Component)child).GetComponent(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } return list; } private RectTransform FindFirstTickRect() { if ((Object)(object)_canvas == (Object)null) { return null; } Transform val = ((Component)_canvas).transform.Find("Tick"); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } private void Remember(RectTransform rect) { if ((Object)(object)rect != (Object)null && !_originalStates.ContainsKey(rect)) { _originalStates[rect] = new RectState(rect); } } private static void SetRightAnchored(RectTransform rect, Vector2 anchoredPosition, Vector2 pivot) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 0.5f); rect.anchorMax = val; rect.anchorMin = val; rect.pivot = pivot; rect.anchoredPosition = anchoredPosition; } } internal sealed class XraySilhouetteManager { private readonly Dictionary _silhouettes = new Dictionary(); private float _nextCheckTime; private bool _running; private readonly List _keyBuffer = new List(); internal XraySilhouetteManager() { SceneManager.sceneLoaded += OnSceneLoaded; } internal void Dispose() { SceneManager.sceneLoaded -= OnSceneLoaded; ClearAll(); } internal void RegisterCharacter(Character character) { if (!((Object)(object)character == (Object)null) && !character.isBot) { int instanceID = ((Object)character).GetInstanceID(); if (!_silhouettes.ContainsKey(instanceID)) { CharacterXraySilhouette value = new CharacterXraySilhouette(character); _silhouettes.Add(instanceID, value); } } } internal void UnregisterCharacter(Character character) { if (!((Object)(object)character == (Object)null)) { int instanceID = ((Object)character).GetInstanceID(); if (_silhouettes.TryGetValue(instanceID, out var value)) { value.Destroy(); _silhouettes.Remove(instanceID); } } } internal void LateUpdate(bool spectatorActive) { EnsureAllCharactersRegistered(); Camera camera = GetCamera(); if (!spectatorActive || !Configuration.ShowXraySilhouette || !((Object)(object)camera != (Object)null)) { if (_running) { SetAllVisible(visible: false); _running = false; } return; } _running = true; bool flag = Time.time >= _nextCheckTime; if (flag) { _nextCheckTime = Time.time + 0.12f; } _keyBuffer.Clear(); _keyBuffer.AddRange(_silhouettes.Keys); foreach (int item in _keyBuffer) { CharacterXraySilhouette characterXraySilhouette = _silhouettes[item]; if (characterXraySilhouette.ShouldRemove()) { characterXraySilhouette.Destroy(); _silhouettes.Remove(item); } else { characterXraySilhouette.Update(camera, flag); } } } private void EnsureAllCharactersRegistered() { foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter != (Object)null && !allCharacter.isBot && !_silhouettes.ContainsKey(((Object)allCharacter).GetInstanceID())) { RegisterCharacter(allCharacter); } } } private void SetAllVisible(bool visible) { foreach (CharacterXraySilhouette value in _silhouettes.Values) { value.SetVisible(visible); } } private void ClearAll() { foreach (CharacterXraySilhouette value in _silhouettes.Values) { value.Destroy(); } _silhouettes.Clear(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { ClearAll(); } private static Camera GetCamera() { if ((Object)(object)MainCamera.instance != (Object)null && (Object)(object)MainCamera.instance.cam != (Object)null) { return MainCamera.instance.cam; } return Camera.main; } } internal sealed class CharacterXraySilhouette { private sealed class RendererPair { internal readonly Renderer Source; internal readonly Renderer Clone; internal readonly MeshFilter CloneFilter; internal readonly bool IsDetail; internal Material[] DetailMaterials; internal int MaterialCount; internal RendererPair(Renderer source, Renderer clone, MeshFilter cloneFilter, int materialCount, bool isDetail, Material[] detailMaterials) { Source = source; Clone = clone; CloneFilter = cloneFilter; MaterialCount = materialCount; IsDetail = isDetail; DetailMaterials = detailMaterials; } internal void Destroy() { if ((Object)(object)Clone != (Object)null) { Object.Destroy((Object)(object)((Component)Clone).gameObject); } DestroyDetailMaterials(); } internal void DestroyDetailMaterials() { if (DetailMaterials == null) { return; } Material[] detailMaterials = DetailMaterials; foreach (Material val in detailMaterials) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } DetailMaterials = null; } } private readonly Character _character; private readonly List _pairs = new List(); private readonly List _detailPairs = new List(); private readonly Material _material; private bool _visible; private bool _lastOccluded; private float _nextEmptyRebuild; internal CharacterXraySilhouette(Character character) { _character = character; _material = CreateMaterial(); RebuildRenderers(); } internal bool IsValid() { if ((Object)(object)_character != (Object)null && (Object)(object)((Component)_character).gameObject != (Object)null) { return ((Component)_character).gameObject.activeInHierarchy; } return false; } internal bool ShouldRemove() { if (!((Object)(object)_character == (Object)null)) { return (Object)(object)((Component)_character).gameObject == (Object)null; } return true; } internal void Update(Camera camera, bool checkOcclusion) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!IsValid() || !CharacterState.IsAliveSpectatorTarget(_character)) { SetVisible(visible: false); return; } if (_pairs.Count == 0 && Time.time >= _nextEmptyRebuild) { RebuildRenderers(); _nextEmptyRebuild = Time.time + 0.5f; } if (checkOcclusion) { _lastOccluded = IsOccluded(camera); } SetColor(PlayerOverlayLabel.GetPlayerColor(_character)); SetVisible(_lastOccluded); } internal void SetVisible(bool visible) { _visible = visible; foreach (RendererPair pair in _pairs) { SyncPair(pair, visible); } foreach (RendererPair detailPair in _detailPairs) { SyncPair(detailPair, visible && Configuration.ShowXrayDetailLayer); } } internal void Destroy() { foreach (RendererPair pair in _pairs) { pair.Destroy(); } _pairs.Clear(); foreach (RendererPair detailPair in _detailPairs) { detailPair.Destroy(); } _detailPairs.Clear(); if ((Object)(object)_material != (Object)null) { Object.Destroy((Object)(object)_material); } } private void RebuildRenderers() { foreach (RendererPair pair in _pairs) { pair.Destroy(); } _pairs.Clear(); foreach (RendererPair detailPair in _detailPairs) { detailPair.Destroy(); } _detailPairs.Clear(); Renderer[] sourceRenderers = GetSourceRenderers(); foreach (Renderer val in sourceRenderers) { if (!CanUseSourceRenderer(val)) { continue; } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val2 != null) { RendererPair rendererPair = CreateSkinnedClone(val2); if (rendererPair != null) { _pairs.Add(rendererPair); } continue; } MeshRenderer val3 = (MeshRenderer)(object)((val is MeshRenderer) ? val : null); if (val3 != null) { RendererPair rendererPair2 = CreateMeshClone(val3); if (rendererPair2 != null) { _pairs.Add(rendererPair2); } } } sourceRenderers = GetDetailSourceRenderers(); foreach (Renderer val4 in sourceRenderers) { if (!CanUseSourceRenderer(val4)) { continue; } SkinnedMeshRenderer val5 = (SkinnedMeshRenderer)(object)((val4 is SkinnedMeshRenderer) ? val4 : null); if (val5 != null) { RendererPair rendererPair3 = CreateSkinnedDetailClone(val5); if (rendererPair3 != null) { _detailPairs.Add(rendererPair3); } continue; } MeshRenderer val6 = (MeshRenderer)(object)((val4 is MeshRenderer) ? val4 : null); if (val6 != null) { RendererPair rendererPair4 = CreateMeshDetailClone(val6); if (rendererPair4 != null) { _detailPairs.Add(rendererPair4); } } } SetVisible(_visible); } private Renderer[] GetSourceRenderers() { List list = new List(); HashSet seen = new HashSet(); try { CustomizationRefs refs = _character.refs.customization.refs; if ((Object)(object)refs != (Object)null) { AddRenderers(list, seen, refs.PlayerRenderers); AddRenderer(list, seen, (Renderer)(object)refs.mainRenderer); AddRenderer(list, seen, refs.shorts); AddRenderer(list, seen, refs.skirt); AddRenderer(list, seen, refs.sashRenderer); AddRenderers(list, seen, refs.playerHats); AddRenderer(list, seen, refs.skeletonRenderer); AddRenderer(list, seen, refs.chickenRenderer); } } catch { } if (list.Count == 0) { Renderer[] componentsInChildren = ((Component)_character).GetComponentsInChildren(true); AddRenderers(list, seen, componentsInChildren); } return list.ToArray(); } private Renderer[] GetDetailSourceRenderers() { List list = new List(); HashSet seen = new HashSet(); try { CustomizationRefs refs = _character.refs.customization.refs; if ((Object)(object)refs != (Object)null) { AddRenderer(list, seen, (Renderer)(object)refs.mainRenderer); AddRenderer(list, seen, refs.shorts); AddRenderer(list, seen, refs.skirt); AddRenderer(list, seen, refs.sashRenderer); AddRenderers(list, seen, refs.playerHats); } } catch { } return list.ToArray(); } private static void AddRenderers(List result, HashSet seen, Renderer[] renderers) { if (renderers != null) { foreach (Renderer renderer in renderers) { AddRenderer(result, seen, renderer); } } } private static void AddRenderer(List result, HashSet seen, Renderer renderer) { if (!((Object)(object)renderer == (Object)null) && !seen.Contains(renderer)) { seen.Add(renderer); result.Add(renderer); } } private bool CanUseSourceRenderer(Renderer source) { if ((Object)(object)source == (Object)null || source is ParticleSystemRenderer) { return false; } string name = ((Object)((Component)source).gameObject).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("PeakSpectatorXray")) { return false; } try { CustomizationRefs refs = _character.refs.customization.refs; if ((Object)(object)refs != (Object)null && ((Object)(object)source == (Object)(object)refs.mainRendererShadow || (Object)(object)source == (Object)(object)refs.shortsShadow || (Object)(object)source == (Object)(object)refs.skirtShadow || (Object)(object)source == (Object)(object)refs.headShadow || IsFaceDetailRenderer(source, refs))) { return false; } } catch { } MeshRenderer val = (MeshRenderer)(object)((source is MeshRenderer) ? source : null); if (val != null) { MeshFilter component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { return (Object)(object)component.sharedMesh != (Object)null; } return false; } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); if (val2 != null) { return (Object)(object)val2.sharedMesh != (Object)null; } return false; } private static bool IsFaceDetailRenderer(Renderer source, CustomizationRefs refs) { if ((Object)(object)source == (Object)null || (Object)(object)refs == (Object)null) { return false; } if ((Object)(object)source == (Object)(object)refs.mouthRenderer || (Object)(object)source == (Object)(object)refs.accessoryRenderer || (Object)(object)source == (Object)(object)refs.blindRenderer) { return true; } if ((Object)(object)refs.thirdEye != (Object)null && (Object)(object)source == (Object)(object)refs.thirdEye.GetComponent()) { return true; } return ContainsRenderer(refs.EyeRenderers, source); } private static bool ContainsRenderer(Renderer[] renderers, Renderer source) { if (renderers == null) { return false; } for (int i = 0; i < renderers.Length; i++) { if ((Object)(object)renderers[i] == (Object)(object)source) { return true; } } return false; } private RendererPair CreateSkinnedClone(SkinnedMeshRenderer source) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PeakSpectatorXraySkinned"); val.transform.SetParent(((Component)source).transform, false); val.layer = ((Component)source).gameObject.layer; SkinnedMeshRenderer val2 = val.AddComponent(); val2.sharedMesh = source.sharedMesh; val2.bones = source.bones; val2.rootBone = source.rootBone; ((Renderer)val2).localBounds = ((Renderer)source).localBounds; val2.updateWhenOffscreen = true; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; ((Renderer)val2).sharedMaterials = BuildMaterialArray(GetMaterialSlotCount((Renderer)(object)source)); ((Renderer)val2).enabled = false; return new RendererPair((Renderer)(object)source, (Renderer)(object)val2, null, GetMaterialSlotCount((Renderer)(object)source), isDetail: false, null); } private RendererPair CreateMeshClone(MeshRenderer source) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) MeshFilter component = ((Component)source).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } GameObject val = new GameObject("PeakSpectatorXrayMesh"); val.transform.SetParent(((Component)source).transform, false); val.layer = ((Component)source).gameObject.layer; MeshFilter val2 = val.AddComponent(); val2.sharedMesh = component.sharedMesh; MeshRenderer val3 = val.AddComponent(); ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; ((Renderer)val3).sharedMaterials = BuildMaterialArray(GetMaterialSlotCount((Renderer)(object)source)); ((Renderer)val3).enabled = false; return new RendererPair((Renderer)(object)source, (Renderer)(object)val3, val2, GetMaterialSlotCount((Renderer)(object)source), isDetail: false, null); } private RendererPair CreateSkinnedDetailClone(SkinnedMeshRenderer source) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PeakSpectatorXrayDetailSkinned"); val.transform.SetParent(((Component)source).transform, false); val.layer = ((Component)source).gameObject.layer; SkinnedMeshRenderer val2 = val.AddComponent(); val2.sharedMesh = source.sharedMesh; val2.bones = source.bones; val2.rootBone = source.rootBone; ((Renderer)val2).localBounds = ((Renderer)source).localBounds; val2.updateWhenOffscreen = true; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; Material[] detailMaterials = (((Renderer)val2).sharedMaterials = BuildDetailMaterialArray((Renderer)(object)source)); ((Renderer)val2).enabled = false; return new RendererPair((Renderer)(object)source, (Renderer)(object)val2, null, GetMaterialSlotCount((Renderer)(object)source), isDetail: true, detailMaterials); } private RendererPair CreateMeshDetailClone(MeshRenderer source) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) MeshFilter component = ((Component)source).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } GameObject val = new GameObject("PeakSpectatorXrayDetailMesh"); val.transform.SetParent(((Component)source).transform, false); val.layer = ((Component)source).gameObject.layer; MeshFilter val2 = val.AddComponent(); val2.sharedMesh = component.sharedMesh; MeshRenderer val3 = val.AddComponent(); ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; Material[] detailMaterials = (((Renderer)val3).sharedMaterials = BuildDetailMaterialArray((Renderer)(object)source)); ((Renderer)val3).enabled = false; return new RendererPair((Renderer)(object)source, (Renderer)(object)val3, val2, GetMaterialSlotCount((Renderer)(object)source), isDetail: true, detailMaterials); } private void SyncPair(RendererPair pair, bool targetVisible) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (pair == null || (Object)(object)pair.Source == (Object)null || (Object)(object)pair.Clone == (Object)null) { return; } if (!targetVisible) { if (pair.Clone.enabled) { pair.Clone.enabled = false; } return; } Renderer source = pair.Source; SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); if (val != null) { Renderer clone = pair.Clone; SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((clone is SkinnedMeshRenderer) ? clone : null); if (val2 != null) { val2.sharedMesh = val.sharedMesh; val2.bones = val.bones; val2.rootBone = val.rootBone; ((Renderer)val2).localBounds = ((Renderer)val).localBounds; val2.updateWhenOffscreen = true; goto IL_00f1; } } Renderer source2 = pair.Source; MeshRenderer val3 = (MeshRenderer)(object)((source2 is MeshRenderer) ? source2 : null); if (val3 != null && (Object)(object)pair.CloneFilter != (Object)null) { MeshFilter component = ((Component)val3).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { pair.Clone.enabled = false; return; } pair.CloneFilter.sharedMesh = component.sharedMesh; } goto IL_00f1; IL_00f1: int materialSlotCount = GetMaterialSlotCount(pair.Source); if (pair.MaterialCount != materialSlotCount) { if (pair.IsDetail) { pair.DestroyDetailMaterials(); pair.DetailMaterials = BuildDetailMaterialArray(pair.Source); pair.Clone.sharedMaterials = pair.DetailMaterials; } else { pair.Clone.sharedMaterials = BuildMaterialArray(materialSlotCount); } pair.MaterialCount = materialSlotCount; } else if (pair.IsDetail) { ApplyDetailMaterialSettings(pair.DetailMaterials); } pair.Clone.enabled = pair.Source.enabled && ((Component)pair.Source).gameObject.activeInHierarchy; } private Material[] BuildMaterialArray(int count) { count = Mathf.Max(1, count); Material[] array = (Material[])(object)new Material[count]; for (int i = 0; i < array.Length; i++) { array[i] = _material; } return array; } private Material[] BuildDetailMaterialArray(Renderer source) { Material[] sharedMaterials = source.sharedMaterials; Material[] array = (Material[])(object)new Material[GetMaterialSlotCount(source)]; for (int i = 0; i < array.Length; i++) { Material sourceMaterial = ((sharedMaterials != null && i < sharedMaterials.Length) ? sharedMaterials[i] : null); array[i] = CreateDetailMaterial(sourceMaterial); } return array; } private Material CreateDetailMaterial(Material sourceMaterial) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown Material val = (((Object)(object)sourceMaterial != (Object)null) ? new Material(sourceMaterial) : new Material(_material)); ((Object)val).hideFlags = (HideFlags)61; ApplyDetailMaterialSettings(val); return val; } private void ApplyDetailMaterialSettings(Material[] materials) { if (materials != null) { foreach (Material material in materials) { ApplyDetailMaterialSettings(material); } } } private void ApplyDetailMaterialSettings(Material material) { if (!((Object)(object)material == (Object)null)) { float num = 0.16f; SetMaterialColorAlpha(material, "_Color", num); SetMaterialColorAlpha(material, "_BaseColor", num); SetMaterialColorAlpha(material, "_TintColor", num); material.SetFloat("_Opacity", num); material.SetInt("_SrcBlend", 5); material.SetInt("_DstBlend", 10); material.SetInt("_ZWrite", 0); material.SetInt("_ZTest", 8); material.renderQueue = 5001; } } private static void SetMaterialColorAlpha(Material material, string propertyName, float alpha) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyName)) { Color color = material.GetColor(propertyName); color.a = alpha; material.SetColor(propertyName, color); } } private static int GetMaterialSlotCount(Renderer renderer) { if ((Object)(object)renderer == (Object)null || renderer.sharedMaterials == null || renderer.sharedMaterials.Length == 0) { return 1; } return renderer.sharedMaterials.Length; } private bool IsOccluded(Camera camera) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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) //IL_004e: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0085: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null) { return false; } Vector3 targetPoint = GetTargetPoint(); Vector3 val = camera.WorldToViewportPoint(targetPoint); if (val.z <= 0f || val.x < 0f || val.x > 1f || val.y < 0f || val.y > 1f) { return false; } Vector3 position = ((Component)camera).transform.position; Vector3 val2 = targetPoint - position; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude <= 0.1f) { return false; } RaycastHit[] array = Physics.RaycastAll(new Ray(position, val2 / magnitude), magnitude, LayerMask.op_Implicit(HelperFunctions.AllPhysicalExceptCharacter), (QueryTriggerInteraction)1); if (array == null || array.Length == 0) { return false; } RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val3 = array2[i]; if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && (Object)(object)((Component)((RaycastHit)(ref val3)).collider).transform.root != (Object)(object)((Component)_character).transform.root) { return true; } } return false; } private Vector3 GetTargetPoint() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0033: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) try { return _character.Center + Vector3.up * 0.8f; } catch { return ((Component)_character).transform.position + Vector3.up * 1.2f; } } private void SetColor(Color color) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) color.a = 0.34f; _material.color = color; if (_material.HasProperty("_Color")) { _material.SetColor("_Color", color); } if (_material.HasProperty("_TintColor")) { _material.SetColor("_TintColor", color); } } private static Material CreateMaterial() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_007c: Expected O, but got Unknown Material val = new Material(Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color")) { hideFlags = (HideFlags)61 }; val.SetInt("_SrcBlend", 5); val.SetInt("_DstBlend", 10); val.SetInt("_Cull", 0); val.SetInt("_ZWrite", 0); val.SetInt("_ZTest", 8); val.renderQueue = 5000; return val; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }