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 BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NilsHUD;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NilsHUD")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("NilsHUD")]
[assembly: AssemblyTitle("NilsHUD")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
public static class HealthBarPatch
{
private static Dictionary<PlayerControllerB, Vector3> lastPlayerPositions = new Dictionary<PlayerControllerB, Vector3>();
private const float POSITION_THRESHOLD = 0.1f;
public static void Postfix(PlayerControllerB __instance)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_0070: Unknown result type (might be due to invalid IL or missing references)
if (!PluginConfig.ConfigEnableHealthBar.Value)
{
return;
}
HealthBar healthBar = HealthBar.GetHealthBar(__instance);
if ((Object)(object)healthBar != (Object)null)
{
Vector3 position = ((Component)__instance).transform.position;
if (!lastPlayerPositions.ContainsKey(__instance) || Vector3.Distance(position, lastPlayerPositions[__instance]) > 0.1f)
{
healthBar.UpdateHealthBarPosition();
lastPlayerPositions[__instance] = position;
}
}
}
}
public class HealthChangeHelper : MonoBehaviour
{
private void Awake()
{
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
}
public void HandleHealthChange(Image healthBarImage, Image redHealthBarImage, float currentHealth, float maxHealth, float previousHealth)
{
Debug.Log((object)$"HandleHealthChange called, healthBarImage: {healthBarImage}, redHealthBarImage: {redHealthBarImage}");
float num3 = (redHealthBarImage.fillAmount = (healthBarImage.fillAmount = currentHealth / maxHealth));
if (currentHealth < previousHealth)
{
Debug.Log((object)$"Player is being damaged, fillAmount: {num3}");
}
else if (currentHealth > previousHealth)
{
Debug.Log((object)$"Player is being healed, fillAmount: {num3}");
}
}
}
public class HealthBar : MonoBehaviour
{
[HarmonyPatch(typeof(PlayerControllerB), "Start")]
public static class AddHealthBarPatch
{
public static void Postfix(PlayerControllerB __instance)
{
if ((Object)(object)__instance != (Object)(object)PlayerUtils.GetPlayerControllerB() && healthBarList.Count < initialHealthBarCount)
{
GetHealthBar(__instance);
}
}
}
private PlayerControllerB player;
public Image healthBarImage;
public Image redHealthBarImage;
private CanvasGroup healthBarAlpha;
private CanvasGroup redHealthBarAlpha;
private bool isLocalPlayer;
private GameObject healthBarObject;
private float lastHealth;
private float fadeOutDelay;
private float fadeOutTimer = 0f;
private RectTransform healthBarTransform;
private RectTransform redHealthBarTransform;
private RectTransform healthBarFillTransform;
private static PlayerControllerB localPlayerController;
private static Queue<HealthBar> healthBarPool = new Queue<HealthBar>();
private float previousHealth;
private Transform usernameBillboard;
private Transform playerGlobalHead;
private CanvasGroup usernameAlpha;
private float fadeInRate;
private float fadeOutRate;
private HealthChangeHelper healthChangeHelper;
private static int initialHealthBarCount = 4;
private static List<HealthBar> healthBarList = new List<HealthBar>();
private static Dictionary<PlayerControllerB, HealthBar> playerHealthBarMap = new Dictionary<PlayerControllerB, HealthBar>();
public static HealthBar GetHealthBar(PlayerControllerB player)
{
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Expected O, but got Unknown
if ((Object)(object)localPlayerController == (Object)null)
{
localPlayerController = PlayerUtils.GetPlayerControllerB();
}
if ((Object)(object)player == (Object)(object)localPlayerController)
{
return null;
}
if (playerHealthBarMap.TryGetValue(player, out HealthBar value))
{
if ((Object)(object)value != (Object)null && ((Component)value).gameObject.activeSelf)
{
return value;
}
playerHealthBarMap.Remove(player);
}
HealthBar healthBar = healthBarList.Find((HealthBar hb) => !((Component)hb).gameObject.activeSelf);
if ((Object)(object)healthBar != (Object)null)
{
healthBar.player = player;
((Component)healthBar).gameObject.SetActive(true);
playerHealthBarMap[player] = healthBar;
return healthBar;
}
GameObject val = new GameObject("HealthBar");
val.SetActive(false);
HealthBar healthBar2 = val.AddComponent<HealthBar>();
healthBar2.player = player;
healthBar2.InitializeHealthBar();
val.SetActive(true);
healthBarList.Add(healthBar2);
playerHealthBarMap[player] = healthBar2;
return healthBar2;
}
private void Awake()
{
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Expected O, but got Unknown
if (!PluginConfig.ConfigEnableHealthBar.Value)
{
((Component)this).gameObject.SetActive(false);
return;
}
isLocalPlayer = (Object)(object)player == (Object)(object)localPlayerController;
lastHealth = player.health;
fadeOutDelay = PluginConfig.ConfigFadeOutDelay.Value;
usernameBillboard = player.usernameBillboard;
playerGlobalHead = player.playerGlobalHead;
usernameAlpha = player.usernameAlpha;
fadeInRate = 1f / PluginConfig.ConfigFadeInDuration.Value;
fadeOutRate = 1f / PluginConfig.ConfigFadeOutDuration.Value;
previousHealth = player.health;
GameObject val = GameObject.Find("HealthChangeHelper");
if ((Object)(object)val == (Object)null)
{
val = new GameObject("HealthChangeHelper");
healthChangeHelper = val.AddComponent<HealthChangeHelper>();
Debug.Log((object)"Created new HealthChangeHelper instance");
}
else
{
healthChangeHelper = val.GetComponent<HealthChangeHelper>();
Debug.Log((object)"Found existing HealthChangeHelper instance");
}
}
private void InitializeHealthBar()
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_0064: 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_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: 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)
//IL_021e: 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_0278: Unknown result type (might be due to invalid IL or missing references)
//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
if (PluginConfig.ConfigEnableHealthBar.Value && (Object)(object)healthBarObject == (Object)null)
{
healthBarObject = new GameObject("HealthBarObject");
healthBarObject.transform.SetParent(((Component)player.usernameBillboard).transform, false);
redHealthBarImage = new GameObject("RedHealthBar").AddComponent<Image>();
((Component)redHealthBarImage).transform.SetParent(healthBarObject.transform, false);
redHealthBarAlpha = ((Component)redHealthBarImage).gameObject.AddComponent<CanvasGroup>();
redHealthBarAlpha.alpha = 0f;
healthBarImage = new GameObject("HealthBar").AddComponent<Image>();
((Component)healthBarImage).transform.SetParent(healthBarObject.transform, false);
healthBarAlpha = ((Component)healthBarImage).gameObject.AddComponent<CanvasGroup>();
healthBarAlpha.alpha = 0f;
Debug.Log((object)$"Initialized health bar: healthBarImage={healthBarImage}, redHealthBarImage={redHealthBarImage}");
redHealthBarTransform = ((Component)redHealthBarImage).GetComponent<RectTransform>();
healthBarTransform = ((Component)healthBarImage).GetComponent<RectTransform>();
redHealthBarTransform.anchorMin = new Vector2(0.5f, 0f);
redHealthBarTransform.anchorMax = new Vector2(0.5f, 0f);
redHealthBarTransform.sizeDelta = new Vector2(PluginConfig.ConfigRedHealthBarWidth.Value, PluginConfig.ConfigRedHealthBarHeight.Value);
redHealthBarTransform.anchoredPosition = new Vector2(PluginConfig.ConfigHealthBarPositionX.Value, PluginConfig.ConfigHealthBarPositionY.Value);
healthBarTransform.anchorMin = new Vector2(0f, 0f);
healthBarTransform.anchorMax = new Vector2(1f, 0f);
healthBarTransform.sizeDelta = new Vector2(PluginConfig.ConfigHealthBarWidth.Value, PluginConfig.ConfigHealthBarHeight.Value);
healthBarTransform.anchoredPosition = new Vector2(PluginConfig.ConfigHealthBarPositionX.Value, PluginConfig.ConfigHealthBarPositionY.Value);
string value = PluginConfig.ConfigHealthBarColorHex.Value;
Color color = default(Color);
if (ColorUtility.TryParseHtmlString("#" + value, ref color))
{
((Graphic)healthBarImage).color = color;
}
string value2 = PluginConfig.ConfigRedHealthBarColorHex.Value;
Color color2 = default(Color);
if (ColorUtility.TryParseHtmlString("#" + value2, ref color2))
{
((Graphic)redHealthBarImage).color = color2;
}
}
}
private void LateUpdate()
{
if (PluginConfig.ConfigEnableHealthBar.Value)
{
UpdateHealthBarFade();
if ((float)player.health != lastHealth)
{
OnHealthChanged();
}
}
}
private void OnHealthChanged()
{
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
if (PluginConfig.ConfigEnableHealthBar.Value)
{
float num = player.health;
float num2 = 100f;
float num3 = lastHealth;
Debug.Log((object)$"OnHealthChanged called for player: {((Object)player).name}, currentHealth: {num}, previousHealth: {num3}");
if ((Object)(object)player != (Object)(object)localPlayerController && num != num3)
{
healthChangeHelper.HandleHealthChange(healthBarImage, redHealthBarImage, num, num2, num3);
float num4 = num / num2;
healthBarTransform.anchorMax = new Vector2(num4, healthBarTransform.anchorMax.y);
float num5 = num4 * PluginConfig.ConfigHealthBarWidth.Value;
healthBarTransform.sizeDelta = new Vector2(num5, healthBarTransform.sizeDelta.y);
lastHealth = num;
}
}
}
private void UpdateHealthBarFade()
{
if (isLocalPlayer)
{
healthBarAlpha.alpha = 0f;
redHealthBarAlpha.alpha = 0f;
return;
}
if (usernameAlpha.alpha > 0f)
{
fadeOutTimer = 0f;
if (healthBarAlpha.alpha < 1f)
{
CanvasGroup obj = healthBarAlpha;
obj.alpha += Time.deltaTime * fadeInRate;
healthBarAlpha.alpha = Mathf.Clamp01(healthBarAlpha.alpha);
}
if (redHealthBarAlpha.alpha < 1f)
{
CanvasGroup obj2 = redHealthBarAlpha;
obj2.alpha += Time.deltaTime * fadeInRate;
redHealthBarAlpha.alpha = Mathf.Clamp01(redHealthBarAlpha.alpha);
}
return;
}
fadeOutTimer += Time.deltaTime;
if (fadeOutTimer >= fadeOutDelay)
{
CanvasGroup obj3 = healthBarAlpha;
obj3.alpha -= Time.deltaTime * fadeOutRate;
healthBarAlpha.alpha = Mathf.Clamp01(healthBarAlpha.alpha);
CanvasGroup obj4 = redHealthBarAlpha;
obj4.alpha -= Time.deltaTime * fadeOutRate;
redHealthBarAlpha.alpha = Mathf.Clamp01(redHealthBarAlpha.alpha);
if (healthBarAlpha.alpha <= 0f && redHealthBarAlpha.alpha <= 0f)
{
healthBarPool.Enqueue(this);
((Component)this).gameObject.SetActive(false);
}
}
}
public void UpdateHealthBarPosition()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if (PluginConfig.ConfigEnableHealthBar.Value)
{
Vector3 position = playerGlobalHead.position;
usernameBillboard.position = new Vector3(position.x, position.y + 0.55f, position.z);
}
}
}
[HarmonyPatch(typeof(UnlockableSuit), "SwitchSuitForPlayer")]
public static class UnlockableSuitPatch
{
private static readonly Dictionary<int, Color> suitColors = new Dictionary<int, Color>
{
{
0,
new Color(1f, 0.5f, 0f)
},
{
1,
Color.green
},
{
2,
Color.yellow
},
{
3,
Color.cyan
},
{
24,
new Color(0.5f, 0f, 0.5f)
}
};
private const string FallbackColorHex = "#FF0000";
[HarmonyPostfix]
public static void SwitchSuitForPlayer_Postfix(PlayerControllerB player, int suitID)
{
if (PluginConfig.ConfigEnableSuitColorOverlay.Value)
{
UpdateHealthOverlayColor(player, suitID);
}
}
public static void UpdateHealthOverlayColor(PlayerControllerB player, int suitID)
{
//IL_0078: 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_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: 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)
Debug.Log((object)$"UpdateHealthOverlayColor called with player: {((Object)player).name}, suitID: {suitID}");
HUDManager instance = HUDManager.Instance;
object obj;
if (instance == null)
{
obj = null;
}
else
{
CanvasGroup selfRedCanvasGroup = instance.selfRedCanvasGroup;
obj = ((selfRedCanvasGroup != null) ? ((Component)selfRedCanvasGroup).GetComponent<Image>() : null);
}
Image val = (Image)obj;
if ((Object)(object)val != (Object)null)
{
if (suitColors.TryGetValue(suitID, out var value))
{
((Graphic)val).color = value;
return;
}
Color val2 = default(Color);
ColorUtility.TryParseHtmlString(PluginConfig.ConfigOverlayColorHex.Value, ref val2);
Color val3 = default(Color);
((Graphic)val).color = ((val2 != default(Color)) ? val2 : (ColorUtility.TryParseHtmlString("#FF0000", ref val3) ? val3 : Color.red));
}
}
}
namespace NilsHUD
{
public static class PlayerUtils
{
private static PlayerControllerB localPlayerController;
public static PlayerControllerB GetPlayerControllerB()
{
if ((Object)(object)localPlayerController == (Object)null)
{
localPlayerController = GameNetworkManager.Instance?.localPlayerController;
PlayerControllerB obj = localPlayerController;
Debug.Log((object)("[NilsHUD] GetPlayerControllerB returned: " + (((obj != null) ? ((Object)obj).name : null) ?? "null")));
}
return localPlayerController;
}
}
public static class HUDManagerPatch
{
private const string HealFromCriticalTrigger = "HealFromCritical";
private const string CriticalHitTrigger = "CriticalHit";
private const string SmallHitTrigger = "SmallHit";
private const int CriticalHealthThreshold = 20;
private static bool playerIsCriticallyInjured;
private static float targetFillAmount;
[HarmonyPatch(typeof(HUDManager), "UpdateHealthUI")]
[HarmonyPrefix]
public static bool UpdateHealthUIPrefix(int health, bool hurtPlayer = true)
{
HUDManager instance = HUDManager.Instance;
if ((Object)(object)instance?.selfRedCanvasGroup == (Object)null)
{
Debug.LogError((object)"HUDManager instance or selfRedCanvasGroup is null!");
return true;
}
if (PluginConfig.ConfigOverlayColorHex.Value != null)
{
_ = PluginConfig.ConfigEnableCriticalHitEffect.Value;
_ = PluginConfig.ConfigEnableSmallHitEffect.Value;
if (0 == 0)
{
Image component = ((Component)instance.selfRedCanvasGroup).GetComponent<Image>();
if ((Object)(object)component == (Object)null)
{
Debug.LogError((object)"Image component not found on selfRedCanvasGroup!");
return false;
}
PlayerControllerB playerControllerB = PlayerUtils.GetPlayerControllerB();
ConfigureHealthImage(component, health, playerControllerB);
if (!Object.op_Implicit((Object)(object)((Component)instance).gameObject.GetComponent<HealthIndicatorInitializer>()))
{
((Component)instance).gameObject.AddComponent<HealthIndicatorInitializer>();
component.fillAmount = 0f;
}
float previousFillAmount = (component.fillAmount = component.fillAmount);
StartHealthMonitoring(instance);
StartSmoothFillTransition(instance, component, previousFillAmount);
if ((Object)(object)instance.HUDAnimator == (Object)null)
{
Debug.LogError((object)"HUDAnimator is null!");
return false;
}
HandlePlayerHealthState(instance, health, hurtPlayer);
return false;
}
}
Debug.LogError((object)"PluginConfig values are not properly initialized!");
return true;
}
private static void StartHealthMonitoring(HUDManager hudManager)
{
if (!Object.op_Implicit((Object)(object)((Component)hudManager).gameObject.GetComponent<HealthMonitorCoroutine>()))
{
((Component)hudManager).gameObject.AddComponent<HealthMonitorCoroutine>();
}
}
private static void StartSmoothFillTransition(HUDManager hudManager, Image image, float previousFillAmount)
{
((MonoBehaviour)hudManager).StopAllCoroutines();
if (PluginConfig.ConfigEnableFillAnimation.Value)
{
float duration = Mathf.Clamp(PluginConfig.ConfigFillTransitionDuration.Value, 0.01f, 1f);
((MonoBehaviour)hudManager).StartCoroutine(SmoothFillTransition(image, targetFillAmount, duration));
}
else
{
image.fillAmount = targetFillAmount;
}
if (PluginConfig.ConfigEnableFadeOut.Value)
{
float fadeOutDuration = Mathf.Clamp(PluginConfig.ConfigFadeOutDuration.Value, 0f, 5f);
((MonoBehaviour)hudManager).StartCoroutine(StartFadeOutEffect(image, fadeOutDuration));
}
}
private static IEnumerator StartFadeOutEffect(Image image, float fadeOutDuration)
{
float elapsedTime = 0f;
Color startColor = ((Graphic)image).color;
float targetAlpha = Mathf.Clamp01(1f - PluginConfig.ConfigFadeOutIntensity.Value);
Color targetColor = new Color(startColor.r, startColor.g, startColor.b, targetAlpha);
while (elapsedTime < fadeOutDuration)
{
float t = elapsedTime / fadeOutDuration;
((Graphic)image).color = Color.Lerp(startColor, targetColor, t);
elapsedTime += Time.deltaTime;
yield return null;
}
((Graphic)image).color = targetColor;
}
private static IEnumerator SmoothFillTransition(Image image, float targetFillAmount, float duration)
{
float elapsedTime = 0f;
float startFillAmount = image.fillAmount;
Debug.LogFormat("Start fill amount: {0}", new object[1] { startFillAmount });
Debug.LogFormat("Target fill amount: {0}", new object[1] { targetFillAmount });
Debug.LogFormat("Fill duration: {0}", new object[1] { duration });
if (Mathf.Approximately(startFillAmount, targetFillAmount))
{
duration = Mathf.Max(duration, 0.1f);
}
while (elapsedTime < duration)
{
float t = elapsedTime / duration;
float smoothT = Mathf.SmoothStep(0f, 1f, t);
image.fillAmount = Mathf.Lerp(startFillAmount, targetFillAmount, smoothT);
elapsedTime += Time.deltaTime;
yield return null;
}
image.fillAmount = targetFillAmount;
}
private static IEnumerator SmoothFillAndFadeTransition(Image image, float startFillAmount, float targetFillAmount, float fillDuration, float fadeOutDuration)
{
Debug.LogFormat("Start fill amount: {0}", new object[1] { image.fillAmount });
Debug.LogFormat("Target fill amount: {0}", new object[1] { targetFillAmount });
Debug.LogFormat("Fill duration: {0}", new object[1] { fillDuration });
Debug.LogFormat("Fade-out duration: {0}", new object[1] { fadeOutDuration });
if (Mathf.Approximately(image.fillAmount, targetFillAmount))
{
fillDuration = Mathf.Max(fillDuration, 0.1f);
}
yield return SmoothFillTransition(image, targetFillAmount, fillDuration);
float elapsedTime = 0f;
Color startColor = ((Graphic)image).color;
float targetAlpha = Mathf.Clamp01(1f - PluginConfig.ConfigFadeOutIntensity.Value);
Color targetColor = new Color(startColor.r, startColor.g, startColor.b, targetAlpha);
Debug.Log((object)$"Starting fade-out effect. Start color: {startColor}, Target color: {targetColor}, Fade-out duration: {fadeOutDuration}");
while (elapsedTime < fadeOutDuration)
{
float t = elapsedTime / fadeOutDuration;
((Graphic)image).color = Color.Lerp(startColor, targetColor, t);
Debug.Log((object)$"Fade-out effect progress: {t}, Current color: {((Graphic)image).color}");
elapsedTime += Time.deltaTime;
yield return null;
}
((Graphic)image).color = targetColor;
Debug.Log((object)$"Fade-out effect completed. Final color: {((Graphic)image).color}");
}
private static void ConfigureHealthImage(Image image, int health, PlayerControllerB controllerInstance)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Invalid comparison between Unknown and I4
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
targetFillAmount = (100f - (float)health) / 100f;
if ((int)image.type != 3)
{
image.type = (Type)3;
image.fillMethod = (FillMethod)1;
}
if (PluginConfig.ConfigFillDirection.Value == FillDirection.TopToBottom)
{
image.fillOrigin = 1;
}
else
{
image.fillOrigin = 0;
}
Color color = default(Color);
if (PluginConfig.ConfigEnableSuitColorOverlay.Value && (Object)(object)controllerInstance != (Object)null)
{
int currentSuitID = controllerInstance.currentSuitID;
Debug.LogFormat("Current Suit ID in HealthIndicatorPatch: {0}", new object[1] { currentSuitID });
UnlockableSuitPatch.UpdateHealthOverlayColor(controllerInstance, currentSuitID);
Debug.Log((object)"Health overlay color updated in HealthIndicatorPatch");
}
else if (ColorUtility.TryParseHtmlString("#" + PluginConfig.ConfigOverlayColorHex.Value, ref color))
{
((Graphic)image).color = color;
}
else
{
((Graphic)image).color = Color.red;
}
}
private static void HandlePlayerHealthState(HUDManager hudManager, int health, bool hurtPlayer)
{
hudManager.selfRedCanvasGroup.alpha = (100f - (float)health) / 100f;
if (health >= 20 && playerIsCriticallyInjured)
{
playerIsCriticallyInjured = false;
hudManager.HUDAnimator.SetTrigger("HealFromCritical");
}
if (hurtPlayer && health > 0)
{
ProcessPlayerInjury(hudManager, health);
}
}
private static void ProcessPlayerInjury(HUDManager hudManager, int health)
{
if (health < 20)
{
playerIsCriticallyInjured = true;
if (PluginConfig.ConfigEnableCriticalHitEffect.Value)
{
hudManager.HUDAnimator.SetTrigger("CriticalHit");
AudioSource uIAudio = hudManager.UIAudio;
if (uIAudio != null)
{
uIAudio.PlayOneShot(hudManager.criticalInjury, 1f);
}
}
}
else if (PluginConfig.ConfigEnableSmallHitEffect.Value)
{
hudManager.HUDAnimator.SetTrigger("SmallHit");
}
}
}
public class HealthIndicatorInitializer : MonoBehaviour
{
}
public class HealthMonitorCoroutine : MonoBehaviour
{
private int lastHealth = -1;
private void Start()
{
((MonoBehaviour)this).StartCoroutine(MonitorHealth());
}
private IEnumerator MonitorHealth()
{
while (true)
{
PlayerControllerB playerController = PlayerUtils.GetPlayerControllerB();
if ((Object)(object)playerController != (Object)null)
{
int currentHealth = playerController.health;
if (currentHealth != lastHealth)
{
lastHealth = currentHealth;
HUDManagerPatch.UpdateHealthUIPrefix(currentHealth, hurtPlayer: false);
}
}
yield return (object)new WaitForSeconds(0.01f);
}
}
}
[BepInPlugin("Nilaier.NilsHUD", "NilsHUD", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
private const string AsciiLogoResourceName = "NilsHUD.Resources.ascii_logo.txt";
private static readonly Assembly ExecutingAssembly = Assembly.GetExecutingAssembly();
private static readonly string[] ExcludedScenes = new string[4] { "InitScene", "InitSceneLaunchOptions", "MainMenu", "InitSceneLANMode" };
private Harmony harmonyInstance;
private bool isPluginInitialized = false;
private void Awake()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
DisplayAsciiLogo();
harmonyInstance = new Harmony("Nilaier.NilsHUD");
harmonyInstance.PatchAll(typeof(HUDManagerPatch));
harmonyInstance.PatchAll(typeof(UnlockableSuitPatch));
harmonyInstance.PatchAll(typeof(HealthBarPatch));
Debug.Log((object)"[NilsHUD] Harmony patches applied.");
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void DisplayAsciiLogo()
{
string text = LoadAsciiLogoFromResource();
Debug.Log((object)(string.IsNullOrEmpty(text) ? "[NilsHUD] ASCII logo not found or empty." : text));
}
private string LoadAsciiLogoFromResource()
{
try
{
using Stream stream = ExecutingAssembly.GetManifestResourceStream("NilsHUD.Resources.ascii_logo.txt");
if (stream != null)
{
using (StreamReader streamReader = new StreamReader(stream))
{
return streamReader.ReadToEnd();
}
}
}
catch (IOException ex)
{
Debug.LogError((object)("[NilsHUD] Error loading ASCII logo: " + ex.Message));
}
return string.Empty;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Debug.Log((object)("[NilsHUD] Loaded scene: " + ((Scene)(ref scene)).name));
if (!isPluginInitialized && !ExcludedScenes.Contains(((Scene)(ref scene)).name))
{
PluginConfig.BindConfig(((BaseUnityPlugin)this).Config);
isPluginInitialized = true;
Debug.Log((object)("[NilsHUD] Plugin initialized in scene: " + ((Scene)(ref scene)).name));
}
}
}
public class PluginConfig
{
private const string DefaultOverlayColor = "FF0000";
private const float DefaultFillTransitionDuration = 0.1f;
private const float DefaultFadeOutDuration = 0.5f;
private const float DefaultFadeOutIntensity = 0.5f;
private const string DefaultHealthBarColor = "FF8000";
private const string DefaultRedHealthBarColor = "FF0000";
private const float DefaultHealthBarPositionX = 0f;
private const float DefaultHealthBarPositionY = 30f;
private const float DefaultFadeInDuration = 0.5f;
private const float DefaultFadeOutDelay = 1f;
private const float DefaultHealthBarWidth = 300f;
private const float DefaultHealthBarHeight = 15f;
private const float DefaultRedHealthBarWidth = 300f;
private const float DefaultRedHealthBarHeight = 15f;
public static ConfigEntry<string> ConfigOverlayColorHex;
public static ConfigEntry<bool> ConfigEnableFillAnimation;
public static ConfigEntry<FillDirection> ConfigFillDirection;
public static ConfigEntry<float> ConfigFillTransitionDuration;
public static ConfigEntry<bool> ConfigEnableSuitColorOverlay;
public static ConfigEntry<bool> ConfigEnableFadeOut;
public static ConfigEntry<float> ConfigFadeOutDuration;
public static ConfigEntry<float> ConfigFadeOutIntensity;
public static ConfigEntry<bool> ConfigEnableCriticalHitEffect;
public static ConfigEntry<bool> ConfigEnableSmallHitEffect;
public static ConfigEntry<bool> ConfigEnableHealthBar;
public static ConfigEntry<string> ConfigHealthBarColorHex;
public static ConfigEntry<string> ConfigRedHealthBarColorHex;
public static ConfigEntry<float> ConfigHealthBarPositionX;
public static ConfigEntry<float> ConfigHealthBarPositionY;
public static ConfigEntry<float> ConfigFadeInDuration;
public static ConfigEntry<float> ConfigFadeOutDelay;
public static ConfigEntry<float> ConfigHealthBarWidth;
public static ConfigEntry<float> ConfigHealthBarHeight;
public static ConfigEntry<float> ConfigRedHealthBarWidth;
public static ConfigEntry<float> ConfigRedHealthBarHeight;
public static void BindConfig(ConfigFile config)
{
ConfigOverlayColorHex = config.Bind<string>("Overlay", "OverlayColorHex", "FF0000", "The color of the overlay image in hexadecimal format (e.g., FF0000 for red).");
ConfigEnableFillAnimation = config.Bind<bool>("Overlay", "EnableFillAnimation", true, "Enables the fill animation. If false, the fill amount is set instantly.");
ConfigFillDirection = config.Bind<FillDirection>("Overlay", "FillDirection", FillDirection.BottomToTop, "The fill direction of the health indicator.");
ConfigFillTransitionDuration = config.Bind<float>("Overlay", "FillTransitionDuration", 0.1f, "The duration over which the health indicator's fill amount changes. Lower values make the transition faster, higher values make it smoother.");
ConfigEnableSuitColorOverlay = config.Bind<bool>("Overlay", "EnableSuitColorOverlay", false, "Enables the feature where the player's suit changes the color of the damage overlay.");
ConfigEnableFadeOut = config.Bind<bool>("FadeOut", "EnableFadeOut", true, "Enables the fade-out effect for the filling overlay.");
ConfigFadeOutDuration = config.Bind<float>("FadeOut", "FadeOutDuration", 0.5f, "The duration of the fade-out effect for the filling overlay (in seconds).");
ConfigFadeOutIntensity = config.Bind<float>("FadeOut", "FadeOutIntensity", 0.5f, "The intensity of the fade-out effect (0 for no fade-out, 1 for full fade-out).");
ConfigEnableCriticalHitEffect = config.Bind<bool>("Effects", "EnableCriticalHitEffect", true, "Enables the critical hit animation and sound effect.");
ConfigEnableSmallHitEffect = config.Bind<bool>("Effects", "EnableSmallHitEffect", true, "Enables the small hit effect.");
ConfigEnableHealthBar = config.Bind<bool>("Experimental", "EnableHealthBar", false, "Enables the health bar.");
ConfigHealthBarColorHex = config.Bind<string>("Experimental", "HealthBarColorHex", "FF8000", "The color of the health bar in hexadecimal format (e.g., FF8000 for orange).");
ConfigRedHealthBarColorHex = config.Bind<string>("Experimental", "RedHealthBarColorHex", "FF0000", "The color of the red health bar in hexadecimal format (e.g., FF0000 for red).");
ConfigHealthBarPositionX = config.Bind<float>("Experimental", "HealthBarPositionX", 0f, "The X position of the health bar.");
ConfigHealthBarPositionY = config.Bind<float>("Experimental", "HealthBarPositionY", 30f, "The Y position of the health bar.");
ConfigFadeInDuration = config.Bind<float>("Experimental", "FadeInDuration", 0.5f, "The duration of the fade-in effect for the health bar (in seconds).");
ConfigFadeOutDelay = config.Bind<float>("Experimental", "FadeOutDelay", 1f, "The delay before the health bar starts fading out (in seconds).");
ConfigHealthBarWidth = config.Bind<float>("Experimental", "HealthBarWidth", 300f, "The width of the health bar.");
ConfigHealthBarHeight = config.Bind<float>("Experimental", "HealthBarHeight", 15f, "The height of the health bar.");
ConfigRedHealthBarWidth = config.Bind<float>("Experimental", "RedHealthBarWidth", 300f, "The width of the red health bar.");
ConfigRedHealthBarHeight = config.Bind<float>("Experimental", "RedHealthBarHeight", 15f, "The height of the red health bar.");
}
}
public enum FillDirection
{
BottomToTop,
TopToBottom
}
internal static class PluginInfo
{
public const string PLUGIN_GUID = "Nilaier.NilsHUD";
public const string PLUGIN_NAME = "NilsHUD";
public const string PLUGIN_VERSION = "1.0.1";
}
}