Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Enemy Health Bars v1.0.6
EnemyHealthBars.dll
Decompiled 3 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Omniscye")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EnemyHealthBars")] [assembly: AssemblyTitle("EnemyHealthBars")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Empress.EnemyHealthBars { [BepInPlugin("Empress.EnemyHealthBars", "Enemy Health Bars", "1.0.1")] public class EnemyHealthBarsPlugin : BaseUnityPlugin { internal static ConfigEntry<bool> AlwaysShow; internal static ConfigEntry<float> ShowOnDamageSeconds; internal static ConfigEntry<float> BarWidth; internal static ConfigEntry<float> BarHeight; internal static ConfigEntry<float> OffsetPercentOfHeight; internal static ConfigEntry<float> ExtraOffsetMeters; internal static ConfigEntry<float> DistanceScaleFactor; internal static ConfigEntry<float> MinScale; internal static ConfigEntry<float> MaxScale; internal static ConfigEntry<bool> OnlyWhenVisible; internal static ConfigEntry<float> LerpSpeed; internal static ConfigEntry<bool> UseMeshParentIfAvailable; internal static ConfigEntry<float> ChipDropSpeed; internal static ConfigEntry<float> HealCatchupSpeed; internal static EnemyHealthBarsPlugin Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; private set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; AlwaysShow = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AlwaysShow", true, "If true, health bars are always visible. If false, they show for a short time after damage."); ShowOnDamageSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ShowOnDamageSeconds", 2.5f, "Seconds to keep the bar visible after damage when AlwaysShow is false."); BarWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "BarWidth", 1f, "Base width before distance scaling."); BarHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "BarHeight", 0.1f, "Bar height."); OffsetPercentOfHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "OffsetPercentOfHeight", 0.2f, "How far above the top of the model to place the bar as a percentage of the model height."); ExtraOffsetMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "ExtraOffsetMeters", 0.15f, "Extra vertical meters to add above the top."); DistanceScaleFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "DistanceScaleFactor", 0.015f, "Scale per meter."); MinScale = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "MinScale", 0.3f, "Min scale."); MaxScale = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "MaxScale", 2f, "Max scale."); OnlyWhenVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyWhenVisible", true, "Hide the bar when the enemy renderers are not visible to the camera."); LerpSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "LerpSpeed", 12f, "Front bar heal smoothing speed."); UseMeshParentIfAvailable = ((BaseUnityPlugin)this).Config.Bind<bool>("Position", "UseMeshParentIfAvailable", true, "Anchor bar to EnemyHealth.meshParent if it's set; otherwise use the enemy root."); ChipDropSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "ChipDropSpeed", 6f, "Speed the dark-red damage chip falls toward the current health after damage."); HealCatchupSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "HealCatchupSpeed", 16f, "Speed the damage chip catches up when healing."); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded. Painting them red."); try { Type type = AccessTools.TypeByName("EnemyHealth"); MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (methodInfo != null) { Logger.LogInfo((object)"Harmony: EnemyHealth.Awake patched OK"); } else { Logger.LogWarning((object)"Harmony: EnemyHealth.Awake not found - bars will not attach to new spawns"); } } catch (Exception ex) { Logger.LogWarning((object)("Harmony check failed: " + ex.Message)); } TryAttachToExisting(); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void TryAttachToExisting() { try { MonoBehaviour[] array = Object.FindObjectsOfType<MonoBehaviour>(); MonoBehaviour[] array2 = array; foreach (MonoBehaviour val in array2) { if (!((Object)(object)val == (Object)null)) { Type type = ((object)val).GetType(); if (type.Name == "EnemyHealth") { HealthBarAttacher.AttachTo(val); } } } } catch (Exception arg) { Logger.LogWarning((object)$"Scan failed: {arg}"); } } } [HarmonyPatch] internal static class EnemyHealthPatches { private static MethodBase TargetMethod() { return AccessTools.Method(AccessTools.TypeByName("EnemyHealth"), "Awake", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Post_Awake(MonoBehaviour __instance) { HealthBarAttacher.AttachTo(__instance); } } [HarmonyPatch] internal static class EnemyHealthAttachFallbackPatches { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type <t>5__1; private string[] <names>5__2; private string[] <>s__3; private int <>s__4; private string <n>5__5; private MethodInfo <m>5__6; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <t>5__1 = null; <names>5__2 = null; <>s__3 = null; <n>5__5 = null; <m>5__6 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00be; } <>1__state = -1; <t>5__1 = AccessTools.TypeByName("EnemyHealth"); <names>5__2 = new string[2] { "Start", "OnEnable" }; <>s__3 = <names>5__2; <>s__4 = 0; goto IL_00db; IL_00be: <m>5__6 = null; <n>5__5 = null; <>s__4++; goto IL_00db; IL_00db: if (<>s__4 < <>s__3.Length) { <n>5__5 = <>s__3[<>s__4]; <m>5__6 = AccessTools.Method(<t>5__1, <n>5__5, (Type[])null, (Type[])null); if (<m>5__6 != null) { <>2__current = <m>5__6; <>1__state = 1; return true; } goto IL_00be; } <>s__3 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } [HarmonyPostfix] private static void Post_AttachFallback(MonoBehaviour __instance) { HealthBarAttacher.AttachTo(__instance); } } [HarmonyPatch] internal static class EnemyHealthEventPatches { [CompilerGenerated] private sealed class <TargetMethods>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private string[] <names>5__1; private string[] <>s__2; private int <>s__3; private string <n>5__4; private MethodInfo <m>5__5; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <names>5__1 = null; <>s__2 = null; <n>5__4 = null; <m>5__5 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00d5; } <>1__state = -1; <names>5__1 = new string[7] { "Hurt", "HurtRPC", "Heal", "HealRPC", "Death", "DeathRPC", "DeathImpulseRPC" }; <>s__2 = <names>5__1; <>s__3 = 0; goto IL_00f2; IL_00d5: <m>5__5 = null; <n>5__4 = null; <>s__3++; goto IL_00f2; IL_00f2: if (<>s__3 < <>s__2.Length) { <n>5__4 = <>s__2[<>s__3]; <m>5__5 = AccessTools.Method(EH, <n>5__4, (Type[])null, (Type[])null); if (<m>5__5 != null) { <>2__current = <m>5__5; <>1__state = 1; return true; } goto IL_00d5; } <>s__2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__2(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } private static Type EH => AccessTools.TypeByName("EnemyHealth"); [IteratorStateMachine(typeof(<TargetMethods>d__2))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__2(-2); } [HarmonyPostfix] private static void Post_HPEvents(MonoBehaviour __instance) { EnemyHealthBar component = ((Component)__instance).GetComponent<EnemyHealthBar>(); if ((Object)(object)component != (Object)null) { component.OnHealthTouched(); } } } internal static class HealthBarAttacher { internal static void AttachTo(MonoBehaviour enemyHealth) { if ((Object)(object)enemyHealth == (Object)null) { return; } Type type = ((object)enemyHealth).GetType(); if (type.Name != "EnemyHealth" || (Object)(object)((Component)enemyHealth).GetComponent<EnemyHealthBar>() != (Object)null) { return; } try { EnemyHealthBar enemyHealthBar = ((Component)enemyHealth).gameObject.AddComponent<EnemyHealthBar>(); enemyHealthBar.Initialize(enemyHealth); } catch (Exception arg) { EnemyHealthBarsPlugin.Logger.LogWarning((object)$"Failed to attach health bar: {arg}"); } } } public class EnemyHealthBar : MonoBehaviour { private static readonly Type EH = AccessTools.TypeByName("EnemyHealth"); private static readonly FieldInfo F_health = AccessTools.Field(EH, "health"); private static readonly FieldInfo F_healthCurrent = AccessTools.Field(EH, "healthCurrent"); private static readonly FieldInfo F_dead = AccessTools.Field(EH, "dead"); private static readonly FieldInfo F_meshParent = AccessTools.Field(EH, "meshParent"); private static readonly FieldInfo F_onHurt = AccessTools.Field(EH, "onHurt"); private static readonly FieldInfo F_onDeath = AccessTools.Field(EH, "onDeath"); private MonoBehaviour enemyHealth = null; private int maxHealth; private int lastHealth; private bool dead; private Transform anchor = null; private readonly List<Renderer> renderers = new List<Renderer>(); private GameObject rootGO = null; private Canvas canvas = null; private RectTransform rect = null; private Image imgFill = null; private Image imgChip = null; private Image imgBack = null; private Text textComp = null; private float showTimer; private float currentFill = 1f; private float chipFill = 1f; private Camera cachedCam; private static Sprite whiteSprite; private bool initialized; public void Initialize(MonoBehaviour eh) { enemyHealth = eh; maxHealth = SafeGet(F_health, enemyHealth, 100); lastHealth = SafeGet(F_healthCurrent, enemyHealth, maxHealth); dead = SafeGet(F_dead, enemyHealth, fallback: false); Transform val = SafeGet<Transform>(F_meshParent, enemyHealth, null); anchor = ((EnemyHealthBarsPlugin.UseMeshParentIfAvailable.Value && (Object)(object)val != (Object)null) ? val : ((Component)enemyHealth).transform); ((Component)anchor).GetComponentsInChildren<Renderer>(true, renderers); if (renderers.Count == 0) { ((Component)enemyHealth).GetComponentsInChildren<Renderer>(true, renderers); } BuildUI(); HookUnityEventsIfPresent(); initialized = true; } private void HookUnityEventsIfPresent() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown try { object? obj = F_onHurt?.GetValue(enemyHealth); UnityEvent val = (UnityEvent)((obj is UnityEvent) ? obj : null); if (val != null) { val.AddListener(new UnityAction(OnHealthTouched)); } object? obj2 = F_onDeath?.GetValue(enemyHealth); UnityEvent val2 = (UnityEvent)((obj2 is UnityEvent) ? obj2 : null); if (val2 != null) { val2.AddListener(new UnityAction(OnDeath)); } } catch (Exception ex) { EnemyHealthBarsPlugin.Logger.LogDebug((object)("UnityEvent hook skipped: " + ex.Message)); } } private void BuildUI() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0022: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Expected O, but got Unknown //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Expected O, but got Unknown //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0519: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_0581: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)whiteSprite == (Object)null) { Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, Color.white); val.Apply(); whiteSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 100f); } rootGO = new GameObject("EmpressHealthBar", new Type[1] { typeof(RectTransform) }); ((Object)rootGO).hideFlags = (HideFlags)52; rootGO.layer = (((Object)(object)anchor != (Object)null) ? ((Component)anchor).gameObject.layer : 0); Canvas val2 = rootGO.AddComponent<Canvas>(); val2.renderMode = (RenderMode)2; val2.sortingOrder = 5000; canvas = val2; CanvasGroup val3 = rootGO.AddComponent<CanvasGroup>(); val3.interactable = false; val3.blocksRaycasts = false; rect = rootGO.GetComponent<RectTransform>(); rect.sizeDelta = new Vector2(EnemyHealthBarsPlugin.BarWidth.Value, EnemyHealthBarsPlugin.BarHeight.Value); GameObject val4 = new GameObject("Frame", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(rootGO.transform, false); RectTransform component = val4.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Image val5 = val4.AddComponent<Image>(); val5.sprite = whiteSprite; val5.type = (Type)0; ((Graphic)val5).color = new Color(0.1f, 0.1f, 0.1f, 1f); GameObject val6 = new GameObject("Back", new Type[1] { typeof(RectTransform) }); val6.transform.SetParent(val4.transform, false); RectTransform component2 = val6.GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; float num = 0.015f; component2.offsetMin = new Vector2(num, num); component2.offsetMax = new Vector2(0f - num, 0f - num); imgBack = val6.AddComponent<Image>(); imgBack.sprite = whiteSprite; imgBack.type = (Type)0; ((Graphic)imgBack).color = new Color(0.8f, 0.8f, 0.8f, 0.25f); GameObject val7 = new GameObject("Chip", new Type[1] { typeof(RectTransform) }); val7.transform.SetParent(val4.transform, false); RectTransform component3 = val7.GetComponent<RectTransform>(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = new Vector2(num, num); component3.offsetMax = new Vector2(0f - num, 0f - num); imgChip = val7.AddComponent<Image>(); imgChip.sprite = whiteSprite; imgChip.type = (Type)3; imgChip.fillMethod = (FillMethod)0; imgChip.fillOrigin = 0; ((Graphic)imgChip).color = new Color(0.9f, 0.7f, 0.1f, 0.95f); imgChip.fillAmount = 1f; GameObject val8 = new GameObject("Fill", new Type[1] { typeof(RectTransform) }); val8.transform.SetParent(val4.transform, false); RectTransform component4 = val8.GetComponent<RectTransform>(); component4.anchorMin = Vector2.zero; component4.anchorMax = Vector2.one; component4.offsetMin = new Vector2(num, num); component4.offsetMax = new Vector2(0f - num, 0f - num); imgFill = val8.AddComponent<Image>(); imgFill.sprite = whiteSprite; imgFill.type = (Type)3; imgFill.fillMethod = (FillMethod)0; imgFill.fillOrigin = 0; ((Graphic)imgFill).color = new Color(0.9f, 0.1f, 0.1f, 1f); imgFill.fillAmount = 1f; GameObject val9 = new GameObject("Text", new Type[1] { typeof(RectTransform) }); val9.transform.SetParent(val4.transform, false); RectTransform component5 = val9.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0f, 0f); component5.anchorMax = new Vector2(1f, 1f); component5.offsetMin = Vector2.zero; component5.offsetMax = Vector2.zero; textComp = val9.AddComponent<Text>(); textComp.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); textComp.alignment = (TextAnchor)4; textComp.horizontalOverflow = (HorizontalWrapMode)1; textComp.verticalOverflow = (VerticalWrapMode)0; ((Graphic)textComp).color = Color.white; textComp.fontSize = 9; Shadow val10 = val9.AddComponent<Shadow>(); val10.effectColor = Color.black; val10.effectDistance = new Vector2(1f, -1f); rootGO.transform.SetParent(((Component)enemyHealth).transform, false); } private void OnDestroy() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown try { object? obj = F_onHurt?.GetValue(enemyHealth); UnityEvent val = (UnityEvent)((obj is UnityEvent) ? obj : null); if (val != null) { val.RemoveListener(new UnityAction(OnHealthTouched)); } object? obj2 = F_onDeath?.GetValue(enemyHealth); UnityEvent val2 = (UnityEvent)((obj2 is UnityEvent) ? obj2 : null); if (val2 != null) { val2.RemoveListener(new UnityAction(OnDeath)); } } catch { } } public void OnHealthTouched() { maxHealth = SafeGet(F_health, enemyHealth, maxHealth); int num = SafeGet(F_healthCurrent, enemyHealth, lastHealth); lastHealth = num; showTimer = Mathf.Max(showTimer, EnemyHealthBarsPlugin.ShowOnDamageSeconds.Value); } private void OnDeath() { dead = true; if ((Object)(object)rootGO != (Object)null) { rootGO.SetActive(false); } } private void Update() { if (!initialized || (Object)(object)enemyHealth == (Object)null) { return; } if ((Object)(object)cachedCam == (Object)null || !((Behaviour)cachedCam).isActiveAndEnabled) { cachedCam = FindCamera(); } if ((Object)(object)cachedCam == (Object)null) { if ((Object)(object)rootGO != (Object)null) { rootGO.SetActive(false); } return; } int num = SafeGet(F_healthCurrent, enemyHealth, lastHealth); int num2 = SafeGet(F_health, enemyHealth, maxHealth); if (num2 <= 0) { num2 = 1; } float num3 = Mathf.Clamp01((float)num / (float)num2); if ((Object)(object)textComp != (Object)null) { textComp.text = $"{num} / {num2}"; } float num4 = currentFill; bool flag = num3 < num4 - 0.0001f; bool flag2 = num3 > num4 + 0.0001f; if (flag) { currentFill = num3; chipFill = Mathf.Max(chipFill, num4); } else if (flag2) { currentFill = Mathf.Lerp(num4, num3, EnemyHealthBarsPlugin.LerpSpeed.Value * Time.deltaTime); } else { currentFill = Mathf.Lerp(num4, num3, EnemyHealthBarsPlugin.LerpSpeed.Value * Time.deltaTime); } float num5 = currentFill; float num6 = ((chipFill > num5) ? EnemyHealthBarsPlugin.ChipDropSpeed.Value : EnemyHealthBarsPlugin.HealCatchupSpeed.Value); chipFill = Mathf.Lerp(chipFill, num5, num6 * Time.deltaTime); if ((Object)(object)imgFill != (Object)null) { imgFill.fillAmount = currentFill; } if ((Object)(object)imgChip != (Object)null) { imgChip.fillAmount = chipFill; } bool flag3 = EnemyHealthBarsPlugin.AlwaysShow.Value; if (!flag3) { showTimer -= Time.deltaTime; if (showTimer > 0f) { flag3 = true; } } if (EnemyHealthBarsPlugin.OnlyWhenVisible.Value && !AnyRendererVisible()) { flag3 = false; } if ((Object)(object)rootGO != (Object)null) { rootGO.SetActive(flag3 && !dead); } } private void LateUpdate() { //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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0063: 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_0075: 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_008d: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if (initialized && !((Object)(object)rootGO == (Object)null) && !((Object)(object)anchor == (Object)null) && !((Object)(object)cachedCam == (Object)null)) { Bounds val = ComputeBounds(); Vector3 val2 = ((Bounds)(ref val)).center + Vector3.up * ((Bounds)(ref val)).extents.y; float num = EnemyHealthBarsPlugin.ExtraOffsetMeters.Value + ((Bounds)(ref val)).size.y * EnemyHealthBarsPlugin.OffsetPercentOfHeight.Value; Vector3 val3 = val2 + Vector3.up * Mathf.Max(0.01f, num); rootGO.transform.position = val3; Vector3 val4 = rootGO.transform.position - ((Component)cachedCam).transform.position; if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f) { rootGO.transform.forward = ((Vector3)(ref val4)).normalized; } float num2 = Mathf.Max(0.01f, Vector3.Distance(((Component)cachedCam).transform.position, val3)); float num3 = Mathf.Clamp(1f + num2 * EnemyHealthBarsPlugin.DistanceScaleFactor.Value, EnemyHealthBarsPlugin.MinScale.Value, EnemyHealthBarsPlugin.MaxScale.Value); rootGO.transform.localScale = Vector3.one * num3; } } private Bounds ComputeBounds() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0111: 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_0106: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor(anchor.position, Vector3.one * 0.5f); bool flag = false; for (int i = 0; i < renderers.Count; i++) { Renderer val = renderers[i]; if (!((Object)(object)val == (Object)null) && val.enabled) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } if (!flag) { renderers.Clear(); ((Component)anchor).GetComponentsInChildren<Renderer>(true, renderers); for (int j = 0; j < renderers.Count; j++) { Renderer val2 = renderers[j]; if (!((Object)(object)val2 == (Object)null) && val2.enabled) { if (!flag) { bounds = val2.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2.bounds); } } } } if (!flag) { ((Bounds)(ref bounds))..ctor(anchor.position + Vector3.up * 1f, new Vector3(1f, 2f, 1f)); } return bounds; } private bool AnyRendererVisible() { for (int i = 0; i < renderers.Count; i++) { Renderer val = renderers[i]; if ((Object)(object)val != (Object)null && val.enabled && val.isVisible) { return true; } } return false; } private Camera FindCamera() { Camera main = Camera.main; if ((Object)(object)main != (Object)null && ((Behaviour)main).isActiveAndEnabled) { return main; } Camera[] array = Object.FindObjectsOfType<Camera>(); Camera[] array2 = array; foreach (Camera val in array2) { if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled) { return val; } } return null; } private static T SafeGet<T>(FieldInfo fi, object inst, T fallback) { try { if (fi == null || inst == null) { return fallback; } object value = fi.GetValue(inst); if (value is T result) { return result; } if (value == null) { return fallback; } return (T)Convert.ChangeType(value, typeof(T)); } catch { return fallback; } } } }