Decompiled source of NativeEnemyHealthBars v1.1.0

plugins/NativeEnemyHealthBars/NativeEnemyHealthUI.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NativeEnemyHealthUI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("NativeEnemyHealthUI")]
[assembly: AssemblyTitle("NativeEnemyHealthUI")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 NativeEnemyHealthUI
{
	internal static class EnemyAccess
	{
		private const BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

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

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

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

		private static readonly FieldInfo EnemyHasRigidbodyField = typeof(Enemy).GetField("HasRigidbody", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly PropertyInfo EnemyHasRigidbodyProperty = typeof(Enemy).GetProperty("HasRigidbody", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

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

		private static readonly PropertyInfo EnemyRigidbodyProperty = typeof(Enemy).GetProperty("Rigidbody", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo EnemyCenterTransformField = typeof(Enemy).GetField("CenterTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly PropertyInfo EnemyCenterTransformProperty = typeof(Enemy).GetProperty("CenterTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static bool _loggedLayout;

		public static Enemy GetEnemy(EnemyHealth health)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			if ((Object)health == (Object)null)
			{
				return null;
			}
			try
			{
				if (HealthEnemyField != null)
				{
					object value = HealthEnemyField.GetValue(health);
					Enemy val = (Enemy)((value is Enemy) ? value : null);
					if ((Object)val != (Object)null)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			return ((Component)health).GetComponentInParent<Enemy>();
		}

		public static Transform GetDamageShowFollowTransform(Enemy enemy)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			if ((Object)enemy == (Object)null)
			{
				return null;
			}
			try
			{
				bool flag = false;
				if (EnemyHasRigidbodyField != null)
				{
					flag = Convert.ToBoolean(EnemyHasRigidbodyField.GetValue(enemy));
				}
				else if (EnemyHasRigidbodyProperty != null)
				{
					flag = Convert.ToBoolean(EnemyHasRigidbodyProperty.GetValue(enemy, null));
				}
				if (flag)
				{
					object obj = null;
					if (EnemyRigidbodyField != null)
					{
						obj = EnemyRigidbodyField.GetValue(enemy);
					}
					else if (EnemyRigidbodyProperty != null)
					{
						obj = EnemyRigidbodyProperty.GetValue(enemy, null);
					}
					Rigidbody val = (Rigidbody)((obj is Rigidbody) ? obj : null);
					if ((Object)val != (Object)null)
					{
						return ((Component)val).transform;
					}
				}
				object obj2 = null;
				if (EnemyCenterTransformField != null)
				{
					obj2 = EnemyCenterTransformField.GetValue(enemy);
				}
				else if (EnemyCenterTransformProperty != null)
				{
					obj2 = EnemyCenterTransformProperty.GetValue(enemy, null);
				}
				Transform val2 = (Transform)((obj2 is Transform) ? obj2 : null);
				if ((Object)val2 != (Object)null)
				{
					return val2;
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogDebug((object)("[NativeEnemyHealthUI] DamageShow follow resolve fallback: " + ex.Message));
				}
			}
			return ((Component)enemy).transform;
		}

		public static EnemyParent GetEnemyParent(Enemy enemy)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			if ((Object)enemy == (Object)null)
			{
				return null;
			}
			try
			{
				if (EnemyParentField != null)
				{
					object value = EnemyParentField.GetValue(enemy);
					EnemyParent val = (EnemyParent)((value is EnemyParent) ? value : null);
					if ((Object)val != (Object)null)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			return ((Component)enemy).GetComponentInParent<EnemyParent>();
		}

		public static int GetCurrentHealth(EnemyHealth health)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if ((Object)health == (Object)null)
			{
				return 0;
			}
			LogLayoutOnce();
			try
			{
				if (HealthCurrentField != null)
				{
					return Convert.ToInt32(HealthCurrentField.GetValue(health));
				}
			}
			catch (Exception ex)
			{
				if (Plugin.Log != null)
				{
					Plugin.Log.LogWarning((object)("[NativeEnemyHealthUI] Could not read private healthCurrent: " + ex.Message));
				}
			}
			return Mathf.Max(0, health.health);
		}

		public static int GetMaxHealth(EnemyHealth health, int current)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if ((Object)health == (Object)null)
			{
				return Mathf.Max(1, current);
			}
			try
			{
				return Mathf.Max(current, health.health);
			}
			catch
			{
				return Mathf.Max(1, current);
			}
		}

		private static void LogLayoutOnce()
		{
			if (!_loggedLayout && Plugin.Log != null)
			{
				_loggedLayout = true;
				Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] Enemy layout: healthCurrent=" + ((HealthCurrentField != null) ? "found" : "missing") + ", EnemyHealth.enemy=" + ((HealthEnemyField != null) ? "found" : "missing") + ", Enemy.EnemyParent=" + ((EnemyParentField != null) ? "found" : "missing")));
			}
		}
	}
	[HarmonyPatch]
	internal static class EnemyHealthPatches
	{
		private static readonly FieldInfo DamageResistanceField = AccessTools.Field(typeof(EnemyHealth), "damageResistance");

		[HarmonyPatch(typeof(EnemyHealth), "HurtRPC")]
		[HarmonyPostfix]
		private static void HurtRpcPostfix(EnemyHealth __instance, int _damage)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if ((Object)__instance == (Object)null || _damage <= 0)
			{
				return;
			}
			try
			{
				NativeEnemyBar orAddBar = GetOrAddBar(__instance);
				if (!SemiFunc.IsMasterClientOrSingleplayer())
				{
					orAddBar.ApplyClientDamage(EffectiveDamage(__instance, _damage));
				}
				orAddBar.ShowAfterDamage();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[NativeEnemyHealthUI] HurtRPC hook failed: " + ex.Message));
				}
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "DeathRPC")]
		[HarmonyPostfix]
		private static void DeathRpcPostfix(EnemyHealth __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			NativeEnemyBar nativeEnemyBar = (((Object)__instance != (Object)null) ? ((Component)__instance).GetComponent<NativeEnemyBar>() : null);
			if ((Object)nativeEnemyBar != (Object)null)
			{
				nativeEnemyBar.OnEnemyDied();
			}
		}

		[HarmonyPatch(typeof(EnemyHealth), "OnSpawn")]
		[HarmonyPostfix]
		private static void OnSpawnPostfix(EnemyHealth __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			NativeEnemyBar nativeEnemyBar = (((Object)__instance != (Object)null) ? ((Component)__instance).GetComponent<NativeEnemyBar>() : null);
			if ((Object)nativeEnemyBar != (Object)null)
			{
				nativeEnemyBar.OnEnemySpawned();
			}
		}

		private static NativeEnemyBar GetOrAddBar(EnemyHealth health)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			NativeEnemyBar nativeEnemyBar = ((Component)health).GetComponent<NativeEnemyBar>();
			if ((Object)nativeEnemyBar == (Object)null)
			{
				nativeEnemyBar = ((Component)health).gameObject.AddComponent<NativeEnemyBar>();
			}
			return nativeEnemyBar;
		}

		private static int EffectiveDamage(EnemyHealth health, int damage)
		{
			float num = 0f;
			try
			{
				if (DamageResistanceField != null)
				{
					num = Convert.ToSingle(DamageResistanceField.GetValue(health));
				}
			}
			catch
			{
			}
			return (int)((float)damage * (1f - Mathf.Min(num, 1f)));
		}
	}
	internal static class HealthUiGeometry
	{
		public static Vector3 GetAnchor(EnemyParent parent, Enemy enemy, Transform fallback, float extraHeight)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_007b: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((!((Object)parent != (Object)null)) ? (((Object)enemy != (Object)null) ? ((Component)enemy).transform : fallback) : ((Component)parent).transform);
			if ((Object)val == (Object)null)
			{
				return Vector3.zero;
			}
			Collider[] colliders = (Collider[])((!((Object)parent != (Object)null)) ? (((Object)enemy != (Object)null) ? ((Array)((Component)enemy).GetComponentsInChildren<Collider>(true)) : ((Array)new Collider[0])) : ((Component)parent).GetComponentsInChildren<Collider>(true));
			if (TryCompactBounds(colliders, val.position, includeTriggers: false, out var bounds) || TryCompactBounds(colliders, val.position, includeTriggers: true, out bounds))
			{
				return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + extraHeight, ((Bounds)(ref bounds)).center.z);
			}
			Renderer[] array = (Renderer[])((!((Object)parent != (Object)null)) ? (((Object)enemy != (Object)null) ? ((Array)((Component)enemy).GetComponentsInChildren<Renderer>(true)) : ((Array)new Renderer[0])) : ((Component)parent).GetComponentsInChildren<Renderer>(true));
			bool flag = false;
			Bounds val2 = default(Bounds);
			((Bounds)(ref val2))..ctor(val.position, Vector3.zero);
			Renderer[] array2 = array;
			foreach (Renderer val3 in array2)
			{
				if ((Object)val3 == (Object)null || !val3.enabled || !((Component)val3).gameObject.activeInHierarchy)
				{
					continue;
				}
				Bounds bounds2 = val3.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				if (!(((Vector3)(ref size)).magnitude > 6f) && !(Vector3.Distance(((Bounds)(ref bounds2)).center, val.position) > 4f))
				{
					if (!flag)
					{
						val2 = bounds2;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(bounds2);
					}
				}
			}
			if (flag)
			{
				return new Vector3(((Bounds)(ref val2)).center.x, ((Bounds)(ref val2)).max.y + extraHeight, ((Bounds)(ref val2)).center.z);
			}
			return val.position + Vector3.up * (1.6f + extraHeight);
		}

		private static bool TryCompactBounds(Collider[] colliders, Vector3 origin, bool includeTriggers, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_003d: 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_0046: 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)
			//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_0090: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			if (colliders == null)
			{
				return false;
			}
			foreach (Collider val in colliders)
			{
				if ((Object)val == (Object)null || !val.enabled || (!includeTriggers && val.isTrigger))
				{
					continue;
				}
				Bounds bounds2 = val.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				float magnitude = ((Vector3)(ref size)).magnitude;
				float num = Vector3.Distance(((Bounds)(ref bounds2)).center, origin);
				if (!(magnitude < 0.05f) && !(magnitude > 6f) && !(num > 4f))
				{
					if (!flag)
					{
						bounds = bounds2;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(bounds2);
					}
				}
			}
			return flag;
		}
	}
	public sealed class NativeEnemyBar : MonoBehaviour
	{
		private EnemyHealth _health;

		private Enemy _enemy;

		private EnemyParent _parent;

		private Transform _followTransform;

		private float _nextFollowResolveTime;

		private float _nextOffsetResolveTime;

		private float _worldOffsetY = 1.25f;

		private float _targetWorldOffsetY = 1.25f;

		private float _worldOffsetVelocity;

		private bool _hasOffsetSample;

		private Vector3 _currentWorldAnchor;

		private GameObject _healthClone;

		private RectTransform _cloneRect;

		private RectTransform _uiParentRect;

		private Canvas _hostCanvas;

		private Camera _worldCamera;

		private float _visibleUntil = -1000f;

		private int _lastCurrent = int.MinValue;

		private int _lastMax = int.MinValue;

		private int _clientHealth = -1;

		private bool _poseActive;

		public void ApplyClientDamage(int damage)
		{
			EnsureReferences();
			if (_clientHealth < 0)
			{
				_clientHealth = MaxHealth();
			}
			_clientHealth = Mathf.Max(0, _clientHealth - Mathf.Max(0, damage));
		}

		public void OnEnemyDied()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			_clientHealth = 0;
			if ((Object)_healthClone != (Object)null && _healthClone.activeSelf)
			{
				_healthClone.SetActive(false);
			}
		}

		public void OnEnemySpawned()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			_clientHealth = -1;
			_visibleUntil = -1000f;
			if ((Object)_healthClone != (Object)null && _healthClone.activeSelf)
			{
				_healthClone.SetActive(false);
			}
		}

		private int MaxHealth()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			if (!((Object)_health != (Object)null))
			{
				return 1;
			}
			return Mathf.Max(1, _health.health);
		}

		private int CurrentHealth()
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				return EnemyAccess.GetCurrentHealth(_health);
			}
			if (_clientHealth >= 0)
			{
				return _clientHealth;
			}
			return MaxHealth();
		}

		public void ShowAfterDamage()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			EnsureReferences();
			EnsureUi();
			_visibleUntil = Time.realtimeSinceStartup + ((Plugin.VisibleSeconds != null) ? Plugin.VisibleSeconds.Value : 4f);
			ResolveFollowTarget(force: true);
			UpdateWorldOffsetFromBounds(force: true);
			UpdateCurrentWorldAnchor();
			RefreshHealthText(force: true);
			UpdateScreenPose(log: true);
			if ((Object)_healthClone != (Object)null)
			{
				_healthClone.SetActive(true);
			}
		}

		private void EnsureReferences()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			if ((Object)_health == (Object)null)
			{
				_health = ((Component)this).GetComponent<EnemyHealth>();
			}
			if ((Object)_health != (Object)null && (Object)_enemy == (Object)null)
			{
				_enemy = EnemyAccess.GetEnemy(_health);
			}
			if ((Object)_enemy == (Object)null)
			{
				_enemy = ((Component)this).GetComponentInParent<Enemy>();
			}
			if ((Object)_parent == (Object)null)
			{
				_parent = EnemyAccess.GetEnemyParent(_enemy);
				if ((Object)_parent == (Object)null)
				{
					_parent = ((Component)this).GetComponentInParent<EnemyParent>();
				}
			}
			if ((Object)_worldCamera == (Object)null)
			{
				_worldCamera = Camera.main;
			}
			if ((Object)_followTransform == (Object)null)
			{
				_followTransform = ResolveFollowTransform();
			}
		}

		private Transform ResolveFollowTransform()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Transform damageShowFollowTransform = EnemyAccess.GetDamageShowFollowTransform(_enemy);
			if ((Object)damageShowFollowTransform != (Object)null)
			{
				return damageShowFollowTransform;
			}
			if (!((Object)_health != (Object)null))
			{
				return ((Component)this).transform;
			}
			return ((Component)_health).transform;
		}

		private void ResolveFollowTarget(bool force)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0038: 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_004d: Expected O, but got Unknown
			//IL_004d: Expected O, but got Unknown
			if (!force && Time.time < _nextFollowResolveTime)
			{
				return;
			}
			_nextFollowResolveTime = Time.time + 0.5f;
			Transform val = ResolveFollowTransform();
			if ((Object)val != (Object)null && (Object)val != (Object)_followTransform)
			{
				_followTransform = val;
				UpdateWorldOffsetFromBounds(force: true);
				if (Plugin.Log != null)
				{
					Plugin.Log.LogDebug((object)("[NativeEnemyHealthUI] DamageShow follow target rebound: " + HierarchyPath(_followTransform)));
				}
			}
		}

		private Transform ResolveBoundsRoot()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			if ((Object)_health != (Object)null && (Object)((Component)_health).transform != (Object)null && (Object)((Component)_health).transform.parent != (Object)null)
			{
				return ((Component)_health).transform.parent;
			}
			if ((Object)_parent != (Object)null)
			{
				return ((Component)_parent).transform;
			}
			if ((Object)_health != (Object)null)
			{
				return ((Component)_health).transform;
			}
			return null;
		}

		private void UpdateWorldOffsetFromBounds(bool force)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0069: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			if (!force && Time.time < _nextOffsetResolveTime)
			{
				return;
			}
			_nextOffsetResolveTime = Time.time + 0.25f;
			Transform val = ResolveBoundsRoot();
			if (!((Object)_followTransform == (Object)null) && (TryGetVisualBounds(out var bounds) || (!((Object)val == (Object)null) && TryGetWorldBounds(val, out bounds))))
			{
				float num = Mathf.Clamp(((Bounds)(ref bounds)).max.y - _followTransform.position.y + 0.15f, 0.35f, 12f);
				float num2 = ((Plugin.ExtraHeight != null) ? Plugin.ExtraHeight.Value : 1.25f);
				if (num2 < 0f)
				{
					num2 = 0f;
				}
				float num3 = Mathf.Clamp(num + num2, 0.35f, 20f);
				if (!_hasOffsetSample || force)
				{
					_targetWorldOffsetY = num3;
					_worldOffsetY = num3;
					_worldOffsetVelocity = 0f;
					_hasOffsetSample = true;
				}
				else
				{
					num3 = Mathf.Clamp(num3, _targetWorldOffsetY - 0.55f, _targetWorldOffsetY + 0.55f);
					_targetWorldOffsetY = num3;
				}
			}
		}

		private bool TryGetVisualBounds(out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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)
			bounds = default(Bounds);
			Transform val = (((Object)_health != (Object)null) ? _health.meshParent : null);
			if ((Object)val == (Object)null)
			{
				return false;
			}
			bool flag = false;
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(false);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)val2 == (Object)null) && val2.enabled && !(val2 is ParticleSystemRenderer))
				{
					if (!flag)
					{
						bounds = val2.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val2.bounds);
					}
				}
			}
			return flag;
		}

		private static bool TryGetWorldBounds(Transform root, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_008d: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			if ((Object)root == (Object)null)
			{
				return false;
			}
			Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)val == (Object)null) && !val.isTrigger)
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			if (flag)
			{
				return true;
			}
			Renderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren2)
			{
				if (!((Object)val2 == (Object)null))
				{
					if (!flag)
					{
						bounds = val2.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val2.bounds);
					}
				}
			}
			return flag;
		}

		private void UpdateCurrentWorldAnchor()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_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)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)_followTransform == (Object)null))
			{
				if (_hasOffsetSample)
				{
					_worldOffsetY = Mathf.SmoothDamp(_worldOffsetY, _targetWorldOffsetY, ref _worldOffsetVelocity, 0.1f, 8f, Mathf.Max(Time.deltaTime, 0.001f));
				}
				_currentWorldAnchor = _followTransform.position + Vector3.up * _worldOffsetY;
			}
		}

		private void EnsureUi()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)_healthClone != (Object)null)
			{
				return;
			}
			GameObject template = NativeTemplateResolver.GetTemplate();
			if ((Object)template == (Object)null)
			{
				return;
			}
			try
			{
				Transform parent = template.transform.parent;
				if (!((Object)parent == (Object)null))
				{
					_healthClone = Object.Instantiate<GameObject>(template, parent, false);
					((Object)_healthClone).name = "Native Enemy Health";
					_healthClone.SetActive(true);
					RemoveNativeHealthControllerDirect(_healthClone);
					_cloneRect = _healthClone.GetComponent<RectTransform>();
					_uiParentRect = (RectTransform)((parent is RectTransform) ? parent : null);
					_hostCanvas = _healthClone.GetComponentInParent<Canvas>();
					if ((Object)_cloneRect != (Object)null)
					{
						_cloneRect.anchorMin = new Vector2(0.5f, 0.5f);
						_cloneRect.anchorMax = new Vector2(0.5f, 0.5f);
						_cloneRect.pivot = new Vector2(0.5f, 0.5f);
						_cloneRect.anchoredPosition = Vector2.zero;
						((Transform)_cloneRect).localScale = Vector3.one * 0.5f;
						((Transform)_cloneRect).localRotation = Quaternion.identity;
					}
					_healthClone.transform.SetAsLastSibling();
					ForceCanvasGroupsVisible(_healthClone);
					if (Plugin.Log != null)
					{
						string text = (((Object)_parent != (Object)null) ? (_parent.enemyName ?? ((Object)_parent).name) : ((Object)((Component)this).gameObject).name);
						Plugin.Log.LogDebug((object)("[NativeEnemyHealthUI] Native bar attached with DamageShow placement: " + text + " | follow=" + (((Object)_followTransform != (Object)null) ? HierarchyPath(_followTransform) : "<pending>") + " | canvas=" + (((Object)_hostCanvas != (Object)null) ? ((object)_hostCanvas.renderMode).ToString() : "<none>")));
					}
				}
			}
			catch (Exception ex)
			{
				if ((Object)_healthClone != (Object)null)
				{
					Object.Destroy((Object)_healthClone);
				}
				_healthClone = null;
				_cloneRect = null;
				_uiParentRect = null;
				_hostCanvas = null;
				if (Plugin.Log != null)
				{
					Plugin.Log.LogWarning((object)("[NativeEnemyHealthUI] UI creation failed: " + ex));
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)_health == (Object)null || (Object)_healthClone == (Object)null)
			{
				return;
			}
			int num = CurrentHealth();
			if (Time.realtimeSinceStartup > _visibleUntil || num <= 0)
			{
				_poseActive = false;
				if (_healthClone.activeSelf)
				{
					_healthClone.SetActive(false);
				}
				return;
			}
			EnsureReferences();
			if ((Object)_worldCamera == (Object)null)
			{
				return;
			}
			ResolveFollowTarget(force: false);
			UpdateWorldOffsetFromBounds(force: false);
			UpdateCurrentWorldAnchor();
			float num2 = ((Plugin.MaxDistance != null) ? Plugin.MaxDistance.Value : 40f);
			if ((Object)_followTransform == (Object)null || Vector3.Distance(((Component)_worldCamera).transform.position, _followTransform.position) > num2)
			{
				if (_healthClone.activeSelf)
				{
					_healthClone.SetActive(false);
				}
				_poseActive = false;
			}
			else
			{
				UpdateScreenPose(log: false);
				RefreshHealthText(force: false);
				_poseActive = true;
			}
		}

		private void OnEnable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Canvas.willRenderCanvases += new WillRenderCanvases(OnWillRenderCanvases);
		}

		private void OnDisable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Canvas.willRenderCanvases -= new WillRenderCanvases(OnWillRenderCanvases);
			_poseActive = false;
		}

		private void OnWillRenderCanvases()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0043: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (_poseActive && !((Object)_healthClone == (Object)null) && _healthClone.activeSelf && !((Object)_followTransform == (Object)null))
			{
				_currentWorldAnchor = _followTransform.position + Vector3.up * _worldOffsetY;
				UpdateScreenPose(log: false);
			}
		}

		private void UpdateScreenPose(bool log)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_005e: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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_00e0: 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_0206: 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)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)_healthClone == (Object)null || (Object)_cloneRect == (Object)null || (Object)_worldCamera == (Object)null || (Object)_followTransform == (Object)null)
			{
				return;
			}
			Vector3 val = _worldCamera.WorldToViewportPoint(_currentWorldAnchor);
			if (val.z <= 0f)
			{
				_healthClone.SetActive(false);
				return;
			}
			if (val.x < 0f || val.x > 1f || val.y < 0f)
			{
				_healthClone.SetActive(false);
				return;
			}
			if (val.y > 0.9f)
			{
				Vector3 val2 = _worldCamera.WorldToViewportPoint(_followTransform.position);
				if (val2.z <= 0f || val2.x < 0f || val2.x > 1f || val2.y < 0f || val2.y > 1f)
				{
					_healthClone.SetActive(false);
					return;
				}
				val.y = 0.9f;
			}
			float num = Vector3.Distance(((Component)_worldCamera).transform.position, _currentWorldAnchor);
			if ((Object)_uiParentRect != (Object)null)
			{
				Rect rect = _uiParentRect.rect;
				float num2 = ((Plugin.ScreenXOffset != null) ? Plugin.ScreenXOffset.Value : 10f);
				_cloneRect.anchoredPosition = new Vector2((val.x - 0.5f) * ((Rect)(ref rect)).width + num2, (val.y - 0.5f) * ((Rect)(ref rect)).height);
			}
			float num3 = ((Plugin.UiScale != null) ? Plugin.UiScale.Value : 0.5f);
			float num4 = Mathf.InverseLerp(5f, 40f, num);
			float num5 = Mathf.Lerp(1f, 0.45f, num4);
			float num6 = num3 * num5;
			((Transform)_cloneRect).localScale = Vector3.one * num6;
			if (!_healthClone.activeSelf)
			{
				_healthClone.SetActive(true);
			}
			if (log && Plugin.Log != null)
			{
				Plugin.Log.LogDebug((object)string.Concat("[NativeEnemyHealthUI] DAMAGESHOW FOLLOW SHOW follow=", _followTransform.position, " anchor=", _currentWorldAnchor, " viewport=", val, " offsetY=", _worldOffsetY.ToString("0.00"), " targetOffsetY=", _targetWorldOffsetY.ToString("0.00"), " anchored=", _cloneRect.anchoredPosition, " scale=", num6.ToString("0.00"), " distance=", num.ToString("0.00")));
			}
		}

		private void RefreshHealthText(bool force)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if ((Object)_healthClone == (Object)null || (Object)_health == (Object)null)
			{
				return;
			}
			int num = Mathf.Max(0, CurrentHealth());
			int num2 = Mathf.Max(1, EnemyAccess.GetMaxHealth(_health, num));
			if (force || num != _lastCurrent || num2 != _lastMax)
			{
				_lastCurrent = num;
				_lastMax = num2;
				TextUtil.SetText(_healthClone, num.ToString());
				GameObject val = TextUtil.FindChild(_healthClone.transform, "HealthMax");
				if ((Object)val != (Object)null)
				{
					TextUtil.SetText(val, num2.ToString());
				}
			}
		}

		private static void RemoveNativeHealthControllerDirect(GameObject clone)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			if ((Object)clone == (Object)null)
			{
				return;
			}
			Component[] components = clone.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!((Object)val == (Object)null) && string.Equals(((object)val).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase))
				{
					Behaviour val2 = (Behaviour)((val is Behaviour) ? val : null);
					if ((Object)val2 != (Object)null)
					{
						val2.enabled = false;
					}
					Object.Destroy((Object)val);
				}
			}
		}

		private static void ForceCanvasGroupsVisible(GameObject root)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if ((Object)root == (Object)null)
			{
				return;
			}
			CanvasGroup[] componentsInChildren = root.GetComponentsInChildren<CanvasGroup>(true);
			foreach (CanvasGroup val in componentsInChildren)
			{
				if (!((Object)val == (Object)null))
				{
					val.alpha = 1f;
					val.interactable = false;
					val.blocksRaycasts = false;
				}
			}
		}

		private static string HierarchyPath(Transform t)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if ((Object)t == (Object)null)
			{
				return "<null>";
			}
			List<string> list = new List<string>();
			Transform val = t;
			while ((Object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Canvas.willRenderCanvases -= new WillRenderCanvases(OnWillRenderCanvases);
			if ((Object)_healthClone != (Object)null)
			{
				Object.Destroy((Object)_healthClone);
			}
			_healthClone = null;
			_cloneRect = null;
			_uiParentRect = null;
			_hostCanvas = null;
			_followTransform = null;
		}
	}
	internal static class NativeTemplateResolver
	{
		private static GameObject _template;

		private static float _nextSearchAt;

		private static bool _pathLogged;

		public static GameObject GetTemplate()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			if ((Object)_template != (Object)null)
			{
				return _template;
			}
			if (Time.realtimeSinceStartup < _nextSearchAt)
			{
				return null;
			}
			_nextSearchAt = Time.realtimeSinceStartup + 2f;
			string[] array = new string[2] { "UI/HUD/HUD Canvas/HUD/Game Hud/Health", "HUD Canvas/HUD/Game Hud/Health" };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = GameObject.Find(array[i]);
				if (IsHealthTemplate(val))
				{
					_template = val;
					LogPath(val.transform);
					return _template;
				}
			}
			Transform[] array2 = Object.FindObjectsOfType<Transform>();
			foreach (Transform val2 in array2)
			{
				if (!((Object)val2 == (Object)null) && string.Equals(((Object)val2).name, "Health", StringComparison.OrdinalIgnoreCase) && IsHealthTemplate(((Component)val2).gameObject))
				{
					_template = ((Component)val2).gameObject;
					LogPath(val2);
					return _template;
				}
			}
			return null;
		}

		private static bool IsHealthTemplate(GameObject go)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			if ((Object)go == (Object)null)
			{
				return false;
			}
			Component[] components = go.GetComponents<Component>();
			foreach (Component val in components)
			{
				if ((Object)val != (Object)null && string.Equals(((object)val).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static void LogPath(Transform t)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if (!_pathLogged && Plugin.Log != null && !((Object)t == (Object)null))
			{
				_pathLogged = true;
				Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] Native template resolved: " + HierarchyPath(t)));
			}
		}

		private static string HierarchyPath(Transform t)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			List<string> list = new List<string>();
			Transform val = t;
			while ((Object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}
	}
	[BepInPlugin("chatgpt.repo.nativeenemyhealthui", "Native Enemy Health UI", "1.1.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<float> MaxDistance;

		internal static ConfigEntry<float> VisibleSeconds;

		internal static ConfigEntry<float> UiScale;

		internal static ConfigEntry<float> ExtraHeight;

		internal static ConfigEntry<float> ScreenXOffset;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			MaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "Max Distance", 40f, new ConfigDescription("Maximum camera distance for the health display.", (AcceptableValueBase)new AcceptableValueRange<float>(5f, 100f), new object[0]));
			VisibleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "Visible Seconds After Damage", 4f, new ConfigDescription("How long the native bar stays visible after a hit.", (AcceptableValueBase)new AcceptableValueRange<float>(0.5f, 15f), new object[0]));
			UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "UI Scale", 0.5f, new ConfigDescription("Base scale of the native enemy health UI.", (AcceptableValueBase)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
			ExtraHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "Extra Height Offset", 0.35f, new ConfigDescription("DamageShow-style extra height added above the enemy bounds.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 5f), new object[0]));
			ScreenXOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "Screen X Offset", 10f, new ConfigDescription("Small horizontal correction in HUD units. Positive values move the enemy bar to the right.", (AcceptableValueBase)new AcceptableValueRange<float>(-50f, 50f), new object[0]));
			if (Mathf.Approximately(ExtraHeight.Value, 1.25f))
			{
				ExtraHeight.Value = 0.35f;
				((BaseUnityPlugin)this).Config.Save();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[NativeEnemyHealthUI] Migrated Extra Height Offset from 1.25 to 0.35.");
			}
			_harmony = new Harmony("chatgpt.repo.nativeenemyhealthui.v108");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Native Enemy Health UI 1.1.0 loaded - HurtRPC driven (host + clients), on-screen clamp.");
		}
	}
	internal static class TextUtil
	{
		public static GameObject FindChild(Transform root, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if ((Object)root == (Object)null)
			{
				return null;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase))
				{
					return ((Component)val).gameObject;
				}
			}
			return null;
		}

		public static void SetText(GameObject obj, string text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if ((Object)obj == (Object)null)
			{
				return;
			}
			Component[] components = obj.GetComponents<Component>();
			foreach (Component val in components)
			{
				if ((Object)val == (Object)null)
				{
					continue;
				}
				PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(property == null) && property.CanWrite && !(property.PropertyType != typeof(string)))
				{
					try
					{
						property.SetValue(val, text, null);
						break;
					}
					catch
					{
					}
				}
			}
		}
	}
}