Decompiled source of DHHFLastChanceMode v0.1.2
plugins\DHHFLastChanceMode.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DHHFLastChanceMode.Modules.Config; using DHHFLastChanceMode.Modules.Gameplay.Core.Abilities; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Diagnostics; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Guards; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Monsters; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Monsters.Adapters; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Monsters.Interactions; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Monsters.Pipeline; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Monsters.Support; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime; using DHHFLastChanceMode.Modules.Gameplay.LastChance.Spectate; using DHHFLastChanceMode.Modules.Gameplay.LastChance.UI; using DHHFLastChanceMode.Modules.Utilities; using DeathHeadHopper.Abilities; using DeathHeadHopper.DeathHead; using DeathHeadHopper.DeathHead.Handlers; using DeathHeadHopper.Helpers; using DeathHeadHopper.Managers; using DeathHeadHopper.UI; using DeathHeadHopperFix.Modules.Config; using DeathHeadHopperFix.Modules.Gameplay.Core.Abilities; using DeathHeadHopperFix.Modules.Gameplay.Spectate; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 DeathHeadHopperFix.Modules.Gameplay.LastChance.Runtime { internal static class LastChanceTimerController { internal static bool IsActive => DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.IsActive; internal static bool IsDirectionIndicatorUiVisible => DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.IsDirectionIndicatorUiVisible; internal static float GetDirectionIndicatorPenaltySecondsPreview() { return DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.GetDirectionIndicatorPenaltySecondsPreview(); } internal static bool IsDirectionIndicatorEnergySufficientPreview() { return DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.IsDirectionIndicatorEnergySufficientPreview(); } internal static void GetDirectionIndicatorEnergyDebugSnapshot(out bool visible, out float timerRemaining, out float penaltyPreview, out bool hasEnoughEnergy) { DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.GetDirectionIndicatorEnergyDebugSnapshot(out visible, out timerRemaining, out penaltyPreview, out hasEnoughEnergy); } internal static bool IsPlayerSurrenderedForData(PlayerAvatar? player) { return DHHFLastChanceMode.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController.IsPlayerSurrenderedForData(player); } } } namespace DHHFLastChanceMode { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("AdrenSnyder.DHHFLastChanceMode", "DHHF LastChance Mode", "0.1.2")] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <DeferredBootstrap>d__10 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DeferredBootstrap>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!<>4__this._runtimeInitialized) { if (<>4__this.IsCoreLoaded()) { <>4__this.InitializeRuntime(); return false; } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string CorePluginGuid = "AdrenSnyder.DeathHeadHopperFix"; internal const string PluginGuid = "AdrenSnyder.DHHFLastChanceMode"; internal const string PluginName = "DHHF LastChance Mode"; internal const string PluginVersion = "0.1.2"; private Harmony? _harmony; private bool _runtimeInitialized; private Coroutine? _deferredBootstrapRoutine; private static ManualLogSource? s_log; private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown s_log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("AdrenSnyder.DHHFLastChanceMode"); _deferredBootstrapRoutine = ((MonoBehaviour)this).StartCoroutine(DeferredBootstrap()); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; ConfigManager.HostControlledChanged -= OnHostControlledChanged; if (_deferredBootstrapRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_deferredBootstrapRoutine); _deferredBootstrapRoutine = null; } } [IteratorStateMachine(typeof(<DeferredBootstrap>d__10))] private IEnumerator DeferredBootstrap() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DeferredBootstrap>d__10(0) { <>4__this = this }; } private bool IsCoreLoaded() { if (Chainloader.PluginInfos.ContainsKey("AdrenSnyder.DeathHeadHopperFix")) { return true; } return false; } private void InitializeRuntime() { if (!_runtimeInitialized) { _runtimeInitialized = true; _deferredBootstrapRoutine = null; ConfigManager.Initialize(((BaseUnityPlugin)this).Config); ManualLogSource? obj = s_log; if (obj != null) { obj.LogInfo((object)"[LastChance] DHHF LastChance Mode loaded."); } AllPlayersDeadGuard.EnsureEnabled(); if (FeatureFlags.LastChangeMode) { LastChanceTimerController.PrewarmGlobalAssetsAtBoot(); } Harmony harmony = _harmony; if (harmony != null) { LastChanceHarmonyPatchRegistry.ApplyAll(harmony, s_log); SceneManager.sceneLoaded += OnSceneLoaded; ConfigManager.HostControlledChanged += OnHostControlledChanged; ReconcileConditionalMonsterPatches(); } } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { CompatibilityGate.EnsureCreated(); LastChanceRuntimeObjectRegistry.ResetForSceneChange(); bool flag = ShouldHandleRuntimeScene(); LastChanceTimerController.OnLevelLoaded(flag); if (flag) { CompatibilityGate.NotifyRuntimeSceneLoaded(); ConfigSyncManager.EnsureCreated(); ConfigSyncManager.RequestHostSnapshotBroadcast(); ReconcileConditionalMonsterPatches(); } } private void OnHostControlledChanged() { LastChanceTimerController.OnHostControlledConfigChanged(); if (FeatureFlags.LastChangeMode) { LastChanceTimerController.PrewarmGlobalAssetsAtBoot(); } ReconcileConditionalMonsterPatches(); } private static bool ShouldHandleRuntimeScene() { if ((Object)(object)RunManager.instance == (Object)null) { return false; } if (SemiFunc.RunIsLobbyMenu() || SemiFunc.RunIsLobby() || SemiFunc.RunIsShop() || SemiFunc.RunIsArena() || SemiFunc.RunIsTutorial() || SemiFunc.MenuLevel()) { return false; } return true; } private void ReconcileConditionalMonsterPatches() { Harmony harmony = _harmony; if (harmony != null) { bool enable = FeatureFlags.LastChangeMode && FeatureFlags.LastChanceMonstersSearchEnabled; LastChanceMonstersPatchLifecycle.ReconcilePipeline(enable, harmony); } } } } namespace DHHFLastChanceMode.Modules.Utilities { internal static class AudioAssetLoader { internal static string GetDefaultAssetsDirectory() { return BundleAssetLoader.GetPluginDirectory(); } internal static bool TryLoadAudioClip(string fileName, string? baseDirectory, out AudioClip? clip, out string resolvedPath) { clip = null; resolvedPath = string.Empty; if (string.IsNullOrWhiteSpace(fileName)) { return false; } if (BundleAssetLoader.TryLoadAudioClip(fileName, out AudioClip clip2, out string resolvedPath2) && (Object)(object)clip2 != (Object)null) { clip = clip2; resolvedPath = resolvedPath2; return true; } return false; } } internal static class BundleAssetLoader { private static readonly ManualLogSource Log = Logger.CreateLogSource("DHHFLastChanceMode.BundleAssetLoader"); private static AssetBundle? s_bundle; private static Sprite[]? s_allSprites; private static AudioClip[]? s_allAudioClips; private static float s_lastLoadAttemptAt = -999f; private const float RetrySeconds = 3f; internal static string GetPluginDirectory() { try { string location = typeof(Plugin).Assembly.Location; if (!string.IsNullOrWhiteSpace(location)) { string directoryName = Path.GetDirectoryName(location); if (!string.IsNullOrWhiteSpace(directoryName)) { return directoryName; } } } catch { } return Paths.PluginPath; } private static void EnsureBundleLoaded() { if ((Object)(object)s_bundle != (Object)null) { return; } float unscaledTime = Time.unscaledTime; if (s_lastLoadAttemptAt > 0f && unscaledTime - s_lastLoadAttemptAt < 3f) { return; } s_lastLoadAttemptAt = unscaledTime; List<string> list = BuildBundleCandidates(); for (int i = 0; i < list.Count; i++) { string text = list[i]; if (!File.Exists(text)) { continue; } try { s_bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)s_bundle != (Object)null) { if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.Loaded", 120)) { Log.LogDebug((object)("[LastChance] Loaded asset bundle from: " + text)); } break; } } catch { } } } private static List<string> BuildBundleCandidates() { List<string> list = new List<string>(); string pluginDirectory = GetPluginDirectory(); if (!string.IsNullOrWhiteSpace(pluginDirectory)) { list.Add(pluginDirectory); } if (!string.IsNullOrWhiteSpace(Paths.PluginPath)) { list.Add(Paths.PluginPath); list.Add(Path.Combine(Paths.PluginPath, "AdrenSnyder-DHHFLastChanceMode")); list.Add(Path.Combine(Paths.PluginPath, "DHHFLastChanceMode")); } string[] array = new string[4] { "DHHFLastChanceMode", "dhhflastchancemode", "DHHFLastChanceMode.bundle", "dhhflastchancemode.bundle" }; List<string> list2 = new List<string>(); for (int i = 0; i < list.Count; i++) { string text = list[i]; if (!string.IsNullOrWhiteSpace(text)) { for (int j = 0; j < array.Length; j++) { list2.Add(Path.Combine(text, array[j])); list2.Add(Path.Combine(text, "Assets", array[j])); } } } return list2.Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList(); } internal static bool TryLoadSprite(string fileName, out Sprite? sprite, out string resolvedPath) { //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) sprite = null; resolvedPath = string.Empty; if (string.IsNullOrWhiteSpace(fileName)) { return false; } EnsureBundleLoaded(); if ((Object)(object)s_bundle == (Object)null) { return false; } string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); string[] array = new string[4] { fileNameWithoutExtension, fileName, "Assets/" + fileName, "assets/" + fileName }; foreach (string text in array) { try { sprite = s_bundle.LoadAsset<Sprite>(text); if ((Object)(object)sprite != (Object)null) { resolvedPath = text; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteHit." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Sprite '" + fileName + "' resolved as Sprite: " + resolvedPath)); } return true; } Texture2D val = s_bundle.LoadAsset<Texture2D>(text); if ((Object)(object)val != (Object)null) { sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)sprite).name = Path.GetFileNameWithoutExtension(fileName); resolvedPath = text; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteHitTex." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Sprite '" + fileName + "' resolved from Texture2D: " + resolvedPath)); } return true; } } catch { } } try { string[] allAssetNames = s_bundle.GetAllAssetNames(); foreach (string text2 in allAssetNames) { if (!text2.EndsWith("/" + fileName, StringComparison.OrdinalIgnoreCase) && !text2.EndsWith("/" + fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, fileName, StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) { continue; } sprite = s_bundle.LoadAsset<Sprite>(text2); if ((Object)(object)sprite != (Object)null) { resolvedPath = text2; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteHitAsset." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Sprite '" + fileName + "' resolved via asset name: " + resolvedPath)); } return true; } Texture2D val2 = s_bundle.LoadAsset<Texture2D>(text2); if ((Object)(object)val2 != (Object)null) { sprite = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f); ((Object)sprite).name = Path.GetFileNameWithoutExtension(fileName); resolvedPath = text2; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteHitAssetTex." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Sprite '" + fileName + "' resolved via asset Texture2D: " + resolvedPath)); } return true; } } } catch { } string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(fileName); Sprite[] allSprites = GetAllSprites(); foreach (Sprite val3 in allSprites) { if (!((Object)(object)val3 == (Object)null) && (string.Equals(((Object)val3).name, fileNameWithoutExtension2, StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)val3).name, fileName, StringComparison.OrdinalIgnoreCase))) { sprite = val3; resolvedPath = ((Object)val3).name; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteHitByName." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Sprite '" + fileName + "' resolved by object name: " + resolvedPath)); } return true; } } if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.SpriteMiss." + fileName, 60)) { Log.LogWarning((object)("[LastChance] Sprite '" + fileName + "' not found in bundle.")); } return false; } internal static bool TryLoadAudioClip(string fileName, out AudioClip? clip, out string resolvedPath) { clip = null; resolvedPath = string.Empty; if (string.IsNullOrWhiteSpace(fileName)) { return false; } EnsureBundleLoaded(); if ((Object)(object)s_bundle == (Object)null) { return false; } string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); string[] array = new string[4] { fileNameWithoutExtension, fileName, "Assets/" + fileName, "assets/" + fileName }; foreach (string text in array) { try { clip = s_bundle.LoadAsset<AudioClip>(text); if ((Object)(object)clip != (Object)null) { resolvedPath = text; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.AudioHit." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Audio '" + fileName + "' resolved as AudioClip: " + resolvedPath)); } return true; } } catch { } } try { string[] allAssetNames = s_bundle.GetAllAssetNames(); foreach (string text2 in allAssetNames) { if (!text2.EndsWith("/" + fileName, StringComparison.OrdinalIgnoreCase) && !text2.EndsWith("/" + fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, fileName, StringComparison.OrdinalIgnoreCase) && !string.Equals(text2, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) { continue; } clip = s_bundle.LoadAsset<AudioClip>(text2); if ((Object)(object)clip != (Object)null) { resolvedPath = text2; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.AudioHitAsset." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Audio '" + fileName + "' resolved via asset name: " + resolvedPath)); } return true; } } } catch { } string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(fileName); AudioClip[] allAudioClips = GetAllAudioClips(); foreach (AudioClip val in allAudioClips) { if (!((Object)(object)val == (Object)null) && (string.Equals(((Object)val).name, fileNameWithoutExtension2, StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)val).name, fileName, StringComparison.OrdinalIgnoreCase))) { clip = val; resolvedPath = ((Object)val).name; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.AudioHitByName." + fileName, 60)) { Log.LogDebug((object)("[LastChance] Audio '" + fileName + "' resolved by object name: " + resolvedPath)); } return true; } } if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.Bundle.AudioMiss." + fileName, 60)) { Log.LogWarning((object)("[LastChance] Audio '" + fileName + "' not found in bundle.")); } return false; } private static Sprite[] GetAllSprites() { if (s_allSprites != null) { return s_allSprites; } if ((Object)(object)s_bundle == (Object)null) { s_allSprites = Array.Empty<Sprite>(); return s_allSprites; } try { s_allSprites = s_bundle.LoadAllAssets<Sprite>() ?? Array.Empty<Sprite>(); } catch { s_allSprites = Array.Empty<Sprite>(); } return s_allSprites; } private static AudioClip[] GetAllAudioClips() { if (s_allAudioClips != null) { return s_allAudioClips; } if ((Object)(object)s_bundle == (Object)null) { s_allAudioClips = Array.Empty<AudioClip>(); return s_allAudioClips; } try { s_allAudioClips = s_bundle.LoadAllAssets<AudioClip>() ?? Array.Empty<AudioClip>(); } catch { s_allAudioClips = Array.Empty<AudioClip>(); } return s_allAudioClips; } } internal static class CoreBatteryInterop { private const string BatteryJumpEnabledKey = "BatteryJumpEnabled"; internal static bool TryGetBatteryJumpEnabled(out bool value) { value = FeatureFlags.BatteryJumpEnabled; return true; } internal static bool TrySetBatteryJumpEnabled(bool value) { FeatureFlags.BatteryJumpEnabled = value; return true; } internal static void SetCoreHostRuntimeOverride(bool enabled) { ConfigManager.SetHostRuntimeOverride("BatteryJumpEnabled", enabled ? bool.TrueString : bool.FalseString); } internal static void ClearCoreHostRuntimeOverride() { ConfigManager.ClearHostRuntimeOverride("BatteryJumpEnabled"); } internal static void RequestCoreConfigSyncBroadcast() { ConfigSyncManager.RequestHostSnapshotBroadcast(); } } internal static class ImageAssetLoader { internal static string GetDefaultAssetsDirectory() { return BundleAssetLoader.GetPluginDirectory(); } internal static bool TryLoadTexture(string fileName, string? baseDirectory, out Texture2D? texture, out string resolvedPath) { texture = null; resolvedPath = string.Empty; if (string.IsNullOrWhiteSpace(fileName)) { return false; } if (BundleAssetLoader.TryLoadSprite(fileName, out Sprite sprite, out string resolvedPath2) && (Object)(object)sprite != (Object)null && (Object)(object)sprite.texture != (Object)null) { texture = sprite.texture; resolvedPath = resolvedPath2; return true; } return false; } internal static bool TryLoadSprite(string fileName, string? baseDirectory, out Sprite? sprite, out string resolvedPath, float pixelsPerUnit = 100f) { sprite = null; if (BundleAssetLoader.TryLoadSprite(fileName, out Sprite sprite2, out resolvedPath) && (Object)(object)sprite2 != (Object)null) { sprite = sprite2; return true; } return false; } } internal static class LogLimiter { public const int DefaultFrameInterval = 240; private static readonly Dictionary<string, int> s_lastFrameByKey = new Dictionary<string, int>(StringComparer.Ordinal); public static bool ShouldLog(string key, int frameInterval = 240) { if (string.IsNullOrEmpty(key) || frameInterval <= 0) { return true; } int frameCount = Time.frameCount; if (s_lastFrameByKey.TryGetValue(key, out var value) && frameCount - value < frameInterval) { return false; } s_lastFrameByKey[key] = frameCount; return true; } public static void Reset(string key) { if (!string.IsNullOrEmpty(key)) { s_lastFrameByKey.Remove(key); } } public static void Clear() { s_lastFrameByKey.Clear(); } } internal static class NetworkProtocol { internal const string ModId = "DHHFLastChanceMode"; internal const int ProtocolVersion = 1; internal const string RoomKeyPrefix = "DHHFLastChanceMode.Room."; internal static string BuildRoomKey(string localKey) { return string.IsNullOrWhiteSpace(localKey) ? "DHHFLastChanceMode.Room." : ("DHHFLastChanceMode.Room." + localKey.Trim()); } } internal readonly struct NetworkEnvelope { internal string ModId { get; } internal int ProtocolVersion { get; } internal string MessageType { get; } internal int MessageSeq { get; } internal object? Payload { get; } internal NetworkEnvelope(string modId, int protocolVersion, string messageType, int messageSeq, object? payload) { ModId = (string.IsNullOrWhiteSpace(modId) ? string.Empty : modId.Trim()); ProtocolVersion = protocolVersion; MessageType = (string.IsNullOrWhiteSpace(messageType) ? string.Empty : messageType.Trim()); MessageSeq = messageSeq; Payload = payload; } internal object?[] ToEventPayload() { return new object[5] { ModId, ProtocolVersion, MessageType, MessageSeq, Payload }; } internal bool IsExpectedSource() { return ModId == "DHHFLastChanceMode" && ProtocolVersion == 1 && !string.IsNullOrWhiteSpace(MessageType); } internal static bool TryParse(object? customData, out NetworkEnvelope envelope) { envelope = default(NetworkEnvelope); if (!(customData is object[] array) || array.Length < 5) { return false; } if (array[0] is string modId && array[1] is int protocolVersion && array[2] is string messageType) { object obj = array[3]; int messageSeq = default(int); int num; if (obj is int) { messageSeq = (int)obj; num = 1; } else { num = 0; } if (num != 0) { envelope = new NetworkEnvelope(modId, protocolVersion, messageType, messageSeq, array[4]); return true; } } return false; } } internal static class PhotonEventCodes { internal const byte ConfigSync = 79; internal const byte LastChanceSurrender = 80; internal const byte LastChanceTimerState = 81; internal const byte LastChanceDirectionPenaltyRequest = 82; internal const byte LastChanceUiState = 83; internal const byte ClientFixPresence = 84; internal const byte HostGateState = 85; internal const byte LastChancePlayerTruckHint = 86; internal const byte HostFixPresenceRequest = 87; } internal static class PlayerStateExtractionHelper { internal readonly struct PlayerStateSnapshot { internal int ActorNumber { get; } internal int SteamIdShort { get; } internal string Name { get; } internal Color Color { get; } internal bool IsAlive { get; } internal bool IsDead { get; } internal bool IsInTruck { get; } internal bool IsSurrendered { get; } internal int SourceOrder { get; } internal PlayerStateSnapshot(int actorNumber, int steamIdShort, string name, Color color, bool isAlive, bool isDead, bool isInTruck, bool isSurrendered, int sourceOrder) { //IL_0017: 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) ActorNumber = actorNumber; SteamIdShort = steamIdShort; Name = name; Color = color; IsAlive = isAlive; IsDead = isDead; IsInTruck = isInTruck; IsSurrendered = isSurrendered; SourceOrder = sourceOrder; } } internal static List<PlayerStateSnapshot> GetPlayersStateSnapshot() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) List<PlayerStateSnapshot> list = new List<PlayerStateSnapshot>(); GameDirector instance = GameDirector.instance; if ((Object)(object)instance == (Object)null || instance.PlayerList == null || instance.PlayerList.Count == 0) { return list; } for (int i = 0; i < instance.PlayerList.Count; i++) { PlayerAvatar val = instance.PlayerList[i]; if (!((Object)(object)val == (Object)null)) { PhotonView photonView = val.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; int valueOrDefault = num.GetValueOrDefault(); int steamIdShort = GetSteamIdShort(val); string playerName = GetPlayerName(val); Color playerColor = GetPlayerColor(val); bool flag = IsDeadSet(val); bool flag2 = IsDisabled(val); bool flag3 = flag || flag2; bool isAlive = !flag3; bool isInTruck = IsPlayerInTruck(val, flag2); bool isSurrendered = LastChanceTimerController.IsPlayerSurrenderedForData(val); list.Add(new PlayerStateSnapshot(valueOrDefault, steamIdShort, playerName, playerColor, isAlive, flag3, isInTruck, isSurrendered, i)); } } list.Sort(CompareSnapshotOrder); return list; } internal static List<PlayerStateSnapshot> GetPlayersStillInLastChance() { List<PlayerStateSnapshot> playersStateSnapshot = GetPlayersStateSnapshot(); List<PlayerStateSnapshot> list = new List<PlayerStateSnapshot>(playersStateSnapshot.Count); for (int i = 0; i < playersStateSnapshot.Count; i++) { PlayerStateSnapshot item = playersStateSnapshot[i]; if (!item.IsSurrendered) { list.Add(item); } } return list; } private static int CompareSnapshotOrder(PlayerStateSnapshot left, PlayerStateSnapshot right) { if (left.ActorNumber > 0 && right.ActorNumber > 0) { return left.ActorNumber.CompareTo(right.ActorNumber); } return left.SourceOrder.CompareTo(right.SourceOrder); } private static string GetPlayerName(PlayerAvatar player) { if (!string.IsNullOrWhiteSpace(player.playerName)) { return player.playerName; } return "unknown"; } private static Color GetPlayerColor(PlayerAvatar player) { //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_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_0025: Unknown result type (might be due to invalid IL or missing references) PlayerAvatarVisuals playerAvatarVisuals = player.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return Color.black; } return playerAvatarVisuals.color; } private static bool IsDeadSet(PlayerAvatar player) { return player.deadSet; } private static bool IsDisabled(PlayerAvatar player) { return player.isDisabled; } private static bool IsPlayerInTruck(PlayerAvatar player, bool isDisabled) { if (!isDisabled) { RoomVolumeCheck roomVolumeCheck = player.RoomVolumeCheck; return (Object)(object)roomVolumeCheck != (Object)null && IsRoomVolumeInTruck(roomVolumeCheck); } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead == (Object)null) { return false; } RoomVolumeCheck roomVolumeCheck2 = playerDeathHead.roomVolumeCheck; if ((Object)(object)roomVolumeCheck2 != (Object)null) { return IsRoomVolumeInTruck(roomVolumeCheck2); } return playerDeathHead.inTruck; } private static bool IsRoomVolumeInTruck(RoomVolumeCheck roomVolumeCheck) { return roomVolumeCheck.inTruck; } private static int GetSteamIdShort(PlayerAvatar player) { return player.steamIDshort; } } internal static class PlayerTruckDistanceHelper { [Flags] internal enum DistanceQueryFields { None = 0, Height = 1, NavMeshDistance = 2, RoomPath = 4, All = 7 } internal readonly struct PlayerTruckDistance { internal PlayerAvatar PlayerAvatar { get; } internal float NavMeshDistance { get; } internal float HeightDelta { get; } internal int ShortestRoomPathToTruck { get; } internal int TotalMapRooms { get; } internal bool HasValidPath { get; } internal PlayerTruckDistance(PlayerAvatar playerAvatar, float navMeshDistance, float heightDelta, int shortestRoomPathToTruck, int totalMapRooms, bool hasValidPath) { PlayerAvatar = playerAvatar; NavMeshDistance = navMeshDistance; HeightDelta = heightDelta; ShortestRoomPathToTruck = shortestRoomPathToTruck; TotalMapRooms = totalMapRooms; HasValidPath = hasValidPath; } } private sealed class CachedPlayerDistance { internal float NavMeshDistance = -1f; internal float HeightDelta; internal int ShortestRoomPathToTruck = -1; internal int TotalMapRooms = -1; internal bool HasValidPath; internal int RoomHash; internal float HeightUpdatedAt = float.NegativeInfinity; internal int LevelStamp; internal Vector3 LastKnownWorldPosition; } private readonly struct RemotePlayerHint { internal int RoomHash { get; } internal float HeightDelta { get; } internal int LevelStamp { get; } internal float UpdatedAt { get; } internal RemotePlayerHint(int roomHash, float heightDelta, int levelStamp, float updatedAt) { RoomHash = roomHash; HeightDelta = heightDelta; LevelStamp = levelStamp; UpdatedAt = updatedAt; } } private struct ActivationProfileStats { internal int Calls; internal int PlayersProcessed; internal int NavRefreshCount; internal int RoomRefreshCount; internal int RemoteHintUsedCount; internal float TotalMs; internal float SetupMs; internal float LoopMs; internal float MaxCallMs; } private static readonly ManualLogSource Log = Logger.CreateLogSource("DHHFLastChanceMode.PlayerTruckDistance"); private const float HeightCacheTtlSeconds = 2f; private static LevelGenerator? s_cachedGraphLevelGenerator; private static int s_cachedGraphPointCount; private static Dictionary<RoomVolume, HashSet<RoomVolume>>? s_cachedRoomGraph; private static readonly Dictionary<int, CachedPlayerDistance> s_playerCache = new Dictionary<int, CachedPlayerDistance>(); private static readonly Dictionary<int, RemotePlayerHint> s_remoteHints = new Dictionary<int, RemotePlayerHint>(); private static LevelGenerator? s_cachedLevelGeneratorForPlayers; private static Vector3 s_cachedTruckPosition; private static bool s_hasCachedTruckPosition; private static int s_cachedLevelPointsCount; private static bool s_activationProfilingEnabled; private static ActivationProfileStats s_activationProfileStats; internal static void PrimeDistancesCache() { GetDistancesFromTruck(DistanceQueryFields.NavMeshDistance | DistanceQueryFields.RoomPath); } internal static PlayerTruckDistance[] GetDistancesFromTruck() { return GetDistancesFromTruck(DistanceQueryFields.All); } internal static PlayerTruckDistance[] GetDistancesFromTruck(DistanceQueryFields fields, ICollection<PlayerAvatar>? players = null, bool forceRefresh = false) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) try { bool debugLogging = FeatureFlags.DebugLogging; float num = (debugLogging ? Time.realtimeSinceStartup : 0f); float num2 = num; float num3 = num; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; if (fields == DistanceQueryFields.None) { return Array.Empty<PlayerTruckDistance>(); } LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance == (Object)null) { return Array.Empty<PlayerTruckDistance>(); } List<LevelPoint> allLevelPoints = GetAllLevelPoints(instance); if (!TryGetTruckTarget(instance, allLevelPoints, out Vector3 truckPosition, out LevelPoint truckPoint)) { return Array.Empty<PlayerTruckDistance>(); } GameDirector instance2 = GameDirector.instance; if (instance2?.PlayerList == null || instance2.PlayerList.Count == 0) { return Array.Empty<PlayerTruckDistance>(); } int num8 = allLevelPoints?.Count ?? 0; if (s_cachedLevelGeneratorForPlayers != instance || !s_hasCachedTruckPosition || Vector3.SqrMagnitude(s_cachedTruckPosition - truckPosition) > 0.0001f || s_cachedLevelPointsCount != num8) { s_playerCache.Clear(); s_remoteHints.Clear(); s_cachedLevelGeneratorForPlayers = instance; s_cachedTruckPosition = truckPosition; s_cachedLevelPointsCount = num8; s_hasCachedTruckPosition = true; } HashSet<int> hashSet = null; if (players != null) { hashSet = new HashSet<int>(); foreach (PlayerAvatar player in players) { if (!((Object)(object)player == (Object)null)) { hashSet.Add(GetPlayerKey(player)); } } if (hashSet.Count == 0) { return Array.Empty<PlayerTruckDistance>(); } } bool flag = (fields & DistanceQueryFields.RoomPath) != 0; bool flag2 = (fields & DistanceQueryFields.NavMeshDistance) != 0; bool flag3 = (fields & DistanceQueryFields.Height) != 0; Dictionary<RoomVolume, HashSet<RoomVolume>> dictionary = ((flag || flag2) ? GetOrBuildRoomGraph(instance, allLevelPoints) : null); int totalMapRooms = ((dictionary != null && dictionary.Count > 0) ? dictionary.Count : (-1)); int num9 = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelsCompleted : 0); if (debugLogging) { num2 = Time.realtimeSinceStartup; num3 = num2; } List<PlayerTruckDistance> list = new List<PlayerTruckDistance>(instance2.PlayerList.Count); foreach (PlayerAvatar player2 in instance2.PlayerList) { if ((Object)(object)player2 == (Object)null) { continue; } int playerKey = GetPlayerKey(player2); if (hashSet != null && !hashSet.Contains(playerKey)) { continue; } if (!s_playerCache.TryGetValue(playerKey, out CachedPlayerDistance value)) { value = new CachedPlayerDistance(); s_playerCache[playerKey] = value; } Vector3 val = (value.LastKnownWorldPosition = GetPlayerWorldPosition(player2)); PhotonView photonView = player2.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num10 = obj; int valueOrDefault = num10.GetValueOrDefault(); s_remoteHints.TryGetValue(valueOrDefault, out var value2); bool flag4 = SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.IsMultiplayer() && valueOrDefault > 0 && PhotonNetwork.LocalPlayer != null && valueOrDefault != PhotonNetwork.LocalPlayer.ActorNumber && value2.LevelStamp == num9; List<RoomVolume> list2 = null; int num11 = value.RoomHash; if (flag4) { num11 = value2.RoomHash; num6++; } else if (flag || flag2) { list2 = GetPlayerRooms(player2); num11 = ComputeRoomsHash(list2); } bool flag5 = num11 != value.RoomHash; bool flag6 = value.LevelStamp != num9; if (flag3) { float num12 = Time.unscaledTime - value.HeightUpdatedAt; if (forceRefresh || flag6 || num12 < 0f || num12 > 2f) { if (flag4 && Time.unscaledTime - value2.UpdatedAt <= 2f) { value.HeightDelta = value2.HeightDelta; value.HeightUpdatedAt = value2.UpdatedAt; } else { value.HeightDelta = val.y - truckPosition.y; value.HeightUpdatedAt = Time.unscaledTime; } } } if (flag2 && (forceRefresh || flag6 || flag5)) { float navMeshDistance = -1f; Vector3 navMeshPosition; bool flag7 = TryGetPlayerNavMeshPosition(player2, val, out navMeshPosition) && TryCalculatePathDistance(navMeshPosition, truckPosition, out navMeshDistance); value.NavMeshDistance = (flag7 ? navMeshDistance : (-1f)); value.HasValidPath = flag7; num4++; } if (flag && (forceRefresh || flag6 || flag5)) { if (list2 == null) { list2 = GetPlayerRooms(player2); } value.ShortestRoomPathToTruck = ResolveShortestRoomPathToTruck(list2 ?? new List<RoomVolume>(), truckPoint, dictionary); num5++; } if (flag || flag2) { value.TotalMapRooms = totalMapRooms; } value.RoomHash = num11; value.LevelStamp = num9; list.Add(new PlayerTruckDistance(player2, value.NavMeshDistance, value.HeightDelta, value.ShortestRoomPathToTruck, value.TotalMapRooms, value.HasValidPath)); num7++; } if (debugLogging && s_activationProfilingEnabled) { float realtimeSinceStartup = Time.realtimeSinceStartup; float num13 = (realtimeSinceStartup - num) * 1000f; float num14 = (num2 - num) * 1000f; float num15 = (realtimeSinceStartup - num3) * 1000f; s_activationProfileStats.Calls++; s_activationProfileStats.PlayersProcessed += num7; s_activationProfileStats.NavRefreshCount += num4; s_activationProfileStats.RoomRefreshCount += num5; s_activationProfileStats.RemoteHintUsedCount += num6; s_activationProfileStats.TotalMs += num13; s_activationProfileStats.SetupMs += num14; s_activationProfileStats.LoopMs += num15; s_activationProfileStats.MaxCallMs = Mathf.Max(s_activationProfileStats.MaxCallMs, num13); } return list.ToArray(); } catch (Exception ex) { LogRuntimeHotPathException("GetDistancesFromTruck", ex); return Array.Empty<PlayerTruckDistance>(); } } internal static void ApplyRemotePlayerHint(int actorNumber, int roomHash, float heightDelta, int levelStamp) { if (actorNumber > 0) { s_remoteHints[actorNumber] = new RemotePlayerHint(roomHash, heightDelta, levelStamp, Time.unscaledTime); } } internal static bool TryBuildLocalPlayerTruckHint(out int roomHash, out float heightDelta, out int levelStamp) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) roomHash = 0; heightDelta = 0f; levelStamp = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelsCompleted : 0); try { if (!PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null) { return false; } LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance == (Object)null) { return false; } List<LevelPoint> allLevelPoints = GetAllLevelPoints(instance); if (!TryGetTruckTarget(instance, allLevelPoints, out Vector3 truckPosition, out LevelPoint _)) { return false; } GameDirector instance2 = GameDirector.instance; if (instance2?.PlayerList == null || instance2.PlayerList.Count == 0) { return false; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; PlayerAvatar val = null; for (int i = 0; i < instance2.PlayerList.Count; i++) { PlayerAvatar val2 = instance2.PlayerList[i]; if (!((Object)(object)val2 == (Object)null)) { PhotonView photonView = val2.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; if (num.GetValueOrDefault() == actorNumber) { val = val2; break; } } } if ((Object)(object)val == (Object)null) { return false; } List<RoomVolume> playerRooms = GetPlayerRooms(val); roomHash = ComputeRoomsHash(playerRooms); Vector3 playerWorldPosition = GetPlayerWorldPosition(val); heightDelta = playerWorldPosition.y - truckPosition.y; return true; } catch (Exception ex) { LogRuntimeHotPathException("TryBuildLocalPlayerTruckHint", ex); return false; } } private static void LogRuntimeHotPathException(string context, Exception ex) { if (FeatureFlags.DebugLogging) { string key = "LastChance.Runtime.PlayerTruckDistance." + context; if (LogLimiter.ShouldLog(key, 600)) { Log.LogWarning((object)("[LastChance] Runtime hot-path failed in " + context + ": " + ex.GetType().Name + ": " + ex.Message)); } } } internal static void BeginActivationProfiling() { s_activationProfileStats = default(ActivationProfileStats); s_activationProfilingEnabled = true; } internal static string EndActivationProfilingSummary() { s_activationProfilingEnabled = false; return $"calls={s_activationProfileStats.Calls} total={s_activationProfileStats.TotalMs:F1}ms setup={s_activationProfileStats.SetupMs:F1}ms loop={s_activationProfileStats.LoopMs:F1}ms maxCall={s_activationProfileStats.MaxCallMs:F1}ms players={s_activationProfileStats.PlayersProcessed} navRefresh={s_activationProfileStats.NavRefreshCount} roomRefresh={s_activationProfileStats.RoomRefreshCount} remoteHints={s_activationProfileStats.RemoteHintUsedCount}"; } private static int GetPlayerKey(PlayerAvatar player) { PhotonView photonView = player.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; int valueOrDefault = num.GetValueOrDefault(); if (valueOrDefault != 0) { return valueOrDefault; } return ((Object)player).GetInstanceID(); } private static int ComputeRoomsHash(List<RoomVolume> rooms) { int num = 17; for (int i = 0; i < rooms.Count; i++) { num = num * 31 + RuntimeHelpers.GetHashCode(rooms[i]); } return num; } private static Dictionary<RoomVolume, HashSet<RoomVolume>> GetOrBuildRoomGraph(LevelGenerator levelGenerator, List<LevelPoint>? allLevelPoints) { int num = allLevelPoints?.Count ?? 0; if (s_cachedRoomGraph != null && levelGenerator == s_cachedGraphLevelGenerator && s_cachedGraphPointCount == num) { return s_cachedRoomGraph; } Dictionary<RoomVolume, HashSet<RoomVolume>> result = BuildRoomGraph(allLevelPoints); s_cachedGraphLevelGenerator = levelGenerator; s_cachedGraphPointCount = num; s_cachedRoomGraph = result; return result; } private static bool TryGetTruckTarget(LevelGenerator levelGenerator, List<LevelPoint>? allLevelPoints, out Vector3 truckPosition, out LevelPoint? truckPoint) { //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) truckPosition = Vector3.zero; truckPoint = null; LevelPoint levelPathTruck = levelGenerator.LevelPathTruck; if (TryGetLevelPointPosition(levelPathTruck, out truckPosition)) { truckPoint = levelPathTruck; return true; } if (allLevelPoints == null) { return false; } foreach (LevelPoint allLevelPoint in allLevelPoints) { if ((Object)(object)allLevelPoint == (Object)null || !TryIsTruckPoint(allLevelPoint) || !TryGetLevelPointPosition(allLevelPoint, out truckPosition)) { continue; } truckPoint = allLevelPoint; return true; } return false; } private static List<LevelPoint>? GetAllLevelPoints(LevelGenerator levelGenerator) { List<LevelPoint> levelPathPoints = levelGenerator.LevelPathPoints; if (levelPathPoints == null) { return null; } List<LevelPoint> list = new List<LevelPoint>(); foreach (LevelPoint item2 in levelPathPoints) { if (item2 != null) { LevelPoint item = item2; if (true) { list.Add(item); } } } return (list.Count > 0) ? list : null; } private static bool TryIsTruckPoint(LevelPoint point) { if (point.Truck) { return true; } return (Object)(object)point.Room != (Object)null && point.Room.Truck; } private static int ResolveShortestRoomPathToTruck(List<RoomVolume> playerRooms, LevelPoint? truckPoint, Dictionary<RoomVolume, HashSet<RoomVolume>>? roomGraph) { if ((Object)(object)truckPoint == (Object)null || roomGraph == null || roomGraph.Count == 0) { return -1; } RoomVolume levelPointRoom = GetLevelPointRoom(truckPoint); if ((Object)(object)levelPointRoom == (Object)null || !roomGraph.ContainsKey(levelPointRoom)) { return -1; } if (playerRooms.Count == 0) { return -1; } HashSet<RoomVolume> hashSet = new HashSet<RoomVolume>(); Queue<(RoomVolume, int)> queue = new Queue<(RoomVolume, int)>(); foreach (RoomVolume playerRoom in playerRooms) { if (!((Object)(object)playerRoom == (Object)null) && roomGraph.ContainsKey(playerRoom) && hashSet.Add(playerRoom)) { queue.Enqueue((playerRoom, 0)); } } while (queue.Count > 0) { var (val, num) = queue.Dequeue(); if (val == levelPointRoom) { return num; } if (!roomGraph.TryGetValue(val, out HashSet<RoomVolume> value)) { continue; } foreach (RoomVolume item in value) { if (!((Object)(object)item == (Object)null) && hashSet.Add(item)) { queue.Enqueue((item, num + 1)); } } } return -1; } private static List<RoomVolume> GetPlayerRooms(PlayerAvatar player) { List<RoomVolume> list = new List<RoomVolume>(); if ((Object)(object)player == (Object)null) { return list; } RoomVolumeCheck val = null; PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null) { val = playerDeathHead.roomVolumeCheck; } if ((Object)(object)val == (Object)null) { val = player.RoomVolumeCheck; } if ((Object)(object)val == (Object)null) { return list; } List<RoomVolume> currentRooms = val.CurrentRooms; if (currentRooms == null) { return list; } foreach (RoomVolume item2 in currentRooms) { if (item2 != null) { RoomVolume item = item2; if (true) { list.Add(item); } } } return list; } private static Dictionary<RoomVolume, HashSet<RoomVolume>> BuildRoomGraph(List<LevelPoint>? allLevelPoints) { Dictionary<RoomVolume, HashSet<RoomVolume>> dictionary = new Dictionary<RoomVolume, HashSet<RoomVolume>>(); if (allLevelPoints == null) { return dictionary; } foreach (LevelPoint allLevelPoint in allLevelPoints) { if ((Object)(object)allLevelPoint == (Object)null) { continue; } RoomVolume levelPointRoom = GetLevelPointRoom(allLevelPoint); if ((Object)(object)levelPointRoom == (Object)null) { continue; } if (!dictionary.ContainsKey(levelPointRoom)) { dictionary[levelPointRoom] = new HashSet<RoomVolume>(); } IEnumerable<LevelPoint> connectedPoints = GetConnectedPoints(allLevelPoint); if (connectedPoints == null) { continue; } foreach (LevelPoint item in connectedPoints) { if ((Object)(object)item == (Object)null) { continue; } RoomVolume levelPointRoom2 = GetLevelPointRoom(item); if (!((Object)(object)levelPointRoom2 == (Object)null)) { if (!dictionary.ContainsKey(levelPointRoom2)) { dictionary[levelPointRoom2] = new HashSet<RoomVolume>(); } if (levelPointRoom != levelPointRoom2) { dictionary[levelPointRoom].Add(levelPointRoom2); dictionary[levelPointRoom2].Add(levelPointRoom); } } } } return dictionary; } private static RoomVolume? GetLevelPointRoom(LevelPoint levelPoint) { return levelPoint.Room; } private static IEnumerable<LevelPoint>? GetConnectedPoints(LevelPoint levelPoint) { if ((Object)(object)levelPoint == (Object)null || levelPoint.ConnectedPoints == null) { return null; } List<LevelPoint> list = new List<LevelPoint>(); foreach (LevelPoint connectedPoint in levelPoint.ConnectedPoints) { if (connectedPoint != null) { LevelPoint item = connectedPoint; if (true) { list.Add(item); } } } return (list.Count > 0) ? list : null; } private static bool TryGetLevelPointPosition(LevelPoint? levelPoint, out Vector3 position) { //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_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) position = Vector3.zero; if ((Object)(object)levelPoint == (Object)null) { return false; } position = ((Component)levelPoint).transform.position; return true; } private static Vector3 GetPlayerWorldPosition(PlayerAvatar player) { //IL_000d: 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_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_0065: 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_004f: 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 ((Object)(object)player == (Object)null) { return Vector3.zero; } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null) { return ((Component)playerDeathHead).transform.position; } if ((Object)(object)player.playerTransform != (Object)null) { return player.playerTransform.position; } return ((Component)player).transform.position; } private static bool TryGetPlayerNavMeshPosition(PlayerAvatar player, Vector3 worldPosition, out Vector3 navMeshPosition) { //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_001f: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_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_0087: 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_0084: 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_0099: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) navMeshPosition = Vector3.zero; if ((Object)(object)player == (Object)null) { return false; } if (TrySamplePosition(worldPosition, 8f, out var navMeshPosition2)) { navMeshPosition = navMeshPosition2; return true; } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null) { Vector3 val = ((Component)playerDeathHead).transform.position; PhysGrabObject physGrabObject = playerDeathHead.physGrabObject; if ((Object)(object)physGrabObject != (Object)null) { val = physGrabObject.centerPoint; } if (TrySamplePosition(val, 12f, out navMeshPosition2) || TrySamplePosition(val - Vector3.up * 0.5f, 18f, out navMeshPosition2) || TrySamplePosition(val, 30f, out navMeshPosition2)) { navMeshPosition = navMeshPosition2; return true; } return false; } if (player.LastNavmeshPosition != Vector3.zero) { navMeshPosition = player.LastNavmeshPosition; return true; } return false; } private static bool TrySamplePosition(Vector3 worldPosition, float maxDistance, out Vector3 navMeshPosition) { //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_000c: 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_002a: Unknown result type (might be due to invalid IL or missing references) navMeshPosition = Vector3.zero; NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(worldPosition, ref val, maxDistance, -1)) { return false; } navMeshPosition = ((NavMeshHit)(ref val)).position; return true; } private static bool TryCalculatePathDistance(Vector3 from, Vector3 to, out float navMeshDistance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_000e: 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_004d: 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_0040: 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_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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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) navMeshDistance = 0f; NavMeshPath val = new NavMeshPath(); if (!NavMesh.CalculatePath(from, to, -1, val)) { return false; } Vector3[] corners = val.corners; if (corners == null || corners.Length == 0) { navMeshDistance = Vector3.Distance(from, to); return true; } Vector3 val2 = from; float num = 0f; Vector3[] array = corners; foreach (Vector3 val3 in array) { num += Vector3.Distance(val2, val3); val2 = val3; } navMeshDistance = num; return true; } } } namespace DHHFLastChanceMode.Modules.Gameplay.LastChance.UI { internal static class LastChanceMapIndicatorUI { internal static bool Show(Texture? texture, bool debugLogging) { return true; } internal static void SetYaw(float yawDegrees) { } internal static void Hide() { } } internal static class LastChanceTimerChangeEffectsModule { private static readonly Color PositiveDeltaColor = new Color(0.35f, 1f, 0.45f, 1f); private static readonly Color NegativeDeltaColor = new Color(1f, 0.35f, 0.35f, 1f); private static readonly Regex ColorTagRegex = new Regex("<color=#[0-9A-Fa-f]{6,8}>", RegexOptions.Compiled); private static TextMeshProUGUI? s_timerLabel; private static RectTransform? s_timerRect; private static TextMeshProUGUI? s_floatingLabel; private static RectTransform? s_floatingRect; private static float s_timerFontSize; private static bool s_initialized; private static string s_baseTimerText = string.Empty; private static string s_lastRenderedTimerText = string.Empty; private static Vector3 s_timerBaseScale = Vector3.one; private static float s_pulseRemainingSeconds; private static Color s_pulseColor = Color.white; private static float s_floatingRemainingSeconds; private static float s_floatingDropDistance; private static Color s_floatingBaseColor = Color.white; private static float PulseDurationSeconds => Mathf.Max(0.05f, InternalConfig.LastChanceTimerChangePulseDurationSeconds); internal static void Initialize(RectTransform? timerRect, TextMeshProUGUI? timerLabel, float timerFontSize) { //IL_002e: 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_0033: Unknown result type (might be due to invalid IL or missing references) s_timerRect = timerRect; s_timerLabel = timerLabel; s_timerFontSize = Mathf.Max(1f, timerFontSize); s_timerBaseScale = (((Object)(object)timerRect != (Object)null) ? ((Transform)timerRect).localScale : Vector3.one); s_baseTimerText = string.Empty; s_lastRenderedTimerText = string.Empty; EnsureFloatingLabel(); ResetVisualState(); s_initialized = (Object)(object)s_timerRect != (Object)null && (Object)(object)s_timerLabel != (Object)null; } internal static void OnBaseTimerTextUpdated(string text) { s_baseTimerText = text ?? string.Empty; if (s_pulseRemainingSeconds <= 0f) { RenderTimerText(s_baseTimerText); } } internal static void NotifyLocalDelta(float deltaSeconds) { TriggerDeltaEffect(deltaSeconds, Mathf.Max(0f, InternalConfig.LastChanceTimerChangeLocalDeltaMinSeconds)); } internal static void NotifyNetworkDelta(float deltaSeconds) { TriggerDeltaEffect(deltaSeconds, Mathf.Max(0f, InternalConfig.LastChanceTimerChangeNetworkDeltaMinSeconds)); } internal static void Tick() { if (s_initialized) { float unscaledDeltaTime = Time.unscaledDeltaTime; TickPulse(unscaledDeltaTime); TickFloating(unscaledDeltaTime); } } internal static void SetVisible(bool visible) { if (!visible) { ResetVisualState(); } } internal static void Reset() { //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_0065: 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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) s_initialized = false; s_timerLabel = null; s_timerRect = null; s_floatingLabel = null; s_floatingRect = null; s_timerFontSize = 0f; s_baseTimerText = string.Empty; s_lastRenderedTimerText = string.Empty; s_timerBaseScale = Vector3.one; s_pulseRemainingSeconds = 0f; s_floatingRemainingSeconds = 0f; s_floatingDropDistance = 0f; s_floatingBaseColor = Color.white; s_pulseColor = Color.white; } private static void TriggerDeltaEffect(float deltaSeconds, float minAbsSeconds) { //IL_0037: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_009e: 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) if (s_initialized && !(Mathf.Abs(deltaSeconds) < minAbsSeconds)) { s_pulseRemainingSeconds = PulseDurationSeconds; s_pulseColor = ((deltaSeconds > 0f) ? PositiveDeltaColor : NegativeDeltaColor); s_floatingRemainingSeconds = Mathf.Max(0.05f, InternalConfig.LastChanceTimerChangeFloatingDurationSeconds); s_floatingDropDistance = s_timerFontSize * Mathf.Max(0.1f, InternalConfig.LastChanceTimerChangeFloatingDropFontMultiplier); s_floatingBaseColor = s_pulseColor; if ((Object)(object)s_floatingRect != (Object)null) { s_floatingRect.anchoredPosition = Vector2.zero; ((Transform)s_floatingRect).localScale = Vector3.one; ((Transform)s_floatingRect).SetAsLastSibling(); } if ((Object)(object)s_floatingLabel != (Object)null) { int num = Mathf.Max(1, Mathf.RoundToInt(Mathf.Abs(deltaSeconds))); string text = ((deltaSeconds >= 0f) ? "+" : "-"); ((TMP_Text)s_floatingLabel).text = text + num; ((Graphic)s_floatingLabel).color = s_floatingBaseColor; ((Behaviour)s_floatingLabel).enabled = true; ((Component)s_floatingLabel).gameObject.SetActive(true); } } } private static void TickPulse(float dt) { //IL_00ac: 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_0033: 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) if ((Object)(object)s_timerRect == (Object)null) { return; } if (s_pulseRemainingSeconds <= 0f) { ((Transform)s_timerRect).localScale = s_timerBaseScale; RenderTimerText(s_baseTimerText); return; } s_pulseRemainingSeconds = Mathf.Max(0f, s_pulseRemainingSeconds - dt); float num = Mathf.Max(0.05f, InternalConfig.LastChanceTimerChangePulseDurationSeconds); float num2 = Mathf.Max(0.01f, InternalConfig.LastChanceTimerChangePulseScaleBoost); float num3 = 1f - s_pulseRemainingSeconds / num; float num4 = 1f + Mathf.Sin(num3 * (float)Math.PI) * num2; ((Transform)s_timerRect).localScale = s_timerBaseScale * num4; if (num4 > 1.02f) { RenderTimerText(ReplaceFirstColorTag(s_baseTimerText, s_pulseColor)); } else { RenderTimerText(s_baseTimerText); } } private static void TickFloating(float dt) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_floatingLabel == (Object)null || (Object)(object)s_floatingRect == (Object)null) { return; } if (s_floatingRemainingSeconds <= 0f) { Behaviour val = (Behaviour)(object)s_floatingLabel; if (val != null) { val.enabled = false; } ((Component)s_floatingLabel).gameObject.SetActive(false); } else { s_floatingRemainingSeconds = Mathf.Max(0f, s_floatingRemainingSeconds - dt); float num = Mathf.Max(0.05f, InternalConfig.LastChanceTimerChangeFloatingDurationSeconds); float num2 = 1f - s_floatingRemainingSeconds / num; float num3 = 0f - Mathf.Lerp(0f, s_floatingDropDistance, num2); s_floatingRect.anchoredPosition = new Vector2(0f, num3); Color color = s_floatingBaseColor; color.a = 1f - num2; ((Graphic)s_floatingLabel).color = color; } } private static void ResetVisualState() { //IL_002a: 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) s_pulseRemainingSeconds = 0f; s_floatingRemainingSeconds = 0f; if ((Object)(object)s_timerRect != (Object)null) { ((Transform)s_timerRect).localScale = s_timerBaseScale; } if ((Object)(object)s_floatingLabel != (Object)null) { ((Behaviour)s_floatingLabel).enabled = false; ((Component)s_floatingLabel).gameObject.SetActive(false); } if ((Object)(object)s_floatingRect != (Object)null) { s_floatingRect.anchoredPosition = Vector2.zero; } RenderTimerText(s_baseTimerText); } private static void EnsureFloatingLabel() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_008c: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)s_timerRect == (Object)null) && !((Object)(object)s_floatingLabel != (Object)null)) { GameObject val = new GameObject("LastChanceTimerDelta", new Type[1] { typeof(RectTransform) }); Transform parent = ((Transform)s_timerRect).parent; RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); val.transform.SetParent((Transform)(((Object)(object)val2 != (Object)null) ? ((object)val2) : ((object)s_timerRect)), false); s_floatingRect = val.GetComponent<RectTransform>(); s_floatingRect.anchorMin = new Vector2(0.5f, 0.5f); s_floatingRect.anchorMax = new Vector2(0.5f, 0.5f); s_floatingRect.pivot = new Vector2(0.5f, 0.5f); s_floatingRect.anchoredPosition = Vector2.zero; s_floatingRect.sizeDelta = new Vector2(240f, 40f); ((Transform)s_floatingRect).SetAsLastSibling(); s_floatingLabel = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)s_floatingLabel).alignment = (TextAlignmentOptions)514; float fontSize = s_timerFontSize * Mathf.Max(1f, InternalConfig.LastChanceTimerChangeFloatingFontSizeMultiplier); ((TMP_Text)s_floatingLabel).fontSize = fontSize; ((TMP_Text)s_floatingLabel).enableAutoSizing = false; ((TMP_Text)s_floatingLabel).enableWordWrapping = false; ((TMP_Text)s_floatingLabel).richText = false; ((Graphic)s_floatingLabel).color = Color.white; ((Behaviour)s_floatingLabel).enabled = false; ((Component)s_floatingLabel).gameObject.SetActive(false); } } private static void RenderTimerText(string text) { if (!((Object)(object)s_timerLabel == (Object)null) && !string.Equals(s_lastRenderedTimerText, text, StringComparison.Ordinal)) { s_lastRenderedTimerText = text; ((TMP_Text)s_timerLabel).text = text; } } private static string ReplaceFirstColorTag(string text, Color color) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(text)) { return text; } string text2 = "<color=#" + ColorUtility.ToHtmlStringRGB(color) + ">"; Match match = ColorTagRegex.Match(text); if (!match.Success) { return text; } return text.Substring(0, match.Index) + text2 + text.Substring(match.Index + match.Length); } } internal static class LastChanceTimerUI { private sealed class PlayerIconSlot { internal RectTransform? Root; internal Image? BaseImage; internal Image? SurrenderImage; internal Image? SafeImage; } private static readonly ManualLogSource Log = Logger.CreateLogSource("DHHFLastChanceMode.LastChance.TimerUI"); private const string SemibotWhiteFileName = "SemibotWhite.png"; private const string TruckWhiteFileName = "TruckWhite.png"; private const string SemibotSurrenderedFileName = "SemibotSurrendered.png"; private const string SemibotSafeFileName = "SemibotSafe.png"; private const int MaxPlayerIcons = 6; private const float TopPaddingFromCanvas = 8f; private const float DefaultTimerVerticalPosition = -8f; private const float SurrenderHintSpacing = 4f; private const float TimerFontSize = 14f; private const float SurrenderHintFontSize = 12f; private const float PlayerIconSize = 28f; private const float PlayerIconSpacing = 8f; private const float PlayerStatusOverlayScale = 0.75f; private const float TruckWidgetOffsetX = 165f; private const float TimerToSurrenderGap = 0.5f; private const float SurrenderToIconsGap = 4f; private const float TruckCounterOffsetY = -22f; private const float TruckCounterBadgeWidth = 74f; private const float TruckCounterBadgeHeight = 22f; private const float TruckCounterBadgeBorderThickness = 2f; private const float TruckCounterFontSize = 11f; private static readonly TextAlignmentOptions CenterAlignment = (TextAlignmentOptions)514; private static readonly TextAlignmentOptions TopAlignment = (TextAlignmentOptions)258; private static TextMeshProUGUI? s_label; private static RectTransform? s_rect; private static TextMeshProUGUI? s_hintLabel; private static RectTransform? s_hintRect; private static string s_defaultHintText = string.Empty; private static string s_lastTimerText = string.Empty; private static string s_lastHintText = string.Empty; private static bool s_isVisible; private static Transform? s_cachedUiParent; private static float s_nextVisibilityRefreshAt; private static RectTransform? s_playersRoot; private static readonly List<PlayerIconSlot> s_playerSlots = new List<PlayerIconSlot>(6); private static RectTransform? s_truckRoot; private static Image? s_truckIconImage; private static TextMeshProUGUI? s_truckCounterLabel; private static string s_lastTruckCounterText = string.Empty; private static Sprite? s_semibotWhiteSprite; private static Sprite? s_truckWhiteSprite; private static Sprite? s_semibotSurrenderedSprite; private static Sprite? s_semibotSafeSprite; private static bool s_assetLoadAttempted; private static float s_nextAssetRetryAt; private const float AssetRetryIntervalSeconds = 2f; private const float VisibilityRefreshIntervalSeconds = 0.5f; private const float AbilitySpotCacheRefreshIntervalSeconds = 0.5f; internal static void Show(string defaultHintText) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0094: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) s_defaultHintText = defaultHintText; if ((Object)(object)s_label != (Object)null) { ReparentToPreferredUiRoot(); EnsureSpritesLoaded(); RefreshVisibility(force: true); return; } Transform val = ResolvePreferredUiParent(); if (!((Object)(object)val == (Object)null)) { EnsureSpritesLoaded(); GameObject val2 = new GameObject("LastChanceTimer", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val, false); s_rect = val2.GetComponent<RectTransform>(); s_rect.anchorMin = new Vector2(0.5f, 1f); s_rect.anchorMax = new Vector2(0.5f, 1f); s_rect.pivot = new Vector2(0.5f, 1f); s_rect.anchoredPosition = new Vector2(0f, -8f); s_rect.sizeDelta = new Vector2(700f, 120f); s_label = val2.AddComponent<TextMeshProUGUI>(); SetDefaults(s_label); LastChanceTimerChangeEffectsModule.Initialize(s_rect, s_label, 14f); SetEnabled(enabled: false); GameObject val3 = new GameObject("LastChanceSurrenderHint", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val2.transform, false); s_hintRect = val3.GetComponent<RectTransform>(); if ((Object)(object)s_hintRect != (Object)null) { s_hintRect.anchorMin = new Vector2(0.5f, 1f); s_hintRect.anchorMax = new Vector2(0.5f, 1f); s_hintRect.pivot = new Vector2(0.5f, 1f); s_hintRect.sizeDelta = new Vector2(700f, 26f); s_hintRect.anchoredPosition = new Vector2(0f, GetSurrenderOffsetY()); } s_hintLabel = val3.AddComponent<TextMeshProUGUI>(); SetHintDefaults(s_hintLabel); s_lastHintText = string.Empty; SetSurrenderHintText(s_defaultHintText); CreatePlayerSlots(val2.transform); CreateTruckWidget(val2.transform); KeepAtTopPosition(); RefreshVisibility(force: true); } } internal static void Prewarm(string defaultHintText) { Show(defaultHintText); Hide(); ResetSurrenderHint(); } internal static void PrewarmAssets() { EnsureSpritesLoaded(); } internal static void DestroyUi() { try { Component val = (Component)(object)s_label; if (val != null && (Object)(object)val != (Object)null) { GameObject gameObject = val.gameObject; if ((Object)(object)gameObject != (Object)null) { Object.Destroy((Object)(object)gameObject); } } } catch { } s_label = null; s_rect = null; s_hintLabel = null; s_hintRect = null; s_lastTimerText = string.Empty; s_lastHintText = string.Empty; s_isVisible = false; s_cachedUiParent = null; s_playersRoot = null; s_playerSlots.Clear(); s_truckRoot = null; s_truckIconImage = null; s_truckCounterLabel = null; s_lastTruckCounterText = string.Empty; AbilitySpotDiscoveryCache.Invalidate(); LastChanceTimerChangeEffectsModule.Reset(); } internal static void UpdateText(string text) { if (!((Object)(object)s_label == (Object)null)) { RefreshVisibility(force: false); LastChanceTimerChangeEffectsModule.OnBaseTimerTextUpdated(text); LastChanceTimerChangeEffectsModule.Tick(); if (!string.Equals(s_lastTimerText, text, StringComparison.Ordinal)) { s_lastTimerText = text; } } } internal static void NotifyTimerDelta(float deltaSeconds, bool isNetworkSync = false) { if (!((Object)(object)s_label == (Object)null)) { if (isNetworkSync) { LastChanceTimerChangeEffectsModule.NotifyNetworkDelta(deltaSeconds); } else { LastChanceTimerChangeEffectsModule.NotifyLocalDelta(deltaSeconds); } } } internal static void UpdatePlayerStates(IReadOnlyList<PlayerStateExtractionHelper.PlayerStateSnapshot> snapshots, int requiredOnTruck) { //IL_0169: 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_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_label == (Object)null || (Object)(object)s_playersRoot == (Object)null) { return; } EnsureSpritesLoaded(); int num = Mathf.Min(6, snapshots?.Count ?? 0); float num2 = ((num <= 0) ? 0f : ((float)num * 28f + (float)(num - 1) * 8f)); float num3 = -0.5f * num2 + 14f; int num4 = 0; if (snapshots != null) { for (int i = 0; i < snapshots.Count; i++) { if (!snapshots[i].IsSurrendered && snapshots[i].IsInTruck) { num4++; } } } UpdateTruckCounter(num4, Mathf.Max(1, requiredOnTruck)); for (int j = 0; j < s_playerSlots.Count; j++) { PlayerIconSlot playerIconSlot = s_playerSlots[j]; if (!((Object)(object)playerIconSlot.Root == (Object)null)) { if (j >= num || snapshots == null) { ((Component)playerIconSlot.Root).gameObject.SetActive(false); continue; } PlayerStateExtractionHelper.PlayerStateSnapshot playerStateSnapshot = snapshots[j]; ((Component)playerIconSlot.Root).gameObject.SetActive(true); playerIconSlot.Root.anchoredPosition = new Vector2(num3 + (float)j * 36f, 0f); SetImage(playerIconSlot.BaseImage, s_semibotWhiteSprite, playerStateSnapshot.Color, enabled: true); SetImage(playerIconSlot.SafeImage, s_semibotSafeSprite, Color.white, !playerStateSnapshot.IsSurrendered && playerStateSnapshot.IsInTruck); SetImage(playerIconSlot.SurrenderImage, s_semibotSurrenderedSprite, Color.white, playerStateSnapshot.IsSurrendered); } } } internal static void Hide() { if (!((Object)(object)s_label == (Object)null)) { SetEnabled(enabled: false); LastChanceTimerChangeEffectsModule.SetVisible(visible: false); } } internal static void SetSurrenderHintText(string text) { if (!((Object)(object)s_hintLabel == (Object)null) && !string.Equals(s_lastHintText, text, StringComparison.Ordinal)) { s_lastHintText = text; ((TMP_Text)s_hintLabel).text = text; } } internal static void ResetSurrenderHint() { SetSurrenderHintText(s_defaultHintText); } private static void CreatePlayerSlots(Transform parent) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LastChancePlayersRow", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); s_playersRoot = val.GetComponent<RectTransform>(); if ((Object)(object)s_playersRoot != (Object)null) { s_playersRoot.anchorMin = new Vector2(0.5f, 1f); s_playersRoot.anchorMax = new Vector2(0.5f, 1f); s_playersRoot.pivot = new Vector2(0.5f, 1f); s_playersRoot.anchoredPosition = new Vector2(0f, GetPlayerIconsOffsetY()); s_playersRoot.sizeDelta = new Vector2(500f, 36f); } s_playerSlots.Clear(); for (int i = 0; i < 6; i++) { GameObject val2 = new GameObject($"PlayerSlot.{i}", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(28f, 28f); Image baseImage = AddImageComponent(val2); GameObject val3 = new GameObject("Safe", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val2.transform, false); RectTransform component2 = val3.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0.5f); component2.anchorMax = new Vector2(0.5f, 0.5f); component2.pivot = new Vector2(0.5f, 0.5f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = Vector2.one * 21f; Image safeImage = AddImageComponent(val3); GameObject val4 = new GameObject("Surrendered", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val2.transform, false); RectTransform component3 = val4.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.5f, 0.5f); component3.anchorMax = new Vector2(0.5f, 0.5f); component3.pivot = new Vector2(0.5f, 0.5f); component3.anchoredPosition = Vector2.zero; component3.sizeDelta = Vector2.one * 21f; Image surrenderImage = AddImageComponent(val4); val2.SetActive(false); s_playerSlots.Add(new PlayerIconSlot { Root = component, BaseImage = baseImage, SafeImage = safeImage, SurrenderImage = surrenderImage }); } } private static void CreateTruckWidget(Transform parent) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_0074: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LastChanceTruckCounter", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); s_truckRoot = val.GetComponent<RectTransform>(); if ((Object)(object)s_truckRoot != (Object)null) { s_truckRoot.anchorMin = new Vector2(0.5f, 1f); s_truckRoot.anchorMax = new Vector2(0.5f, 1f); s_truckRoot.pivot = new Vector2(0.5f, 1f); s_truckRoot.anchoredPosition = new Vector2(165f, -1f); s_truckRoot.sizeDelta = new Vector2(64f, 56f); } GameObject val2 = new GameObject("TruckIcon", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, 0f); component.sizeDelta = new Vector2(26f, 26f); s_truckIconImage = AddImageComponent(val2); CreateTruckCounterBadge(val.transform); SetTruckCounterText("00 / 00"); } private static void UpdateTruckCounter(int onTruck, int required) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_truckIconImage != (Object)null) { SetImage(s_truckIconImage, s_truckWhiteSprite, Color.white, enabled: true); } SetTruckCounterText($"{Mathf.Clamp(onTruck, 0, 99):00} / {Mathf.Clamp(required, 0, 99):00}"); } private static void SetTruckCounterText(string text) { if (!((Object)(object)s_truckCounterLabel == (Object)null) && !string.Equals(s_lastTruckCounterText, text, StringComparison.Ordinal)) { s_lastTruckCounterText = text; ((TMP_Text)s_truckCounterLabel).text = text; ((Behaviour)s_truckCounterLabel).enabled = true; ((Component)s_truckCounterLabel).gameObject.SetActive(true); } } private static void CreateTruckCounterBadge(Transform parent) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_003f: 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_006b: 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_0097: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("TruckCounterBadgeOuter", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -22f); component.sizeDelta = new Vector2(74f, 22f); Image image = AddImageComponent(val); SetImage(image, null, new Color(1f, 0.84f, 0.12f, 1f), enabled: true); GameObject val2 = new GameObject("TruckCounterBadgeInner", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0.5f); component2.anchorMax = new Vector2(0.5f, 0.5f); component2.pivot = new Vector2(0.5f, 0.5f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = new Vector2(Mathf.Max(1f, 70f), Mathf.Max(1f, 18f)); Image image2 = AddImageComponent(val2); SetImage(image2, null, new Color(0f, 0f, 0f, 0.55f), enabled: true); GameObject val3 = new GameObject("TruckCounterText", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val2.transform, false); RectTransform component3 = val3.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(1f, 1f); component3.pivot = new Vector2(0.5f, 0.5f); component3.anchoredPosition = Vector2.zero; component3.sizeDelta = Vector2.zero; s_truckCounterLabel = val3.AddComponent<TextMeshProUGUI>(); SetHintDefaults(s_truckCounterLabel); ((TMP_Text)s_truckCounterLabel).fontSize = 11f; ((Graphic)s_truckCounterLabel).color = new Color(1f, 0.92f, 0.3f, 1f); } private static Image? AddImageComponent(GameObject go) { return go.AddComponent<Image>(); } private static void SetImage(Image? image, Sprite? sprite, Color color, bool enabled) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)image == (Object)null)) { image.sprite = sprite; ((Graphic)image).color = color; image.preserveAspect = true; ((Behaviour)image).enabled = enabled; ((Component)image).gameObject.SetActive(enabled); } } private static void EnsureSpritesLoaded() { if (HasAllSprites()) { return; } float unscaledTime = Time.unscaledTime; if (!s_assetLoadAttempted || !(unscaledTime < s_nextAssetRetryAt)) { s_assetLoadAttempted = true; s_nextAssetRetryAt = unscaledTime + 2f; string defaultAssetsDirectory = ImageAssetLoader.GetDefaultAssetsDirectory(); string resolvedPath; if ((Object)(object)s_semibotWhiteSprite == (Object)null) { ImageAssetLoader.TryLoadSprite("SemibotWhite.png", defaultAssetsDirectory, out s_semibotWhiteSprite, out resolvedPath); } if ((Object)(object)s_truckWhiteSprite == (Object)null) { ImageAssetLoader.TryLoadSprite("TruckWhite.png", defaultAssetsDirectory, out s_truckWhiteSprite, out resolvedPath); } if ((Object)(object)s_semibotSurrenderedSprite == (Object)null) { ImageAssetLoader.TryLoadSprite("SemibotSurrendered.png", defaultAssetsDirectory, out s_semibotSurrenderedSprite, out resolvedPath); } if ((Object)(object)s_semibotSafeSprite == (Object)null) { ImageAssetLoader.TryLoadSprite("SemibotSafe.png", defaultAssetsDirectory, out s_semibotSafeSprite, out resolvedPath); } if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("LastChance.UI.Sprites", 30)) { Log.LogDebug((object)($"[LastChance] UI sprites status: semibot={(Object)(object)s_semibotWhiteSprite != (Object)null} truck={(Object)(object)s_truckWhiteSprite != (Object)null} " + $"surrendered={(Object)(object)s_semibotSurrenderedSprite != (Object)null} safe={(Object)(object)s_semibotSafeSprite != (Object)null}")); } } } private static bool HasAllSprites() { return (Object)(object)s_semibotWhiteSprite != (Object)null && (Object)(object)s_truckWhiteSprite != (Object)null && (Object)(object)s_semibotSurrenderedSprite != (Object)null && (Object)(object)s_semibotSafeSprite != (Object)null; } private static void RefreshVisibility(bool force) { if (force || !(Time.unscaledTime < s_nextVisibilityRefreshAt)) { s_nextVisibilityRefreshAt = Time.unscaledTime + 0.5f; KeepAtTopPosition(); UpdateSurrenderHintPosition(); SetEnabled(ShouldBeVisibleNow()); } } private static void KeepAtTopPosition() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)s_rect == (Object)null)) { Vector2 anchoredPosition = s_rect.anchoredPosition; if (!(Mathf.Abs(anchoredPosition.y - -8f) <= 0.01f)) { s_rect.anchoredPosition = new Vector2(anchoredPosition.x, -8f); } } } private static void UpdateSurrenderHintPosition() { //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_0037: 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_005c: 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_0084: 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_00af: 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) if ((Object)(object)s_rect == (Object)null || (Object)(object)s_hintRect == (Object)null) { return; } float surrenderOffsetY = GetSurrenderOffsetY(); Vector2 anchoredPosition = s_hintRect.anchoredPosition; if (Mathf.Abs(anchoredPosition.y - surrenderOffsetY) > 0.01f) { s_hintRect.anchoredPosition = new Vector2(anchoredPosition.x, surrenderOffsetY); } if ((Object)(object)s_playersRoot != (Object)null) { Vector2 anchoredPosition2 = s_playersRoot.anchoredPosition; float playerIconsOffsetY = GetPlayerIconsOffsetY(); if (Mathf.Abs(anchoredPosition2.y - playerIconsOffsetY) > 0.01f) { s_playersRoot.anchoredPosition = new Vector2(anchoredPosition2.x, playerIconsOffsetY); } } } private static float GetSurrenderOffsetY() { return -14.5f; } private static float GetPlayerIconsOffsetY() { return GetSurrenderOffsetY() - 16f; } private static bool ShouldBeVisibleNow() { if (!LastChanceTimerController.IsActive) { return false; } if ((Object)(object)GetPreferredUiParentCached() == (Object)null) { return false; } if ((Object)(object)MenuManager.instance != (Object)null && (Object)(object)MenuManager.instance.currentMenuPage != (Object)null) { return false; } return true; } private static void ReparentToPreferredUiRoot() { Component val = (Component)(object)s_label; if (val != null) { Transform preferredUiParentCached = GetPreferredUiParentCached(); if (!((Object)(object)preferredUiParentCached