Decompiled source of EladsHUDPlus v1.0.0

EladsHUDPlus.dll

Decompiled 18 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using CustomHUD;
using Dissonance;
using GameNetcodeStuff;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EladsHUD")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EladsHUD")]
[assembly: AssemblyTitle("EladsHUD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public enum PocketFlashlightOptions
{
	Disabled,
	Vanilla,
	Separate
}
public enum StaminaTextOptions
{
	Disabled,
	PercentageOnly,
	Full
}
internal class CustomHUD_Mono : MonoBehaviour
{
	public static CustomHUD_Mono instance;

	[Header("Health")]
	public CanvasGroup healthGroup;

	public Image healthBar;

	public TextMeshProUGUI healthText;

	public TextMeshProUGUI healthText2;

	[Header("Stamina")]
	public CanvasGroup staminaGroup;

	public Image staminaBar;

	public Image staminaBarChangeFG;

	public TextMeshProUGUI staminaText;

	public TextMeshProUGUI carryText;

	[Header("Battery")]
	public CanvasGroup batteryGroup;

	public Image batteryBar;

	public TextMeshProUGUI batteryText;

	[Header("Flashlight")]
	public CanvasGroup flashlightGroup;

	public Image flashlightBar;

	public TextMeshProUGUI flashlightText;

	private Color staminaColor;

	internal Color staminaWarnColor = new Color(255f, 0f, 0f);

	internal float colorLerp;

	private int lastHealth = 100;

	private float lastHealthChange;

	private float shownStaminaRate;

	private void Awake()
	{
		if ((Object)(object)instance != (Object)null)
		{
			throw new Exception("2 instances of CustomHUD_Mono!");
		}
		instance = this;
	}

	private void Start()
	{
		//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)
		staminaColor = ((Graphic)staminaBar).color;
	}

	public void UpdateFromPlayer(PlayerControllerB player)
	{
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		lastHealthChange += Time.deltaTime;
		if (player.health < lastHealth)
		{
			Debug.Log((object)"o shit");
			Debug.Log((object)player.health);
			Debug.Log((object)lastHealth);
			lastHealthChange = 0f;
		}
		lastHealth = player.health;
		int health = player.health;
		float sprintMeter = player.sprintMeter;
		_ = player.sprintTime;
		if ((double)sprintMeter < 0.3)
		{
			colorLerp = Mathf.Clamp01(colorLerp + Time.deltaTime * 8f);
		}
		else
		{
			colorLerp = Mathf.Clamp01(colorLerp - Time.deltaTime * 8f);
		}
		((Graphic)staminaBar).color = Color.Lerp(staminaColor, staminaWarnColor, colorLerp);
		int num = Mathf.FloorToInt(sprintMeter * 100f);
		float num2 = CalculateStaminaOverTime(player);
		float num3 = num2 * 100f;
		if (Mathf.Sign(num3) != Mathf.Sign(shownStaminaRate) || Mathf.Abs(num3 - shownStaminaRate) >= 0.05f)
		{
			shownStaminaRate = num3;
		}
		float num4 = shownStaminaRate;
		if (Plugin.detailedStamina.Value != StaminaTextOptions.Disabled)
		{
			((TMP_Text)staminaText).text = $"{num}<size=75%><voffset=1>%</voffset></size>";
		}
		else
		{
			((TMP_Text)staminaText).text = "";
		}
		float num5 = Mathf.Sign(num2);
		if (num5 != -1f)
		{
			if (num5 != 0f)
			{
				if (num5 != 1f)
				{
				}
				staminaBar.fillAmount = sprintMeter;
				staminaBarChangeFG.fillAmount = 0f;
				if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
				{
					TextMeshProUGUI obj = staminaText;
					((TMP_Text)obj).text = ((TMP_Text)obj).text + " | +" + num4.ToString("0.0") + "<size=75%>/sec</size>";
				}
			}
			else
			{
				staminaBar.fillAmount = sprintMeter;
				staminaBarChangeFG.fillAmount = 0f;
				if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
				{
					TextMeshProUGUI obj2 = staminaText;
					((TMP_Text)obj2).text = ((TMP_Text)obj2).text + " | +0.0<size=75%>/sec</size>";
				}
			}
		}
		else
		{
			staminaBar.fillAmount = sprintMeter - Mathf.Abs(num2);
			((Graphic)staminaBarChangeFG).color = Color.Lerp(Color.white, staminaWarnColor, colorLerp);
			staminaBarChangeFG.fillAmount = Mathf.Min(sprintMeter, Mathf.Abs(num2));
			((Transform)((Graphic)staminaBarChangeFG).rectTransform).localPosition = new Vector3(1f + 276f * Mathf.Max(0f, sprintMeter - Mathf.Abs(num2)) + 0.05f, 0f);
			if (Plugin.detailedStamina.Value == StaminaTextOptions.Full)
			{
				TextMeshProUGUI obj3 = staminaText;
				((TMP_Text)obj3).text = ((TMP_Text)obj3).text + " | " + num4.ToString("0.0") + "<size=75%>/sec</size>";
			}
		}
		float num6 = Mathf.RoundToInt(Mathf.Clamp(player.carryWeight - 1f, 0f, 100f) * 105f);
		if (Plugin.shouldDoKGConversion)
		{
			num6 *= 0.453592f;
			((TMP_Text)carryText).text = $"{num6}<size=60%>kg</size>";
		}
		else
		{
			((TMP_Text)carryText).text = $"{num6}<size=60%>lb</size>";
		}
		healthBar.fillAmount = (float)health / 100f;
		((TMP_Text)healthText).text = health.ToString();
		if ((Object)(object)healthText2 != (Object)null)
		{
			((TMP_Text)healthText2).text = health.ToString();
		}
		float value = Plugin.healthbarHideDelay.Value;
		healthGroup.alpha = (Plugin.autoHideHealthbar.Value ? Mathf.InverseLerp(value + 1f, value, lastHealthChange) : 1f);
		((Component)flashlightGroup).gameObject.SetActive(UpdateFlashlight(player));
		((Component)batteryGroup).gameObject.SetActive(UpdateBattery(player));
		try
		{
			HeadwearHud.instance?.Apply(player);
		}
		catch (Exception ex)
		{
			Plugin.Log("Head item battery: " + ex);
			Plugin.showHeadwear.Value = false;
		}
	}

	private bool UpdateFlashlight(PlayerControllerB player)
	{
		if (Plugin.pocketedFlashlightDisplayMode.Value != PocketFlashlightOptions.Separate)
		{
			return false;
		}
		if (!((Behaviour)player.helmetLight).enabled)
		{
			return false;
		}
		GrabbableObject pocketedFlashlight = player.pocketedFlashlight;
		if ((Object)(object)pocketedFlashlight == (Object)null)
		{
			return false;
		}
		if (!pocketedFlashlight.itemProperties.requiresBattery)
		{
			return false;
		}
		if (pocketedFlashlight.insertedBattery == null)
		{
			return false;
		}
		flashlightBar.fillAmount = pocketedFlashlight.insertedBattery.charge;
		int num = Mathf.CeilToInt(pocketedFlashlight.insertedBattery.charge * pocketedFlashlight.itemProperties.batteryUsage);
		((TMP_Text)flashlightText).text = $"{Mathf.CeilToInt(pocketedFlashlight.insertedBattery.charge * 100f)}%";
		if (!Plugin.displayTimeLeft.Value)
		{
			return true;
		}
		TextMeshProUGUI obj = flashlightText;
		((TMP_Text)obj).text = ((TMP_Text)obj).text + string.Format(" <size=60%>{0}:{1}", num / 60, (num % 60).ToString("D2"));
		return true;
	}

	private bool UpdateBattery(PlayerControllerB player)
	{
		GrabbableObject val = player.currentlyHeldObjectServer;
		if ((Object)(object)val == (Object)null && Plugin.pocketedFlashlightDisplayMode.Value == PocketFlashlightOptions.Vanilla)
		{
			val = player.pocketedFlashlight;
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (!val.itemProperties.requiresBattery)
		{
			return false;
		}
		if (val.insertedBattery == null)
		{
			return false;
		}
		batteryBar.fillAmount = val.insertedBattery.charge;
		int num = (int)(val.insertedBattery.charge / val.itemProperties.batteryUsage);
		int num2 = Mathf.CeilToInt(val.insertedBattery.charge * val.itemProperties.batteryUsage);
		((TMP_Text)batteryText).text = $"{Mathf.CeilToInt(val.insertedBattery.charge * 100f)}%";
		if (!Plugin.displayTimeLeft.Value)
		{
			return true;
		}
		if (val.itemProperties.itemIsTrigger)
		{
			TextMeshProUGUI obj = batteryText;
			((TMP_Text)obj).text = ((TMP_Text)obj).text + $" ({num} uses remaining)";
		}
		else
		{
			TextMeshProUGUI obj2 = batteryText;
			((TMP_Text)obj2).text = ((TMP_Text)obj2).text + string.Format(" ({0}:{1} remaining)", num2 / 60, (num2 % 60).ToString("D2"));
		}
		return true;
	}

	private float CalculateStaminaOverTime(PlayerControllerB player)
	{
		if (player.sprintMeter == 1f)
		{
			return 0f;
		}
		bool privateField = player.GetPrivateField<bool>("isWalking");
		float sprintTime = player.sprintTime;
		float num = 1f;
		if ((double)player.drunkness > 0.019999999552965164)
		{
			num *= Mathf.Abs(StartOfRound.Instance.drunknessSpeedEffect.Evaluate(player.drunkness) - 1.25f);
		}
		if (player.isSprinting)
		{
			return -1f / sprintTime * player.carryWeight * num;
		}
		if (player.isMovementHindered > 0 && privateField)
		{
			return -1f / sprintTime * num * 0.5f;
		}
		if (privateField)
		{
			return 1f / (sprintTime + 9f) * num;
		}
		return 1f / (sprintTime + 4f) * num;
	}
}
namespace CustomHUD
{
	internal class CursorMode : MonoBehaviour
	{
		[HarmonyPatch(typeof(PlayerControllerB), "PlayerLookInput")]
		internal static class LookPatch
		{
			[HarmonyPrefix]
			private static bool Prefix()
			{
				return !Active;
			}
		}

		internal static ConfigEntry<bool> enabledCfg;

		internal static ConfigEntry<string> keyCfg;

		internal static ConfigEntry<bool> holdCfg;

		private InputAction action;

		internal static bool Active { get; private set; }

		public static void Bind(ConfigFile cfg)
		{
			enabledCfg = cfg.Bind<bool>("Cursor", "EnableCursorKey", true, "Press a key to show the mouse cursor so you can point at the HUD (hover a buff / injury icon to see what it does). The camera stops turning while the cursor is shown.");
			keyCfg = cfg.Bind<string>("Cursor", "CursorKey", "<Mouse>/middleButton", "Input System path of the key. Examples: <Mouse>/middleButton, <Mouse>/forwardButton, <Keyboard>/leftAlt, <Keyboard>/f2");
			holdCfg = cfg.Bind<bool>("Cursor", "HoldToShow", false, "Off: press once to show the cursor, again to hide it. On: the cursor shows only while you hold the key.");
		}

		public static void Create(GameObject hud)
		{
			hud.AddComponent<CursorMode>();
		}

		private void OnEnable()
		{
			MakeAction();
			keyCfg.SettingChanged += OnKeyChanged;
		}

		private void OnDisable()
		{
			keyCfg.SettingChanged -= OnKeyChanged;
			InputAction obj = action;
			if (obj != null)
			{
				obj.Disable();
			}
			InputAction obj2 = action;
			if (obj2 != null)
			{
				obj2.Dispose();
			}
			action = null;
			SetActive(on: false, touchCursor: true);
		}

		private void OnKeyChanged(object sender, EventArgs e)
		{
			InputAction obj = action;
			if (obj != null)
			{
				obj.Disable();
			}
			InputAction obj2 = action;
			if (obj2 != null)
			{
				obj2.Dispose();
			}
			MakeAction();
		}

		private void MakeAction()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			try
			{
				action = new InputAction("EladsHUD Cursor", (InputActionType)1, keyCfg.Value, (string)null, (string)null, (string)null);
				action.Enable();
			}
			catch (Exception ex)
			{
				Plugin.Log("Cursor key '" + keyCfg.Value + "' is not valid: " + ex.Message);
				action = null;
			}
		}

		private void Update()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
				bool flag = (Object)(object)val == (Object)null || val.isPlayerDead || !val.isPlayerControlled || ((Object)(object)val.quickMenuManager != (Object)null && val.quickMenuManager.isMenuOpen) || val.inTerminalMenu || val.isTypingChat || val.inSpecialMenu;
				if (!enabledCfg.Value || action == null || flag)
				{
					SetActive(on: false, !flag);
					return;
				}
				if (holdCfg.Value)
				{
					SetActive(action.IsPressed(), touchCursor: true);
				}
				else if (action.WasPressedThisFrame())
				{
					SetActive(!Active, touchCursor: true);
				}
				if (Active && (int)Cursor.lockState != 0)
				{
					Cursor.lockState = (CursorLockMode)0;
					Cursor.visible = true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log("Cursor: " + ex.Message);
				SetActive(on: false, touchCursor: true);
				((Behaviour)this).enabled = false;
			}
		}

		private static void SetActive(bool on, bool touchCursor)
		{
			if (on != Active)
			{
				Active = on;
				if (touchCursor)
				{
					Cursor.lockState = (CursorLockMode)(!on);
					Cursor.visible = on;
				}
			}
		}

		internal static Vector2 MousePosition()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Mouse current = Mouse.current;
			if (current == null)
			{
				return new Vector2(-9999f, -9999f);
			}
			return ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue();
		}
	}
	internal class HeadwearHud
	{
		private class LampIcon
		{
			public RectTransform root;

			public Image fill;

			public Image outline;

			public Image rays;
		}

		private class Segment
		{
			public RectTransform root;

			public RectTransform batteryIcon;

			public Image batteryFillImage;

			public LampIcon lamp;

			public RectTransform flashIcon;

			public Image flashFillImage;

			public TextMeshProUGUI text;
		}

		public static HeadwearHud instance;

		private const float LampAngle = -47f;

		private const float SpriteAspect = 0.79591835f;

		private static Sprite fillSprite;

		private static Sprite outlineSprite;

		private static Sprite raysSprite;

		private readonly CustomHUD_Mono hud;

		private readonly RectTransform batteryLayout;

		private readonly RectTransform flashlightRow;

		private readonly RectTransform smallRow;

		private readonly LampIcon smallIcon;

		private readonly TextMeshProUGUI smallText;

		private readonly LayoutElement smallLayout;

		private readonly Vector2 rowAnchorMin;

		private readonly Vector2 rowAnchorMax;

		private readonly Vector2 rowPivot;

		private readonly LayoutElement flashlightLayout;

		private readonly Vector2 flashAnchorMin;

		private readonly Vector2 flashAnchorMax;

		private readonly Vector2 flashPivot;

		private readonly Vector2 flashSize;

		private readonly LampIcon bigIcon;

		private readonly Graphic batteryBG;

		private readonly Graphic batteryFill;

		private bool batteryIconsHidden;

		private static bool acChecked;

		private static MethodInfo getPlayer;

		private static FieldInfo helmetField;

		private static MethodInfo perkMultiplier;

		private static FieldInfo serverConfigInstance;

		private static FieldInfo itemsField;

		private static FieldInfo tacticalField;

		private static FieldInfo tacticalTime;

		private static FieldInfo tacticalTimeLight;

		private static bool acConfigChecked;

		private static readonly Dictionary<Type, FieldInfo> lightFieldByType = new Dictionary<Type, FieldInfo>();

		private static readonly Color DrainRed = new Color(1f, 0.22f, 0.12f);

		private readonly Dictionary<TextMeshProUGUI, float> redAmount = new Dictionary<TextMeshProUGUI, float>();

		private readonly Dictionary<TextMeshProUGUI, Color> baseColor = new Dictionary<TextMeshProUGUI, Color>();

		private readonly HashSet<TextMeshProUGUI> redThisFrame = new HashSet<TextMeshProUGUI>();

		private RectTransform compactRoot;

		private Segment[] segments;

		private bool compactActive;

		private Graphic eladBatteryText;

		private const string CompactTimeSize = "<size=70%>";

		private const float FlashIconScale = 1.3f;

		private const float SegmentGap = 10f;

		private const float BatteryIconWidth = 30f;

		private const float LampIconWidth = 42f;

		private const float FlashIconWidth = 46f;

		private const float RowStartX = -4f;

		private static Type helmetInterface;

		private static bool helmetInterfaceChecked;

		private static void CheckAC()
		{
			if (acChecked)
			{
				return;
			}
			acChecked = true;
			Type type = Plugin.FindType("AdvancedCompany", "AdvancedCompany.Game.Player");
			if (!(type == null))
			{
				getPlayer = AccessTools.Method(type, "GetPlayer", new Type[1] { typeof(PlayerControllerB) }, (Type[])null);
				helmetField = AccessTools.Field(type, "Helmet");
				if (getPlayer == null || helmetField == null)
				{
					Plugin.Log("AdvancedCompany found, but its head slot changed - head item battery not shown.");
				}
				else
				{
					Plugin.Log("AdvancedCompany found: head-slot item battery is shown.");
				}
			}
		}

		private static void CheckACConfig()
		{
			if (!acConfigChecked)
			{
				acConfigChecked = true;
				Type type = Plugin.FindType("AdvancedCompany", "AdvancedCompany.Perks");
				perkMultiplier = ((type != null) ? AccessTools.Method(type, "GetMultiplier", new Type[1] { typeof(string) }, (Type[])null) : null);
				Type type2 = Plugin.FindType("AdvancedCompany", "AdvancedCompany.Config.ServerConfiguration");
				serverConfigInstance = ((type2 != null) ? AccessTools.Field(type2, "Instance") : null);
				itemsField = ((type2 != null) ? AccessTools.Field(type2, "Items") : null);
				tacticalField = ((itemsField != null) ? AccessTools.Field(itemsField.FieldType, "TacticalHelmet") : null);
				tacticalTime = ((tacticalField != null) ? AccessTools.Field(tacticalField.FieldType, "BatteryTime") : null);
				tacticalTimeLight = ((tacticalField != null) ? AccessTools.Field(tacticalField.FieldType, "BatteryTimeWithLight") : null);
			}
		}

		private static float SecondsPerFullCharge(GrabbableObject item)
		{
			CheckACConfig();
			float num = 1f;
			try
			{
				if (perkMultiplier != null)
				{
					num = Convert.ToSingle(perkMultiplier.Invoke(null, new object[1] { "ExtraBattery" }));
				}
			}
			catch
			{
			}
			float num2 = Mathf.Max(0.01f, item.itemProperties.batteryUsage * Mathf.Max(0.01f, num));
			float num3 = (item.isBeingUsed ? (1f / num2) : 0f);
			if (!(num3 > 0f))
			{
				return num2;
			}
			return 1f / num3;
		}

		private static bool TacticalLightOn(GrabbableObject item)
		{
			Type type = ((object)item).GetType();
			if (!lightFieldByType.TryGetValue(type, out var value))
			{
				value = type.GetField("isFlashlightBeingUsed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (value != null && value.FieldType != typeof(bool))
				{
					value = null;
				}
				lightFieldByType[type] = value;
			}
			if (value != null)
			{
				return (bool)value.GetValue(item);
			}
			return false;
		}

		private static GrabbableObject GetHeadItem(PlayerControllerB player)
		{
			CheckAC();
			if (getPlayer == null || helmetField == null || (Object)(object)player == (Object)null)
			{
				return null;
			}
			object obj = getPlayer.Invoke(null, new object[1] { player });
			if (obj == null)
			{
				return null;
			}
			object? value = helmetField.GetValue(obj);
			GrabbableObject val = (GrabbableObject)((value is GrabbableObject) ? value : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.itemProperties == (Object)null || !val.itemProperties.requiresBattery || val.insertedBattery == null)
			{
				return null;
			}
			return val;
		}

		private static bool IsOn(GrabbableObject item)
		{
			if (!item.isBeingUsed)
			{
				return TacticalLightOn(item);
			}
			return true;
		}

		public static void Create(CustomHUD_Mono hud)
		{
			try
			{
				LoadSprites();
				instance = new HeadwearHud(hud);
			}
			catch (Exception ex)
			{
				Plugin.Log("Head item battery HUD could not be created: " + ex);
				instance = null;
			}
		}

		private static void LoadSprites()
		{
			if (!((Object)(object)fillSprite != (Object)null))
			{
				fillSprite = StatusPanel.LoadSprite("LampFill.png", mipmaps: false);
				outlineSprite = StatusPanel.LoadSprite("LampOutline.png", mipmaps: false);
				raysSprite = StatusPanel.LoadSprite("LampRays.png", mipmaps: false);
			}
		}

		private HeadwearHud(CustomHUD_Mono hud)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: 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_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			this.hud = hud;
			flashlightRow = (RectTransform)((Component)hud.flashlightGroup).transform;
			batteryLayout = (RectTransform)((Transform)flashlightRow).parent;
			GameObject val = Object.Instantiate<GameObject>(((Component)flashlightRow).gameObject, (Transform)(object)batteryLayout);
			((Object)val).name = "HeadwearRow";
			smallRow = (RectTransform)val.transform;
			((Transform)smallRow).SetSiblingIndex(((Transform)flashlightRow).GetSiblingIndex());
			Transform obj = ((Transform)smallRow).Find("Battery");
			smallText = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			string[] array = new string[3] { "Icon", "Outline", "Flash" };
			foreach (string text in array)
			{
				Transform val2 = ((Transform)smallRow).Find(text);
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
			smallIcon = MakeIcon(smallRow, new Vector2(0f, 0.5f), new Vector2(60f, 1f), 30f);
			smallLayout = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			rowAnchorMin = smallRow.anchorMin;
			rowAnchorMax = smallRow.anchorMax;
			rowPivot = smallRow.pivot;
			val.SetActive(false);
			flashlightLayout = ((Component)flashlightRow).GetComponent<LayoutElement>() ?? ((Component)flashlightRow).gameObject.AddComponent<LayoutElement>();
			flashAnchorMin = flashlightRow.anchorMin;
			flashAnchorMax = flashlightRow.anchorMax;
			flashPivot = flashlightRow.pivot;
			flashSize = flashlightRow.sizeDelta;
			((Transform)flashlightRow).SetAsLastSibling();
			if (Plugin.flashlightGap.Value)
			{
				Transform obj2 = ((Transform)flashlightRow).Find("Icon");
				Image val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null);
				Sprite val4 = StatusPanel.LoadSprite("FlashlightGap.png", mipmaps: false);
				if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
				{
					val3.sprite = val4;
				}
			}
			RectTransform val5 = (RectTransform)((Component)hud.batteryGroup).transform;
			Transform obj3 = ((Transform)val5).Find("BG");
			batteryBG = ((obj3 != null) ? ((Component)obj3).GetComponent<Graphic>() : null);
			batteryFill = (Graphic)(object)hud.batteryBar;
			bigIcon = MakeIcon(val5, new Vector2(0f, 0f), new Vector2(17f, 20f), 34f);
			((Component)bigIcon.root).gameObject.SetActive(false);
		}

		private static LampIcon MakeIcon(RectTransform parent, Vector2 anchor, Vector2 center, float width)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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)
			LampIcon lampIcon = new LampIcon();
			GameObject val = new GameObject("HeadLamp", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			lampIcon.root = (RectTransform)val.transform;
			RectTransform root = lampIcon.root;
			Vector2 anchorMin = (lampIcon.root.anchorMax = anchor);
			root.anchorMin = anchorMin;
			lampIcon.root.pivot = new Vector2(0.5f, 0.5f);
			lampIcon.root.anchoredPosition = center;
			lampIcon.root.sizeDelta = new Vector2(width, width * 0.79591835f);
			((Transform)lampIcon.root).localRotation = Quaternion.Euler(0f, 0f, -47f);
			lampIcon.fill = MakeImage(lampIcon.root, "Fill", fillSprite);
			lampIcon.fill.type = (Type)3;
			lampIcon.fill.fillMethod = (FillMethod)0;
			lampIcon.fill.fillOrigin = 0;
			lampIcon.outline = MakeImage(lampIcon.root, "Outline", outlineSprite);
			lampIcon.rays = MakeImage(lampIcon.root, "Rays", raysSprite);
			return lampIcon;
		}

		private static Image MakeImage(RectTransform parent, string name, Sprite sprite)
		{
			//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_0026: 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_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = new Color(1f, 0.996f, 0f);
			return obj;
		}

		public void Apply(PlayerControllerB player)
		{
			redThisFrame.Clear();
			ApplyLayout(player);
			ApplyTints();
		}

		private void MarkRedIfFastDrain(TextMeshProUGUI text, GrabbableObject item)
		{
			if ((Object)(object)text != (Object)null && (Object)(object)item != (Object)null && TacticalLightOn(item) && item.insertedBattery != null && item.insertedBattery.charge > 0f)
			{
				redThisFrame.Add(text);
			}
		}

		private void ApplyTints()
		{
			Tint(hud.batteryText);
			Tint(smallText);
			if (segments != null)
			{
				Segment[] array = segments;
				foreach (Segment segment in array)
				{
					Tint(segment.text);
				}
			}
		}

		private void Tint(TextMeshProUGUI text)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			if ((Object)(object)text == (Object)null)
			{
				return;
			}
			redAmount.TryGetValue(text, out var value);
			if (value <= 0f)
			{
				baseColor[text] = ((Graphic)text).color;
			}
			float num = (redThisFrame.Contains(text) ? 1f : 0f);
			if (value != 0f || num != 0f)
			{
				value = Mathf.MoveTowards(value, num, Time.deltaTime * 3f);
				redAmount[text] = value;
				if (baseColor.TryGetValue(text, out var value2))
				{
					((Graphic)text).color = Color.Lerp(value2, DrainRed, value);
				}
			}
		}

		private void ApplyLayout(PlayerControllerB player)
		{
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			GrabbableObject val = (((Object)(object)player != (Object)null) ? player.currentlyHeldObjectServer : null);
			GrabbableObject val2 = null;
			if (Plugin.showHeadwear.Value)
			{
				val2 = GetHeadItem(player);
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2 == (Object)(object)val)
				{
					val2 = null;
				}
				if ((Object)(object)val2 != (Object)null && !IsOn(val2) && !Plugin.showHeadwearWhenOff.Value)
				{
					val2 = null;
				}
			}
			bool activeSelf = ((Component)hud.batteryGroup).gameObject.activeSelf;
			bool activeSelf2 = ((Component)hud.flashlightGroup).gameObject.activeSelf;
			bool flag = activeSelf && Plugin.showHeadwear.Value && IsHeadwear(val);
			if (Plugin.compactBattery.Value)
			{
				ApplyCompact(val, activeSelf, flag, val2, activeSelf2);
				return;
			}
			LeaveCompact();
			if (flag)
			{
				SetBigMode(big: true);
				ShowBig(val);
			}
			else
			{
				if (!activeSelf && (Object)(object)val2 != (Object)null)
				{
					RestoreFlashlightRow();
					((Component)smallRow).gameObject.SetActive(false);
					SetBigMode(big: true);
					((Component)hud.batteryGroup).gameObject.SetActive(true);
					ShowBig(val2);
					return;
				}
				SetBigMode(big: false);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				RestoreFlashlightRow();
				((Component)smallRow).gameObject.SetActive(false);
				return;
			}
			((Component)smallRow).gameObject.SetActive(true);
			Describe(val2, out var charge, out var on, out var percent, out var secondsLeft);
			SetIcon(smallIcon, charge, on);
			MarkRedIfFastDrain(smallText, val2);
			if ((Object)(object)smallText != (Object)null)
			{
				((TMP_Text)smallText).text = $"{percent}%";
				if (Plugin.displayTimeLeft.Value)
				{
					TextMeshProUGUI obj = smallText;
					((TMP_Text)obj).text = ((TMP_Text)obj).text + string.Format(" <size=60%>{0}:{1}", secondsLeft / 60, (secondsLeft % 60).ToString("D2"));
				}
			}
			if (activeSelf2)
			{
				flashlightLayout.ignoreLayout = true;
				if ((Object)(object)((Transform)flashlightRow).parent != (Object)(object)smallRow)
				{
					((Transform)flashlightRow).SetParent((Transform)(object)smallRow, false);
				}
				RectTransform obj2 = flashlightRow;
				RectTransform obj3 = flashlightRow;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0f, 0.5f);
				obj3.anchorMax = val3;
				obj2.anchorMin = val3;
				flashlightRow.pivot = new Vector2(0f, 0.5f);
				flashlightRow.anchoredPosition = new Vector2(TextEnd(smallText) - 36f, 0f);
			}
			else
			{
				RestoreFlashlightRow();
			}
		}

		private void RestoreFlashlightRow()
		{
			//IL_003f: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)((Transform)flashlightRow).parent == (Object)(object)batteryLayout) || flashlightLayout.ignoreLayout)
			{
				((Transform)flashlightRow).SetParent((Transform)(object)batteryLayout, false);
				flashlightRow.anchorMin = flashAnchorMin;
				flashlightRow.anchorMax = flashAnchorMax;
				flashlightRow.pivot = flashPivot;
				flashlightRow.sizeDelta = flashSize;
				flashlightLayout.ignoreLayout = false;
				((Transform)flashlightRow).SetAsLastSibling();
			}
		}

		private static float TextEnd(TextMeshProUGUI text)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)text == (Object)null)
			{
				return 180f;
			}
			return ((TMP_Text)text).rectTransform.anchoredPosition.x + ((TMP_Text)text).preferredWidth;
		}

		private void BuildCompact()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Expected O, but got Unknown
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Expected O, but got Unknown
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0493: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)hud.batteryGroup).transform;
			GameObject val2 = new GameObject("CompactBatteryRow", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent((Transform)(object)val, false);
			compactRoot = (RectTransform)val2.transform;
			compactRoot.anchorMin = Vector2.zero;
			compactRoot.anchorMax = Vector2.one;
			RectTransform obj = compactRoot;
			Vector2 offsetMin = (compactRoot.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			eladBatteryText = (Graphic)(object)hud.batteryText;
			segments = new Segment[3];
			for (int i = 0; i < 3; i++)
			{
				Segment segment = new Segment();
				GameObject val3 = new GameObject("Segment" + i, new Type[1] { typeof(RectTransform) });
				val3.transform.SetParent((Transform)(object)compactRoot, false);
				segment.root = (RectTransform)val3.transform;
				RectTransform root = segment.root;
				offsetMin = (segment.root.anchorMax = Vector2.zero);
				root.anchorMin = offsetMin;
				segment.root.pivot = Vector2.zero;
				segment.root.sizeDelta = new Vector2(10f, 36f);
				GameObject val4 = new GameObject("BatteryIcon", new Type[1] { typeof(RectTransform) });
				val4.transform.SetParent((Transform)(object)segment.root, false);
				segment.batteryIcon = (RectTransform)val4.transform;
				RectTransform batteryIcon = segment.batteryIcon;
				offsetMin = (segment.batteryIcon.anchorMax = Vector2.zero);
				batteryIcon.anchorMin = offsetMin;
				segment.batteryIcon.pivot = Vector2.zero;
				segment.batteryIcon.anchoredPosition = Vector2.zero;
				segment.batteryIcon.sizeDelta = new Vector2(30f, 36f);
				if ((Object)(object)batteryBG != (Object)null)
				{
					Object.Instantiate<GameObject>(((Component)batteryBG).gameObject, (Transform)(object)segment.batteryIcon, false);
				}
				if ((Object)(object)hud.batteryBar != (Object)null)
				{
					segment.batteryFillImage = Object.Instantiate<GameObject>(((Component)hud.batteryBar).gameObject, (Transform)(object)segment.batteryIcon, false).GetComponent<Image>();
				}
				Graphic[] componentsInChildren = ((Component)segment.batteryIcon).GetComponentsInChildren<Graphic>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					((Behaviour)componentsInChildren[j]).enabled = true;
				}
				segment.lamp = MakeIcon(segment.root, Vector2.zero, new Vector2(21f, 19f), 34f);
				GameObject val5 = new GameObject("FlashIcon", new Type[1] { typeof(RectTransform) });
				val5.transform.SetParent((Transform)(object)segment.root, false);
				segment.flashIcon = (RectTransform)val5.transform;
				RectTransform flashIcon = segment.flashIcon;
				offsetMin = (segment.flashIcon.anchorMax = Vector2.zero);
				flashIcon.anchorMin = offsetMin;
				segment.flashIcon.pivot = Vector2.zero;
				segment.flashIcon.sizeDelta = new Vector2(30f, 24f);
				((Transform)segment.flashIcon).localScale = Vector3.one * 1.3f;
				segment.flashIcon.anchoredPosition = new Vector2(-55f, 0.84000015f);
				string[] array = new string[3] { "Icon", "Outline", "Flash" };
				foreach (string text in array)
				{
					Transform val6 = ((Transform)flashlightRow).Find(text);
					if (!((Object)(object)val6 == (Object)null))
					{
						GameObject val7 = Object.Instantiate<GameObject>(((Component)val6).gameObject, (Transform)(object)segment.flashIcon, false);
						if (text == "Icon")
						{
							segment.flashFillImage = val7.GetComponent<Image>();
						}
					}
				}
				if ((Object)(object)eladBatteryText != (Object)null)
				{
					GameObject val8 = Object.Instantiate<GameObject>(((Component)eladBatteryText).gameObject, (Transform)(object)segment.root, false);
					segment.text = val8.GetComponent<TextMeshProUGUI>();
					((Behaviour)segment.text).enabled = true;
					((TMP_Text)segment.text).fontSize = ((TMP_Text)hud.batteryText).fontSize;
					((TMP_Text)segment.text).enableWordWrapping = false;
					((TMP_Text)segment.text).overflowMode = (TextOverflowModes)0;
					RectTransform rectTransform = ((TMP_Text)segment.text).rectTransform;
					offsetMin = (rectTransform.anchorMax = Vector2.zero);
					rectTransform.anchorMin = offsetMin;
					rectTransform.pivot = Vector2.zero;
					rectTransform.sizeDelta = new Vector2(200f, 22.5f);
				}
				segments[i] = segment;
			}
			((Component)compactRoot).gameObject.SetActive(false);
		}

		private void ApplyCompact(GrabbableObject held, bool heldShown, bool heldIsHeadwear, GrabbableObject item, bool flashlightShown)
		{
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)compactRoot == (Object)null)
			{
				BuildCompact();
			}
			int num = 0;
			if (heldShown)
			{
				Segment segment = segments[num++];
				if (heldIsHeadwear)
				{
					ShowLampSegment(segment, held);
				}
				else
				{
					ShowKind(segment, battery: true);
					if ((Object)(object)segment.batteryFillImage != (Object)null && (Object)(object)hud.batteryBar != (Object)null)
					{
						segment.batteryFillImage.fillAmount = hud.batteryBar.fillAmount;
					}
					SetSegText(segment, CompactBatteryText(((Object)(object)hud.batteryText != (Object)null) ? ((TMP_Text)hud.batteryText).text : ""), 30f);
				}
			}
			if ((Object)(object)item != (Object)null)
			{
				ShowLampSegment(segments[num++], item);
			}
			if (flashlightShown)
			{
				Segment segment2 = segments[num++];
				ShowKind(segment2, battery: false, lamp: false, flash: true);
				if ((Object)(object)segment2.flashFillImage != (Object)null && (Object)(object)hud.flashlightBar != (Object)null)
				{
					segment2.flashFillImage.fillAmount = hud.flashlightBar.fillAmount;
				}
				SetSegText(segment2, CompactFlashlightText(((Object)(object)hud.flashlightText != (Object)null) ? ((TMP_Text)hud.flashlightText).text : ""), 46f);
			}
			float num2 = -4f;
			for (int i = 0; i < segments.Length; i++)
			{
				Segment segment3 = segments[i];
				((Component)segment3.root).gameObject.SetActive(i < num);
				if (i < num)
				{
					segment3.root.anchoredPosition = new Vector2(num2, 0f);
					num2 += ((TMP_Text)segment3.text).rectTransform.anchoredPosition.x + ((TMP_Text)segment3.text).preferredWidth + 10f;
				}
			}
			((Component)smallRow).gameObject.SetActive(false);
			RestoreFlashlightRow();
			((Component)hud.flashlightGroup).gameObject.SetActive(false);
			SetBigMode(big: false);
			SetEladBatteryVisible(num == 0);
			((Component)compactRoot).gameObject.SetActive(num > 0);
			((Component)hud.batteryGroup).gameObject.SetActive(num > 0);
			compactActive = true;
		}

		private void LeaveCompact()
		{
			if (compactActive)
			{
				compactActive = false;
				if ((Object)(object)compactRoot != (Object)null)
				{
					((Component)compactRoot).gameObject.SetActive(false);
				}
				SetEladBatteryVisible(visible: true);
			}
		}

		private void SetEladBatteryVisible(bool visible)
		{
			if ((Object)(object)batteryBG != (Object)null)
			{
				((Behaviour)batteryBG).enabled = visible && !batteryIconsHidden;
			}
			if ((Object)(object)batteryFill != (Object)null)
			{
				((Behaviour)batteryFill).enabled = visible && !batteryIconsHidden;
			}
			if ((Object)(object)eladBatteryText != (Object)null)
			{
				((Behaviour)eladBatteryText).enabled = visible;
			}
		}

		private void ShowLampSegment(Segment seg, GrabbableObject item)
		{
			ShowKind(seg, battery: false, lamp: true);
			Describe(item, out var charge, out var on, out var percent, out var secondsLeft);
			SetIcon(seg.lamp, charge, on);
			MarkRedIfFastDrain(seg.text, item);
			string text = $"{percent}%";
			if (Plugin.displayTimeLeft.Value)
			{
				text += string.Format(" {0}({1}:{2})</size>", "<size=70%>", secondsLeft / 60, (secondsLeft % 60).ToString("D2"));
			}
			SetSegText(seg, text, 42f);
		}

		private static void ShowKind(Segment seg, bool battery = false, bool lamp = false, bool flash = false)
		{
			((Component)seg.batteryIcon).gameObject.SetActive(battery);
			((Component)seg.lamp.root).gameObject.SetActive(lamp);
			((Component)seg.flashIcon).gameObject.SetActive(flash);
		}

		private static void SetSegText(Segment seg, string text, float iconWidth)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)seg.text == (Object)null))
			{
				((TMP_Text)seg.text).text = text;
				((TMP_Text)seg.text).rectTransform.anchoredPosition = new Vector2(iconWidth + 2f, 5f);
			}
		}

		private static string CompactBatteryText(string text)
		{
			text = text.Replace(" remaining)", ")");
			int num = text.IndexOf(" (", StringComparison.Ordinal);
			if (num >= 0)
			{
				return text.Substring(0, num) + " <size=70%>" + text.Substring(num + 1) + "</size>";
			}
			return text;
		}

		private static string CompactFlashlightText(string text)
		{
			int num = text.IndexOf("<size=60%>", StringComparison.Ordinal);
			if (num < 0)
			{
				return text.Trim();
			}
			string text2 = text.Substring(0, num).Trim();
			string text3 = text.Substring(num + "<size=60%>".Length).Replace("</size>", "").Trim();
			if (text3.Length <= 0)
			{
				return text2;
			}
			return text2 + " <size=70%>(" + text3 + ")</size>";
		}

		private void ShowBig(GrabbableObject item)
		{
			Describe(item, out var charge, out var on, out var percent, out var secondsLeft);
			SetIcon(bigIcon, charge, on);
			MarkRedIfFastDrain(hud.batteryText, item);
			if ((Object)(object)hud.batteryText != (Object)null)
			{
				((TMP_Text)hud.batteryText).text = $"{percent}%";
				if (Plugin.displayTimeLeft.Value)
				{
					TextMeshProUGUI batteryText = hud.batteryText;
					((TMP_Text)batteryText).text = ((TMP_Text)batteryText).text + string.Format(" ({0}:{1} remaining)", secondsLeft / 60, (secondsLeft % 60).ToString("D2"));
				}
			}
		}

		private static void Describe(GrabbableObject item, out float charge, out bool on, out int percent, out int secondsLeft)
		{
			charge = Mathf.Clamp01(item.insertedBattery.charge);
			on = IsOn(item) && charge > 0f;
			percent = Mathf.CeilToInt(charge * 100f);
			secondsLeft = Mathf.CeilToInt(charge * SecondsPerFullCharge(item));
		}

		private static bool IsHeadwear(GrabbableObject item)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null || !item.itemProperties.requiresBattery || item.insertedBattery == null)
			{
				return false;
			}
			if (!helmetInterfaceChecked)
			{
				helmetInterfaceChecked = true;
				helmetInterface = Plugin.FindType("AdvancedCompany", "AdvancedCompany.Objects.IHelmet");
			}
			if (helmetInterface != null)
			{
				return helmetInterface.IsInstanceOfType(item);
			}
			return false;
		}

		private void SetIcon(LampIcon icon, float charge, bool on)
		{
			icon.fill.fillAmount = charge;
			((Behaviour)icon.fill).enabled = charge > 0f;
			((Behaviour)icon.rays).enabled = on;
		}

		private void SetBigMode(bool big)
		{
			((Component)bigIcon.root).gameObject.SetActive(big);
			if (big != batteryIconsHidden)
			{
				batteryIconsHidden = big;
				if ((Object)(object)batteryBG != (Object)null)
				{
					((Behaviour)batteryBG).enabled = !big;
				}
				if ((Object)(object)batteryFill != (Object)null)
				{
					((Behaviour)batteryFill).enabled = !big;
				}
			}
		}
	}
	internal class HudExtras : MonoBehaviour
	{
		internal enum MicIconStyle
		{
			Solid,
			TopGap,
			FullGap
		}

		private enum MicState
		{
			Hidden,
			Talking,
			Muted
		}

		internal static ConfigEntry<bool> moveUtilitySlot;

		internal static ConfigEntry<bool> hideUtilityKey;

		internal static ConfigEntry<float> utilityOffsetX;

		internal static ConfigEntry<float> utilityOffsetY;

		internal static ConfigEntry<bool> showMic;

		internal static ConfigEntry<bool> showMuted;

		internal static ConfigEntry<float> micOffsetX;

		internal static ConfigEntry<float> micOffsetY;

		internal static ConfigEntry<float> micSize;

		internal static ConfigEntry<MicIconStyle> micStyle;

		public static HudExtras instance;

		private const float SlotLeft = 291f;

		private const float SlotCenterY = -138f;

		private const float MicLeft = 277f;

		private const float MicCenterY = -84f;

		private const float MicBaseSize = 36f;

		private static readonly Color MutedColor = new Color(1f, 0.22f, 0.2f, 0.9f);

		private RectTransform hudRect;

		private RectTransform slot;

		private RectTransform slotFrame;

		private Behaviour slotKeyText;

		private Vector3 slotHomePos;

		private bool slotPlaced;

		private RectTransform micRect;

		private Image micImage;

		private Sprite micSprite;

		private Sprite mutedSprite;

		private Color talkingColor;

		private float talkHold;

		private readonly Dictionary<string, Sprite> spriteCache = new Dictionary<string, Sprite>();

		private Image vanillaPTT;

		private float vanillaPTTAlpha = -1f;

		internal static void Bind(ConfigFile config)
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			moveUtilitySlot = config.Bind<bool>("UtilitySlot", "NextToHealthBar", true, "Put the utility slot at the right end of the health bar. Off = where it was before (above the HUD).");
			hideUtilityKey = config.Bind<bool>("UtilitySlot", "HideKeyText", true, "Hide the [TAB] key text next to the utility slot.");
			utilityOffsetX = config.Bind<float>("UtilitySlot", "OffsetX", 0f, "Move the utility slot left/right (negative = left).");
			utilityOffsetY = config.Bind<float>("UtilitySlot", "OffsetY", 0f, "Move the utility slot up/down (negative = down).");
			showMic = config.Bind<bool>("Mic", "ShowMicIcon", true, "Show a mic icon at the right end of the stamina bar while you talk (push to talk: while the talk key is held; voice activation: while the game hears you). Off = no mic icon (the muted icon has its own setting).");
			showMuted = config.Bind<bool>("Mic", "ShowMutedIcon", true, "Show a red crossed-out mic while your mic is turned off in the game settings.");
			micStyle = config.Bind<MicIconStyle>("Mic", "IconStyle", MicIconStyle.Solid, "How the mic icon is drawn.\nSolid - one solid shape.\nTopGap - the top part has an outline with a gap inside, like the battery icon; thin stand.\nFullGap - the top part and the stand both have an outline with a gap inside.");
			micOffsetX = config.Bind<float>("Mic", "OffsetX", 0f, "Move the mic icon left/right (negative = left).");
			micOffsetY = config.Bind<float>("Mic", "OffsetY", 0f, "Move the mic icon up/down (negative = down).");
			micSize = config.Bind<float>("Mic", "Size", 1f, new ConfigDescription("Size of the mic icon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			utilityOffsetX.SettingChanged += delegate
			{
				instance?.Dirty();
			};
			utilityOffsetY.SettingChanged += delegate
			{
				instance?.Dirty();
			};
			moveUtilitySlot.SettingChanged += delegate
			{
				instance?.Dirty();
			};
			micOffsetX.SettingChanged += delegate
			{
				instance?.PlaceMic();
			};
			micOffsetY.SettingChanged += delegate
			{
				instance?.PlaceMic();
			};
			micSize.SettingChanged += delegate
			{
				instance?.PlaceMic();
			};
			micStyle.SettingChanged += delegate
			{
				instance?.LoadMicSprites();
			};
		}

		internal static void Create(GameObject hud, HUDManager hudManager, CustomHUD_Mono mono)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			HudExtras hudExtras = (instance = hud.AddComponent<HudExtras>());
			hudExtras.hudRect = (RectTransform)hud.transform;
			try
			{
				ref RectTransform reference = ref hudExtras.slot;
				Transform parent = ((Component)hudManager.itemOnlySlotIcon).transform.parent;
				reference = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				hudExtras.slotFrame = (((Object)(object)hudManager.itemOnlySlotIconFrame != (Object)null) ? ((Graphic)hudManager.itemOnlySlotIconFrame).rectTransform : null);
				hudExtras.slotKeyText = (Behaviour)(object)hudManager.utilitySlotKeyText;
				if ((Object)(object)hudExtras.slot != (Object)null)
				{
					hudExtras.slotHomePos = ((Transform)hudExtras.slot).localPosition;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log("Utility slot: " + ex.Message);
			}
			hudExtras.talkingColor = (Color)(((Object)(object)mono.carryText != (Object)null) ? ((Graphic)mono.carryText).color : new Color(1f, 0.43f, 0f));
			hudExtras.talkingColor.a = 1f;
			hudExtras.BuildMic();
		}

		private void Dirty()
		{
			slotPlaced = false;
		}

		private void PlaceSlot()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)slot == (Object)null)
			{
				return;
			}
			((Transform)slot).localPosition = slotHomePos;
			if (!moveUtilitySlot.Value)
			{
				slotPlaced = true;
				return;
			}
			RectTransform obj = (((Object)(object)slotFrame != (Object)null) ? slotFrame : slot);
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			obj.GetWorldCorners(array);
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			Vector3[] array2 = array;
			foreach (Vector3 val in array2)
			{
				Vector3 val2 = ((Transform)hudRect).InverseTransformPoint(val);
				num = Mathf.Min(num, val2.x);
				num2 = Mathf.Max(num2, val2.x);
				num3 = Mathf.Min(num3, val2.y);
				num4 = Mathf.Max(num4, val2.y);
			}
			if (!(num4 - num3 < 1f))
			{
				float num5 = 291f + utilityOffsetX.Value - num;
				float num6 = -138f + utilityOffsetY.Value - (num3 + num4) / 2f;
				RectTransform obj2 = slot;
				((Transform)obj2).localPosition = ((Transform)obj2).localPosition + new Vector3(num5, num6, 0f);
				slotPlaced = true;
			}
		}

		private void BuildMic()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0064: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			LoadMicSprites();
			GameObject val = new GameObject("SleepyMiles Mic", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)hudRect, false);
			micRect = (RectTransform)val.transform;
			RectTransform obj = micRect;
			RectTransform obj2 = micRect;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0f, 1f);
			obj2.anchorMax = val2;
			obj.anchorMin = val2;
			micRect.pivot = new Vector2(0f, 0.5f);
			micImage = val.AddComponent<Image>();
			((Graphic)micImage).raycastTarget = false;
			micImage.preserveAspect = true;
			((Behaviour)micImage).enabled = false;
			PlaceMic();
		}

		private Sprite GetSprite(string file)
		{
			if (!spriteCache.TryGetValue(file, out var value))
			{
				value = StatusPanel.LoadSprite(file, mipmaps: false);
				spriteCache[file] = value;
			}
			return value;
		}

		private void LoadMicSprites()
		{
			string text = micStyle.Value.ToString();
			micSprite = GetSprite("Mic_" + text + ".png");
			mutedSprite = GetSprite("Mic_" + text + "_Muted.png");
		}

		private void PlaceMic()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)micRect == (Object)null))
			{
				float num = 36f * micSize.Value;
				micRect.sizeDelta = new Vector2(num, num);
				micRect.anchoredPosition = new Vector2(277f + micOffsetX.Value, -84f + micOffsetY.Value);
			}
		}

		private void HideVanillaPTT()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)vanillaPTT == (Object)null)
			{
				vanillaPTT = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.PTTIcon : null);
				if ((Object)(object)vanillaPTT == (Object)null)
				{
					return;
				}
				vanillaPTTAlpha = ((Graphic)vanillaPTT).color.a;
			}
			Color color = ((Graphic)vanillaPTT).color;
			float num = (showMic.Value ? 0f : vanillaPTTAlpha);
			if (color.a != num)
			{
				color.a = num;
				((Graphic)vanillaPTT).color = color;
			}
		}

		private MicState GetMicState()
		{
			Settings val = IngamePlayerSettings.Instance?.settings;
			if (val == null)
			{
				return MicState.Hidden;
			}
			if (!val.micEnabled)
			{
				if (!showMuted.Value)
				{
					return MicState.Hidden;
				}
				return MicState.Muted;
			}
			if (!showMic.Value)
			{
				return MicState.Hidden;
			}
			DissonanceComms val2 = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.voiceChatModule : null);
			if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).enabled)
			{
				return MicState.Hidden;
			}
			if (val2.IsMuted)
			{
				talkHold = 0f;
				return MicState.Hidden;
			}
			if (val.pushToTalk)
			{
				return MicState.Talking;
			}
			bool flag = false;
			try
			{
				VoicePlayerState val3 = val2.FindPlayer(val2.LocalPlayerName);
				flag = val3 != null && val3.IsSpeaking;
			}
			catch
			{
			}
			if (flag)
			{
				talkHold = 0.3f;
			}
			else
			{
				talkHold -= Time.deltaTime;
			}
			if (!(talkHold > 0f))
			{
				return MicState.Hidden;
			}
			return MicState.Talking;
		}

		private void LateUpdate()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (!slotPlaced)
			{
				try
				{
					PlaceSlot();
				}
				catch (Exception ex)
				{
					Plugin.Log("Utility slot: " + ex.Message);
					slotPlaced = true;
				}
			}
			if ((Object)(object)slotKeyText != (Object)null)
			{
				bool flag = !hideUtilityKey.Value;
				if (slotKeyText.enabled != flag)
				{
					slotKeyText.enabled = flag;
				}
			}
			if (!((Object)(object)micImage == (Object)null))
			{
				HideVanillaPTT();
				MicState micState = MicState.Hidden;
				try
				{
					micState = GetMicState();
				}
				catch
				{
				}
				Sprite val = null;
				Color mutedColor = talkingColor;
				switch (micState)
				{
				case MicState.Talking:
					val = micSprite;
					break;
				case MicState.Muted:
					val = mutedSprite;
					mutedColor = MutedColor;
					break;
				}
				if ((Object)(object)val == (Object)null)
				{
					((Behaviour)micImage).enabled = false;
					return;
				}
				micImage.sprite = val;
				((Graphic)micImage).color = mutedColor;
				((Behaviour)micImage).enabled = true;
			}
		}
	}
	internal class HudOutline : MonoBehaviour
	{
		private bool applied;

		private bool dirty = true;

		private float nextScan;

		private TMP_FontAsset vanillaFont;

		private Material vanillaMaterial;

		private static HudOutline instance;

		public static void Create(GameObject hud)
		{
			instance = hud.AddComponent<HudOutline>();
		}

		public static void Bind(ConfigFile cfg)
		{
			Plugin.textOutline = cfg.Bind<bool>("Outline", "OutlineNumbers", false, "Outline the stamina / weight numbers and the battery, flashlight and head item % rows like the vanilla control tips on the right of the screen (same game font and outline).");
			Plugin.textOutline.SettingChanged += delegate
			{
				if ((Object)(object)instance != (Object)null)
				{
					instance.dirty = true;
				}
			};
		}

		private void LateUpdate()
		{
			if (!dirty && Time.unscaledTime < nextScan)
			{
				return;
			}
			nextScan = Time.unscaledTime + 0.5f;
			bool value = Plugin.textOutline.Value;
			if (!value && !applied)
			{
				dirty = false;
				return;
			}
			try
			{
				if (!value || !((Object)(object)vanillaFont == (Object)null) || FindVanilla())
				{
					Apply(value, dirty);
					applied = value;
					dirty = false;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log("Outline: " + ex.Message);
			}
		}

		private void Apply(bool on, bool force)
		{
			TextMeshProUGUI[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val in componentsInChildren)
			{
				if (!IsNumberText(val))
				{
					continue;
				}
				OutlineMarker outlineMarker = ((Component)val).GetComponent<OutlineMarker>();
				if (!force && (Object)(object)outlineMarker != (Object)null)
				{
					continue;
				}
				if ((Object)(object)outlineMarker == (Object)null)
				{
					outlineMarker = ((Component)val).gameObject.AddComponent<OutlineMarker>();
					outlineMarker.originalFont = ((TMP_Text)val).font;
					outlineMarker.original = ((TMP_Text)val).fontSharedMaterial;
				}
				if (on)
				{
					if ((Object)(object)((TMP_Text)val).font != (Object)(object)vanillaFont)
					{
						((TMP_Text)val).font = vanillaFont;
					}
					((TMP_Text)val).fontSharedMaterial = vanillaMaterial;
				}
				else
				{
					if ((Object)(object)outlineMarker.originalFont != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)(object)outlineMarker.originalFont)
					{
						((TMP_Text)val).font = outlineMarker.originalFont;
					}
					((TMP_Text)val).fontSharedMaterial = outlineMarker.original;
				}
				((TMP_Text)val).UpdateMeshPadding();
				((Graphic)val).SetVerticesDirty();
			}
		}

		private bool FindVanilla()
		{
			HUDManager val = HUDManager.Instance;
			if ((Object)(object)val == (Object)null || val.controlTipLines == null)
			{
				return false;
			}
			TextMeshProUGUI[] controlTipLines = val.controlTipLines;
			foreach (TextMeshProUGUI val2 in controlTipLines)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((TMP_Text)val2).font == (Object)null) && !((Object)(object)((TMP_Text)val2).fontSharedMaterial == (Object)null))
				{
					vanillaFont = ((TMP_Text)val2).font;
					vanillaMaterial = ((TMP_Text)val2).fontSharedMaterial;
					return true;
				}
			}
			return false;
		}

		private static bool IsNumberText(TextMeshProUGUI text)
		{
			string name = ((Object)text).name;
			switch (name)
			{
			default:
				return name.StartsWith("BatteryStuf");
			case "StaminaInfo":
			case "CarryInfo":
			case "Battery":
				return true;
			}
		}
	}
	internal class OutlineMarker : MonoBehaviour
	{
		public TMP_FontAsset originalFont;

		public Material original;
	}
	[HarmonyPatch(typeof(CustomHUD_Mono), "UpdateFromPlayer")]
	internal static class InjectorTint
	{
		private static readonly Color InjectorColor = new Color(0f, 0.9f, 1f);

		private const float FadeInSpeed = 2f;

		private const float FadeOutSpeed = 1f;

		private static bool checkedType;

		private static Type effectType;

		private static float intensity;

		[HarmonyPostfix]
		[HarmonyPriority(200)]
		[HarmonyAfter(new string[] { "Miles.TZPPlus" })]
		private static void Postfix(CustomHUD_Mono __instance, PlayerControllerB player)
		{
			//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_00bd: 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_00cf: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!checkedType)
				{
					checkedType = true;
					effectType = Plugin.FindType("UsualScrap", "UsualScrap.Behaviors.Effects.ProductivityAutoinjectorEffect");
				}
				if (!(effectType == null) && !((Object)(object)__instance.staminaBar == (Object)null))
				{
					bool flag = Plugin.injectorStaminaColor.Value && (Object)(object)player != (Object)null && (Object)(object)((Component)player).GetComponent(effectType) != (Object)null;
					intensity = Mathf.MoveTowards(intensity, flag ? 1f : 0f, (flag ? 2f : 1f) * Time.deltaTime);
					if (!(intensity <= 0f))
					{
						Color val = Color.Lerp(InjectorColor, __instance.staminaWarnColor, __instance.colorLerp);
						((Graphic)__instance.staminaBar).color = Color.Lerp(((Graphic)__instance.staminaBar).color, val, intensity);
					}
				}
			}
			catch
			{
			}
		}
	}
	[BepInPlugin("me.eladnlg.customhud", "EladsHUD+", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin instance;

		public AssetBundle assets;

		public GameObject HUD;

		public static bool shouldDoKGConversion;

		internal static ConfigEntry<PocketFlashlightOptions> pocketedFlashlightDisplayMode;

		internal static ConfigEntry<StaminaTextOptions> detailedStamina;

		internal static ConfigEntry<bool> displayTimeLeft;

		internal static ConfigEntry<float> hudScale;

		internal static ConfigEntry<bool> autoHideHealthbar;

		internal static ConfigEntry<float> healthbarHideDelay;

		internal static ConfigEntry<bool> hidePlanetInfo;

		internal static ConfigEntry<bool> showStatusWarnings;

		internal static ConfigEntry<float> statusWarningTime;

		internal static ConfigEntry<bool> showFrailtyConditions;

		internal static ConfigEntry<bool> showBuffs;

		internal static ConfigEntry<bool> coloredBuffNumbers;

		internal static ConfigEntry<bool> injectorStaminaColor;

		internal static ConfigEntry<bool> showHeadwear;

		internal static ConfigEntry<bool> showHeadwearWhenOff;

		internal static ConfigEntry<bool> flashlightGap;

		internal static ConfigEntry<bool> compactBattery;

		internal static ConfigEntry<bool> textOutline;

		internal static ConfigEntry<float> statusOffsetX;

		internal static ConfigEntry<int> statusIconsPerRow;

		internal static ConfigEntry<bool> statusShrinkRows;

		internal static ConfigEntry<float> statusOffsetY;

		internal static void Log(string message)
		{
			Plugin plugin = instance;
			if (plugin != null)
			{
				((BaseUnityPlugin)plugin).Logger.LogInfo((object)message);
			}
		}

		internal static void LogError(string message)
		{
			Plugin plugin = instance;
			if (plugin != null)
			{
				((BaseUnityPlugin)plugin).Logger.LogError((object)message);
			}
		}

		internal static Type FindType(string assemblyName, string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetName().Name == assemblyName)
					{
						return assembly.GetType(fullName, throwOnError: false);
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private void Awake()
		{
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Expected O, but got Unknown
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)instance != (Object)null)
			{
				throw new Exception("what the cuck??? more than 1 plugin instance.");
			}
			instance = this;
			hudScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HUDScale", 1f, "The size of the HUD.");
			autoHideHealthbar = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideHealthbarAutomatically", true, "Should the healthbar be hidden after not taking damage for a while.");
			healthbarHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HealthbarHideDelay", 4f, "The amount of time before the healthbar starts fading away.");
			pocketedFlashlightDisplayMode = ((BaseUnityPlugin)this).Config.Bind<PocketFlashlightOptions>("General", "FlashlightBattery", PocketFlashlightOptions.Separate, "How the flashlight battery is displayed whilst unequipped.\nDisabled - Flashlight battery will not be displayed.\nVanilla - Flashlight battery will be displayed when you don't have a battery-using item equipped.\nSeparate - Flashlight battery will be displayed using a dedicated panel. (recommended)");
			detailedStamina = ((BaseUnityPlugin)this).Config.Bind<StaminaTextOptions>("General", "DetailedStamina", StaminaTextOptions.PercentageOnly, "What the stamina text should display.\nDisabled - The stamina text will be hidden.\nPercentageOnly - Only the percentage will be displayed. (recommended)\nFull - Both percentage and rate of gain/loss will be displayed.");
			displayTimeLeft = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisplayTimeLeft", true, "Should the uses/time left for a battery-using item be displayed.");
			hidePlanetInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HidePlanetInfo", false, "Should planet info be hidden. If modifying from an in-game menu, this requires you to rejoin the game.");
			showStatusWarnings = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "ShowWarnings", true, "Show the vanilla warning text (steam leak, Cadaver spores / fever, low oxygen) under the health bar. Vanilla shows it in the HUD that Elad's HUD hides.");
			statusWarningTime = ((BaseUnityPlugin)this).Config.Bind<float>("Status", "WarningTime", 4f, new ConfigDescription("How many seconds a warning stays after its cause stops (steam leak warnings stay while you are in the steam).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), Array.Empty<object>()));
			showFrailtyConditions = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "ShowFrailtyConditions", true, "If the Frailty mod is installed, show its status effects (broken leg, bleeding, ...) with the time left under the health bar, instead of Frailty's own icons.");
			showBuffs = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "ShowBuffs", true, "Show UsualScrap's Productivity Auto-Injector (time left) under the health bar. Other mods (e.g. TZPPlus) add their own icons here through StatusApi and have their own settings.");
			coloredBuffNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "ColoredBuffNumbers", false, "Buff numbers (TZP %, TZP Rush and injector time) in the buff's own colour instead of white.");
			injectorStaminaColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "InjectorStaminaColor", true, "The stamina bar fades to cyan while UsualScrap's Productivity Auto-Injector is active (still turns red when stamina is low).");
			showHeadwear = ((BaseUnityPlugin)this).Config.Bind<bool>("Headwear", "ShowHeadwearBattery", true, "Show the battery of the AdvancedCompany head-slot item (Helmet Lamp, Tactical Helmet, Headset, Vision Enhancer). Alone it uses the normal battery row; with a battery item or TZP in your hand it moves to a small row above (next to the flashlight if that is shown too).");
			showHeadwearWhenOff = ((BaseUnityPlugin)this).Config.Bind<bool>("Headwear", "ShowWhenSwitchedOff", true, "Keep showing the head item while it is switched off (light rays only show while it is on). Off = only show it while it is on, like the pocketed flashlight.");
			flashlightGap = ((BaseUnityPlugin)this).Config.Bind<bool>("Headwear", "FlashlightIconGap", true, "Give the pocketed-flashlight icon a small gap inside its outline, like the battery and head lamp icons. Needs a rejoin to change.");
			compactBattery = ((BaseUnityPlugin)this).Config.Bind<bool>("Headwear", "CompactBatteryUI", false, "Compact battery UI: held item, head item and flashlight all in the main battery row (left to right, in that order), with slightly smaller numbers and (4:30) instead of (4:30 remaining).");
			HudOutline.Bind(((BaseUnityPlugin)this).Config);
			CursorMode.Bind(((BaseUnityPlugin)this).Config);
			HudExtras.Bind(((BaseUnityPlugin)this).Config);
			statusIconsPerRow = ((BaseUnityPlugin)this).Config.Bind<int>("Status", "IconsPerRow", 7, new ConfigDescription("Status icons per row. While everything fits, it stays one row (buffs first, then injuries / debuffs). With more, buffs get their own row(s) and injuries / debuffs start a new row below.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			statusShrinkRows = ((BaseUnityPlugin)this).Config.Bind<bool>("Status", "ShrinkWithMoreRows", false, "Make the status icons a bit smaller once there are 2 or more rows.");
			statusOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Status", "OffsetX", 0f, "Move the status area left/right (negative = left).");
			statusOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Status", "OffsetY", 0f, "Move the status area up/down (negative = down).");
			statusOffsetX.SettingChanged += delegate
			{
				StatusPanel.instance?.ApplyOffset();
			};
			statusOffsetY.SettingChanged += delegate
			{
				StatusPanel.instance?.ApplyOffset();
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"EladsHUD+ 1.0.0 is loaded!");
			assets = AssetUtils.LoadAssetBundleFromResources("customhud", typeof(PlayerPatches).Assembly);
			HUD = assets.LoadAsset<GameObject>("PlayerInfo");
			new Harmony("me.eladnlg.customhud").PatchAll(Assembly.GetExecutingAssembly());
		}

		private void Start()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(Chainloader.PluginInfos.Count + " plugins loaded"));
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin GUID: " + pluginInfo.Value.Metadata.GUID));
			}
			shouldDoKGConversion = Chainloader.PluginInfos.Any((KeyValuePair<string, PluginInfo> pair) => pair.Value.Metadata.GUID == "com.zduniusz.lethalcompany.lbtokg");
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class HUDPatches
	{
		private static void Safe(string what, Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				Plugin.LogError(what + " could not be created: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(HUDManager __instance)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			HUDElement[] privateField = __instance.GetPrivateField<HUDElement[]>("HUDElements");
			HUDElement val = privateField[2];
			GameObject HUD = Object.Instantiate<GameObject>(Plugin.instance.HUD, ((Component)val.canvasGroup).transform.parent);
			HUD.transform.localScale = Vector3.one * 0.75f * Plugin.hudScale.Value;
			Transform parent = ((Component)__instance.itemOnlySlotIcon).transform.parent;
			parent.SetParent(HUD.transform, true);
			parent.SetAsLastSibling();
			val.canvasGroup.alpha = 0f;
			Transform val2 = ((Component)val.canvasGroup).transform.Find("CinematicGraphics");
			if ((Object)(object)val2 != (Object)null && !Plugin.hidePlanetInfo.Value)
			{
				val2.SetParent(HUD.transform.parent);
			}
			privateField[2].canvasGroup = HUD.GetComponent<CanvasGroup>();
			CustomHUD_Mono mono = HUD.GetComponent<CustomHUD_Mono>();
			if ((Object)(object)mono == (Object)null)
			{
				Plugin.LogError("The HUD prefab lost its CustomHUD_Mono script (assembly must be named EladsHUD). EladsHUD+ extras disabled.");
				return;
			}
			Safe("Status row", delegate
			{
				StatusPanel.Create(HUD, mono);
			});
			Safe("Head item battery", delegate
			{
				HeadwearHud.Create(mono);
			});
			Safe("Outline", delegate
			{
				HudOutline.Create(HUD);
			});
			Safe("Cursor mode", delegate
			{
				CursorMode.Create(HUD);
			});
			Safe("Utility slot / mic", delegate
			{
				HudExtras.Create(HUD, __instance, mono);
			});
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class PlayerPatches
	{
		private static readonly HashSet<string> loggedErrors = new HashSet<string>();

		[HarmonyPrefix]
		[HarmonyPatch("LateUpdate")]
		private static void LateUpdate_Prefix(PlayerControllerB __instance)
		{
			if (!((NetworkBehaviour)__instance).IsOwner || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject) || (Object)(object)CustomHUD_Mono.instance == (Object)null)
			{
				return;
			}
			try
			{
				CustomHUD_Mono.instance.UpdateFromPlayer(__instance);
			}
			catch (Exception ex)
			{
				string item = ex.GetType().Name + ex.StackTrace;
				if (loggedErrors.Add(item))
				{
					Plugin.LogError("Elad's HUD update failed (shown once, further ones hidden): " + ex);
				}
			}
		}
	}
	internal static class ReflectionUtils
	{
		public static T GetPrivateField<T>(this object obj, string field)
		{
			return (T)obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
		}
	}
	public static class StatusApi
	{
		public const int Version = 1;

		public static bool Available => (Object)(object)StatusPanel.instance != (Object)null;

		public static void Show(string key, Sprite icon, bool isBuff, Color frameColor, string timer, Color timerColor, string title, string description)
		{
			//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_003a: 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)
			if (!string.IsNullOrEmpty(key))
			{
				StatusPanel.pendingExternal[key] = new StatusPanel.External
				{
					icon = icon,
					isBuff = isBuff,
					frameColor = frameColor,
					timer = timer,
					timerColor = timerColor,
					title = title,
					description = description
				};
			}
		}
	}
	internal static class StatusInfo
	{
		private static readonly Color Injury = new Color(1f, 0.35f, 0.35f);

		private static readonly Color TZP = new Color(1f, 0.72f, 0.11f);

		private static readonly Color Injector = new Color(0f, 0.86f, 1f);

		private static readonly Dictionary<string, (string title, string body, Color color)> entries = new Dictionary<string, (string, string, Color)>
		{
			{
				"BrokenLeg",
				("Broken Leg", "Sprinting drains your stamina much faster.", Injury)
			},
			{
				"FracturedLeg",
				("Fractured Leg", "Sprinting drains your stamina faster.", Injury)
			},
			{
				"BrokenArm",
				("Broken Arm", "You can only hold light items. Anything heavier slips out of your hands.", Injury)
			},
			{
				"FracturedArm",
				("Fractured Arm", "Heavy items slip out of your hands.", Injury)
			},
			{
				"Bleeding",
				("Bleeding", "Your health doesn't regenerate and you leave a blood trail. UsualScrap's Bandages and Medical Kit make it end sooner.", Injury)
			},
			{
				"Blindness",
				("Blinded", "A bright glare washes out your vision.", Injury)
			},
			{
				"Concussed",
				("Concussed", "Your vision blurs when you move, with a red tint and dark edges.", Injury)
			},
			{
				"Laceration",
				("Laceration", "A deep wound. Treat it with a UsualScrap Bandage or Medical Kit before the time runs out, or it turns into Fatal Bleeding.", Injury)
			},
			{
				"FatalBleeding",
				("Fatal Bleeding", "You keep losing health until it stops, and it can kill you. UsualScrap's Bandages and Medical Kit make it end sooner. Healing helps you survive it.", Injury)
			},
			{
				"Paralyze",
				("Paralyze", "Electricity in your body. Every now and then it locks you up for a moment. Higher levels lock you up more often.", Injury)
			},
			{
				"Paralyze2",
				("Paralyze II", "Electricity in your body. Every now and then it locks you up for a moment. Level II: it locks you up more often.", Injury)
			},
			{
				"Paralyze3",
				("Paralyze III", "Electricity in your body. Every now and then it locks you up for a moment. Level III: it locks you up the most often.", Injury)
			},
			{
				"Paralysis",
				("Paralysis", "You can't move or jump, and your camera turns slowly.", Injury)
			},
			{
				"buff:Injector",
				("Productivity Auto-Injector", "You move faster, jump higher and don't feel the weight you carry.", Injector)
			}
		};

		public static bool TryGet(string key, out string title, out string body, out Color color)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			if (entries.TryGetValue(key, out (string, string, Color) value))
			{
				(title, body, color) = value;
				return true;
			}
			title = key;
			body = "";
			color = Color.white;
			return false;
		}
	}
	internal class StatusPanel : MonoBehaviour
	{
		private class Slot
		{
			public RectTransform rect;

			public CanvasGroup group;

			public Image frame;

			public Image icon;

			public TextMeshProUGUI timer;

			public bool active;
		}

		internal struct External
		{
			public Sprite icon;

			public bool isBuff;

			public Color frameColor;

			public Color timerColor;

			public string timer;

			public string title;

			public string description;
		}

		public static StatusPanel instance;

		private const float SlotSize = 30f;

		private const float SlotSpacing = 6f;

		private const float TimerHeight = 16f;

		private const float RowGap = 4f;

		private const float PanelWidth = 270f;

		private RectTransform root;

		private RectTransform conditionRow;

		private RectTransform warningRect;

		private CanvasGroup warningGroup;

		private TextMeshProUGUI warningText;

		private TMP_FontAsset font;

		private float warningHideTime = -1f;

		private readonly Dictionary<string, Slot> slots = new Dictionary<string, Slot>();

		private readonly List<string> order = new List<string>();

		private static bool frailtyChecked;

		private static Type frailtyManagerType;

		private static FieldInfo conditionsField;

		private static FieldInfo startField;

		private static FieldInfo durationField;

		private static FieldInfo typeField;

		private static Type frailtyHudType;

		private static readonly Dictionary<string, string> hudFieldByType = new Dictionary<string, string>
		{
			{ "BrokenLeg", "brokenLegHud" },
			{ "BrokenArm", "brokenArmHud" },
			{ "FracturedLeg", "fracturedLegHud" },
			{ "FracturedArm", "fracturedArmHud" },
			{ "Bleeding", "bleedingHud" },
			{ "Blindness", "blindnessHud" },
			{ "Concussed", "concussedHud" },
			{ "Laceration", "lacerationHud" },
			{ "FatalBleeding", "fatalBleedingHud" },
			{ "Paralyze", "paralyzeHud" },
			{ "Paralyze2", "paralyze2Hud" },
			{ "Paralyze3", "paralyze3Hud" },
			{ "Paralysis", "paralysisHud" }
		};

		private static FieldInfo tierField;

		private static readonly Color InjectorColor = new Color(0f, 0.86f, 1f);

		private static Sprite buffFrame;

		private static Sprite injectorIcon;

		private static bool buffsChecked;

		private static Type injectorType;

		private static FieldInfo injectorTicks;

		private static FieldInfo frailtyConditionHudField;

		private static bool tzpPlusInstalled;

		internal static readonly Dictionary<string, External> pendingExternal = new Dictionary<string, External>();

		private static readonly Dictionary<string, External> externalInfo = new Dictionary<string, External>();

		private const float TooltipWidth = 240f;

		private const float TooltipPad = 7f;

		private RectTransform tooltipRect;

		private CanvasGroup tooltipGroup;

		private TextMeshProUGUI tooltipText;

		private Image tooltipAccent;

		private string tooltipKey;

		public static void Create(GameObject hud, CustomHUD_Mono mono)
		{
			//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)
			GameObject val = new GameObject("StatusPanel (SleepyMiles)", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(hud.transform, false);
			instance = val.AddComponent<StatusPanel>();
			instance.font = (((Object)(object)mono != (Object)null && (Object)(object)mono.healthText != (Object)null) ? ((TMP_Text)mono.healthText).font : null);
			instance.Build();
		}

		private void Build()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			root = (RectTransform)((Component)this).transform;
			root.anchorMin = new Vector2(0f, 0f);
			root.anchorMax = new Vector2(0f, 0f);
			root.pivot = new Vector2(0f, 1f);
			root.sizeDelta = new Vector2(270f, 0f);
			ApplyOffset();
			conditionRow = NewRect("Conditions", (Transform)(object)root);
			RectTransform obj = conditionRow;
			RectTransform obj2 = conditionRow;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			obj2.anchorMax = val;
			obj.anchorMin = val;
			conditionRow.pivot = new Vector2(0f, 1f);
			conditionRow.sizeDelta = new Vector2(270f, 46f);
			warningRect = NewRect("Warning", (Transform)(object)root);
			RectTransform obj3 = warningRect;
			RectTransform obj4 = warningRect;
			((Vector2)(ref val))..ctor(0f, 1f);
			obj4.anchorMax = val;
			obj3.anchorMin = val;
			warningRect.pivot = new Vector2(0f, 1f);
			warningRect.sizeDelta = new Vector2(270f, 80f);
			warningGroup = ((Component)warningRect).gameObject.AddComponent<CanvasGroup>();
			warningGroup.alpha = 0f;
			warningGroup.blocksRaycasts = false;
			warningGroup.interactable = false;
			warningText = NewText(warningRect, 17f, (TextAlignmentOptions)257);
			((TMP_Text)warningText).enableWordWrapping = true;
			RectTransform rectTransform = ((TMP_Text)warningText).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			val = (rectTransform.offsetMin = (rectTransform.offsetMax = Vector2.zero));
			BuildTooltip();
		}

		internal void ApplyOffset()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root != (Object)null)
			{
				root.anchoredPosition = new Vector2(Plugin.statusOffsetX.Value, 5f + Plugin.statusOffsetY.Value);
			}
		}

		private static RectTransform NewRect(string name, Transform parent)
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		private TextMeshProUGUI NewText(RectTransform parent, float size, TextAlignmentOptions align)
		{
			//IL_0038: 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)
			TextMeshProUGUI val = ((Component)NewRect("Text", (Transform)(object)parent)).gameObject.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val).font = font;
			}
			((TMP_Text)val).fontSize = size;
			((TMP_Text)val).alignment = align;
			((Graphic)val).raycastTarget = false;
			((TMP_Text)val).enableWordWrapping = false;
			((TMP_Text)val).overflowMode = (TextOverflowModes)0;
			((Graphic)val).color = Color.white;
			return val;
		}

		public void ShowWarning(string message)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.showStatusWarnings.Value && !string.IsNullOrEmpty(message))
			{
				((TMP_Text)warningText).text = FormatWarning(message);
				TextMeshProUGUI val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.statusEffectText : null);
				((Graphic)warningText).color = (((Object)(object)val != (Object)null) ? new Color(((Graphic)val).color.r, ((Graphic)val).color.g, ((Graphic)val).color.b, 1f) : new Color(1f, 0.35f, 0.25f));
				warningHideTime = Time.time + Mathf.Max(0.5f, Plugin.statusWarningTime.Value);
			}
		}

		private static string FormatWarning(string message)
		{
			string text = message.Replace("\r", "").Replace("\n\n", "\n").Trim();
			int num = text.IndexOf('\n');
			if (num < 0)
			{
				return text;
			}
			return text.Substring(0, num) + "\n<size=80%>" + text.Substring(num + 1) + "</size>";
		}

		private static bool FrailtyAvailable()
		{
			if (!frailtyChecked)
			{
				frailtyChecked = true;
				frailtyManagerType = Plugin.FindType("Frailty", "Frailty.Manager.ConditionManager");
				Type type = Plugin.FindType("Frailty", "Frailty.Manager.Condition");
				frailtyHudType = Plugin.FindType("Frailty", "Frailty.Patches.HUDPatch");
				if (frailtyManagerType != null && type != null)
				{
					conditionsField = AccessTools.Field(frailtyManagerType, "conditions");
					startField = AccessTools.Field(type, "startTime");
					durationField = AccessTools.Field(type, "duration");
					typeField = AccessTools.Field(type, "type");
					tierField = AccessTools.Field(type, "tier");
				}
				if (frailtyManagerType != null)
				{
					if (conditionsField == null || startField == null || durationField == null || typeField == null)
					{
						Plugin.Log("Frailty found, but its conditions changed - status effects not shown in Elad's HUD.");
						frailtyManagerType = null;
					}
					else
					{
						Plugin.Log("Frailty found: status effects with time left are shown under the health bar.");
					}
				}
			}
			return frailtyManagerType != null;
		}

		private Slot GetSlot(string typeName, Action<Slot> setup = null)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			if (slots.TryGetValue(typeName, out var value))
			{
				return value;
			}
			value = new Slot();
			value.rect = NewRect(typeName, (Transform)(object)conditionRow);
			RectTransform rect = value.rect;
			RectTransform rect2 = value.rect;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect2.anchorMax = val;
			rect.anchorMin = val;
			value.rect.pivot = new Vector2(0f, 1f);
			value.rect.sizeDelta = new Vector2(30f, 46f);
			value.group = ((Component)value.rect).gameObject.AddComponent<CanvasGroup>();
			value.group.alpha = 0f;
			value.group.blocksRaycasts = false;
			RectTransform val2 = NewRect("Frame", (Transform)(object)value.rect);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			val2.anchorMax = val;
			val2.anchorMin = val;
			val2.pivot = new Vector2(0.5f, 1f);
			val2.sizeDelta = new Vector2(30f, 30f);
			value.frame = ((Component)val2).gameObject.AddComponent<Image>();
			((Graphic)value.frame).raycastTarget = false;
			RectTransform val3 = NewRect("Icon", (Transform)(object)val2);
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val = (val3.offsetMin = (val3.offsetMax = Vector2.zero));
			value.icon = ((Component)val3).gameObject.AddComponent<Image>();
			((Graphic)value.icon).raycastTarget = false;
			value.icon.preserveAspect = true;
			if (setup != null)
			{
				setup(value);
			}
			else
			{
				CopyFrailtySprites(typeName, value);
			}
			RectTransform val5 = NewRect("Time", (Transform)(object)value.rect);
			((Vector2)(ref val))..ctor(0.5f, 0f);
			val5.anchorMax = val;
			val5.anchorMin = val;
			val5.pivot = new Vector2(0.5f, 0f);
			val5.sizeDelta = new Vector2(36f, 16f);
			value.timer = NewText(val5, 14f, (TextAlignmentOptions)514);
			RectTransform rectTransform = ((TMP_Text)value.timer).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			val = (rectTransform.offsetMin = (rectTransform.offsetMax = Vector2.zero));
			slots[typeName] = value;
			return value;
		}

		private static void CopyFrailtySprites(string typeName, Slot slot)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)slot.frame).color = new Color(1f, 0f, 0.216f, 0.22f);
			((Behaviour)slot.icon).enabled = false;
			try
			{
				if (frailtyHudType == null || !hudFieldByType.TryGetValue(typeName, out var value))
				{
					return;
				}
				object? obj = AccessTools.Field(frailtyHudType, value)?.GetValue(null);
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Image component = val.GetComponent<Image>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null)
				{
					slot.frame.sprite = component.sprite;
					((Graphic)slot.frame).color = ((Graphic)component).color;
				}
				Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
				foreach (Image val2 in componentsInChildren)
				{
					if (!((Object)(object)val2 == (Object)(object)component) && !((Object)(ob