Decompiled source of HealthBarViewer v1.0.0

HealthBarViewer.dll

Decompiled 3 months ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.CameraModes;
using RoR2.UI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Local.HealthBar.Viewer
{
	[BepInPlugin("local.healthbar.viewer", "HealthBarViewer", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private class ConfigValue<T> : ConfigValue<T, T>
		{
			public ConfigValue(ConfigEntry<T> entry)
				: base(entry)
			{
				convert = (T _) => _;
			}

			public static implicit operator ConfigValue<T>(ConfigEntry<T> entry)
			{
				return new ConfigValue<T>(entry);
			}
		}

		private class ConfigValue<T, U>
		{
			private readonly ConfigEntry<T> entry;

			public Func<T, U> convert;

			public ConfigValue(ConfigEntry<T> entry)
			{
				this.entry = entry;
				base..ctor();
			}

			public static implicit operator ConfigValue<T, U>(ConfigEntry<T> entry)
			{
				return new ConfigValue<T, U>(entry);
			}

			public static implicit operator U(ConfigValue<T, U> configuration)
			{
				return configuration.convert(configuration.entry.Value);
			}
		}

		public const string version = "1.0.0";

		public const string identifier = "local.healthbar.viewer";

		private static ConfigValue<uint> duration;

		private static ConfigValue<uint> range;

		private static ConfigValue<float> threshold;

		private static ConfigValue<float> alpha;

		private static ConfigValue<bool> ally;

		private static ConfigValue<uint, float> delay;

		private static ConfigValue<uint, float> interval;

		public void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			duration = ((BaseUnityPlugin)this).Config.Bind<uint>("General", "Minimum Duration", 10u, "After damage is dealt, the target's health bar will remain visible for this many seconds.");
			threshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Health Threshold", 75f, new ConfigDescription("Enemies at this hit point percentage or below remain visible indefinitely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			threshold.convert = percent;
			range = ((BaseUnityPlugin)this).Config.Bind<uint>("General", "Maximum Range", 100u, "Remove health bar regardless of health threshold if distance to target exceeds this value in meters. Set to zero for unlimited range.");
			ally = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Allied Targets", true, "Determines whether allies reveal their target upon dealing damage.");
			delay = ((BaseUnityPlugin)this).Config.Bind<uint>("Other", "Targeting Delay", 0u, "Aiming directly at an enemy will display their health for this many milliseconds. If target is below the health threshold, minimum duration parameter is used instead.");
			delay.convert = milliseconds;
			alpha = ((BaseUnityPlugin)this).Config.Bind<float>("Other", "Alpha Channel", 85f, new ConfigDescription("Use this parameter to adjust transparency/opacity of the health bar interface.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			alpha.convert = percent;
			interval = ((BaseUnityPlugin)this).Config.Bind<uint>("Other", "Refresh Interval", 500u, "How often to check target health/range, in milliseconds. Note that decreasing this value could negatively affect performance.");
			interval.convert = milliseconds;
			ReplaceEventHandler();
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			static float milliseconds(uint input)
			{
				return (float)input / 1000f;
			}
			static float percent(float input)
			{
				return input / 100f;
			}
		}

		private static void ReplaceEventHandler()
		{
			try
			{
				Type typeFromHandle = typeof(CombatHealthBarViewer);
				Type typeFromHandle2 = typeof(GlobalEventManager);
				string name = "onClientDamageNotified";
				RuntimeHelpers.RunClassConstructor(typeFromHandle.TypeHandle);
				EventInfo @event = typeFromHandle2.GetEvent(name);
				Delegate[] invocationList = (typeFromHandle2.GetField(name, BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as Delegate).GetInvocationList();
				foreach (Delegate @delegate in invocationList)
				{
					if (typeFromHandle == @delegate.Method.DeclaringType.DeclaringType)
					{
						@event.RemoveEventHandler(null, @delegate);
						return;
					}
				}
				throw new Exception("Unable to locate original health bar event handler.");
			}
			catch (Exception value)
			{
				Console.WriteLine(value);
			}
			finally
			{
				GlobalEventManager.onClientDamageNotified += ShowHealthBar;
			}
		}

		[HarmonyPatch(typeof(CombatHealthBarViewer), "Awake")]
		[HarmonyPostfix]
		private static void ApplySettings(CombatHealthBarViewer __instance)
		{
			__instance.healthBarDuration = (uint)duration;
			if ((float)alpha != 1f && Object.op_Implicit((Object)(object)((Component)__instance).gameObject))
			{
				((Component)__instance).gameObject.AddComponent<CanvasGroup>().alpha = alpha;
			}
		}

		[HarmonyPatch(typeof(CombatHealthBarViewer), "CleanUp")]
		[HarmonyPrefix]
		private static bool CheckStatus(CombatHealthBarViewer __instance)
		{
			//IL_008a: 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)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			int num = __instance.trackedVictims.Count;
			while (--num >= 0)
			{
				HealthComponent val = __instance.trackedVictims[num];
				HealthBarInfo healthBarInfo = __instance.GetHealthBarInfo(val);
				if (Object.op_Implicit((Object)(object)val) && val.alive && Object.op_Implicit((Object)(object)val.body))
				{
					if (healthBarInfo.endTime > Time.time)
					{
						continue;
					}
					float num2;
					if ((uint)range == 0 || !Object.op_Implicit((Object)(object)__instance.viewerBody))
					{
						num2 = (uint)range;
					}
					else
					{
						Vector3 val2 = __instance.viewerBody.corePosition - val.body.corePosition;
						num2 = ((Vector3)(ref val2)).magnitude;
					}
					float num3 = num2;
					if (val.combinedHealthFraction <= (float)threshold && num3 <= (float)(uint)range)
					{
						healthBarInfo.endTime = Time.time + (float)interval;
						continue;
					}
				}
				__instance.Remove(num, healthBarInfo);
			}
			return false;
		}

		private static void ShowHealthBar(DamageDealtMessage message)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (message.isSilent || !Object.op_Implicit((Object)(object)message.victim) || !Object.op_Implicit((Object)(object)message.attacker))
			{
				return;
			}
			HealthComponent component = message.victim.GetComponent<HealthComponent>();
			if (!Object.op_Implicit((Object)(object)component) || component.dontShowHealthbar)
			{
				return;
			}
			foreach (CombatHealthBarViewer instances in CombatHealthBarViewer.instancesList)
			{
				if (Object.op_Implicit((Object)(object)instances.viewerBodyObject))
				{
					object obj = instances.viewerBodyObject;
					object obj2 = message.attacker;
					if ((bool)ally)
					{
						obj = instances.viewerTeamIndex;
						obj2 = TeamComponent.GetObjectTeam(message.attacker);
					}
					if (obj.Equals(obj2))
					{
						instances.HandleDamage(component, TeamComponent.GetObjectTeam(message.victim));
					}
				}
			}
		}

		[HarmonyPatch(typeof(CameraRigController), "SetCameraState")]
		[HarmonyPostfix]
		private static void UpdateCrosshair(CameraRigController __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			CameraModeBase cameraMode = __instance.cameraMode;
			HurtBox val2 = (__instance.lastCrosshairHurtBox = ((InstanceData)(/*isinst with value type is only supported in some contexts*/?)).lastCrosshairHurtBox);
			if (Object.op_Implicit((Object)(object)__instance.hud))
			{
				CombatHealthBarViewer combatHealthBarViewer = __instance.hud.combatHealthBarViewer;
				if (Object.op_Implicit((Object)(object)combatHealthBarViewer))
				{
					combatHealthBarViewer.crosshairTarget = (Object.op_Implicit((Object)(object)val2) ? val2.healthComponent : null);
				}
			}
		}

		[HarmonyPatch(typeof(CombatHealthBarViewer), "Update")]
		[HarmonyPrefix]
		private static bool ShowCrosshairTarget(CombatHealthBarViewer __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.crosshairTarget))
			{
				float num = delay;
				if (__instance.crosshairTarget.combinedHealthFraction <= (float)threshold)
				{
					num = (uint)duration;
				}
				if (num > 0f)
				{
					HealthBarInfo healthBarInfo = __instance.GetHealthBarInfo(__instance.crosshairTarget);
					healthBarInfo.endTime = Mathf.Max(healthBarInfo.endTime, Time.time + num);
				}
			}
			__instance.SetDirty();
			return false;
		}
	}
}