Decompiled source of BossHP v0.1.2

BepInEx/plugins/HowToFish.BossHP/HowToFish.BossHP.dll

Decompiled an hour ago
using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: AssemblyDescription("Shows the active boss's exact synchronized HP beside the native health bar.")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyCompany("evansvl")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HowToFish.BossHP;

[BepInPlugin("community.howtofish.bosshp", "Boss HP", "0.1.2")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "community.howtofish.bosshp";

	public const string PluginName = "Boss HP";

	public const string PluginVersion = "0.1.2";

	private static readonly FieldInfo BossHealthField = typeof(BossUI).GetField("_bossHealth", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo BossNameField = typeof(BossUI).GetField("_bossNameText", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo BossHpRotateField = typeof(BossUI).GetField("_bossHpToRotate", BindingFlags.Instance | BindingFlags.NonPublic);

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<bool> _showMaximum;

	private ConfigEntry<float> _scale;

	private ConfigEntry<float> _opacity;

	private ConfigEntry<float> _horizontalOffset;

	private ConfigEntry<float> _verticalOffset;

	private BossUI _nativeBossUi;

	private Image _nativeHealth;

	private RectTransform _nativeHudRoot;

	private TextMeshProUGUI _text;

	private readonly Vector3[] _healthCorners = (Vector3[])(object)new Vector3[4];

	private void Awake()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Expected O, but got Unknown
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Expected O, but got Unknown
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Expected O, but got Unknown
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Enabled", true, "Show exact boss HP beside the native boss health bar.");
		_showMaximum = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowMaximum", true, "Show current and maximum HP instead of current HP only.");
		_scale = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Scale", 1f, new ConfigDescription("Boss HP text scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 1.8f), new object[0]));
		_opacity = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Opacity", 1f, new ConfigDescription("Boss HP text opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
		_horizontalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "HorizontalOffset", 18f, new ConfigDescription("Distance to the left of the native health bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 180f), new object[0]));
		_verticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "VerticalOffset", 0f, new ConfigDescription("Vertical adjustment relative to the native health bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 80f), new object[0]));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded. Boss HP reads synchronized boss state and attaches text to the native boss health bar.");
	}

	private void Update()
	{
		Creature boss = BossManager.Boss;
		if (!_enabled.Value || (Object)(object)boss == (Object)null || boss.IsDead || !IsGameplayBossHudVisible())
		{
			SetVisible(visible: false);
			return;
		}
		if (!EnsureAttached())
		{
			SetVisible(visible: false);
			return;
		}
		int num = BossManager.BossMaxHp;
		if (num <= 0)
		{
			num = boss.MaxHp;
		}
		if (num <= 0)
		{
			SetVisible(visible: false);
			return;
		}
		int value = Math.Max(0, Math.Min(boss.Hp, num));
		((TMP_Text)_text).text = (_showMaximum.Value ? (FormatHp(value) + " / " + FormatHp(num)) : FormatHp(value));
		ApplyLiveSettings();
		SetVisible(visible: true);
	}

	private static bool IsGameplayBossHudVisible()
	{
		if (MainMenuManager.IsInMenu || PauseManager.IsPaused)
		{
			return false;
		}
		try
		{
			return PlayerUI.BossCanvasActive;
		}
		catch
		{
			return false;
		}
	}

	private bool EnsureAttached()
	{
		if ((Object)(object)_nativeBossUi != (Object)null && (Object)(object)_nativeHealth != (Object)null && (Object)(object)_nativeHudRoot != (Object)null && (Object)(object)_text != (Object)null)
		{
			return true;
		}
		ClearAttachment();
		if (BossHealthField == null || BossHpRotateField == null)
		{
			return false;
		}
		BossUI[] array = Resources.FindObjectsOfTypeAll<BossUI>();
		BossUI[] array2 = array;
		foreach (BossUI val in array2)
		{
			if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
			{
				object? value = BossHealthField.GetValue(val);
				Image val2 = (Image)((value is Image) ? value : null);
				object? value2 = BossHpRotateField.GetValue(val);
				RectTransform val3 = (RectTransform)((value2 is RectTransform) ? value2 : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Graphic)val2).rectTransform == (Object)null) && !((Object)(object)val3 == (Object)null))
				{
					_nativeBossUi = val;
					_nativeHealth = val2;
					_nativeHudRoot = val3;
					CreateText(val3, FindTemplate(val));
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Attached numeric HP to the native boss shake-and-rotation transform.");
					return (Object)(object)_text != (Object)null;
				}
			}
		}
		return false;
	}

	private void CreateText(RectTransform hudRoot, TextMeshProUGUI template)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("BossHPText", new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(TextMeshProUGUI)
		});
		val.transform.SetParent((Transform)(object)hudRoot, false);
		val.transform.SetAsLastSibling();
		_text = val.GetComponent<TextMeshProUGUI>();
		RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
		Vector2 anchorMin = (rectTransform.anchorMax = new Vector2(0.5f, 0.5f));
		rectTransform.anchorMin = anchorMin;
		rectTransform.pivot = new Vector2(1f, 0.5f);
		rectTransform.sizeDelta = new Vector2(300f, 70f);
		if ((Object)(object)template != (Object)null && (Object)(object)((TMP_Text)template).font != (Object)null)
		{
			((TMP_Text)_text).font = ((TMP_Text)template).font;
			if ((Object)(object)((TMP_Text)template).fontSharedMaterial != (Object)null)
			{
				((TMP_Text)_text).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
			}
			((TMP_Text)_text).characterSpacing = ((TMP_Text)template).characterSpacing;
		}
		((TMP_Text)_text).fontSize = 30f;
		((TMP_Text)_text).alignment = (TextAlignmentOptions)4100;
		((TMP_Text)_text).enableWordWrapping = false;
		((TMP_Text)_text).overflowMode = (TextOverflowModes)0;
		((Graphic)_text).raycastTarget = false;
		((TMP_Text)_text).outlineColor = new Color32((byte)20, (byte)18, (byte)18, byte.MaxValue);
		((TMP_Text)_text).outlineWidth = 0.18f;
		((TMP_Text)_text).text = string.Empty;
	}

	private static TextMeshProUGUI FindTemplate(BossUI bossUi)
	{
		TextMeshProUGUI val = (TextMeshProUGUI)((BossNameField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
		{
			return val;
		}
		TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<TextMeshProUGUI>();
		TextMeshProUGUI[] array2 = array;
		foreach (TextMeshProUGUI val2 in array2)
		{
			if ((Object)(object)val2 != (Object)null && ((TMP_Text)val2).text != null && ((TMP_Text)val2).text.IndexOf("Version", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return val2;
			}
		}
		return null;
	}

	private void ApplyLiveSettings()
	{
		//IL_002e: 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)
		//IL_0044: 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_0053: 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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
		((Graphic)_nativeHealth).rectTransform.GetWorldCorners(_healthCorners);
		Vector3 val = (_healthCorners[0] + _healthCorners[1]) * 0.5f;
		Vector3 val2 = ((Transform)_nativeHudRoot).InverseTransformPoint(val);
		((Transform)rectTransform).localPosition = new Vector3(val2.x - _horizontalOffset.Value, val2.y + _verticalOffset.Value, 0f);
		((Transform)rectTransform).localScale = Vector3.one * _scale.Value;
		((Graphic)_text).color = new Color(1f, 1f, 1f, _opacity.Value);
	}

	private static string FormatHp(int value)
	{
		return value.ToString("N0", CultureInfo.InvariantCulture);
	}

	private void SetVisible(bool visible)
	{
		if ((Object)(object)_text != (Object)null && ((Behaviour)_text).enabled != visible)
		{
			((Behaviour)_text).enabled = visible;
		}
	}

	private void ClearAttachment()
	{
		if ((Object)(object)_text != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_text).gameObject);
		}
		_text = null;
		_nativeHealth = null;
		_nativeHudRoot = null;
		_nativeBossUi = null;
	}

	private void OnDestroy()
	{
		ClearAttachment();
	}
}