Decompiled source of ShowEnemyHealth Fixed v1.0.2

REPO_ShowEnemyHealth.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("REPO_ShowEnemyHealth")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+16aa0046be6243b25b8d3c518bf413179277c854")]
[assembly: AssemblyProduct("ShowEnemyHealth Fixed Edition")]
[assembly: AssemblyTitle("REPO_ShowEnemyHealth")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.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;
		}
	}
}
namespace ShowEnemyHealth
{
	internal static class ConfigManager
	{
		public static ConfigFile ConfigFile { get; private set; }

		public static ConfigEntry<bool> ShowEnemyHealth { get; private set; }

		public static ConfigEntry<float> HealthFontSize { get; private set; }

		public static ConfigEntry<string> HealthFontColor { get; private set; }

		public static ConfigEntry<bool> ShowEnemyDamage { get; private set; }

		public static ConfigEntry<float> DamageFontSize { get; private set; }

		public static ConfigEntry<string> DamageFontHighlightColor { get; private set; }

		public static ConfigEntry<string> DamageFontColor { get; private set; }

		public static void Initialize(ConfigFile configFile)
		{
			ConfigFile = configFile;
			BindConfigs();
		}

		private static void BindConfigs()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Expected O, but got Unknown
			AcceptableValueList<string> val = new AcceptableValueList<string>(new string[10] { "black", "blue", "cyan", "green", "grey", "magenta", "orange", "red", "white", "yellow" });
			ShowEnemyHealth = ConfigFile.Bind<bool>("Health", "ShowEnemyHealth", true, "Show enemy health text");
			HealthFontSize = ConfigFile.Bind<float>("Health", "HealthFontSize", 15f, new ConfigDescription("Health text size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
			HealthFontColor = ConfigFile.Bind<string>("Health", "HealthFontColor", "grey", new ConfigDescription("Health text color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			ShowEnemyDamage = ConfigFile.Bind<bool>("Damage", "ShowEnemyDamage", true, "Show damage text");
			DamageFontSize = ConfigFile.Bind<float>("Damage", "DamageFontSize", 25f, new ConfigDescription("Damage text size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
			DamageFontHighlightColor = ConfigFile.Bind<string>("Damage", "DamageFontHighlightColor", "red", new ConfigDescription("Damage highlight color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			DamageFontColor = ConfigFile.Bind<string>("Damage", "DamageFontColor", "orange", new ConfigDescription("Damage text color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
		}
	}
	internal class CustomDamageTextOcclusion : MonoBehaviour
	{
		private WorldSpaceUIValueLost valueLost;

		private CanvasGroup canvasGroup;

		private Enemy currEnemy;

		private EnemyHealth currEnemyHealth;

		private EnemyRigidbody enemyRigidBody;

		private int occlusionMask;

		private bool isOccluded;

		private bool wasOccluded;

		private float baseAlpha = 1f;

		private float nextOcclusionCheckTime;

		private void Awake()
		{
			occlusionMask = Patches.BuildOcclusionMask();
		}

		internal void Initialize(WorldSpaceUIValueLost component, Enemy enemy, EnemyHealth enemyHealth, EnemyRigidbody rigidBody)
		{
			valueLost = component;
			currEnemy = enemy;
			currEnemyHealth = enemyHealth;
			enemyRigidBody = rigidBody;
			EnsureCanvasGroup();
		}

		private void LateUpdate()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)valueLost == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			EnsureCanvasGroup();
			if (!((Object)(object)canvasGroup == (Object)null))
			{
				if (!wasOccluded || canvasGroup.alpha > 0f)
				{
					baseAlpha = canvasGroup.alpha;
				}
				if (Time.time >= nextOcclusionCheckTime)
				{
					nextOcclusionCheckTime = Time.time + 0.1f;
					isOccluded = IsOccluded(Camera.main, GetWorldPosition());
				}
				canvasGroup.alpha = (isOccluded ? 0f : baseAlpha);
				wasOccluded = isOccluded;
			}
		}

		private void EnsureCanvasGroup()
		{
			if (!((Object)(object)canvasGroup != (Object)null))
			{
				canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
				if ((Object)(object)canvasGroup == (Object)null)
				{
					canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
				}
			}
		}

		private Vector3 GetWorldPosition()
		{
			//IL_0056: 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_005f: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)valueLost != (Object)null && Patches.WorldSpaceUIValueLostWorldPositionField != null && Patches.WorldSpaceUIValueLostWorldPositionField.GetValue(valueLost) is Vector3 result)
			{
				return result;
			}
			return ((Component)this).transform.position;
		}

		private bool IsOccluded(Camera mainCamera, Vector3 labelPosition)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			if ((Object)(object)mainCamera == (Object)null || occlusionMask == 0)
			{
				return false;
			}
			Vector3 position = ((Component)mainCamera).transform.position;
			Vector3 val = labelPosition - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= Mathf.Epsilon)
			{
				return false;
			}
			RaycastHit[] array = Physics.RaycastAll(position, ((Vector3)(ref val)).normalized, magnitude, occlusionMask, (QueryTriggerInteraction)1);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !IsCurrentEnemyCollider(((RaycastHit)(ref val2)).collider))
				{
					return true;
				}
			}
			return false;
		}

		private bool IsCurrentEnemyCollider(Collider collider)
		{
			Transform transform = ((Component)collider).transform;
			return IsInHierarchy(transform, ((Object)(object)currEnemy != (Object)null) ? ((Component)currEnemy).transform : null) || IsInHierarchy(transform, ((Object)(object)enemyRigidBody != (Object)null) ? ((Component)enemyRigidBody).transform : null) || IsInHierarchy(transform, ((Object)(object)currEnemyHealth != (Object)null) ? ((Component)currEnemyHealth).transform : null);
		}

		private static bool IsInHierarchy(Transform colliderTransform, Transform ownerTransform)
		{
			return (Object)(object)colliderTransform != (Object)null && (Object)(object)ownerTransform != (Object)null && colliderTransform.IsChildOf(ownerTransform);
		}
	}
	[RequireComponent(typeof(RectTransform))]
	[RequireComponent(typeof(TextMeshProUGUI))]
	internal class CustomEnemyHealthUI : WorldSpaceUIChild
	{
		private Vector3 scale = default(Vector3);

		internal Vector3 newWorldPosition = default(Vector3);

		private Enemy currEnemy;

		private EnemyHealth currEnemyHealth;

		private EnemyRigidbody enemyRigidBody;

		private TextMeshProUGUI text;

		private bool initialized = false;

		private bool isOccluded = false;

		private float nextOcclusionCheckTime = 0f;

		private int occlusionMask;

		private Vector3 worldspaceOffset = default(Vector3);

		private Vector3 targetWorldspaceOffset = default(Vector3);

		public int recalcIntervalFrames = 50;

		private int frameCounter = 0;

		public float worldspaceOffsetLerpRate = 5f;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Patches.SetWorldSpaceUIChildPositionOffset((WorldSpaceUIChild)(object)this, new Vector3(0f, -0.05f, 0f));
			scale = Vector3.one;
			text = ((Component)this).GetComponent<TextMeshProUGUI>();
			occlusionMask = BuildOcclusionMask();
		}

		public void Show(EnemyHealth enemyHealth, Vector3 screenspaceOffset)
		{
			//IL_003b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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)
			if (!ConfigManager.ShowEnemyHealth.Value)
			{
				Patches.RemoveHealthUI(((Object)(object)currEnemyHealth != (Object)null) ? currEnemyHealth : enemyHealth);
				return;
			}
			((Graphic)text).color = Color.gray;
			Color32 val = default(Color32);
			if (ColorUtility.DoTryParseHtmlColor(ConfigManager.HealthFontColor.Value, ref val))
			{
				((Graphic)text).color = Color32.op_Implicit(val);
			}
			((TMP_Text)text).fontSize = ConfigManager.HealthFontSize.Value;
			if (!Object.op_Implicit((Object)(object)currEnemy) || !Object.op_Implicit((Object)(object)currEnemyHealth))
			{
				Patches.SetWorldSpaceUIChildPositionOffset((WorldSpaceUIChild)(object)this, screenspaceOffset);
				currEnemyHealth = enemyHealth;
				currEnemy = Patches.GetEnemy(enemyHealth);
				if ((Object)(object)currEnemy == (Object)null)
				{
					Patches.RemoveHealthUI(this);
					return;
				}
				newWorldPosition = Patches.GetEnemyPosition(currEnemy, currEnemyHealth);
				Patches.SetWorldSpaceUIChildPosition((WorldSpaceUIChild)(object)this, newWorldPosition);
				enemyRigidBody = Patches.GetEnemyRigidbody(currEnemy);
				UpdateTargetWorldSpaceOffset();
				worldspaceOffset = targetWorldspaceOffset;
				UpdateTextValues();
				initialized = true;
			}
		}

		internal void UpdateTargetWorldSpaceOffset()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemyRigidBody == (Object)null)
			{
				return;
			}
			Bounds val = default(Bounds);
			bool flag = false;
			Collider[] componentsInChildren = ((Component)enemyRigidBody).GetComponentsInChildren<Collider>();
			Collider[] array = componentsInChildren;
			foreach (Collider val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger)
				{
					if (!flag)
					{
						val = val2.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val2.bounds);
					}
				}
			}
			if (!flag)
			{
				targetWorldspaceOffset = new Vector3(0f, 1f, 0f);
				return;
			}
			float y = Patches.GetEnemyPosition(currEnemy, currEnemyHealth).y;
			float num = Mathf.Clamp(((Bounds)(ref val)).max.y - y + 0.15f, 0.5f, 12f);
			targetWorldspaceOffset = new Vector3(0f, num, 0f);
		}

		internal void UpdateTextValues()
		{
			if (!((Object)(object)currEnemy == (Object)null) && !((Object)(object)currEnemyHealth == (Object)null) && !((Object)(object)text == (Object)null))
			{
				int num = Mathf.Max(0, Patches.GetHealthCurrent(currEnemyHealth));
				int health = currEnemyHealth.health;
				((TMP_Text)text).text = $"{num}/{health}";
			}
		}

		protected override void Update()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			if (!initialized)
			{
				return;
			}
			if ((Object)(object)currEnemyHealth == (Object)null || (Object)(object)currEnemy == (Object)null)
			{
				Patches.RemoveHealthUI(this);
				return;
			}
			if (!Patches.IsEnemyHealthDisplayable(currEnemyHealth))
			{
				Patches.RemoveHealthUI(currEnemyHealth);
				return;
			}
			((WorldSpaceUIChild)this).Update();
			frameCounter++;
			if (frameCounter >= recalcIntervalFrames)
			{
				frameCounter = 0;
				UpdateTargetWorldSpaceOffset();
			}
			worldspaceOffset = Vector3.Lerp(worldspaceOffset, targetWorldspaceOffset, Time.deltaTime * worldspaceOffsetLerpRate);
			Patches.SetWorldSpaceUIChildPosition((WorldSpaceUIChild)(object)this, newWorldPosition + worldspaceOffset);
			if ((Object)(object)currEnemy != (Object)null)
			{
				newWorldPosition = Patches.GetEnemyPosition(currEnemy, currEnemyHealth);
			}
			float num = 1f;
			float num2 = 5f;
			float num3 = 20f;
			Camera main = Camera.main;
			float num4 = (((Object)(object)main != (Object)null) ? Vector3.Distance(((Component)main).transform.position, newWorldPosition) : num2);
			Vector3 localScale = scale;
			if (num4 > num2)
			{
				num4 = Mathf.Clamp(num4, num2, num3);
				num = 1f - (num4 - num2) / (num3 - num2);
				((Vector3)(ref localScale))..ctor(num, num, num);
			}
			if (num4 < num3 && Time.time >= nextOcclusionCheckTime)
			{
				nextOcclusionCheckTime = Time.time + 0.1f;
				isOccluded = IsOccluded(main, newWorldPosition + worldspaceOffset);
			}
			else if (num4 >= num3)
			{
				isOccluded = false;
			}
			((TMP_Text)text).alpha = (isOccluded ? 0f : num);
			((Component)this).transform.localScale = localScale;
			UpdateTextValues();
		}

		private static int BuildOcclusionMask()
		{
			return Patches.BuildOcclusionMask();
		}

		private bool IsOccluded(Camera mainCamera, Vector3 labelPosition)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			if ((Object)(object)mainCamera == (Object)null || occlusionMask == 0)
			{
				return false;
			}
			Vector3 position = ((Component)mainCamera).transform.position;
			Vector3 val = labelPosition - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= Mathf.Epsilon)
			{
				return false;
			}
			RaycastHit[] array = Physics.RaycastAll(position, ((Vector3)(ref val)).normalized, magnitude, occlusionMask, (QueryTriggerInteraction)1);
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !IsCurrentEnemyCollider(((RaycastHit)(ref val2)).collider))
				{
					return true;
				}
			}
			return false;
		}

		private bool IsCurrentEnemyCollider(Collider collider)
		{
			Transform transform = ((Component)collider).transform;
			return IsInHierarchy(transform, ((Object)(object)currEnemy != (Object)null) ? ((Component)currEnemy).transform : null) || IsInHierarchy(transform, ((Object)(object)enemyRigidBody != (Object)null) ? ((Component)enemyRigidBody).transform : null) || IsInHierarchy(transform, ((Object)(object)currEnemyHealth != (Object)null) ? ((Component)currEnemyHealth).transform : null);
		}

		private static bool IsInHierarchy(Transform colliderTransform, Transform ownerTransform)
		{
			return (Object)(object)colliderTransform != (Object)null && (Object)(object)ownerTransform != (Object)null && colliderTransform.IsChildOf(ownerTransform);
		}
	}
	[HarmonyPatch]
	public static class Patches
	{
		[CompilerGenerated]
		private sealed class <DelayedCreateHealthUI>d__46 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public EnemyHealth enemyHealth;

			private float <fastRetryUntil>5__1;

			private Enemy <enemy>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedCreateHealthUI>d__46(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<enemy>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Invalid comparison between Unknown and I4
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<fastRetryUntil>5__1 = Time.realtimeSinceStartup + 3f;
					break;
				case 1:
					<>1__state = -1;
					goto IL_012e;
				case 2:
					{
						<>1__state = -1;
						goto IL_012e;
					}
					IL_012e:
					<enemy>5__2 = null;
					break;
				}
				if (ConfigManager.ShowEnemyHealth.Value && (Object)(object)enemyHealth != (Object)null && !GetDead(enemyHealth))
				{
					<enemy>5__2 = GetEnemy(enemyHealth);
					if (!((Object)(object)<enemy>5__2 != (Object)null) || (int)<enemy>5__2.CurrentState != 11)
					{
						if ((Object)(object)WorldSpaceUIParent.instance != (Object)null && (Object)(object)WorldSpaceUIParent.instance.TTSPrefab != (Object)null)
						{
							CreateHealthUI(enemyHealth, GetEnemyPosition(<enemy>5__2, enemyHealth));
							if (healthUIElements.ContainsKey(enemyHealth))
							{
								goto IL_016a;
							}
						}
						if (Time.realtimeSinceStartup < <fastRetryUntil>5__1)
						{
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 2;
						return true;
					}
				}
				goto IL_016a;
				IL_016a:
				createHealthCoroutines.Remove(enemyHealth);
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <DelayedSetText>d__43 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public FieldInfo fieldInfo;

			public object target;

			public string targetText;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedSetText>d__43(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (!TrySetDamageText(fieldInfo, target, targetText))
					{
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					break;
				case 2:
					<>1__state = -1;
					TrySetDamageText(fieldInfo, target, targetText);
					break;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <DelayedShowHealthUI>d__45 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public CustomEnemyHealthUI healthUI;

			public EnemyHealth enemyHealth;

			public Vector3 offset;

			private Exception <e>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedShowHealthUI>d__45(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<e>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						if (!IsEnemyHealthDisplayable(enemyHealth))
						{
							RemoveHealthUI(enemyHealth);
							return false;
						}
						healthUI.Show(enemyHealth, offset);
					}
					catch (Exception ex)
					{
						<e>5__1 = ex;
						Plugin.Logger.LogDebug((object)$"Handling exception in DelayedShowHealthUI: {<e>5__1}");
						try
						{
							RemoveHealthUI(enemyHealth);
						}
						catch
						{
						}
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal static readonly Dictionary<EnemyHealth, CustomEnemyHealthUI> healthUIElements = new Dictionary<EnemyHealth, CustomEnemyHealthUI>();

		internal static readonly Dictionary<EnemyHealth, Coroutine> createHealthCoroutines = new Dictionary<EnemyHealth, Coroutine>();

		internal static readonly FieldInfo EnemyHealthEnemyField = typeof(EnemyHealth).GetField("enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyHealthCurrentField = typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyHealthDeadField = typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyHealthField = typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyEnemyParentField = typeof(Enemy).GetField("EnemyParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyRigidbodyField = typeof(Enemy).GetField("Rigidbody", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyParentEnemyField = typeof(EnemyParent).GetField("Enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(EnemyParent).GetField("enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo EnemyBangEnemyField = typeof(EnemyBang).GetField("enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIChildWorldPositionField = typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIChildPositionOffsetField = typeof(WorldSpaceUIChild).GetField("positionOffset", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIValueLostWorldPositionField = typeof(WorldSpaceUIValueLost).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIValueLostValueField = typeof(WorldSpaceUIValueLost).GetField("value", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIValueLostTextField = typeof(WorldSpaceUIValueLost).GetField("text", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIValueLostTextColorField = typeof(WorldSpaceUIValueLost).GetField("textColor", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static readonly FieldInfo WorldSpaceUIParentValueLostListField = typeof(WorldSpaceUIParent).GetField("valueLostList", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static Enemy GetEnemy(EnemyHealth enemyHealth)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if ((Object)(object)enemyHealth == (Object)null)
			{
				return null;
			}
			return (Enemy)(EnemyHealthEnemyField?.GetValue(enemyHealth));
		}

		internal static int GetHealthCurrent(EnemyHealth enemyHealth)
		{
			if ((Object)(object)enemyHealth == (Object)null)
			{
				return 0;
			}
			return (int)(EnemyHealthCurrentField?.GetValue(enemyHealth) ?? ((object)0));
		}

		internal static void SetHealthCurrent(EnemyHealth enemyHealth, int value)
		{
			if (!((Object)(object)enemyHealth == (Object)null))
			{
				EnemyHealthCurrentField?.SetValue(enemyHealth, value);
			}
		}

		internal static bool GetDead(EnemyHealth enemyHealth)
		{
			if ((Object)(object)enemyHealth == (Object)null)
			{
				return false;
			}
			return (bool)(EnemyHealthDeadField?.GetValue(enemyHealth) ?? ((object)false));
		}

		internal static Vector3 GetEnemyPosition(Enemy enemy, EnemyHealth enemyHealth)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0077: 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)
			if ((Object)(object)enemy != (Object)null && (Object)(object)enemy.CenterTransform != (Object)null)
			{
				return enemy.CenterTransform.position;
			}
			if ((Object)(object)enemy != (Object)null && (Object)(object)((Component)enemy).transform != (Object)null)
			{
				return ((Component)enemy).transform.position;
			}
			if ((Object)(object)enemyHealth != (Object)null && (Object)(object)((Component)enemyHealth).transform != (Object)null)
			{
				return ((Component)enemyHealth).transform.position;
			}
			return Vector3.zero;
		}

		internal static EnemyRigidbody GetEnemyRigidbody(Enemy enemy)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if ((Object)(object)enemy == (Object)null)
			{
				return null;
			}
			return (EnemyRigidbody)(EnemyRigidbodyField?.GetValue(enemy));
		}

		internal static bool IsEnemyHealthDisplayable(EnemyHealth enemyHealth)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			if (!ConfigManager.ShowEnemyHealth.Value || (Object)(object)enemyHealth == (Object)null || GetDead(enemyHealth))
			{
				return false;
			}
			Enemy enemy = GetEnemy(enemyHealth);
			if ((Object)(object)enemy == (Object)null || (int)enemy.CurrentState == 11)
			{
				return false;
			}
			return true;
		}

		internal static int BuildOcclusionMask()
		{
			int mask = 0;
			AddLayerToMask(ref mask, "Default");
			AddLayerToMask(ref mask, "StaticGrabObject");
			AddLayerToMask(ref mask, "PhysGrabObject");
			AddLayerToMask(ref mask, "PhysGrabObjectCart");
			AddLayerToMask(ref mask, "PhysGrabObjectHinge");
			return mask;
		}

		internal static void AddLayerToMask(ref int mask, string layerName)
		{
			int num = LayerMask.NameToLayer(layerName);
			if (num >= 0)
			{
				mask |= 1 << num;
			}
		}

		internal static void SetWorldSpaceUIChildPosition(WorldSpaceUIChild child, Vector3 position)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)child == (Object)null) && !(WorldSpaceUIChildWorldPositionField == null))
			{
				WorldSpaceUIChildWorldPositionField.SetValue(child, position);
			}
		}

		internal static void SetWorldSpaceUIChildPositionOffset(WorldSpaceUIChild child, Vector3 offset)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)child == (Object)null) && !(WorldSpaceUIChildPositionOffsetField == null))
			{
				WorldSpaceUIChildPositionOffsetField.SetValue(child, offset);
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "Awake")]
		[HarmonyPostfix]
		public static void CreateEnemyHealthOnAwake(EnemyHealth __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				StartOrRestartCreateHealthCoroutine(__instance);
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "OnSpawn")]
		[HarmonyPostfix]
		public static void CreateEnemyHealthOnSpawn(EnemyHealth __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				RemoveHealthUI(__instance);
				StartOrRestartCreateHealthCoroutine(__instance);
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "DeathRPC")]
		[HarmonyPostfix]
		public static void RemoveEnemyHealthOnDeath(EnemyHealth __instance)
		{
			RemoveHealthUI(__instance);
		}

		[HarmonyPatch(typeof(EnemyHealth), "DeathImpulseRPC")]
		[HarmonyPostfix]
		public static void RemoveEnemyHealthOnDeathImpulse(EnemyHealth __instance)
		{
			RemoveHealthUI(__instance);
		}

		[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
		[HarmonyPostfix]
		public static void ShowEnemyHealthOnHurt(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			try
			{
				Enemy enemy = GetEnemy(__instance);
				if (!((Object)(object)enemy == (Object)null))
				{
					EnemyParent val = (EnemyParent)(EnemyEnemyParentField?.GetValue(enemy));
					int healthCurrent = GetHealthCurrent(__instance);
					bool flag = healthCurrent <= 0 || GetDead(__instance);
					Vector3 enemyPosition = GetEnemyPosition(enemy, __instance);
					Plugin.Logger.LogDebug((object)string.Format("{0} HURT by {1}, now has {2}, willDie:{3} ...", val?.enemyName ?? "Enemy", _damage, healthCurrent, flag));
					CreateDamageUI(_damage, enemyPosition, enemy, __instance);
					if (flag)
					{
						RemoveHealthUI(__instance);
					}
					else
					{
						CreateHealthUI(__instance, enemyPosition);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "HurtRPC")]
		[HarmonyPostfix]
		public static void ShowEnemyHealthOnHurtRPC(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() || _damage <= 0)
			{
				return;
			}
			try
			{
				Enemy enemy = GetEnemy(__instance);
				if (!((Object)(object)enemy == (Object)null))
				{
					EnemyParent val = (EnemyParent)(EnemyEnemyParentField?.GetValue(enemy));
					Vector3 enemyPosition = GetEnemyPosition(enemy, __instance);
					int healthCurrent = GetHealthCurrent(__instance);
					int num = Math.Max(0, healthCurrent - _damage);
					SetHealthCurrent(__instance, num);
					CreateDamageUI(_damage, enemyPosition, enemy, __instance);
					bool flag = num <= 0 || GetDead(__instance);
					Plugin.Logger.LogDebug((object)string.Format("{0} HURT by {1}, currHealth: {2}, now has {3}, willDie:{4} ...", val?.enemyName ?? "Enemy", _damage, healthCurrent, num, flag));
					if (flag)
					{
						RemoveHealthUI(__instance);
					}
					else
					{
						CreateHealthUI(__instance, enemyPosition);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
			}
		}

		[HarmonyPatch(typeof(EnemyBang), "ExplodeRPC")]
		[HarmonyPostfix]
		public static void HandleBangerExplode(EnemyBang __instance)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			try
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					Enemy val = (Enemy)(EnemyBangEnemyField?.GetValue(__instance));
					if (!((Object)(object)val == (Object)null) && !(EnemyHealthField == null))
					{
						EnemyHealth enemyHealth = (EnemyHealth)EnemyHealthField.GetValue(val);
						RemoveHealthUI(enemyHealth);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"HandleBangerExplode failed:\n{arg}");
			}
		}

		[HarmonyPatch(typeof(EnemyParent), "DespawnRPC")]
		[HarmonyPostfix]
		public static void RemoveEnemyHealthOnDespawn(EnemyParent __instance)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			try
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					Enemy val = null;
					if (EnemyParentEnemyField != null)
					{
						val = (Enemy)EnemyParentEnemyField.GetValue(__instance);
					}
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)__instance).GetComponentInChildren<Enemy>(true);
					}
					if (!((Object)(object)val == (Object)null) && !(EnemyHealthField == null))
					{
						EnemyHealth enemyHealth = (EnemyHealth)EnemyHealthField.GetValue(val);
						RemoveHealthUI(enemyHealth);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"RemoveEnemyHealthOnDespawn failed:\n{arg}");
			}
		}

		internal static void StartOrRestartCreateHealthCoroutine(EnemyHealth enemyHealth)
		{
			if (!((Object)(object)enemyHealth == (Object)null))
			{
				StopCreateHealthCoroutine(enemyHealth);
				Coroutine val = Plugin.StartPluginCoroutine(DelayedCreateHealthUI(enemyHealth));
				if (val != null)
				{
					createHealthCoroutines[enemyHealth] = val;
				}
			}
		}

		internal static void StopCreateHealthCoroutine(EnemyHealth enemyHealth)
		{
			if (!((Object)(object)enemyHealth == (Object)null) && createHealthCoroutines.TryGetValue(enemyHealth, out var value))
			{
				createHealthCoroutines.Remove(enemyHealth);
				Plugin.StopPluginCoroutine(value);
			}
		}

		internal static void CreateHealthUI(EnemyHealth enemyHealth, Vector3 enemyPosition)
		{
			//IL_0046: 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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			if (!IsEnemyHealthDisplayable(enemyHealth))
			{
				RemoveHealthUI(enemyHealth);
			}
			else
			{
				if ((Object)(object)WorldSpaceUIParent.instance == (Object)null || (Object)(object)WorldSpaceUIParent.instance.TTSPrefab == (Object)null)
				{
					return;
				}
				Vector3 val = default(Vector3);
				val.x = 0f;
				val.y = 0f;
				val.z = 0f;
				Vector3 val2 = val;
				if (healthUIElements.TryGetValue(enemyHealth, out var value))
				{
					if (!((Object)(object)value == (Object)null) && !((Object)(object)((Component)value).gameObject == (Object)null))
					{
						value.Show(enemyHealth, val2);
						return;
					}
					healthUIElements.Remove(enemyHealth);
				}
				if (healthUIElements.ContainsKey(enemyHealth))
				{
					return;
				}
				GameObject val3 = Object.Instantiate<GameObject>(WorldSpaceUIParent.instance.TTSPrefab, ((Component)WorldSpaceUIParent.instance).transform.position, ((Component)WorldSpaceUIParent.instance).transform.rotation, ((Component)WorldSpaceUIParent.instance).transform);
				Object.Destroy((Object)(object)val3.GetComponent<WorldSpaceUITTS>());
				CustomEnemyHealthUI customEnemyHealthUI = val3.AddComponent<CustomEnemyHealthUI>();
				if (WorldSpaceUIChildWorldPositionField == null)
				{
					Object.Destroy((Object)(object)val3);
					return;
				}
				SetWorldSpaceUIChildPosition((WorldSpaceUIChild)(object)customEnemyHealthUI, enemyPosition);
				healthUIElements.Add(enemyHealth, customEnemyHealthUI);
				if (Plugin.StartPluginCoroutine(DelayedShowHealthUI(healthUIElements[enemyHealth], enemyHealth, val2)) == null)
				{
					try
					{
						customEnemyHealthUI.Show(enemyHealth, val2);
					}
					catch (Exception arg)
					{
						Plugin.Logger.LogDebug((object)$"Handling exception in immediate ShowHealthUI fallback: {arg}");
						RemoveHealthUI(enemyHealth);
					}
				}
			}
		}

		internal static void RemoveHealthUI(EnemyHealth enemyHealth)
		{
			if ((Object)(object)enemyHealth == (Object)null)
			{
				CleanupStaleHealthUIEntries();
				return;
			}
			StopCreateHealthCoroutine(enemyHealth);
			if (healthUIElements.TryGetValue(enemyHealth, out var value))
			{
				healthUIElements.Remove(enemyHealth);
				if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
		}

		internal static void RemoveHealthUI(CustomEnemyHealthUI healthUI)
		{
			if ((Object)(object)healthUI == (Object)null)
			{
				CleanupStaleHealthUIEntries();
				return;
			}
			EnemyHealth val = null;
			bool flag = false;
			foreach (KeyValuePair<EnemyHealth, CustomEnemyHealthUI> healthUIElement in healthUIElements)
			{
				if ((Object)(object)healthUIElement.Value == (Object)(object)healthUI)
				{
					val = healthUIElement.Key;
					flag = true;
					break;
				}
			}
			if (flag)
			{
				StopCreateHealthCoroutine(val);
				healthUIElements.Remove(val);
			}
			if ((Object)(object)((Component)healthUI).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)healthUI).gameObject);
			}
		}

		internal static void CleanupStaleHealthUIEntries()
		{
			List<EnemyHealth> list = new List<EnemyHealth>();
			List<EnemyHealth> list2 = new List<EnemyHealth>();
			foreach (KeyValuePair<EnemyHealth, CustomEnemyHealthUI> healthUIElement in healthUIElements)
			{
				if ((Object)(object)healthUIElement.Key == (Object)null || (Object)(object)healthUIElement.Value == (Object)null || (Object)(object)((Component)healthUIElement.Value).gameObject == (Object)null)
				{
					list.Add(healthUIElement.Key);
				}
			}
			foreach (KeyValuePair<EnemyHealth, Coroutine> createHealthCoroutine in createHealthCoroutines)
			{
				if ((Object)(object)createHealthCoroutine.Key == (Object)null || createHealthCoroutine.Value == null)
				{
					list2.Add(createHealthCoroutine.Key);
				}
			}
			foreach (EnemyHealth item in list2)
			{
				createHealthCoroutines.Remove(item);
			}
			foreach (EnemyHealth item2 in list)
			{
				if (healthUIElements.TryGetValue(item2, out var value) && (Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
				healthUIElements.Remove(item2);
			}
		}

		internal static void CreateDamageUI(int damage, Vector3 worldPosition, Enemy enemy, EnemyHealth enemyHealth)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.ShowEnemyDamage.Value)
			{
				return;
			}
			WorldSpaceUIParent instance = WorldSpaceUIParent.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.valueLostPrefab == (Object)null)
			{
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(instance.valueLostPrefab, ((Component)instance).transform.position, ((Component)instance).transform.rotation, ((Component)instance).transform);
			WorldSpaceUIValueLost component = val.GetComponent<WorldSpaceUIValueLost>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return;
			}
			CustomDamageTextOcclusion customDamageTextOcclusion = val.GetComponent<CustomDamageTextOcclusion>() ?? val.AddComponent<CustomDamageTextOcclusion>();
			customDamageTextOcclusion.Initialize(component, enemy, enemyHealth, GetEnemyRigidbody(enemy));
			WorldSpaceUIValueLostWorldPositionField?.SetValue(component, worldPosition);
			WorldSpaceUIValueLostValueField?.SetValue(component, damage);
			if (Plugin.StartPluginCoroutine(DelayedSetText(WorldSpaceUIValueLostTextField, component, $"-{damage}")) == null)
			{
				TrySetDamageText(WorldSpaceUIValueLostTextField, component, $"-{damage}");
			}
			((List<WorldSpaceUIValueLost>)(WorldSpaceUIParentValueLostListField?.GetValue(instance)))?.Add(component);
		}

		[IteratorStateMachine(typeof(<DelayedSetText>d__43))]
		internal static IEnumerator DelayedSetText(FieldInfo fieldInfo, object target, string targetText)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedSetText>d__43(0)
			{
				fieldInfo = fieldInfo,
				target = target,
				targetText = targetText
			};
		}

		internal static bool TrySetDamageText(FieldInfo fieldInfo, object target, string targetText)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = (TextMeshProUGUI)(fieldInfo?.GetValue(target));
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			((TMP_Text)val).text = targetText;
			((TMP_Text)val).fontSize = ConfigManager.DamageFontSize.Value;
			((Graphic)val).color = Color.blue;
			Color32 val2 = default(Color32);
			if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontHighlightColor.Value, ref val2))
			{
				((Graphic)val).color = Color32.op_Implicit(val2);
			}
			Color32 val3 = default(Color32);
			if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontColor.Value, ref val3))
			{
				Color val4 = Color32.op_Implicit(val3);
				WorldSpaceUIValueLostTextColorField?.SetValue(target, val4);
			}
			else
			{
				WorldSpaceUIValueLostTextColorField?.SetValue(target, Color.cyan);
			}
			return true;
		}

		[IteratorStateMachine(typeof(<DelayedShowHealthUI>d__45))]
		internal static IEnumerator DelayedShowHealthUI(CustomEnemyHealthUI healthUI, EnemyHealth enemyHealth, Vector3 offset)
		{
			//IL_0015: 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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedShowHealthUI>d__45(0)
			{
				healthUI = healthUI,
				enemyHealth = enemyHealth,
				offset = offset
			};
		}

		[IteratorStateMachine(typeof(<DelayedCreateHealthUI>d__46))]
		internal static IEnumerator DelayedCreateHealthUI(EnemyHealth enemyHealth)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedCreateHealthUI>d__46(0)
			{
				enemyHealth = enemyHealth
			};
		}
	}
	[BepInPlugin("REPO_ShowEnemyHealth", "ShowEnemyHealth Fixed Edition", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static Coroutine StartPluginCoroutine(IEnumerator routine)
		{
			if ((Object)(object)Instance == (Object)null || routine == null || !((Behaviour)Instance).isActiveAndEnabled)
			{
				return null;
			}
			return ((MonoBehaviour)Instance).StartCoroutine(routine);
		}

		internal static void StopPluginCoroutine(Coroutine coroutine)
		{
			if (!((Object)(object)Instance == (Object)null) && coroutine != null)
			{
				((MonoBehaviour)Instance).StopCoroutine(coroutine);
			}
		}

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin ShowEnemyHealth Fixed Edition by Rozza is loaded!");
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("EnemyHealth");
			PatchAll();
		}

		private void PatchAll()
		{
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				_harmony.PatchAll(item);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "REPO_ShowEnemyHealth";

		public const string PLUGIN_NAME = "ShowEnemyHealth Fixed Edition";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}