Decompiled source of EladsHUD v1.3.0

BepInEx/plugins/EladsHUD.dll

Decompiled 5 months ago
using System;
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 GameNetcodeStuff;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EladsHUD")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Custom HUD for lethal company :]")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: AssemblyProduct("EladsHUD")]
[assembly: AssemblyTitle("EladsHUD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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;

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

	private float colorLerp;

	private int lastHealth = 100;

	private float lastHealthChange = 0f;

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

	private void Start()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		staminaColor = ((Graphic)staminaBar).color;
	}

	public void UpdateFromPlayer(PlayerControllerB player)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: 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;
		float sprintTime = 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 (Plugin.detailedStamina.Value != 0)
		{
			((TMP_Text)staminaText).text = $"{num}<size=75%><voffset=1>%</voffset></size>";
		}
		else
		{
			((TMP_Text)staminaText).text = "";
		}
		float num4 = Mathf.Sign(num2);
		float num5 = num4;
		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 + " | +" + num3.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 + " | " + num3.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));
	}

	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;
		}
		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;
		}
		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);
		}
		return player.isSprinting ? (-1f / sprintTime * player.carryWeight * num) : ((player.isMovementHindered > 0 && privateField) ? (-1f / sprintTime * num * 0.5f) : ((!privateField) ? (1f / (sprintTime + 4f) * num) : (1f / (sprintTime + 9f) * num)));
	}
}
namespace EladsHUD
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "EladsHUD";

		public const string PLUGIN_NAME = "EladsHUD";

		public const string PLUGIN_VERSION = "1.3.0";
	}
}
namespace CustomHUD
{
	[BepInPlugin("me.eladnlg.customhud", "Elads HUD", "1.2.3")]
	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;

		private void Awake()
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			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.\r\nDisabled - Flashlight battery will not be displayed.\r\nVanilla - Flashlight battery will be displayed when you don't have a battery-using item equipped.\r\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.\r\nDisabled - The stamina text will be hidden.\r\nPercentageOnly - Only the percentage will be displayed. (recommended)\r\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.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Elad's HUD is loaded!");
			assets = AssetUtils.LoadAssetBundleFromResources("customhud", typeof(PlayerPatches).Assembly);
			HUD = assets.LoadAsset<GameObject>("PlayerInfo");
			Harmony val = new Harmony("me.eladnlg.customhud");
			val.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
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(HUDManager __instance)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			HUDElement[] privateField = __instance.GetPrivateField<HUDElement[]>("HUDElements");
			HUDElement val = privateField[2];
			GameObject val2 = Object.Instantiate<GameObject>(Plugin.instance.HUD, ((Component)val.canvasGroup).transform.parent);
			val2.transform.localScale = Vector3.one * 0.75f * Plugin.hudScale.Value;
			val.canvasGroup.alpha = 0f;
			Transform val3 = ((Component)val.canvasGroup).transform.Find("CinematicGraphics");
			if ((Object)(object)val3 != (Object)null && !Plugin.hidePlanetInfo.Value)
			{
				val3.SetParent(val2.transform.parent);
			}
			privateField[2].canvasGroup = val2.GetComponent<CanvasGroup>();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class PlayerPatches
	{
		[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))
			{
				CustomHUD_Mono.instance.UpdateFromPlayer(__instance);
			}
		}
	}
	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);
		}
	}
}
namespace Jotunn.Utils
{
	public static class AssetUtils
	{
		public const char AssetBundlePathSeparator = '$';

		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			string text = texturePath;
			if (relativePath)
			{
				text = Path.Combine(Paths.PluginPath, texturePath);
			}
			if (!File.Exists(text))
			{
				return null;
			}
			if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
			{
				throw new Exception("LoadTexture can only load png or jpg textures");
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			val.LoadRawTextureData(array);
			return val;
		}

		public static Sprite LoadSpriteFromFile(string spritePath)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture(spritePath);
			if ((Object)(object)val != (Object)null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), default(Vector2), 100f);
			}
			return null;
		}

		public static AssetBundle LoadAssetBundle(string bundlePath)
		{
			string text = Path.Combine(Paths.PluginPath, bundlePath);
			if (!File.Exists(text))
			{
				return null;
			}
			return AssetBundle.LoadFromFile(text);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Debug.LogError((object)("AssetBundle " + bundleName + " not found in assembly manifest"));
				return null;
			}
			AssetBundle result;
			using (Stream stream = resourceAssembly.GetManifestResourceStream(text))
			{
				result = AssetBundle.LoadFromStream(stream);
			}
			return result;
		}

		public static string LoadText(string path)
		{
			string text = Path.Combine(Paths.PluginPath, path);
			if (!File.Exists(text))
			{
				Debug.LogError((object)("Error, failed to load contents from non-existant path: $" + text));
				return null;
			}
			return File.ReadAllText(text);
		}

		public static Sprite LoadSprite(string assetPath)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Paths.PluginPath, assetPath);
			if (!File.Exists(text))
			{
				return null;
			}
			if (text.Contains('$'.ToString()))
			{
				string[] array = text.Split('$');
				string text2 = array[0];
				string text3 = array[1];
				AssetBundle val = AssetBundle.LoadFromFile(text2);
				Sprite result = val.LoadAsset<Sprite>(text3);
				val.Unload(false);
				return result;
			}
			Texture2D val2 = LoadTexture(text, relativePath: false);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return null;
			}
			return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero);
		}
	}
}