Decompiled source of NativeEnemyHealthBars v1.0.0

BepInEx/plugins/NativeEnemyHealthBars/NativeEnemyHealthUI.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace NativeEnemyHealthUI;

[BepInPlugin("chatgpt.repo.nativeenemyhealthui", "Native Enemy Health UI", "1.0.8")]
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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Expected O, but got Unknown
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Expected O, but got Unknown
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: 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)(object)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)(object)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)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
		ExtraHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Enemy Health UI", "Extra Height Offset", 1.25f, new ConfigDescription("DamageShow-style extra height added above the enemy bounds.", (AcceptableValueBase)(object)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)(object)new AcceptableValueRange<float>(-50f, 50f), new object[0]));
		_harmony = new Harmony("chatgpt.repo.nativeenemyhealthui.v108");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Native Enemy Health UI 1.0.8 loaded - final stabilized placement.");
	}
}
[HarmonyPatch]
internal static class EnemyHealthPatches
{
	[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
	[HarmonyPostfix]
	private static void HurtPostfix(EnemyHealth __instance, int _damage)
	{
		if ((Object)(object)__instance == (Object)null || _damage <= 0)
		{
			return;
		}
		try
		{
			NativeEnemyBar nativeEnemyBar = ((Component)__instance).GetComponent<NativeEnemyBar>();
			if ((Object)(object)nativeEnemyBar == (Object)null)
			{
				nativeEnemyBar = ((Component)__instance).gameObject.AddComponent<NativeEnemyBar>();
			}
			nativeEnemyBar.ShowAfterDamage();
			if (Plugin.Log != null)
			{
				Plugin.Log.LogDebug((object)"[NativeEnemyHealthUI] Hurt detected; requested native health bar.");
			}
		}
		catch (Exception ex)
		{
			if (Plugin.Log != null)
			{
				Plugin.Log.LogWarning((object)("[NativeEnemyHealthUI] Hurt hook failed: " + ex.Message));
			}
		}
	}
}
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;

	public void ShowAfterDamage()
	{
		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)(object)_healthClone != (Object)null)
		{
			_healthClone.SetActive(true);
		}
	}

	private void EnsureReferences()
	{
		if ((Object)(object)_health == (Object)null)
		{
			_health = ((Component)this).GetComponent<EnemyHealth>();
		}
		if ((Object)(object)_health != (Object)null && (Object)(object)_enemy == (Object)null)
		{
			_enemy = EnemyAccess.GetEnemy(_health);
		}
		if ((Object)(object)_enemy == (Object)null)
		{
			_enemy = ((Component)this).GetComponentInParent<Enemy>();
		}
		if ((Object)(object)_parent == (Object)null)
		{
			_parent = EnemyAccess.GetEnemyParent(_enemy);
			if ((Object)(object)_parent == (Object)null)
			{
				_parent = ((Component)this).GetComponentInParent<EnemyParent>();
			}
		}
		if ((Object)(object)_worldCamera == (Object)null)
		{
			_worldCamera = Camera.main;
		}
		if ((Object)(object)_followTransform == (Object)null)
		{
			_followTransform = ResolveFollowTransform();
		}
	}

	private Transform ResolveFollowTransform()
	{
		Transform damageShowFollowTransform = EnemyAccess.GetDamageShowFollowTransform(_enemy);
		if ((Object)(object)damageShowFollowTransform != (Object)null)
		{
			return damageShowFollowTransform;
		}
		if (!((Object)(object)_health != (Object)null))
		{
			return ((Component)this).transform;
		}
		return ((Component)_health).transform;
	}

	private void ResolveFollowTarget(bool force)
	{
		if (!force && Time.time < _nextFollowResolveTime)
		{
			return;
		}
		_nextFollowResolveTime = Time.time + 0.5f;
		Transform val = ResolveFollowTransform();
		if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(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()
	{
		if ((Object)(object)_health != (Object)null && (Object)(object)((Component)_health).transform != (Object)null && (Object)(object)((Component)_health).transform.parent != (Object)null)
		{
			return ((Component)_health).transform.parent;
		}
		if ((Object)(object)_parent != (Object)null)
		{
			return ((Component)_parent).transform;
		}
		if ((Object)(object)_health != (Object)null)
		{
			return ((Component)_health).transform;
		}
		return null;
	}

	private void UpdateWorldOffsetFromBounds(bool force)
	{
		//IL_004e: 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)
		if (!force && Time.time < _nextOffsetResolveTime)
		{
			return;
		}
		_nextOffsetResolveTime = Time.time + 0.25f;
		Transform val = ResolveBoundsRoot();
		if (!((Object)(object)val == (Object)null) && !((Object)(object)_followTransform == (Object)null) && TryGetWorldBounds(val, out var bounds))
		{
			float num = ((Bounds)(ref bounds)).max.y - _followTransform.position.y + 0.15f;
			num = Mathf.Clamp(num, 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 static bool TryGetWorldBounds(Transform root, out Bounds bounds)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		bounds = default(Bounds);
		bool flag = false;
		if ((Object)(object)root == (Object)null)
		{
			return false;
		}
		Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
		Collider[] array = componentsInChildren;
		foreach (Collider val in array)
		{
			if (!((Object)(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);
		Renderer[] array2 = componentsInChildren2;
		foreach (Renderer val2 in array2)
		{
			if (!((Object)(object)val2 == (Object)null))
			{
				if (!flag)
				{
					bounds = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
			}
		}
		return flag;
	}

	private void UpdateCurrentWorldAnchor()
	{
		//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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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)
		if (!((Object)(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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_healthClone != (Object)null)
		{
			return;
		}
		GameObject template = NativeTemplateResolver.GetTemplate();
		if ((Object)(object)template == (Object)null)
		{
			return;
		}
		try
		{
			Transform parent = template.transform.parent;
			if (!((Object)(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)(object)((parent is RectTransform) ? parent : null);
				_hostCanvas = _healthClone.GetComponentInParent<Canvas>();
				if ((Object)(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)(object)_parent != (Object)null) ? (_parent.enemyName ?? ((Object)_parent).name) : ((Object)((Component)this).gameObject).name);
					Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] Native bar attached with DamageShow placement: " + text + " | follow=" + (((Object)(object)_followTransform != (Object)null) ? HierarchyPath(_followTransform) : "<pending>") + " | canvas=" + (((Object)(object)_hostCanvas != (Object)null) ? ((object)_hostCanvas.renderMode).ToString() : "<none>")));
				}
			}
		}
		catch (Exception ex)
		{
			if ((Object)(object)_healthClone != (Object)null)
			{
				Object.Destroy((Object)(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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_health == (Object)null || (Object)(object)_healthClone == (Object)null)
		{
			return;
		}
		int currentHealth = EnemyAccess.GetCurrentHealth(_health);
		if (Time.realtimeSinceStartup > _visibleUntil || currentHealth <= 0)
		{
			if (_healthClone.activeSelf)
			{
				_healthClone.SetActive(false);
			}
			return;
		}
		EnsureReferences();
		if ((Object)(object)_worldCamera == (Object)null)
		{
			return;
		}
		ResolveFollowTarget(force: false);
		UpdateWorldOffsetFromBounds(force: false);
		UpdateCurrentWorldAnchor();
		float num = ((Plugin.MaxDistance != null) ? Plugin.MaxDistance.Value : 40f);
		if ((Object)(object)_followTransform == (Object)null || Vector3.Distance(((Component)_worldCamera).transform.position, _followTransform.position) > num)
		{
			if (_healthClone.activeSelf)
			{
				_healthClone.SetActive(false);
			}
		}
		else
		{
			UpdateScreenPose(log: false);
			RefreshHealthText(force: false);
		}
	}

	private void UpdateScreenPose(bool log)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_0071: 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_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: 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_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_healthClone == (Object)null || (Object)(object)_cloneRect == (Object)null || (Object)(object)_worldCamera == (Object)null || (Object)(object)_followTransform == (Object)null)
		{
			return;
		}
		Vector3 val = _worldCamera.WorldToViewportPoint(_currentWorldAnchor);
		if (val.z <= 0f)
		{
			_healthClone.SetActive(false);
			return;
		}
		float num = Vector3.Distance(((Component)_worldCamera).transform.position, _currentWorldAnchor);
		if ((Object)(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.LogInfo((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)
	{
		if ((Object)(object)_healthClone == (Object)null || (Object)(object)_health == (Object)null)
		{
			return;
		}
		int num = Mathf.Max(0, EnemyAccess.GetCurrentHealth(_health));
		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)(object)val != (Object)null)
			{
				TextUtil.SetText(val, num2.ToString());
			}
		}
	}

	private static void RemoveNativeHealthControllerDirect(GameObject clone)
	{
		if ((Object)(object)clone == (Object)null)
		{
			return;
		}
		Component[] components = clone.GetComponents<Component>();
		Component[] array = components;
		foreach (Component val in array)
		{
			if (!((Object)(object)val == (Object)null) && string.Equals(((object)val).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase))
			{
				Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
				Object.Destroy((Object)(object)val);
			}
		}
	}

	private static void ForceCanvasGroupsVisible(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		CanvasGroup[] componentsInChildren = root.GetComponentsInChildren<CanvasGroup>(true);
		CanvasGroup[] array = componentsInChildren;
		foreach (CanvasGroup val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				val.alpha = 1f;
				val.interactable = false;
				val.blocksRaycasts = false;
			}
		}
	}

	private static string HierarchyPath(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return "<null>";
		}
		List<string> list = new List<string>();
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			list.Add(((Object)val).name);
			val = val.parent;
		}
		list.Reverse();
		return string.Join("/", list.ToArray());
	}

	private void OnDestroy()
	{
		if ((Object)(object)_healthClone != (Object)null)
		{
			Object.Destroy((Object)(object)_healthClone);
		}
		_healthClone = null;
		_cloneRect = null;
		_uiParentRect = null;
		_hostCanvas = null;
		_followTransform = null;
	}
}
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)
	{
		if ((Object)(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)(object)val != (Object)null)
				{
					return val;
				}
			}
		}
		catch
		{
		}
		return ((Component)health).GetComponentInParent<Enemy>();
	}

	public static Transform GetDamageShowFollowTransform(Enemy enemy)
	{
		if ((Object)(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)(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)(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)
	{
		if ((Object)(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)(object)val != (Object)null)
				{
					return val;
				}
			}
		}
		catch
		{
		}
		return ((Component)enemy).GetComponentInParent<EnemyParent>();
	}

	public static int GetCurrentHealth(EnemyHealth health)
	{
		if ((Object)(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)
	{
		if ((Object)(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")));
		}
	}
}
internal static class NativeTemplateResolver
{
	private static GameObject _template;

	private static float _nextSearchAt;

	private static bool _pathLogged;

	public static GameObject GetTemplate()
	{
		if ((Object)(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" };
		string[] array2 = array;
		foreach (string text in array2)
		{
			GameObject val = GameObject.Find(text);
			if (IsHealthTemplate(val))
			{
				_template = val;
				LogPath(val.transform);
				return _template;
			}
		}
		Transform[] array3 = Object.FindObjectsOfType<Transform>();
		Transform[] array4 = array3;
		foreach (Transform val2 in array4)
		{
			if (!((Object)(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)
	{
		if ((Object)(object)go == (Object)null)
		{
			return false;
		}
		Component[] components = go.GetComponents<Component>();
		Component[] array = components;
		foreach (Component val in array)
		{
			if ((Object)(object)val != (Object)null && string.Equals(((object)val).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
		}
		return false;
	}

	private static void LogPath(Transform t)
	{
		if (!_pathLogged && Plugin.Log != null && !((Object)(object)t == (Object)null))
		{
			_pathLogged = true;
			Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] Native template resolved: " + HierarchyPath(t)));
		}
	}

	private static string HierarchyPath(Transform t)
	{
		List<string> list = new List<string>();
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			list.Add(((Object)val).name);
			val = val.parent;
		}
		list.Reverse();
		return string.Join("/", list.ToArray());
	}
}
internal static class HealthUiGeometry
{
	public static Vector3 GetAnchor(EnemyParent parent, Enemy enemy, Transform fallback, float extraHeight)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: 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_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		Transform val = (((Object)(object)parent != (Object)null) ? ((Component)parent).transform : (((Object)(object)enemy != (Object)null) ? ((Component)enemy).transform : fallback));
		if ((Object)(object)val == (Object)null)
		{
			return Vector3.zero;
		}
		Collider[] colliders = (Collider[])(((Object)(object)parent != (Object)null) ? ((Component)parent).GetComponentsInChildren<Collider>(true) : (((Object)(object)enemy != (Object)null) ? ((Array)((Component)enemy).GetComponentsInChildren<Collider>(true)) : ((Array)new Collider[0])));
		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)(object)parent != (Object)null) ? ((Component)parent).GetComponentsInChildren<Renderer>(true) : (((Object)(object)enemy != (Object)null) ? ((Array)((Component)enemy).GetComponentsInChildren<Renderer>(true)) : ((Array)new Renderer[0])));
		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)(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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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)
		bounds = default(Bounds);
		bool flag = false;
		if (colliders == null)
		{
			return false;
		}
		foreach (Collider val in colliders)
		{
			if ((Object)(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;
	}
}
internal static class TextUtil
{
	public static GameObject FindChild(Transform root, string name)
	{
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		Transform[] array = componentsInChildren;
		foreach (Transform val in array)
		{
			if ((Object)(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)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return;
		}
		Component[] components = obj.GetComponents<Component>();
		Component[] array = components;
		foreach (Component val in array)
		{
			if ((Object)(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
				{
				}
			}
		}
	}
}

BepInEx/plugins/NativeEnemyHealthBars/NativeEnemyHealthUIFix.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ChatGPT.NativeEnemyHealthUI.DamageShowEventFix;

[BepInPlugin("chatgpt.nativeenemyhealthui.damageshoweventfix", "Native Enemy Health UI - DamageShow Event Fix", "1.0.9.2")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "chatgpt.nativeenemyhealthui.damageshoweventfix";

	public const string PluginName = "Native Enemy Health UI - DamageShow Event Fix";

	public const string PluginVersion = "1.0.9.2";

	internal static Plugin Instance;

	internal static ManualLogSource Log;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		_harmony = new Harmony("chatgpt.nativeenemyhealthui.damageshoweventfix");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Native Enemy Health UI 1.0.9c loaded - direct NativeEnemyBar death cleanup, no periodic scan.");
	}

	internal static void QueueCleanup(EnemyHealth health)
	{
		if (!((Object)(object)Instance == (Object)null) && !((Object)(object)health == (Object)null))
		{
			((MonoBehaviour)Instance).StartCoroutine(DelayedCleanup(health));
		}
	}

	private static IEnumerator DelayedCleanup(EnemyHealth health)
	{
		yield return null;
		yield return (object)new WaitForEndOfFrame();
		if ((Object)(object)health != (Object)null)
		{
			NativeBarCleanup.CleanupFor(health, "DeathImpulseRPC");
		}
	}
}
[HarmonyPatch(typeof(EnemyHealth), "DeathImpulseRPC")]
internal static class EnemyHealthDeathImpulseRpcPatch
{
	private static void Postfix(EnemyHealth __instance)
	{
		Plugin.QueueCleanup(__instance);
	}
}
internal static class NativeBarCleanup
{
	private static readonly HashSet<int> CleanedEnemyIds = new HashSet<int>();

	private static Assembly _nativeAssembly;

	internal static void CleanupFor(EnemyHealth health, string reason)
	{
		if ((Object)(object)health == (Object)null)
		{
			return;
		}
		int instanceID;
		try
		{
			instanceID = ((Object)health).GetInstanceID();
		}
		catch
		{
			return;
		}
		if (CleanedEnemyIds.Contains(instanceID))
		{
			return;
		}
		Assembly assembly = FindNativeAssembly();
		if (assembly == null)
		{
			Plugin.Log.LogWarning((object)"[NativeEnemyHealthUI] DamageShow cleanup skipped: NativeEnemyHealthUI assembly not found.");
			return;
		}
		Transform val = FindEnemyRoot(health);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		try
		{
			MonoBehaviour[] array = Resources.FindObjectsOfTypeAll<MonoBehaviour>();
			foreach (MonoBehaviour val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Type type;
				try
				{
					type = ((object)val2).GetType();
				}
				catch
				{
					continue;
				}
				if (type.Assembly != assembly || !ReferencesEnemy(val2, health, val))
				{
					continue;
				}
				num++;
				GameObject val3 = null;
				try
				{
					val3 = ((Component)val2).gameObject;
				}
				catch
				{
				}
				if (type.FullName == "NativeEnemyHealthUI.NativeEnemyBar" && (Object)(object)val3 != (Object)null)
				{
					try
					{
						val3.SetActive(false);
					}
					catch
					{
					}
					Object.Destroy((Object)(object)val3);
					num2++;
					continue;
				}
				try
				{
					((Behaviour)val2).enabled = false;
				}
				catch
				{
				}
				if ((Object)(object)val3 != (Object)null && IsIndividualUiObject(val3))
				{
					try
					{
						val3.SetActive(false);
					}
					catch
					{
					}
					Object.Destroy((Object)(object)val3);
					num2++;
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("[NativeEnemyHealthUI] DamageShow component cleanup error: " + ex.GetType().Name + ": " + ex.Message));
		}
		try
		{
			num3 = RemoveNativeCacheEntries(assembly, health, val);
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogDebug((object)("[NativeEnemyHealthUI] Cache cleanup skipped: " + ex2.GetType().Name + ": " + ex2.Message));
		}
		CleanedEnemyIds.Add(instanceID);
		string text = "(unknown)";
		try
		{
			text = (((Object)(object)val != (Object)null) ? ((Object)val).name : ((Object)health).name);
		}
		catch
		{
		}
		Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] DAMAGESHOW DEATH CLEANUP | enemy='" + text + "' | reason=" + reason + " | matched=" + num + " | destroyed=" + num2 + " | cacheEntries=" + num3));
	}

	private static Assembly FindNativeAssembly()
	{
		if (_nativeAssembly != null)
		{
			return _nativeAssembly;
		}
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		for (int i = 0; i < assemblies.Length; i++)
		{
			string text = "";
			try
			{
				text = assemblies[i].GetName().Name;
			}
			catch
			{
			}
			if (!string.IsNullOrEmpty(text))
			{
				string text2 = text.ToLowerInvariant();
				if (text2 == "nativeenemyhealthui" || text2.Contains("nativeenemyhealthui"))
				{
					_nativeAssembly = assemblies[i];
					Plugin.Log.LogInfo((object)("[NativeEnemyHealthUI] 1.0.8 assembly detected: " + text));
					return _nativeAssembly;
				}
			}
		}
		return null;
	}

	private static Transform FindEnemyRoot(EnemyHealth health)
	{
		Transform val;
		try
		{
			val = ((Component)health).transform;
		}
		catch
		{
			return null;
		}
		Transform result = val;
		while ((Object)(object)val != (Object)null)
		{
			string text = "";
			try
			{
				text = ((Object)val).name;
			}
			catch
			{
			}
			if (!string.IsNullOrEmpty(text) && text.StartsWith("Enemy - ", StringComparison.OrdinalIgnoreCase))
			{
				return val;
			}
			result = val;
			val = val.parent;
		}
		return result;
	}

	private static bool ReferencesEnemy(object instance, EnemyHealth health, Transform enemyRoot)
	{
		if (instance == null)
		{
			return false;
		}
		FieldInfo[] fields;
		try
		{
			fields = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
			return false;
		}
		for (int i = 0; i < fields.Length; i++)
		{
			object value;
			try
			{
				value = fields[i].GetValue(instance);
			}
			catch
			{
				continue;
			}
			if (ValueReferencesEnemy(value, health, enemyRoot))
			{
				return true;
			}
		}
		return false;
	}

	private static bool ValueReferencesEnemy(object value, EnemyHealth health, Transform enemyRoot)
	{
		if (value == null)
		{
			return false;
		}
		if (object.ReferenceEquals(value, health))
		{
			return true;
		}
		Component val = (Component)((value is Component) ? value : null);
		if ((Object)(object)val != (Object)null && (Object)(object)enemyRoot != (Object)null)
		{
			try
			{
				Transform transform = val.transform;
				if ((Object)(object)transform == (Object)(object)enemyRoot || transform.IsChildOf(enemyRoot))
				{
					return true;
				}
			}
			catch
			{
			}
		}
		GameObject val2 = (GameObject)((value is GameObject) ? value : null);
		if ((Object)(object)val2 != (Object)null && (Object)(object)enemyRoot != (Object)null)
		{
			try
			{
				Transform transform2 = val2.transform;
				if ((Object)(object)transform2 == (Object)(object)enemyRoot || transform2.IsChildOf(enemyRoot))
				{
					return true;
				}
			}
			catch
			{
			}
		}
		return false;
	}

	private static bool IsIndividualUiObject(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return false;
		}
		string text = "";
		try
		{
			text = (((Object)go).name ?? "").ToLowerInvariant();
		}
		catch
		{
		}
		if (text.Contains("manager") || text.Contains("plugin") || text.Contains("controller") || text.Contains("canvas"))
		{
			return false;
		}
		try
		{
			if ((Object)(object)go.GetComponent<RectTransform>() != (Object)null)
			{
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static int RemoveNativeCacheEntries(Assembly native, EnemyHealth health, Transform enemyRoot)
	{
		int num = 0;
		Type[] types;
		try
		{
			types = native.GetTypes();
		}
		catch (ReflectionTypeLoadException ex)
		{
			types = ex.Types;
		}
		foreach (Type type in types)
		{
			if (type == null)
			{
				continue;
			}
			FieldInfo[] fields;
			try
			{
				fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			catch
			{
				continue;
			}
			for (int j = 0; j < fields.Length; j++)
			{
				object value;
				try
				{
					value = fields[j].GetValue(null);
				}
				catch
				{
					continue;
				}
				if (!(value is IDictionary dictionary))
				{
					continue;
				}
				ArrayList arrayList = new ArrayList();
				foreach (DictionaryEntry item in dictionary)
				{
					if (!ValueReferencesEnemy(item.Key, health, enemyRoot) && !ValueReferencesEnemy(item.Value, health, enemyRoot))
					{
						continue;
					}
					arrayList.Add(item.Key);
					object? value2 = item.Value;
					Object val = (Object)((value2 is Object) ? value2 : null);
					if (!(val != (Object)null))
					{
						continue;
					}
					Component val2 = (Component)(object)((val is Component) ? val : null);
					if ((Object)(object)val2 != (Object)null)
					{
						try
						{
							GameObject gameObject = val2.gameObject;
							if (IsIndividualUiObject(gameObject))
							{
								Object.Destroy((Object)(object)gameObject);
							}
						}
						catch
						{
						}
					}
					GameObject val3 = (GameObject)(object)((val is GameObject) ? val : null);
					if ((Object)(object)val3 != (Object)null && IsIndividualUiObject(val3))
					{
						Object.Destroy((Object)(object)val3);
					}
				}
				for (int k = 0; k < arrayList.Count; k++)
				{
					try
					{
						dictionary.Remove(arrayList[k]);
						num++;
					}
					catch
					{
					}
				}
			}
		}
		return num;
	}

	private static void TryInvokeNoArg(object instance, string methodName)
	{
		try
		{
			MethodInfo methodInfo = AccessTools.Method(instance.GetType(), methodName, Type.EmptyTypes, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(instance, null);
			}
		}
		catch
		{
		}
	}
}