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);
}
}
}