Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DHHFLastChanceMode v0.1.3
plugins\DHHFLastChanceMode.dll
Decompiled 2 weeks 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