Decompiled source of Nitronic HUD v1.0.0

Distance.NitronicHUD.dll

Decompiled a day ago
using System;
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.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Distance.NitronicHUD.Data;
using Distance.NitronicHUD.Scripts;
using Events;
using Events.Game;
using Events.GameMode;
using Events.Level;
using Events.LevelEditor;
using Events.RaceEnd;
using Events.Scene;
using HarmonyLib;
using Reactor.API.Configuration;
using UnityEngine;
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: AssemblyTitle("Distance.ModTemplate")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Distance.ModTemplate")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7bcb2908-b003-45d9-be68-50cba5217603")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Distance.NitronicHUD
{
	public class Assets
	{
		private string _filePath = null;

		private string RootDirectory { get; }

		private string FileName { get; set; }

		private string FilePath => _filePath ?? Path.Combine(Path.Combine(RootDirectory, "Assets"), FileName);

		public object Bundle { get; private set; }

		private Assets()
		{
		}

		public Assets(string fileName, bool fromRootDirectory)
		{
			RootDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
			FileName = fileName;
			string text = Path.Combine(RootDirectory, FileName);
			if (fromRootDirectory)
			{
				if (!File.Exists(text))
				{
					Mod.Log.LogInfo((object)("Couldn't find requested asset bundle at " + text));
					return;
				}
			}
			else if (!File.Exists(FilePath))
			{
				Mod.Log.LogInfo((object)("Couldn't find requested asset bundle at " + FilePath));
				return;
			}
			if (fromRootDirectory)
			{
				Bundle = Load(text);
			}
			else
			{
				Bundle = Load();
			}
		}

		public static Assets FromUnsafePath(string filePath)
		{
			if (!File.Exists(filePath))
			{
				Mod.Log.LogInfo((object)("Could not find requested asset bundle at " + filePath));
				return null;
			}
			Assets assets = new Assets
			{
				_filePath = filePath,
				FileName = Path.GetFileName(filePath)
			};
			assets.Bundle = assets.Load();
			if (assets.Bundle == null)
			{
				return null;
			}
			return assets;
		}

		private object Load()
		{
			try
			{
				object result = AssetBundleBridge.LoadFrom(FilePath);
				Mod.Log.LogInfo((object)("Loaded asset bundle " + FilePath));
				return result;
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)ex);
				return null;
			}
		}

		private object Load(string filePath)
		{
			try
			{
				object result = AssetBundleBridge.LoadFrom(filePath);
				Mod.Log.LogInfo((object)("Loaded asset bundle " + filePath));
				return result;
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Could not load asset bundle " + filePath));
				Mod.Log.LogInfo((object)ex);
				return null;
			}
		}
	}
	internal static class AssetBundleBridge
	{
		public static Type AssetBundleType => Kernel.FindTypeByFullName("UnityEngine.AssetBundle", "UnityEngine");

		private static MethodInfo LoadFromFile => AssetBundleType.GetMethod("LoadFromFile", new Type[1] { typeof(string) });

		public static object LoadFrom(string path)
		{
			MethodInfo loadFromFile = LoadFromFile;
			object[] parameters = new string[1] { path };
			return loadFromFile.Invoke(null, parameters);
		}
	}
	internal static class Kernel
	{
		internal static Type FindTypeByFullName(string fullName, string assemblyFilter)
		{
			IEnumerable<Assembly> enumerable = from a in AppDomain.CurrentDomain.GetAssemblies()
				where a.GetName().Name.Contains(assemblyFilter)
				select a;
			foreach (Assembly item in enumerable)
			{
				Type type = item.GetTypes().FirstOrDefault((Type t) => t.FullName == fullName);
				if ((object)type == null)
				{
					continue;
				}
				return type;
			}
			Mod.Log.LogInfo((object)("Type " + fullName + " wasn't found in the main AppDomain at this moment."));
			throw new Exception("Type " + fullName + " wasn't found in the main AppDomain at this moment.");
		}
	}
	public class ConfigurationLogic : MonoBehaviour
	{
		internal Settings Config;

		public bool DisplayHeatMeters
		{
			get
			{
				return Get("DisplayHeatMeters", @default: false);
			}
			set
			{
				Set("DisplayHeatMeters", value);
			}
		}

		public bool DisplayCountdown
		{
			get
			{
				return Get("DisplayCountdown", @default: false);
			}
			set
			{
				Set("DisplayCountdown", value);
			}
		}

		public bool DisplayTimer
		{
			get
			{
				return Get("DisplayTimer", @default: false);
			}
			set
			{
				Set("DisplayTimer", value);
			}
		}

		public bool AnnouncerCountdown
		{
			get
			{
				return Get("AnnouncerCountdown", @default: false);
			}
			set
			{
				Set("AnnouncerCountdown", value);
			}
		}

		public float HeatMetersScale
		{
			get
			{
				return Get("HeatMetersScale", 0f);
			}
			set
			{
				Set("HeatMetersScale", value);
			}
		}

		public int HeatMetersHorizontalOffset
		{
			get
			{
				return Get("HeatMetersHorizontalOffset", 0);
			}
			set
			{
				Set("HeatMetersHorizontalOffset", value);
			}
		}

		public int HeatMetersVerticalOffset
		{
			get
			{
				return Get("HeatMetersVerticalOffset", 0);
			}
			set
			{
				Set("HeatMetersVerticalOffset", value);
			}
		}

		public float TimerScale
		{
			get
			{
				return Get("TimerScale", 0f);
			}
			set
			{
				Set("TimerScale", value);
			}
		}

		public int TimerVerticalOffset
		{
			get
			{
				return Get("TimerVerticalOffset", 0);
			}
			set
			{
				Set("TimerVerticalOffset", value);
			}
		}

		public float HeatBlinkStartAmount
		{
			get
			{
				return Get("HeatBlinkStartAmount", 0f);
			}
			set
			{
				Set("HeatBlinkStartAmount", value);
			}
		}

		public float HeatBlinkFrequence
		{
			get
			{
				return Get("HeatBlinkFrequence", 0f);
			}
			set
			{
				Set("HeatBlinkFrequence", value);
			}
		}

		public float HeatBlinkFrequenceBoost
		{
			get
			{
				return Get("HeatBlinkFrequenceBoost", 0f);
			}
			set
			{
				Set("HeatBlinkFrequenceBoost", value);
			}
		}

		public float HeatBlinkAmount
		{
			get
			{
				return Get("HeatBlinkAmount", 0f);
			}
			set
			{
				Set("HeatBlinkAmount", value);
			}
		}

		public float HeatFlameAmount
		{
			get
			{
				return Get("HeatFlameAmount", 0f);
			}
			set
			{
				Set("HeatFlameAmount", value);
			}
		}

		public event Action<ConfigurationLogic> OnChanged;

		private void Load()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Config = new Settings("Config");
		}

		public void Awake()
		{
			Load();
			Get("DisplayHeatMeters", @default: true);
			Get("DisplayCountdown", @default: true);
			Get("DisplayTimer", @default: true);
			Get("AnnouncerCountdown", @default: true);
			Get("HeatMetersScale", 1f);
			Get("HeatMetersHorizontalOffset", 0);
			Get("HeatMetersVerticalOffset", 0);
			Get("TimerScale", 1f);
			Get("TimerVerticalOffset", 0);
			Get("HeatBlinkStartAmount", 0.7f);
			Get("HeatBlinkFrequence", 2f);
			Get("HeatBlinkFrequenceBoost", 1.15f);
			Get("HeatBlinkAmount", 0.7f);
			Get("HeatFlameAmount", 0.5f);
			Save();
		}

		public T Get<T>(string key, T @default = default(T))
		{
			return ((Section)Config).GetOrCreate<T>(key, @default);
		}

		public void Set<T>(string key, T value)
		{
			((Section)Config)[key] = value;
			Save();
		}

		public void Save()
		{
			Settings config = Config;
			if (config != null)
			{
				config.Save(true);
			}
			this.OnChanged?.Invoke(this);
		}
	}
	[BepInPlugin("Distance.NitronicHUD", "Nitronic HUD", "1.0.0")]
	public sealed class Mod : BaseUnityPlugin
	{
		private const string modGUID = "Distance.NitronicHUD";

		private const string modName = "Nitronic HUD";

		private const string modVersion = "1.0.0";

		public static string DisplayHeatMeterKey = "Display Heat Meter";

		public static string DisplayCountdownKey = "Display Countdown";

		public static string DisplayTimerKey = "Display Timer";

		public static string AnnouncerCountdownKey = "Display Countdown";

		public static string HeatMeterScaleKey = "Overheat Scale";

		public static string HeatMeterHorizontalKey = "Overheat HOffset";

		public static string HeatMeterVerticalKey = "Overheat VOffset";

		public static string TimerScaleKey = "Timer Scale";

		public static string TimerVeritcalKey = "Timer VOffset";

		public static string HeatBlinkStartAmountKey = "Blink Start";

		public static string HeatBlinkFrequencyKey = "Blink Frequency";

		public static string HeatBlinkFrequencyBoostKey = "Blink Freq Boost";

		public static string HeatBlinkAmountKey = "Heat Blink Amount";

		public static string HeatFlameAmountKey = "Heat Flame Amount";

		private static readonly Harmony harmony = new Harmony("Distance.NitronicHUD");

		public static ManualLogSource Log = new ManualLogSource("Nitronic HUD");

		public static Mod Instance;

		public static ConfigEntry<bool> DisplayHeatMeter { get; set; }

		public static ConfigEntry<bool> DisplayCountdown { get; set; }

		public static ConfigEntry<bool> DisplayTimer { get; set; }

		public static ConfigEntry<float> HeatMeterScale { get; set; }

		public static ConfigEntry<int> HeatMetersHorizontalOffset { get; set; }

		public static ConfigEntry<int> HeatMetersVerticalOffset { get; set; }

		public static ConfigEntry<float> TimerScale { get; set; }

		public static ConfigEntry<int> TimerVerticalOffset { get; set; }

		public static ConfigEntry<float> HeatBlinkStartAmount { get; set; }

		public static ConfigEntry<float> HeatBlinkFrequency { get; set; }

		public static ConfigEntry<float> HeatBlinkFrequencyBoost { get; set; }

		public static ConfigEntry<float> HeatBlinkAmount { get; set; }

		public static ConfigEntry<float> HeatFlameAmount { get; set; }

		public MonoBehaviour[] Scripts { get; set; }

		public void Awake()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Expected O, but got Unknown
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Expected O, but got Unknown
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Expected O, but got Unknown
			Object.DontDestroyOnLoad((Object)(object)this);
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Log = Logger.CreateLogSource("Distance.NitronicHUD");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Thanks for using Nitronic HUD!");
			DisplayCountdown = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface Options", DisplayCountdownKey, true, new ConfigDescription("Displays the 3... 2... 1... RUSH countdown when playing a level.", (AcceptableValueBase)null, new object[0]));
			DisplayHeatMeter = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface Options", DisplayHeatMeterKey, true, new ConfigDescription("Displays overheat indicator bars in the lower screen corners.", (AcceptableValueBase)null, new object[0]));
			DisplayTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface Options", DisplayTimerKey, true, new ConfigDescription("Displays the timer at the bottom of the screen.", (AcceptableValueBase)null, new object[0]));
			HeatMeterScale = ((BaseUnityPlugin)this).Config.Bind<float>("Interface Options", HeatMeterScaleKey, 20f, new ConfigDescription("Set the size of the overheat bars.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[0]));
			HeatMetersHorizontalOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Interface Options", HeatMeterHorizontalKey, 0, new ConfigDescription("Set the horizontal position offset of the overheat bars.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-200, 200), new object[0]));
			HeatMetersVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Interface Options", HeatMeterVerticalKey, 0, new ConfigDescription("Set the vertical position offset of the overheat bars.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-100, 100), new object[0]));
			TimerScale = ((BaseUnityPlugin)this).Config.Bind<float>("Interface Options", TimerScaleKey, 20f, new ConfigDescription("Set the size of the timer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[0]));
			TimerVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Interface Options", TimerVeritcalKey, 0, new ConfigDescription("Set the vertical position of the timer.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-100, 100), new object[0]));
			HeatBlinkStartAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced Interface Options", HeatBlinkStartAmountKey, 0.7f, new ConfigDescription("Set the heat threshold after which the hud starts to blink.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
			HeatBlinkFrequency = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced Interface Options", HeatBlinkFrequencyKey, 2f, new ConfigDescription("Set the hud blink rate (per second).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[0]));
			HeatBlinkFrequencyBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced Interface Options", HeatBlinkFrequencyBoostKey, 1.15f, new ConfigDescription("Sets the blink rate boost.\nThe blink rate at 100% heat is the blink rate times this value (set this to 1 to keep the rate constant).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[0]));
			HeatBlinkAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced Interface Options", HeatBlinkAmountKey, 0.7f, new ConfigDescription("Sets the color intensity of the overheat blink animation (lower values means smaller color changes).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
			HeatFlameAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced Interface Options", HeatFlameAmountKey, 0.5f, new ConfigDescription("Sets the color intensity of the overheat flame animation (lower values means smaller color changes).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading...");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded!");
		}

		public void OnEnable()
		{
			Flags.SubscribeEvents();
		}

		public void OnDisable()
		{
			Flags.UnsubscribeEvents();
		}

		public void LateInitialize()
		{
			Scripts = (MonoBehaviour[])(object)new MonoBehaviour[2]
			{
				((Component)this).gameObject.AddComponent<VisualCountdown>(),
				((Component)this).gameObject.AddComponent<VisualDisplay>()
			};
		}
	}
	public static class Flags
	{
		public static bool IsModeStarted { get; private set; }

		public static bool IsPaused { get; private set; }

		public static bool IsMenuOpen
		{
			get
			{
				MenuPanelManager menuPanelManager_ = G.Sys.MenuPanelManager_;
				return menuPanelManager_ != null && menuPanelManager_.panelStack_?.Count > 0;
			}
		}

		public static bool IsLoading => (int)G.Sys.GameManager_.BlackFade_.currentState_ != 0 && !G.Sys.GameManager_.IsLevelLoaded_;

		public static bool IsReplayMode => G.Sys.ReplayManager_.IsReplayMode_;

		public static GameModeID[] NonPlayModeIDS { get; }

		public static bool CurrentModeIsPlayable => !NonPlayModeIDS.Contains(G.Sys.GameManager_.ModeID_);

		public static bool CanDisplayHudElements => IsModeStarted && !IsLoading && CurrentModeIsPlayable && !IsPaused && !IsMenuOpen && !IsReplayMode;

		static Flags()
		{
			NonPlayModeIDS = (GameModeID[])(object)new GameModeID[3]
			{
				(GameModeID)17,
				(GameModeID)13,
				default(GameModeID)
			};
		}

		internal static void SubscribeEvents()
		{
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnGamePauseToggled);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnGameModeInitialized);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnGameModeModeStarted);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnRaceEndLocalCarHitFinish);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnLevelEditorEnterPlayMode);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnLevelEditorEnterEditorMode);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnLevelUninitializeOptimizations);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnSceneChanged);
		}

		internal static void UnsubscribeEvents()
		{
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnGamePauseToggled);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnGameModeInitialized);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnGameModeModeStarted);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnRaceEndLocalCarHitFinish);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnLevelEditorEnterPlayMode);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnLevelEditorEnterEditorMode);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnLevelUninitializeOptimizations);
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnSceneChanged);
		}

		private static void OnLevelUninitializeOptimizations(Data data)
		{
			IsModeStarted = false;
		}

		private static void OnGameModeModeStarted(Data data)
		{
			IsPaused = false;
			IsModeStarted = true;
		}

		private static void OnLevelEditorEnterEditorMode(Data data)
		{
			IsPaused = false;
			IsModeStarted = false;
		}

		private static void OnLevelEditorEnterPlayMode(Data data)
		{
			IsModeStarted = true;
		}

		private static void OnRaceEndLocalCarHitFinish(Data data)
		{
			IsModeStarted = false;
		}

		private static void OnGameModeInitialized(Data data)
		{
			IsPaused = false;
		}

		private static void OnGamePauseToggled(Data data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			IsPaused = data.paused_;
		}

		private static void OnSceneChanged(Data data)
		{
			IsModeStarted = false;
		}
	}
	internal static class Utilities
	{
		internal static GameObject FindLocalCar()
		{
			PlayerManager playerManager_ = G.Sys.PlayerManager_;
			object result;
			if (playerManager_ == null)
			{
				result = null;
			}
			else
			{
				LocalPlayer current_ = playerManager_.Current_;
				if (current_ == null)
				{
					result = null;
				}
				else
				{
					PlayerDataLocal playerData_ = current_.playerData_;
					result = ((playerData_ != null) ? ((PlayerDataBase)playerData_).Car_ : null);
				}
			}
			return (GameObject)result;
		}

		internal static CarLogic FindLocalCarLogic()
		{
			PlayerManager playerManager_ = G.Sys.PlayerManager_;
			object result;
			if (playerManager_ == null)
			{
				result = null;
			}
			else
			{
				LocalPlayer current_ = playerManager_.Current_;
				if (current_ == null)
				{
					result = null;
				}
				else
				{
					PlayerDataLocal playerData_ = current_.playerData_;
					result = ((playerData_ != null) ? ((PlayerDataBase)playerData_).CarLogic_ : null);
				}
			}
			return (CarLogic)result;
		}

		internal static CarScreenLogic FindLocalVehicleScreen()
		{
			PlayerManager playerManager_ = G.Sys.PlayerManager_;
			object obj;
			if (playerManager_ == null)
			{
				obj = null;
			}
			else
			{
				LocalPlayer current_ = playerManager_.Current_;
				if (current_ == null)
				{
					obj = null;
				}
				else
				{
					PlayerDataLocal playerData_ = current_.playerData_;
					obj = ((playerData_ != null) ? ((PlayerDataBase)playerData_).CarScreenLogic_ : null);
				}
			}
			CarScreenLogic val = (CarScreenLogic)obj;
			if (val != null && val.CarLogic_.IsLocalCar_)
			{
				return val;
			}
			return null;
		}
	}
	public static class Vehicle
	{
		public static CarStats CarStats => Utilities.FindLocalVehicleScreen().CarLogic_.CarStats_;

		private static CarLogic CarLogic { get; set; }

		public static float HeatLevel
		{
			get
			{
				UpdateObjectReferences();
				if (Object.op_Implicit((Object)(object)CarLogic))
				{
					return CarLogic.Heat_;
				}
				return 0f;
			}
		}

		public static float VelocityKPH
		{
			get
			{
				UpdateObjectReferences();
				if (Object.op_Implicit((Object)(object)CarLogic))
				{
					return CarLogic.CarStats_.GetKilometersPerHour();
				}
				return 0f;
			}
		}

		public static float VelocityMPH
		{
			get
			{
				UpdateObjectReferences();
				if (Object.op_Implicit((Object)(object)CarLogic))
				{
					return CarLogic.CarStats_.GetMilesPerHour();
				}
				return 0f;
			}
		}

		private static void UpdateObjectReferences()
		{
			GameObject obj = Utilities.FindLocalCar();
			CarLogic = ((obj != null) ? obj.GetComponent<CarLogic>() : null) ?? Utilities.FindLocalCarLogic();
		}
	}
}
namespace Distance.NitronicHUD.Scripts
{
	public class VisualCountdown : MonoBehaviour
	{
		public const string AssetName = "Assets/Prefabs/NitronicCountdownHUD.prefab";

		private KeyValuePair<Image, VisualCountdownDigit>[] digits_;

		public Assets Assets { get; internal set; }

		public AssetBundle Bundle
		{
			get
			{
				object bundle = Assets.Bundle;
				return (AssetBundle)((bundle is AssetBundle) ? bundle : null);
			}
		}

		private GameObject Prefab { get; set; }

		public void Awake()
		{
			CreatePrefab();
			InitializeDigits();
			SubscribeEvents();
		}

		private void CreatePrefab(bool loadBundle = true)
		{
			if (loadBundle)
			{
				Assets = new Assets("countdown.assets", fromRootDirectory: true);
			}
			if (!Object.op_Implicit((Object)(object)Bundle))
			{
				Mod.Log.LogInfo((object)"The following assets file could not be loaded: countdown.assets");
				Object.DestroyImmediate((Object)(object)this);
				return;
			}
			Prefab = Object.Instantiate<GameObject>(Bundle.LoadAsset<GameObject>("Assets/Prefabs/NitronicCountdownHUD.prefab"), ((Component)this).transform);
			if (!Object.op_Implicit((Object)(object)Prefab))
			{
				Mod.Log.LogInfo((object)"The following asset from the countdown.assets could not be loaded: \"Assets/Prefabs/NitronicCountdownHUD.prefab\"");
				Object.DestroyImmediate((Object)(object)this);
			}
			else
			{
				((Object)Prefab).name = "Visual Countdown";
			}
		}

		private void InitializeDigits()
		{
			digits_ = new KeyValuePair<Image, VisualCountdownDigit>[4];
			GameObject[] children = GameObjectEx.GetChildren(Prefab);
			foreach (GameObject val in children)
			{
				Image component = val.GetComponent<Image>();
				int result = 0;
				VisualCountdownDigit value = ((((Object)val).name.Length < 4 || !int.TryParse(((Object)val).name.Substring(3), out result)) ? new VisualCountdownDigit(0f, 1f) : new VisualCountdownDigit(-result, 0.75f));
				digits_[result] = new KeyValuePair<Image, VisualCountdownDigit>(component, value);
			}
		}

		private void SubscribeEvents()
		{
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnPauseToggled);
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnModeInitialized);
		}

		private void OnPauseToggled(Data data)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Prefab.SetActive(!data.paused_);
		}

		private void OnModeInitialized(Data data)
		{
			Prefab.SetActive(true);
		}

		public void Update()
		{
			if (digits_.Length != 0)
			{
				float time = (float)Timex.ModeTime_;
				if (!Mod.DisplayCountdown.Value || !Flags.CanDisplayHudElements)
				{
					time = -10f;
				}
				KeyValuePair<Image, VisualCountdownDigit>[] array = digits_;
				for (int i = 0; i < array.Length; i++)
				{
					KeyValuePair<Image, VisualCountdownDigit> keyValuePair = array[i];
					((Graphic)keyValuePair.Key).material.SetFloat("_Progress", GetInterpolation(time, keyValuePair.Value));
				}
			}
		}

		public float GetInterpolation(float time, VisualCountdownDigit data)
		{
			float num = data.start + data.duration / 2f;
			float num2 = num - data.start;
			float num3 = 1f / num2 * (0f - Mathf.Abs(time - data.start - num2)) + 1f;
			return Mathf.Max(0f, num3);
		}
	}
	public class VisualDisplay : MonoBehaviour
	{
		public const string AssetName = "assets/nr hud/nr_hud.prefab";

		private VisualDisplayContent[] huds_;

		private Text timer_;

		public static bool ForceDisplay { get; set; }

		public Assets Assets { get; internal set; }

		public AssetBundle Bundle
		{
			get
			{
				object bundle = Assets.Bundle;
				return (AssetBundle)((bundle is AssetBundle) ? bundle : null);
			}
		}

		private GameObject Prefab { get; set; }

		private void CreatePrefab(bool loadBundle = true)
		{
			if (loadBundle)
			{
				Assets = new Assets("hud.assets", fromRootDirectory: true);
			}
			if (!Object.op_Implicit((Object)(object)Bundle))
			{
				Mod.Log.LogInfo((object)"The following assets file could not be loaded: hud.assets");
				Object.DestroyImmediate((Object)(object)this);
				return;
			}
			Prefab = Object.Instantiate<GameObject>(Bundle.LoadAsset<GameObject>("assets/nr hud/nr_hud.prefab"), ((Component)this).transform);
			if (!Object.op_Implicit((Object)(object)Prefab))
			{
				Mod.Log.LogInfo((object)"The following asset from the hud.assets could not be loaded: \"assets/nr hud/nr_hud.prefab\"");
				Object.DestroyImmediate((Object)(object)this);
				return;
			}
			((Object)Prefab).name = "Visual Display";
			GameObject gameObject = ((Component)Prefab.transform.Find("Hud_Left")).gameObject;
			GameObject gameObject2 = ((Component)Prefab.transform.Find("Hud_Right")).gameObject;
			huds_ = new VisualDisplayContent[2]
			{
				new VisualDisplayContent(gameObject),
				new VisualDisplayContent(gameObject2)
			};
			GameObject prefab = Prefab;
			object obj;
			if (prefab == null)
			{
				obj = null;
			}
			else
			{
				Transform obj2 = prefab.transform.Find("Time");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<Text>() : null);
			}
			timer_ = (Text)obj;
		}

		public void Awake()
		{
			CreatePrefab();
		}

		public void Update()
		{
			if (huds_.Length != 0)
			{
				UpdateVisibility();
				UpdateTransforms();
				UpdateTimerText();
				UpdateHeatIndicators();
				UpdateScoreLabel();
				UpdateSpeedLabel();
			}
		}

		private void UpdateVisibility()
		{
			CollectionExtensions.Do<VisualDisplayContent>((IEnumerable<VisualDisplayContent>)huds_, (Action<VisualDisplayContent>)delegate(VisualDisplayContent x)
			{
				((Component)x.rectTransform).gameObject.SetActive((Flags.CanDisplayHudElements && Mod.DisplayHeatMeter.Value) || ForceDisplay);
			});
			Text obj = timer_;
			if (obj != null)
			{
				GameObject gameObject = ((Component)obj).gameObject;
				if (gameObject != null)
				{
					gameObject.SetActive((Flags.CanDisplayHudElements && Mod.DisplayTimer.Value) || ForceDisplay);
				}
			}
		}

		public void UpdateTransforms()
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (huds_.Length >= 2)
			{
				for (int i = 0; i <= 1; i++)
				{
					float num = ((i == 0) ? 1 : (-1));
					float num2 = 1.7f * (Mod.HeatMeterScale.Value / 30f);
					((Transform)huds_[i].rectTransform).localScale = new Vector3(num2 * num, num2, num2);
					huds_[i].rectTransform.anchoredPosition = new Vector2((float)Mod.HeatMetersHorizontalOffset.Value * num, (float)Mod.HeatMetersVerticalOffset.Value);
				}
			}
			if (Object.op_Implicit((Object)(object)timer_))
			{
				RectTransform component = ((Component)timer_).GetComponent<RectTransform>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Transform)component).localScale = Vector2.op_Implicit(Vector2.one * 0.5f * (Mod.TimerScale.Value / 30f));
					component.anchoredPosition = new Vector2(0f, (float)(Mod.TimerVerticalOffset.Value + 45));
				}
			}
		}

		private void UpdateHeatIndicators()
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float num = Mathf.Clamp(Vehicle.HeatLevel, 0f, 1f);
				if (huds_.Length < 2)
				{
					return;
				}
				for (int i = 0; i <= 1; i++)
				{
					VisualDisplayContent visualDisplayContent = huds_[i];
					if (Object.op_Implicit((Object)(object)visualDisplayContent.main))
					{
						visualDisplayContent.heatHigh.fillAmount = num;
						visualDisplayContent.heatLow.fillAmount = num;
						float num2 = 0f;
						if (num > Mod.HeatBlinkStartAmount.Value)
						{
							num2 = (num - Mod.HeatBlinkStartAmount.Value) / (1f - Mod.HeatBlinkStartAmount.Value);
						}
						num2 *= 0.5f * Mathf.Sin((float)Timex.ModeTime_ * (Mod.HeatBlinkFrequency.Value - (1f - num) * num * Mod.HeatBlinkFrequencyBoost.Value) * 3f * (float)Math.PI) + 0.5f;
						((Graphic)visualDisplayContent.main).color = new Color(1f, 1f - num2 * Mod.HeatBlinkAmount.Value, 1f - num2 * Mod.HeatBlinkAmount.Value);
						float num3 = 0f;
						if (num > Mod.HeatFlameAmount.Value)
						{
							num3 = (num - Mod.HeatFlameAmount.Value) / (1f - Mod.HeatFlameAmount.Value);
						}
						((Graphic)visualDisplayContent.flame).color = new Color(1f, 1f, 1f, num3);
					}
				}
			}
			catch (Exception ex)
			{
				Mod.Log.LogError((object)ex);
			}
		}

		private void UpdateTimerText()
		{
			GameManager gameManager_ = G.Sys.GameManager_;
			GameMode mode_ = gameManager_.Mode_;
			if (Object.op_Implicit((Object)(object)mode_) && Object.op_Implicit((Object)(object)timer_))
			{
				float num = Mathf.Max(0f, (float)mode_.GetDisplayTime(0));
				StringBuilder stringBuilder = new StringBuilder();
				GUtils.GetFormattedTime(stringBuilder, num, (!(num >= 3600f)) ? 2 : 0, num > 3600f);
				timer_.text = stringBuilder.ToString();
			}
		}

		private void UpdateScoreLabel()
		{
			if (huds_.Length < 2)
			{
				return;
			}
			for (int i = 0; i <= 1; i++)
			{
				VisualDisplayContent visualDisplayContent = huds_[i];
				if (Object.op_Implicit((Object)(object)visualDisplayContent.main) && Object.op_Implicit((Object)(object)visualDisplayContent.score))
				{
					visualDisplayContent.score.text = GetScore().ToString(CultureInfo.GetCultureInfo("en-GB") ?? CultureInfo.InvariantCulture);
				}
			}
		}

		private long GetScore()
		{
			if (G.Sys.GameManager_.IsModeStarted_)
			{
				StatsManager statsManager_ = G.Sys.StatsManager_;
				return (statsManager_ != null) ? statsManager_.GetMatchStats((PlayerDataBase)(object)G.Sys.PlayerManager_?.current_.playerData_).totalPoints_ : 0;
			}
			return 0L;
		}

		private void UpdateSpeedLabel()
		{
			if (huds_.Length < 2)
			{
				return;
			}
			for (int i = 0; i <= 1; i++)
			{
				VisualDisplayContent visualDisplayContent = huds_[i];
				if (Object.op_Implicit((Object)(object)visualDisplayContent.speed))
				{
					visualDisplayContent.speed.text = Mathf.RoundToInt(GetSpeedValue()).ToString();
				}
				if (Object.op_Implicit((Object)(object)visualDisplayContent.speedLabel))
				{
					visualDisplayContent.speedLabel.text = GetSpeedUnit();
				}
			}
		}

		private float GetSpeedValue()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			if (G.Sys.GameManager_.IsModeStarted_)
			{
				Units units_ = G.Sys.OptionsManager_.General_.Units_;
				Units val = units_;
				if ((int)val != 0)
				{
					if ((int)val == 1)
					{
						return Vehicle.VelocityKPH;
					}
					return 0f;
				}
				return Vehicle.VelocityMPH;
			}
			return 0f;
		}

		private string GetSpeedUnit()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			Units units_ = G.Sys.OptionsManager_.General_.Units_;
			Units val = units_;
			if ((int)val != 0)
			{
				if ((int)val == 1)
				{
					return "KM/H";
				}
				return "ERR";
			}
			return "MPH";
		}
	}
}
namespace Distance.NitronicHUD.Patches
{
	[HarmonyPatch(typeof(GameManager), "Awake")]
	internal static class GameManager__Awake
	{
		[HarmonyPostfix]
		internal static void Postfix()
		{
			Mod.Instance.LateInitialize();
		}
	}
	[HarmonyPatch(typeof(StatsManager), "OnEventPlayerAdded")]
	internal static class StatsManager__OnEventPlayerAdded
	{
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instr)
		{
			return instr.Skip(5);
		}
	}
}
namespace Distance.NitronicHUD.Data
{
	public struct VisualCountdownDigit
	{
		public float start;

		public float duration;

		public VisualCountdownDigit(float start, float duration)
		{
			this.start = start;
			this.duration = duration;
		}
	}
	public struct VisualDisplayContent
	{
		public GameObject prefab;

		public RectTransform rectTransform;

		public Image flame;

		public Image main;

		public Image heatLow;

		public Image heatHigh;

		public Text speed;

		public Text speedLabel;

		public Text score;

		public Text scoreLabel;

		public VisualDisplayContent(GameObject obj)
		{
			prefab = obj;
			GameObject obj2 = prefab;
			main = ((obj2 != null) ? obj2.GetComponent<Image>() : null);
			GameObject obj3 = prefab;
			rectTransform = ((obj3 != null) ? obj3.GetComponent<RectTransform>() : null);
			GameObject obj4 = prefab;
			object obj5;
			if (obj4 == null)
			{
				obj5 = null;
			}
			else
			{
				Transform obj6 = obj4.transform.Find("Flame");
				obj5 = ((obj6 != null) ? ((Component)obj6).GetComponent<Image>() : null);
			}
			flame = (Image)obj5;
			GameObject obj7 = prefab;
			object obj8;
			if (obj7 == null)
			{
				obj8 = null;
			}
			else
			{
				Transform obj9 = obj7.transform.Find("Heat_Low");
				obj8 = ((obj9 != null) ? ((Component)obj9).GetComponent<Image>() : null);
			}
			heatLow = (Image)obj8;
			GameObject obj10 = prefab;
			object obj11;
			if (obj10 == null)
			{
				obj11 = null;
			}
			else
			{
				Transform obj12 = obj10.transform.Find("Heat_High");
				obj11 = ((obj12 != null) ? ((Component)obj12).GetComponent<Image>() : null);
			}
			heatHigh = (Image)obj11;
			GameObject obj13 = prefab;
			object obj14;
			if (obj13 == null)
			{
				obj14 = null;
			}
			else
			{
				Transform obj15 = obj13.transform.Find("Speed");
				obj14 = ((obj15 != null) ? ((Component)obj15).GetComponent<Text>() : null);
			}
			speed = (Text)obj14;
			GameObject obj16 = prefab;
			object obj17;
			if (obj16 == null)
			{
				obj17 = null;
			}
			else
			{
				Transform obj18 = obj16.transform.Find("Speed_Label");
				obj17 = ((obj18 != null) ? ((Component)obj18).GetComponent<Text>() : null);
			}
			speedLabel = (Text)obj17;
			GameObject obj19 = prefab;
			object obj20;
			if (obj19 == null)
			{
				obj20 = null;
			}
			else
			{
				Transform obj21 = obj19.transform.Find("Score");
				obj20 = ((obj21 != null) ? ((Component)obj21).GetComponent<Text>() : null);
			}
			score = (Text)obj20;
			GameObject obj22 = prefab;
			object obj23;
			if (obj22 == null)
			{
				obj23 = null;
			}
			else
			{
				Transform obj24 = obj22.transform.Find("Score_Label");
				obj23 = ((obj24 != null) ? ((Component)obj24).GetComponent<Text>() : null);
			}
			scoreLabel = (Text)obj23;
		}
	}
}