Decompiled source of DHHFLastChanceMode v0.1.2

plugins\DHHFLastChanceMode.dll

Decompiled a day ago
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