Decompiled source of FishHP v0.2.2

BepInEx/plugins/HowToFish.FishHP/HowToFish.FishHP.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: AssemblyCompany("evansvl")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyDescription("Shows stacked native-style health bars for non-boss creatures damaged by the local player.")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HowToFish.FishHP;

[BepInPlugin("community.howtofish.fishhp", "Fish HP", "0.2.2")]
public sealed class Plugin : BaseUnityPlugin
{
	private sealed class FishHudEntry
	{
		internal Creature Target;

		internal RectTransform Root;

		internal CanvasGroup Group;

		internal RectTransform MoveRoot;

		internal RectTransform RotateRoot;

		internal TextMeshProUGUI NameText;

		internal TextMeshProUGUI HpText;

		internal Image Health;

		internal Image HealthLerped;

		internal Vector3 StartPosition;

		internal Vector3 Velocity;

		internal Vector3 AngularVelocity;

		internal int ShownHp = -1;

		internal int ShownMaxHp = -1;

		internal float PredictionUntil;

		internal bool Fading;

		internal float FadeStartedAt;
	}

	[HarmonyPatch(typeof(Creature), "LocalHit")]
	private static class LocalCreatureHitPatch
	{
		private static void Postfix(Creature __instance, Player player, int damage, bool fromNpc)
		{
			if ((Object)(object)_instance == (Object)null || (Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null || fromNpc || damage <= 0)
			{
				return;
			}
			try
			{
				if (((NetworkBehaviour)player).Owner == (NetworkConnection)null || !((NetworkBehaviour)player).Owner.IsLocalClient)
				{
					return;
				}
			}
			catch
			{
				return;
			}
			_instance.SelectTarget(__instance, damage);
		}
	}

	public const string PluginGuid = "community.howtofish.fishhp";

	public const string PluginName = "Fish HP";

	public const string PluginVersion = "0.2.2";

	private const float ShakeForce = 750f;

	private const float PositionSpring = 1200f;

	private const float PositionDamping = 12f;

	private const float AngularShakeForce = 10f;

	private const float RotationSpring = 120f;

	private const float RotationDamping = 20f;

	private const float DeathFadeDuration = 0.5f;

	private static readonly FieldInfo MainCanvasField = typeof(PlayerUI).GetField("_mainCanvas", BindingFlags.Instance | BindingFlags.NonPublic);

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

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

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

	private static readonly FieldInfo LocalHpField = typeof(Creature).GetField("_localHp", BindingFlags.Instance | BindingFlags.NonPublic);

	private static Plugin _instance;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<float> _scale;

	private ConfigEntry<float> _opacity;

	private ConfigEntry<string> _barColor;

	private ConfigEntry<int> _maximumTargets;

	private ConfigEntry<float> _rowSpacing;

	private ConfigEntry<float> _leftOffset;

	private ConfigEntry<float> _topOffset;

	private Harmony _harmony;

	private CanvasGroup _mainCanvas;

	private RectTransform _container;

	private TextMeshProUGUI _nameTemplate;

	private Image _healthTemplate;

	private Image _lerpedTemplate;

	private readonly List<FishHudEntry> _entries = new List<FishHudEntry>();

	private void Awake()
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Expected O, but got Unknown
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Expected O, but got Unknown
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Expected O, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Expected O, but got Unknown
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Expected O, but got Unknown
		_instance = this;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Enabled", true, "Show health bars for living non-boss creatures damaged by the local player.");
		_scale = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Scale", 0.58f, new ConfigDescription("HUD scale relative to the native boss bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.35f, 1f), new object[0]));
		_opacity = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Opacity", 1f, new ConfigDescription("HUD opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
		_barColor = ((BaseUnityPlugin)this).Config.Bind<string>("HUD", "BarColor", "Default", "Health fill color. Use Default or an HTML color such as #800080 or #A020F0FF.");
		_maximumTargets = ((BaseUnityPlugin)this).Config.Bind<int>("HUD", "MaximumTargets", 4, new ConfigDescription("Maximum number of living creature bars shown at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), new object[0]));
		_rowSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "RowSpacing", 150f, new ConfigDescription("Vertical distance between creature rows before HUD scaling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(110f, 240f), new object[0]));
		_leftOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "LeftOffset", 72f, new ConfigDescription("Distance from the left edge of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), new object[0]));
		_topOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "TopOffset", 54f, new ConfigDescription("Distance from the top edge of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), new object[0]));
		if (Mathf.Abs(_leftOffset.Value - 36f) < 0.01f)
		{
			_leftOffset.Value = 72f;
			((BaseUnityPlugin)this).Config.Save();
		}
		_harmony = new Harmony("community.howtofish.fishhp");
		_harmony.PatchAll(typeof(LocalCreatureHitPatch));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded. Fish HP tracks and vertically stacks multiple living non-boss targets.");
	}

	private void Update()
	{
		if (!_enabled.Value || !IsGameplayHudVisible())
		{
			SetRootVisible(visible: false);
			return;
		}
		if (_entries.Count == 0)
		{
			SetRootVisible(visible: false);
			return;
		}
		if ((Object)(object)_container == (Object)null)
		{
			ClearEntries();
			SetRootVisible(visible: false);
			return;
		}
		for (int num = _entries.Count - 1; num >= 0; num--)
		{
			FishHudEntry fishHudEntry = _entries[num];
			if ((Object)(object)fishHudEntry.Target == (Object)null || fishHudEntry.Target.IsDead || fishHudEntry.Target.Hp <= 0)
			{
				BeginDeathFade(fishHudEntry);
			}
			if (fishHudEntry.Fading)
			{
				float num2 = Mathf.Clamp01((Time.unscaledTime - fishHudEntry.FadeStartedAt) / 0.5f);
				if ((Object)(object)fishHudEntry.Group != (Object)null)
				{
					fishHudEntry.Group.alpha = _opacity.Value * (1f - num2);
				}
				if (num2 >= 1f)
				{
					RemoveEntryAt(num);
				}
			}
			else
			{
				UpdateTargetValues(fishHudEntry);
			}
		}
		TrimEntries();
		ApplyLiveSettings();
		SetRootVisible(_entries.Count > 0);
	}

	private void LateUpdate()
	{
		//IL_0061: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_007e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: 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)
		//IL_00d8: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		float deltaTime = Time.deltaTime;
		if (deltaTime <= 0f)
		{
			return;
		}
		foreach (FishHudEntry entry in _entries)
		{
			if (!((Object)(object)entry.MoveRoot == (Object)null) && !((Object)(object)entry.RotateRoot == (Object)null) && ((Component)entry.MoveRoot).gameObject.activeInHierarchy)
			{
				Vector3 val = entry.StartPosition - ((Transform)entry.MoveRoot).localPosition;
				entry.Velocity += val * 1200f * deltaTime;
				entry.Velocity -= entry.Velocity * 12f * deltaTime;
				RectTransform moveRoot = entry.MoveRoot;
				((Transform)moveRoot).localPosition = ((Transform)moveRoot).localPosition + entry.Velocity * deltaTime;
				Quaternion localRotation = ((Transform)entry.RotateRoot).localRotation;
				DazedUtils.SimulateSpringRotation(ref localRotation, ref entry.AngularVelocity, Quaternion.identity, 120f, 20f);
				((Transform)entry.RotateRoot).localRotation = localRotation;
			}
		}
	}

	private static bool IsGameplayHudVisible()
	{
		if (MainMenuManager.IsInMenu || PauseManager.IsPaused || (Object)(object)Player.LocalPlayer == (Object)null)
		{
			return false;
		}
		try
		{
			return !PlayerUI.UIDisabled;
		}
		catch
		{
			return true;
		}
	}

	private void SelectTarget(Creature creature, int damage)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (!_enabled.Value || (Object)(object)creature == (Object)null || creature.IsDead || damage <= 0 || (int)creature.BossType != 0 || !EnsureHud())
		{
			return;
		}
		FishHudEntry fishHudEntry = FindEntry(creature);
		if (fishHudEntry == null)
		{
			fishHudEntry = CreateEntry(creature);
			if (fishHudEntry == null)
			{
				return;
			}
			_entries.Insert(0, fishHudEntry);
		}
		else
		{
			int num = _entries.IndexOf(fishHudEntry);
			if (num > 0)
			{
				_entries.RemoveAt(num);
				_entries.Insert(0, fishHudEntry);
			}
		}
		fishHudEntry.Fading = false;
		if ((Object)(object)fishHudEntry.Group != (Object)null)
		{
			fishHudEntry.Group.alpha = _opacity.Value;
		}
		int num2 = Math.Max(1, creature.MaxHp);
		int num3 = Math.Max(0, Math.Min(creature.Hp, num2));
		int val = ReadLocalHp(creature, num3 - damage);
		val = Math.Max(0, Math.Min(val, num2));
		if (fishHudEntry.ShownHp < 0 || fishHudEntry.ShownMaxHp != num2)
		{
			float fillAmount = (float)num3 / (float)num2;
			fishHudEntry.Health.fillAmount = fillAmount;
			fishHudEntry.HealthLerped.fillAmount = fillAmount;
			fishHudEntry.ShownHp = val;
			fishHudEntry.ShownMaxHp = num2;
		}
		fishHudEntry.PredictionUntil = Time.unscaledTime + 1f;
		ApplyHealth(fishHudEntry, val, num2, shake: true);
		TrimEntries();
		ApplyLiveSettings();
		SetRootVisible(visible: true);
	}

	private FishHudEntry FindEntry(Creature creature)
	{
		foreach (FishHudEntry entry in _entries)
		{
			if ((Object)(object)entry.Target == (Object)(object)creature)
			{
				return entry;
			}
		}
		return null;
	}

	private static int ReadLocalHp(Creature creature, int fallback)
	{
		if (LocalHpField == null)
		{
			return fallback;
		}
		try
		{
			return (int)LocalHpField.GetValue(creature);
		}
		catch
		{
			return fallback;
		}
	}

	private void UpdateTargetValues(FishHudEntry entry)
	{
		int num = Math.Max(1, entry.Target.MaxHp);
		int num2 = Math.Max(0, Math.Min(entry.Target.Hp, num));
		((TMP_Text)entry.NameText).text = SafeName(entry.Target);
		if (!(Time.unscaledTime < entry.PredictionUntil) || num2 <= entry.ShownHp)
		{
			if (entry.ShownMaxHp != num)
			{
				entry.ShownMaxHp = num;
				entry.ShownHp = num2;
				UpdateHpText(entry, num2, num);
				float fillAmount = (float)num2 / (float)num;
				entry.Health.fillAmount = fillAmount;
				entry.HealthLerped.fillAmount = fillAmount;
			}
			else if (entry.ShownHp != num2)
			{
				ApplyHealth(entry, num2, num, num2 < entry.ShownHp);
			}
		}
	}

	private void ApplyHealth(FishHudEntry entry, int current, int maximum, bool shake)
	{
		float num = Mathf.Clamp01((float)current / (float)Math.Max(1, maximum));
		float fillAmount = entry.Health.fillAmount;
		entry.Health.fillAmount = num;
		entry.ShownHp = current;
		entry.ShownMaxHp = maximum;
		UpdateHpText(entry, current, maximum);
		LeanTween.cancel(((Component)entry.HealthLerped).gameObject);
		Image lerped = entry.HealthLerped;
		LeanTween.value(((Component)lerped).gameObject, lerped.fillAmount, num, 0.5f).setDelay(0.25f).setEase((LeanTweenType)9)
			.setOnUpdate((Action<float>)delegate(float value)
			{
				if ((Object)(object)lerped != (Object)null)
				{
					lerped.fillAmount = value;
				}
			});
		if (shake && num < fillAmount)
		{
			ApplyDamageShake(entry, fillAmount - num);
		}
	}

	private static void UpdateHpText(FishHudEntry entry, int current, int maximum)
	{
		if (!((Object)(object)entry.HpText == (Object)null))
		{
			((TMP_Text)entry.HpText).text = FormatHp(current) + " / " + FormatHp(maximum);
		}
	}

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

	private static void ApplyDamageShake(FishHudEntry entry, float healthLostRatio)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_006c: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp(healthLostRatio, 0.025f, 1f);
		Vector3 insideUnitSphere = Random.insideUnitSphere;
		Vector3 val = ((Vector3)(ref insideUnitSphere)).normalized * num;
		val *= ((Random.Range(0, 2) == 1) ? 1f : (-1f));
		entry.Velocity = val * 750f;
		float num2 = ((Random.Range(0, 2) == 1) ? 1f : (-1f));
		entry.AngularVelocity += new Vector3(0f, 0f, num2 * num * 10f);
	}

	private bool EnsureHud()
	{
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Expected O, but got Unknown
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_container != (Object)null && (Object)(object)_nameTemplate != (Object)null && (Object)(object)_healthTemplate != (Object)null && (Object)(object)_lerpedTemplate != (Object)null)
		{
			return true;
		}
		DestroyHud();
		if (!TryFindTemplates(out var bossUi, out var mainCanvas))
		{
			return false;
		}
		ref TextMeshProUGUI nameTemplate = ref _nameTemplate;
		object? value = BossNameField.GetValue(bossUi);
		nameTemplate = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
		ref Image healthTemplate = ref _healthTemplate;
		object? value2 = BossHealthField.GetValue(bossUi);
		healthTemplate = (Image)((value2 is Image) ? value2 : null);
		ref Image lerpedTemplate = ref _lerpedTemplate;
		object? value3 = BossHealthLerpedField.GetValue(bossUi);
		lerpedTemplate = (Image)((value3 is Image) ? value3 : null);
		if ((Object)(object)_nameTemplate == (Object)null || (Object)(object)_healthTemplate == (Object)null || (Object)(object)_lerpedTemplate == (Object)null)
		{
			return false;
		}
		_mainCanvas = mainCanvas;
		GameObject val = new GameObject("FishHPHUD", new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(((Component)mainCanvas).transform, false);
		_container = val.GetComponent<RectTransform>();
		RectTransform container = _container;
		Vector2 anchorMin = (_container.anchorMax = new Vector2(0f, 1f));
		container.anchorMin = anchorMin;
		_container.pivot = new Vector2(0f, 1f);
		_container.sizeDelta = new Vector2(1200f, 1200f);
		ApplyLiveSettings();
		return true;
	}

	private FishHudEntry CreateEntry(Creature creature)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: 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)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: 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_033b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0340: Unknown result type (might be due to invalid IL or missing references)
		//IL_0341: Unknown result type (might be due to invalid IL or missing references)
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_035b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_043d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0442: Unknown result type (might be due to invalid IL or missing references)
		//IL_0458: Unknown result type (might be due to invalid IL or missing references)
		//IL_0486: Unknown result type (might be due to invalid IL or missing references)
		//IL_048b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_container == (Object)null || (Object)(object)_nameTemplate == (Object)null || (Object)(object)_healthTemplate == (Object)null || (Object)(object)_lerpedTemplate == (Object)null)
		{
			return null;
		}
		FishHudEntry fishHudEntry = new FishHudEntry();
		fishHudEntry.Target = creature;
		FishHudEntry fishHudEntry2 = fishHudEntry;
		GameObject val = new GameObject("FishHP_" + SafeName(creature), new Type[2]
		{
			typeof(RectTransform),
			typeof(CanvasGroup)
		});
		val.transform.SetParent((Transform)(object)_container, false);
		fishHudEntry2.Root = val.GetComponent<RectTransform>();
		fishHudEntry2.Group = val.GetComponent<CanvasGroup>();
		RectTransform root = fishHudEntry2.Root;
		Vector2 anchorMin = (fishHudEntry2.Root.anchorMax = new Vector2(0f, 1f));
		root.anchorMin = anchorMin;
		fishHudEntry2.Root.pivot = new Vector2(0f, 1f);
		fishHudEntry2.Root.sizeDelta = new Vector2(1200f, 145f);
		fishHudEntry2.MoveRoot = CreateRect("FishHPMove", (Transform)(object)fishHudEntry2.Root);
		StretchToParent(fishHudEntry2.MoveRoot);
		fishHudEntry2.StartPosition = ((Transform)fishHudEntry2.MoveRoot).localPosition;
		fishHudEntry2.RotateRoot = CreateRect("FishHPRotate", (Transform)(object)fishHudEntry2.MoveRoot);
		StretchToParent(fishHudEntry2.RotateRoot);
		Rect rect = ((Graphic)_healthTemplate).rectTransform.rect;
		Vector2 size = ((Rect)(ref rect)).size;
		if (size.x < 100f)
		{
			size.x = 1065f;
		}
		if (size.y < 12f)
		{
			size.y = 38f;
		}
		fishHudEntry2.NameText = Object.Instantiate<TextMeshProUGUI>(_nameTemplate, (Transform)(object)fishHudEntry2.RotateRoot);
		((Object)fishHudEntry2.NameText).name = "FishName";
		PrepareText(fishHudEntry2.NameText);
		((TMP_Text)fishHudEntry2.NameText).alignment = (TextAlignmentOptions)257;
		RectTransform rectTransform = ((TMP_Text)fishHudEntry2.NameText).rectTransform;
		Vector2 anchorMin2 = (rectTransform.anchorMax = new Vector2(0f, 1f));
		rectTransform.anchorMin = anchorMin2;
		rectTransform.pivot = new Vector2(0f, 1f);
		rectTransform.anchoredPosition = Vector2.zero;
		rectTransform.sizeDelta = new Vector2(Mathf.Max(200f, size.x - 340f), 48f);
		fishHudEntry2.HpText = Object.Instantiate<TextMeshProUGUI>(_nameTemplate, (Transform)(object)fishHudEntry2.RotateRoot);
		((Object)fishHudEntry2.HpText).name = "FishHPText";
		PrepareText(fishHudEntry2.HpText);
		((TMP_Text)fishHudEntry2.HpText).alignment = (TextAlignmentOptions)260;
		RectTransform rectTransform2 = ((TMP_Text)fishHudEntry2.HpText).rectTransform;
		Vector2 anchorMin3 = (rectTransform2.anchorMax = new Vector2(0f, 1f));
		rectTransform2.anchorMin = anchorMin3;
		rectTransform2.pivot = new Vector2(1f, 1f);
		rectTransform2.anchoredPosition = new Vector2(size.x, 0f);
		rectTransform2.sizeDelta = new Vector2(320f, 48f);
		RectTransform val5 = CreateRect("FishHealthBar", (Transform)(object)fishHudEntry2.RotateRoot);
		Vector2 anchorMin4 = (val5.anchorMax = new Vector2(0f, 1f));
		val5.anchorMin = anchorMin4;
		val5.pivot = new Vector2(0f, 1f);
		val5.anchoredPosition = new Vector2(0f, -52f);
		val5.sizeDelta = size;
		Image val7 = CreateNativeImage("Border", (Transform)(object)val5, _lerpedTemplate, filled: false);
		SetImageRect(((Graphic)val7).rectTransform, new Vector2(-4f, -4f), new Vector2(4f, 4f));
		((Graphic)val7).color = Color.white;
		Image val8 = CreateNativeImage("Background", (Transform)(object)val5, _healthTemplate, filled: false);
		SetImageRect(((Graphic)val8).rectTransform, Vector2.zero, Vector2.zero);
		((Graphic)val8).color = new Color(0.055f, 0.075f, 0.12f, 0.9f);
		fishHudEntry2.HealthLerped = CreateNativeImage("DamageTrail", (Transform)(object)val5, _lerpedTemplate, filled: true);
		SetImageRect(((Graphic)fishHudEntry2.HealthLerped).rectTransform, Vector2.zero, Vector2.zero);
		((Graphic)fishHudEntry2.HealthLerped).color = ((Graphic)_lerpedTemplate).color;
		fishHudEntry2.Health = CreateNativeImage("Health", (Transform)(object)val5, _healthTemplate, filled: true);
		SetImageRect(((Graphic)fishHudEntry2.Health).rectTransform, Vector2.zero, Vector2.zero);
		((Graphic)fishHudEntry2.Health).color = ResolveColor(_barColor.Value, GameInfo.RedColor);
		((TMP_Text)fishHudEntry2.NameText).text = SafeName(creature);
		((TMP_Text)fishHudEntry2.HpText).text = string.Empty;
		fishHudEntry2.Group.alpha = _opacity.Value;
		return fishHudEntry2;
	}

	private static void PrepareText(TextMeshProUGUI text)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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)
		((Component)text).gameObject.SetActive(true);
		((Behaviour)text).enabled = true;
		((Graphic)text).raycastTarget = false;
		((Transform)((TMP_Text)text).rectTransform).localScale = Vector3.one;
		((Transform)((TMP_Text)text).rectTransform).localRotation = Quaternion.identity;
		((TMP_Text)text).margin = Vector4.zero;
		((TMP_Text)text).enableAutoSizing = false;
		((TMP_Text)text).enableWordWrapping = false;
		((TMP_Text)text).overflowMode = (TextOverflowModes)0;
	}

	private static RectTransform CreateRect(string name, Transform parent)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		return val.GetComponent<RectTransform>();
	}

	private static void StretchToParent(RectTransform rect)
	{
		//IL_0001: 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)
		//IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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)
		rect.anchorMin = Vector2.zero;
		rect.anchorMax = Vector2.one;
		rect.pivot = new Vector2(0.5f, 0.5f);
		rect.offsetMin = Vector2.zero;
		rect.offsetMax = Vector2.zero;
		((Transform)rect).localScale = Vector3.one;
		((Transform)rect).localRotation = Quaternion.identity;
	}

	private static Image CreateNativeImage(string name, Transform parent, Image template, bool filled)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		val.transform.SetParent(parent, false);
		Image component = val.GetComponent<Image>();
		component.sprite = template.sprite;
		component.overrideSprite = template.overrideSprite;
		((Graphic)component).material = ((Graphic)template).material;
		component.preserveAspect = false;
		((Graphic)component).raycastTarget = false;
		component.type = (Type)(filled ? 3 : ((int)BorderImageType(template)));
		if (filled)
		{
			component.fillMethod = (FillMethod)0;
			component.fillOrigin = 0;
			component.fillClockwise = true;
			component.fillAmount = 1f;
		}
		return component;
	}

	private static Type BorderImageType(Image template)
	{
		//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)
		if ((Object)(object)template.sprite != (Object)null)
		{
			Vector4 border = template.sprite.border;
			if (((Vector4)(ref border)).sqrMagnitude > 0f)
			{
				return (Type)1;
			}
		}
		return (Type)0;
	}

	private static void SetImageRect(RectTransform rect, Vector2 minimumOffset, Vector2 maximumOffset)
	{
		//IL_0001: 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)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		rect.anchorMin = Vector2.zero;
		rect.anchorMax = Vector2.one;
		rect.offsetMin = minimumOffset;
		rect.offsetMax = maximumOffset;
		((Transform)rect).localScale = Vector3.one;
		((Transform)rect).localRotation = Quaternion.identity;
	}

	private static bool TryFindTemplates(out BossUI bossUi, out CanvasGroup mainCanvas)
	{
		bossUi = null;
		mainCanvas = null;
		if (MainCanvasField == null || BossNameField == null || BossHealthField == null || BossHealthLerpedField == null)
		{
			return false;
		}
		PlayerUI[] array = Resources.FindObjectsOfTypeAll<PlayerUI>();
		PlayerUI[] array2 = array;
		foreach (PlayerUI val in array2)
		{
			if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
			{
				object? value = MainCanvasField.GetValue(val);
				CanvasGroup val2 = (CanvasGroup)((value is CanvasGroup) ? value : null);
				if ((Object)(object)val2 != (Object)null)
				{
					mainCanvas = val2;
					break;
				}
			}
		}
		if ((Object)(object)mainCanvas == (Object)null)
		{
			return false;
		}
		BossUI[] array3 = Resources.FindObjectsOfTypeAll<BossUI>();
		BossUI[] array4 = array3;
		foreach (BossUI val3 in array4)
		{
			if (!((Object)(object)val3 == (Object)null) && ((Component)val3).gameObject.activeInHierarchy && BossNameField.GetValue(val3) != null && BossHealthField.GetValue(val3) != null && BossHealthLerpedField.GetValue(val3) != null)
			{
				bossUi = val3;
				break;
			}
		}
		return (Object)(object)bossUi != (Object)null;
	}

	private static string SafeName(Creature creature)
	{
		try
		{
			string name = ((Item)creature).GetName();
			return string.IsNullOrEmpty(name) ? "Fish" : name;
		}
		catch
		{
			return "Fish";
		}
	}

	private void ApplyLiveSettings()
	{
		//IL_002c: 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_004c: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: 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)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_container == (Object)null)
		{
			return;
		}
		_container.anchoredPosition = new Vector2(_leftOffset.Value, 0f - _topOffset.Value);
		((Transform)_container).localScale = Vector3.one * _scale.Value;
		Color color = ResolveColor(_barColor.Value, GameInfo.RedColor);
		for (int i = 0; i < _entries.Count; i++)
		{
			FishHudEntry fishHudEntry = _entries[i];
			fishHudEntry.Root.anchoredPosition = new Vector2(0f, (float)(-i) * _rowSpacing.Value);
			if (!fishHudEntry.Fading)
			{
				fishHudEntry.Group.alpha = _opacity.Value;
			}
			if ((Object)(object)fishHudEntry.Health != (Object)null)
			{
				((Graphic)fishHudEntry.Health).color = color;
			}
		}
	}

	private static Color ResolveColor(string configured, Color fallback)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: 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)
		if (string.IsNullOrEmpty(configured) || string.Equals(configured.Trim(), "Default", StringComparison.OrdinalIgnoreCase))
		{
			return fallback;
		}
		string text = configured.Trim();
		if (!text.StartsWith("#", StringComparison.Ordinal))
		{
			text = "#" + text;
		}
		Color result = default(Color);
		if (!ColorUtility.TryParseHtmlString(text, ref result))
		{
			return fallback;
		}
		return result;
	}

	private void BeginDeathFade(FishHudEntry entry)
	{
		if (!entry.Fading)
		{
			entry.Fading = true;
			entry.FadeStartedAt = Time.unscaledTime;
			if ((Object)(object)entry.HealthLerped != (Object)null)
			{
				LeanTween.cancel(((Component)entry.HealthLerped).gameObject);
			}
		}
	}

	private void TrimEntries()
	{
		int num = Mathf.Clamp(_maximumTargets.Value, 1, 8);
		while (_entries.Count > num)
		{
			RemoveEntryAt(_entries.Count - 1);
		}
	}

	private void RemoveEntryAt(int index)
	{
		if (index >= 0 && index < _entries.Count)
		{
			FishHudEntry fishHudEntry = _entries[index];
			_entries.RemoveAt(index);
			if ((Object)(object)fishHudEntry.HealthLerped != (Object)null)
			{
				LeanTween.cancel(((Component)fishHudEntry.HealthLerped).gameObject);
			}
			if ((Object)(object)fishHudEntry.Root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)fishHudEntry.Root).gameObject);
			}
		}
	}

	private void ClearEntries()
	{
		for (int num = _entries.Count - 1; num >= 0; num--)
		{
			RemoveEntryAt(num);
		}
	}

	private void SetRootVisible(bool visible)
	{
		if ((Object)(object)_container != (Object)null && ((Component)_container).gameObject.activeSelf != visible)
		{
			((Component)_container).gameObject.SetActive(visible);
		}
	}

	private void DestroyHud()
	{
		ClearEntries();
		if ((Object)(object)_container != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_container).gameObject);
		}
		_mainCanvas = null;
		_container = null;
		_nameTemplate = null;
		_healthTemplate = null;
		_lerpedTemplate = null;
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		DestroyHud();
		if ((Object)(object)_instance == (Object)(object)this)
		{
			_instance = null;
		}
	}
}