Decompiled source of ShowEnemyHealth v1.0.3

REPO_ShowEnemyHealth.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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 Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("REPO_ShowEnemyHealth")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+1b27dec367654b521dc41d1a2bb4fbcca648c4e7")]
[assembly: AssemblyProduct("ShowEnemyHealth")]
[assembly: AssemblyTitle("REPO_ShowEnemyHealth")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.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> HealthShowTimer { 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 ConfigEntry<bool> AttemptMultiplayerHealthSync { get; private set; }

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

		private static void BindConfigs()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Expected O, but got Unknown
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: 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>("General", "ShowEnemyHealth", true, "");
			HealthShowTimer = ConfigFile.Bind<float>("General", "HealthShowTimer", 120f, new ConfigDescription("Max seconds to show enemy health", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), Array.Empty<object>()));
			HealthFontSize = ConfigFile.Bind<float>("General", "HealthFontSize", 15f, new ConfigDescription("Enemy health font size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
			HealthFontColor = ConfigFile.Bind<string>("General", "HealthFontColor", "grey", new ConfigDescription("Enemy health font color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			ShowEnemyDamage = ConfigFile.Bind<bool>("General", "ShowEnemyDamage", true, "");
			DamageFontSize = ConfigFile.Bind<float>("General", "DamageFontSize", 25f, new ConfigDescription("Damage font size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
			DamageFontHighlightColor = ConfigFile.Bind<string>("General", "DamageFontHighlightColor", "red", new ConfigDescription("Damage font highlight color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			DamageFontColor = ConfigFile.Bind<string>("General", "DamageFontColor", "orange", new ConfigDescription("Damage font primary color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			AttemptMultiplayerHealthSync = ConfigFile.Bind<bool>("General", "AttemptMultiplayerHealthSync", true, "Sync enemy health across all clients");
		}
	}
	[RequireComponent(typeof(RectTransform))]
	[RequireComponent(typeof(TextMeshProUGUI))]
	internal class CustomEnemyHealthUI : WorldSpaceUIChild
	{
		public static CustomEnemyHealthUI instance;

		private Vector3 scale;

		internal Vector3 newWorldPosition;

		private float showTimer;

		private Enemy currEnemy;

		private EnemyHealth currEnemyHealth;

		private EnemyRigidbody enemyRigidBody;

		private TextMeshProUGUI text;

		private Vector3 worldspaceOffset;

		private Vector3 targetWorldspaceOffset;

		public int recalcIntervalFrames = 50;

		private int frameCounter;

		public float worldspaceOffsetLerpRate = 5f;

		public AnimationCurve curveIntro = new AnimationCurve();

		public AnimationCurve curveOutro = new AnimationCurve();

		private bool hasDied;

		internal bool hasExploded;

		private void Awake()
		{
			//IL_002c: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			typeof(WorldSpaceUIChild).GetField("positionOffset", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, (object)new Vector3(0f, -0.05f, 0f));
			instance = this;
			scale = Vector3.one;
			text = ((Component)this).GetComponent<TextMeshProUGUI>();
		}

		public void Show(EnemyHealth enemyHealth, Vector3 screenspaceOffset)
		{
			//IL_002f: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.ShowEnemyHealth.Value)
			{
				Patches.healthUIElements.Remove(currEnemyHealth);
				Object.Destroy((Object)(object)((Component)this).gameObject);
				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;
			showTimer = ConfigManager.HealthShowTimer.Value;
			if (!Object.op_Implicit((Object)(object)currEnemy) || !Object.op_Implicit((Object)(object)currEnemyHealth))
			{
				typeof(WorldSpaceUIChild).GetField("positionOffset", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, screenspaceOffset);
				currEnemyHealth = enemyHealth;
				currEnemy = (Enemy)((object)enemyHealth).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(enemyHealth);
				newWorldPosition = ((Component)currEnemy).transform.position;
				typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, newWorldPosition);
				enemyRigidBody = (EnemyRigidbody)((object)currEnemy).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemy);
				UpdateTargetWorldSpaceOffset();
				worldspaceOffset = targetWorldspaceOffset;
				UpdateTextValues();
			}
		}

		internal void UpdateTargetWorldSpaceOffset()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0029: 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_007a: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(Vector3.zero, Vector3.zero);
			Collider[] componentsInChildren = ((Component)enemyRigidBody).GetComponentsInChildren<Collider>();
			if (componentsInChildren.Length != 0)
			{
				bounds = componentsInChildren[0].bounds;
			}
			Collider[] array = componentsInChildren;
			foreach (Collider val in array)
			{
				if (!val.isTrigger)
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
			float num = ((Bounds)(ref bounds)).max.y / 2f;
			targetWorldspaceOffset = new Vector3(0f, num, 0f);
		}

		internal void UpdateTextValues()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			if (!((Object)(object)currEnemy == (Object)null) && !((Object)(object)currEnemyHealth == (Object)null))
			{
				int num = (int)typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemyHealth);
				int health = currEnemyHealth.health;
				((TMP_Text)text).text = $"{num}/{health}";
				bool num2 = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemyHealth);
				bool flag = (int)currEnemy.CurrentState == 11;
				if ((num2 || flag || hasExploded) && !hasDied)
				{
					Plugin.Logger.LogDebug((object)"Enemy should have died/despawned, clearing healthbar timer");
					showTimer = 0.5f;
					hasDied = true;
				}
			}
		}

		protected override void Update()
		{
			//IL_0031: 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_0048: 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_006f: 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_007d: 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_00ab: 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_00f3: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			((WorldSpaceUIChild)this).Update();
			frameCounter++;
			if (frameCounter >= recalcIntervalFrames)
			{
				frameCounter = 0;
				UpdateTargetWorldSpaceOffset();
			}
			worldspaceOffset = Vector3.Lerp(worldspaceOffset, targetWorldspaceOffset, Time.deltaTime * worldspaceOffsetLerpRate);
			FieldInfo? field = typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic);
			_ = (Vector3)field.GetValue(this);
			field.SetValue(this, newWorldPosition + worldspaceOffset);
			if ((Object)(object)currEnemy != (Object)null)
			{
				newWorldPosition = currEnemy.CenterTransform.position;
			}
			if (showTimer > 0f)
			{
				showTimer -= Time.deltaTime;
				float num = 1f;
				float num2 = 5f;
				float num3 = 20f;
				float num4 = Vector3.Distance(((Component)Camera.main).transform.position, newWorldPosition);
				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);
				}
				((TMP_Text)text).alpha = num;
				((Component)this).transform.localScale = localScale;
				UpdateTextValues();
			}
			else if (showTimer <= 0f && (Object)(object)currEnemyHealth != (Object)null)
			{
				EnemyParent val = (EnemyParent)((object)currEnemy).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemy);
				Plugin.Logger.LogDebug((object)("Removing enemy health UI for " + val.enemyName + "..."));
				Patches.healthUIElements.Remove(currEnemyHealth);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	[HarmonyPatch]
	public static class Patches
	{
		[CompilerGenerated]
		private sealed class <DelayedSetText>d__7 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public FieldInfo fieldInfo;

			public object target;

			public string targetText;

			private TextMeshProUGUI <text>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_00ad: 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_005c: Expected O, but got Unknown
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: 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;
					<text>5__2 = (TextMeshProUGUI)(fieldInfo?.GetValue(target));
					if ((Object)(object)<text>5__2 == (Object)null)
					{
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				((TMP_Text)<text>5__2).text = targetText;
				((TMP_Text)<text>5__2).fontSize = ConfigManager.DamageFontSize.Value;
				((Graphic)<text>5__2).color = Color.blue;
				Color32 val = default(Color32);
				if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontHighlightColor.Value, ref val))
				{
					((Graphic)<text>5__2).color = Color32.op_Implicit(val);
				}
				Color32 val2 = default(Color32);
				if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontColor.Value, ref val2))
				{
					Color val3 = Color32.op_Implicit(val2);
					typeof(WorldSpaceUIValueLost).GetField("textColor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, val3);
				}
				else
				{
					typeof(WorldSpaceUIValueLost).GetField("textColor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, Color.cyan);
				}
				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__8 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public CustomEnemyHealthUI healthBar;

			public EnemyHealth enemyHealth;

			public Vector3 offset;

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

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

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

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

			private bool MoveNext()
			{
				//IL_003b: 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
					{
						healthBar.Show(enemyHealth, offset);
					}
					catch (Exception arg)
					{
						Plugin.Logger.LogDebug((object)$"Handling exception in DelayedShowHealthBar: {arg}");
						try
						{
							healthUIElements.Remove(enemyHealth);
							Object.Destroy((Object)(object)healthBar);
						}
						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>();

		[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
		[HarmonyPrefix]
		public static void ShowEnemyHealthOnHurt(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_008d: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			int num = (int)((object)__instance).GetType().GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
			Enemy val = (Enemy)((object)__instance).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
			Vector3 position = val.CenterTransform.position;
			int num2 = num - _damage;
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				try
				{
					EnemyParent val2 = (EnemyParent)((object)val).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
					_ = (EnemyRigidbody)((object)val).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
					bool flag = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
					Vector3 val3 = default(Vector3);
					val3.x = 0f;
					val3.y = 0f;
					val3.z = 0f;
					bool flag2 = num2 <= 0 || flag;
					Plugin.Logger.LogDebug((object)$"{val2.enemyName} HURT by {_damage}, currHealth: {num}, will have {num - _damage},  willDie:{flag2} ...");
					CreateDamageUI(_damage, position);
					if (!flag2)
					{
						CreateHealthUI(__instance, position);
					}
					return;
				}
				catch (Exception arg)
				{
					Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
					return;
				}
			}
			try
			{
				CreateDamageUI(_damage, val.CenterTransform.position);
			}
			catch (Exception arg2)
			{
				Plugin.Logger.LogError((object)$"FAILED TO ADD UI:\n{arg2}");
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "HurtRPC")]
		[HarmonyPrefix]
		public static void ShowEnemyHealthOnHurtRPC(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_006c: 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_00c7: 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)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			bool flag = false;
			int num = Math.Abs(_damage);
			if (_damage < 0)
			{
				flag = true;
			}
			try
			{
				Enemy val = (Enemy)((object)__instance).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
				EnemyParent val2 = (EnemyParent)((object)val).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
				_ = (EnemyRigidbody)((object)val).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
				bool flag2 = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
				Vector3 val3 = default(Vector3);
				val3.x = 0f;
				val3.y = 0f;
				val3.z = 0f;
				Vector3 position = val.CenterTransform.position;
				FieldInfo field = ((object)__instance).GetType().GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic);
				int num2 = (int)field.GetValue(__instance);
				int num3 = num2 - num;
				if (ConfigManager.AttemptMultiplayerHealthSync.Value && flag)
				{
					field.SetValue(__instance, num3);
					CreateDamageUI(num, position);
				}
				bool flag3 = num3 <= 0 || flag2;
				Plugin.Logger.LogDebug((object)$"{val2.enemyName} HURT by {num}, currHealth: {num2}, will have {num3},  willDie:{flag3} ...");
				if (!flag3)
				{
					CreateHealthUI(__instance, position);
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
			}
		}

		[HarmonyPatch(typeof(EnemyBang), "ExplodeRPC")]
		[HarmonyPostfix]
		public static void HandleBangerExplode(EnemyBang __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			try
			{
				Enemy obj = (Enemy)typeof(EnemyBang).GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
				EnemyHealth key = (EnemyHealth)typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
				if (healthUIElements.TryGetValue(key, out var value))
				{
					value.hasExploded = true;
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"HandleBangerExplode failed:\n{arg}");
			}
		}

		public static void HurtColliderEnemyHurtHook(EnemyHealth enemyHealth, int damage, Vector3 hurtDirection)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			if (SemiFunc.IsNotMasterClient() || !SemiFunc.IsMultiplayer())
			{
				enemyHealth.Hurt(damage, hurtDirection);
				return;
			}
			try
			{
				if (ConfigManager.AttemptMultiplayerHealthSync.Value)
				{
					((PhotonView)typeof(EnemyHealth).GetField("photonView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(enemyHealth)).RPC("HurtRPC", (RpcTarget)0, new object[2]
					{
						-damage,
						hurtDirection
					});
				}
			}
			finally
			{
				enemyHealth.Hurt(damage, hurtDirection);
			}
		}

		internal static void CreateHealthUI(EnemyHealth enemyHealth, Vector3 enemyPosition)
		{
			//IL_0002: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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)
			Vector3 val = default(Vector3);
			val.x = 0f;
			val.y = 0f;
			val.z = 0f;
			Vector3 val2 = val;
			if (!healthUIElements.ContainsKey(enemyHealth))
			{
				GameObject obj = Object.Instantiate<GameObject>(WorldSpaceUIParent.instance.TTSPrefab, ((Component)WorldSpaceUIParent.instance).transform.position, ((Component)WorldSpaceUIParent.instance).transform.rotation, ((Component)WorldSpaceUIParent.instance).transform);
				Object.Destroy((Object)(object)obj.GetComponent<WorldSpaceUITTS>());
				CustomEnemyHealthUI customEnemyHealthUI = obj.AddComponent<CustomEnemyHealthUI>();
				typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(customEnemyHealthUI, enemyPosition);
				healthUIElements.Add(enemyHealth, customEnemyHealthUI);
				((MonoBehaviour)enemyHealth).StartCoroutine(DelayedShowHealthUI(healthUIElements[enemyHealth], enemyHealth, val2));
			}
			else
			{
				healthUIElements[enemyHealth].Show(enemyHealth, val2);
			}
		}

		internal static void CreateDamageUI(int damage, Vector3 worldPosition)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.ShowEnemyDamage.Value)
			{
				WorldSpaceUIParent instance = WorldSpaceUIParent.instance;
				WorldSpaceUIValueLost component = Object.Instantiate<GameObject>(instance.valueLostPrefab, ((Component)instance).transform.position, ((Component)instance).transform.rotation, ((Component)instance).transform).GetComponent<WorldSpaceUIValueLost>();
				typeof(WorldSpaceUIValueLost).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component, worldPosition);
				typeof(WorldSpaceUIValueLost).GetField("value", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component, damage);
				FieldInfo field = typeof(WorldSpaceUIValueLost).GetField("text", BindingFlags.Instance | BindingFlags.NonPublic);
				((MonoBehaviour)component).StartCoroutine(DelayedSetText(field, component, $"-{damage}"));
				((List<WorldSpaceUIValueLost>)((object)instance).GetType().GetField("valueLostList", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance)).Add(component);
			}
		}

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

		[IteratorStateMachine(typeof(<DelayedShowHealthUI>d__8))]
		internal static IEnumerator DelayedShowHealthUI(CustomEnemyHealthUI healthBar, 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__8(0)
			{
				healthBar = healthBar,
				enemyHealth = enemyHealth,
				offset = offset
			};
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "EnemyHurt")]
	public static class EnemyHurtTranspilerPatch
	{
		[CompilerGenerated]
		private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private MethodInfo <targetHurtMethod>5__2;

			private MethodInfo <hookMethod>5__3;

			private IEnumerator<CodeInstruction> <>7__wrap3;

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

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

			[DebuggerHidden]
			public <Transpiler>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 1u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<targetHurtMethod>5__2 = null;
				<hookMethod>5__3 = null;
				<>7__wrap3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0119: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<targetHurtMethod>5__2 = AccessTools.Method(typeof(EnemyHealth), "Hurt", new Type[2]
						{
							typeof(int),
							typeof(Vector3)
						}, (Type[])null);
						<hookMethod>5__3 = AccessTools.Method(typeof(Patches), "HurtColliderEnemyHurtHook", new Type[3]
						{
							typeof(EnemyHealth),
							typeof(int),
							typeof(Vector3)
						}, (Type[])null);
						<>7__wrap3 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					case 2:
						<>1__state = -3;
						break;
					}
					if (<>7__wrap3.MoveNext())
					{
						CodeInstruction current = <>7__wrap3.Current;
						if (current.opcode == OpCodes.Callvirt && current.operand is MethodInfo methodInfo && methodInfo == <targetHurtMethod>5__2)
						{
							<>2__current = new CodeInstruction(OpCodes.Call, (object)<hookMethod>5__3);
							<>1__state = 1;
							return true;
						}
						<>2__current = current;
						<>1__state = 2;
						return true;
					}
					<>m__Finally1();
					<>7__wrap3 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap3 != null)
				{
					<>7__wrap3.Dispose();
				}
			}

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

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<Transpiler>d__0 <Transpiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<Transpiler>d__ = this;
				}
				else
				{
					<Transpiler>d__ = new <Transpiler>d__0(0);
				}
				<Transpiler>d__.instructions = <>3__instructions;
				return <Transpiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<Transpiler>d__0))]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Transpiler>d__0(-2)
			{
				<>3__instructions = instructions
			};
		}
	}
	[BepInPlugin("REPO_ShowEnemyHealth", "ShowEnemyHealth", "1.0.3")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin ShowEnemyHealth 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";

		public const string PLUGIN_VERSION = "1.0.3";
	}
}