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 MonsterHealthBars v1.0.0
MonsterHealthBars.dll
Decompiled 5 days agousing 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 ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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("MonsterHealthBars")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MonsterHealthBars")] [assembly: AssemblyTitle("MonsterHealthBars")] [assembly: AssemblyVersion("1.0.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 MonsterHealthBars { internal class BarsOverlay : MonoBehaviour { private class Entry { public EnemyParent parent; public Enemy enemy; public EnemyHealth health; public int viewId; public Collider[] colliders; public Renderer[] renderers; public float lastHitTime; public float alpha; public int lastSentHp = int.MinValue; public float lastSendTime = -999f; public Bar bar; } private class Bar { public GameObject root; public RectTransform rect; public CanvasGroup group; public Image back; public Image fill; public RectTransform fillRect; public TextMeshProUGUI label; private float _shownFill = -1f; private float _appliedWidth = -1f; private Color _lastColor; private string _lastText; public void Show(Vector2 anchoredPosition, float scale, float alpha, float fillTarget, float barWidth, float barHeight, Color color, string text, float dt) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0137: Unknown result type (might be due to invalid IL or missing references) if (!root.activeSelf) { root.SetActive(true); } rect.anchoredPosition = anchoredPosition; ((Transform)rect).localScale = new Vector3(scale, scale, 1f); rect.sizeDelta = new Vector2(barWidth, barHeight); group.alpha = alpha; if (_shownFill < 0f) { _shownFill = fillTarget; } else { float num = 1f - Mathf.Exp(-14f * dt); _shownFill = Mathf.Lerp(_shownFill, fillTarget, num); if (Mathf.Abs(_shownFill - fillTarget) < 0.002f) { _shownFill = fillTarget; } } if (_appliedWidth < 0f || !Mathf.Approximately(barWidth, _appliedWidth) || !Mathf.Approximately(fillRect.sizeDelta.x, barWidth * _shownFill)) { _appliedWidth = barWidth; fillRect.sizeDelta = new Vector2(barWidth * _shownFill, 0f); } if (color != _lastColor) { _lastColor = color; ((Graphic)fill).color = color; } if (text != _lastText) { _lastText = text; ((TMP_Text)label).text = text ?? string.Empty; ((Component)label).gameObject.SetActive(!string.IsNullOrEmpty(text)); } } public void Hide() { if (root.activeSelf) { root.SetActive(false); } _shownFill = -1f; _appliedWidth = -1f; } public void Destroy() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } } } private class Popup { public GameObject go; public RectTransform rect; public TextMeshProUGUI text; public Vector3 world; public Vector2 screenOffset; public float rise; public float riseCurrent; public float age; public float life; } private const float RescanInterval = 0.5f; private const float FadeInTime = 0.12f; private const float FillSmoothing = 14f; private const float PopupFadeIn = 0.15f; private const float PopupFadeOut = 0.5f; private Camera _cam; private Canvas _canvas; private RectTransform _canvasRect; private Sprite _whiteSprite; private readonly List<Entry> _entries = new List<Entry>(); private readonly List<Popup> _popups = new List<Popup>(); private float _rescanTimer; private TMP_FontAsset _font; private int _popupCounter; internal static BarsOverlay Instance { get; private set; } private void Awake() { Instance = this; BuildCanvas(); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } if ((Object)(object)_canvas != (Object)null) { Object.Destroy((Object)(object)((Component)_canvas).gameObject); } } private void OnEnable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.onBeforeRender += new UnityAction(RepositionOnly); } private void OnDisable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.onBeforeRender -= new UnityAction(RepositionOnly); } private void RepositionOnly() { //IL_007f: 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_008a: 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_0094: 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_0102: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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_0122: 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_0138: 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) if ((Object)(object)_cam == (Object)null || (_entries.Count == 0 && _popups.Count == 0)) { return; } float value = MonsterHealthBarsPlugin.BarYOffset.Value; float depth; for (int i = 0; i < _entries.Count; i++) { Entry entry = _entries[i]; if (entry.bar != null && entry.bar.root.activeSelf && !((Object)(object)entry.parent == (Object)null) && !((Object)(object)entry.health == (Object)null)) { Vector3 world = GetTopPoint(entry) + Vector3.up * value; if (Project(world, out var screen, out depth)) { entry.bar.rect.anchoredPosition = ToCanvas(screen); } } } for (int j = 0; j < _popups.Count; j++) { Popup popup = _popups[j]; if (!((Object)(object)popup.go == (Object)null) && popup.go.activeSelf && Project(popup.world, out var screen2, out depth)) { popup.rect.anchoredPosition = ToCanvas(screen2) + popup.screenOffset + new Vector2(0f, popup.riseCurrent); } } } private void BuildCanvas() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("MonsterHealthBars_Canvas", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)this).transform, false); _canvas = val.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 30000; _canvas.pixelPerfect = false; CanvasScaler obj = val.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)0; obj.scaleFactor = 1f; _canvasRect = (RectTransform)val.transform; _whiteSprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); ((Object)_whiteSprite).name = "MHB_White"; } private void LateUpdate() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_0205: 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_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Invalid comparison between Unknown and I4 //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null) { Instance = this; } float num = Mathf.Min(Time.unscaledDeltaTime, 0.1f); if ((Object)(object)_cam == (Object)null) { _cam = Camera.main; } if ((Object)(object)_cam == (Object)null) { HideAllBars(); return; } HealthSync.TrySubscribe(); _rescanTimer -= num; if (_rescanTimer <= 0f) { _rescanTimer = 0.5f; Rescan(); } Vector3 playerPosition = GetPlayerPosition(); float num2 = Mathf.Max(1f, MonsterHealthBarsPlugin.Radius.Value); float value = MonsterHealthBarsPlugin.BarYOffset.Value; bool flag = HealthSync.IsMaster(); bool flag2 = HealthSync.IsMultiplayer(); float interval = Mathf.Max(0.2f, MonsterHealthBarsPlugin.SyncInterval.Value); bool value2 = MonsterHealthBarsPlugin.ShowBars.Value; bool value3 = MonsterHealthBarsPlugin.AlwaysShow.Value; float num3 = Mathf.Max(0f, MonsterHealthBarsPlugin.HideDelay.Value); float num4 = Mathf.Max(0.05f, MonsterHealthBarsPlugin.FadeOutDuration.Value); float num5 = Mathf.Clamp(MonsterHealthBarsPlugin.MinDistanceScale.Value, 0.2f, 1f); float value4 = MonsterHealthBarsPlugin.BarWidth.Value; float value5 = MonsterHealthBarsPlugin.BarHeight.Value; bool value6 = MonsterHealthBarsPlugin.ShowHpText.Value; bool value7 = MonsterHealthBarsPlugin.RequireLineOfSight.Value; Color barColor = MonsterHealthBarsPlugin.BarColor; float unscaledTime = Time.unscaledTime; for (int num6 = _entries.Count - 1; num6 >= 0; num6--) { Entry entry = _entries[num6]; if ((Object)(object)entry.parent == (Object)null || (Object)(object)entry.health == (Object)null) { RemoveEntry(num6); } else { if (flag && flag2) { int current = HealthSync.GetCurrent(entry.health, 0); if (HealthSync.ShouldSend(ref entry.lastSentHp, ref entry.lastSendTime, current, interval)) { HealthSync.Send(entry.viewId, current); } } bool flag3 = HealthSync.IsDead(entry.health); Vector3 val = GetTopPoint(entry) + Vector3.up * value; float num7 = Vector3.Distance(playerPosition, val); Vector2 screen = default(Vector2); float depth; bool flag4 = Project(val, out screen, out depth); bool num8 = value2 && ((Behaviour)entry.health).isActiveAndEnabled && ((Component)entry.health).gameObject.activeInHierarchy && ((Object)(object)entry.enemy == (Object)null || (int)entry.enemy.CurrentState != 11) && num7 <= num2 && flag4 && (!value7 || HasLineOfSight(val, ((Component)entry.parent).transform)); bool flag5 = value3 || unscaledTime - entry.lastHitTime <= num3; float num9 = ((num8 && !flag3 && flag5) ? 1f : 0f); if (num9 > entry.alpha) { entry.alpha = Mathf.Min(num9, entry.alpha + num / 0.12f); } else if (num9 < entry.alpha) { entry.alpha = Mathf.Max(num9, entry.alpha - num / num4); } if (!num8 || entry.alpha <= 0.001f) { entry.bar.Hide(); } else { int current2 = HealthSync.GetCurrent(entry.health, entry.viewId); int max = HealthSync.GetMax(entry.health); float num10 = Mathf.Clamp01(num7 / num2); float scale = Mathf.Lerp(1f, num5, num10); entry.bar.Show(ToCanvas(screen), scale, entry.alpha, (max > 0) ? Mathf.Clamp01((float)current2 / (float)max) : 0f, value4, value5, barColor, value6 ? (current2 + " / " + max) : null, num); } } } UpdatePopups(num); } private void Rescan() { EnemyDirector instance = EnemyDirector.instance; if ((Object)(object)instance == (Object)null) { ClearEntries(); return; } HealthSync.NotifyDirector(instance); List<EnemyParent> enemiesSpawned = instance.enemiesSpawned; if (enemiesSpawned == null) { return; } for (int i = 0; i < enemiesSpawned.Count; i++) { EnemyParent val = enemiesSpawned[i]; if (!((Object)(object)val == (Object)null) && FindEntry(val) == null) { AddEntry(val); } } } private Entry FindEntry(EnemyParent parent) { for (int i = 0; i < _entries.Count; i++) { if ((Object)(object)_entries[i].parent == (Object)(object)parent) { return _entries[i]; } } return null; } private Entry FindEntryByHealth(EnemyHealth health) { for (int i = 0; i < _entries.Count; i++) { if ((Object)(object)_entries[i].health == (Object)(object)health) { return _entries[i]; } } return null; } private Entry AddEntry(EnemyParent parent) { if ((Object)(object)parent == (Object)null) { return null; } EnemyHealth componentInChildren = ((Component)parent).GetComponentInChildren<EnemyHealth>(true); if ((Object)(object)componentInChildren == (Object)null) { return null; } Enemy componentInChildren2 = ((Component)parent).GetComponentInChildren<Enemy>(true); PhotonView component = ((Component)componentInChildren).GetComponent<PhotonView>(); Entry entry = new Entry { parent = parent, health = componentInChildren, enemy = componentInChildren2, viewId = (((Object)(object)component != (Object)null) ? component.ViewID : 0), colliders = CollectColliders(((Component)parent).transform), renderers = CollectRenderers(((Component)parent).transform), lastHitTime = float.NegativeInfinity, bar = CreateBar() }; _entries.Add(entry); return entry; } private void RemoveEntry(int index) { Entry entry = _entries[index]; if (entry.bar != null) { entry.bar.Destroy(); } _entries.RemoveAt(index); } private void ClearEntries() { for (int num = _entries.Count - 1; num >= 0; num--) { RemoveEntry(num); } } private void HideAllBars() { for (int i = 0; i < _entries.Count; i++) { _entries[i].bar?.Hide(); } } private static Vector3 GetTopPoint(Entry e) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) return GetTopPoint(((Object)(object)e.enemy != (Object)null && (Object)(object)e.enemy.CenterTransform != (Object)null) ? e.enemy.CenterTransform : ((Component)e.health).transform, e.colliders, e.renderers); } private static Vector3 GetTopPoint(Transform center, Collider[] colliders, Renderer[] renderers) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: 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_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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f3: 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_0105: 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_008f: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) float num = float.NegativeInfinity; float x = center.position.x; float z = center.position.z; Vector3 size; if (colliders != null) { foreach (Collider val in colliders) { if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy) { Bounds bounds = val.bounds; size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude > 2500f) && ((Bounds)(ref bounds)).max.y > num) { num = ((Bounds)(ref bounds)).max.y; x = ((Bounds)(ref bounds)).center.x; z = ((Bounds)(ref bounds)).center.z; } } } } if (float.IsNegativeInfinity(num) && renderers != null) { foreach (Renderer val2 in renderers) { if (!((Object)(object)val2 == (Object)null) && val2.enabled) { Bounds bounds2 = val2.bounds; size = ((Bounds)(ref bounds2)).size; if (!(((Vector3)(ref size)).sqrMagnitude > 2500f) && ((Bounds)(ref bounds2)).max.y > num) { num = ((Bounds)(ref bounds2)).max.y; x = ((Bounds)(ref bounds2)).center.x; z = ((Bounds)(ref bounds2)).center.z; } } } } if (float.IsNegativeInfinity(num)) { num = center.position.y + 1.2f; x = center.position.x; z = center.position.z; } if (num < center.position.y + 0.2f) { num = center.position.y + 0.2f; } return new Vector3(x, num, z); } private static Collider[] CollectColliders(Transform root) { Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true); List<Collider> list = new List<Collider>(componentsInChildren.Length); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && !componentsInChildren[i].isTrigger) { list.Add(componentsInChildren[i]); } } return list.ToArray(); } private static Renderer[] CollectRenderers(Transform root) { Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true); List<Renderer> list = new List<Renderer>(componentsInChildren.Length); for (int i = 0; i < componentsInChildren.Length; i++) { if (componentsInChildren[i] is MeshRenderer || componentsInChildren[i] is SkinnedMeshRenderer) { list.Add(componentsInChildren[i]); } } return list.ToArray(); } private Bar CreateBar() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0078: 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) //IL_00bf: 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_00ca: 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_00d3: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0251: 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_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Bar", new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)_canvasRect, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(110f, 10f); CanvasGroup val4 = val.AddComponent<CanvasGroup>(); val4.interactable = false; val4.blocksRaycasts = false; val4.alpha = 0f; GameObject val5 = new GameObject("Back", new Type[1] { typeof(RectTransform) }); RectTransform val6 = (RectTransform)val5.transform; ((Transform)val6).SetParent((Transform)(object)val2, false); val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.one; val6.offsetMin = new Vector2(-1f, -1f); val6.offsetMax = new Vector2(1f, 1f); Image val7 = val5.AddComponent<Image>(); val7.sprite = _whiteSprite; ((Graphic)val7).color = MonsterHealthBarsPlugin.BarBackColor; ((Graphic)val7).raycastTarget = false; GameObject val8 = new GameObject("Fill", new Type[1] { typeof(RectTransform) }); RectTransform val9 = (RectTransform)val8.transform; ((Transform)val9).SetParent((Transform)(object)val2, false); val9.anchorMin = new Vector2(0f, 0f); val9.anchorMax = new Vector2(0f, 1f); val9.pivot = new Vector2(0f, 0.5f); val9.anchoredPosition = Vector2.zero; val9.sizeDelta = new Vector2(110f, 0f); Image val10 = val8.AddComponent<Image>(); val10.sprite = _whiteSprite; ((Graphic)val10).color = MonsterHealthBarsPlugin.BarColor; ((Graphic)val10).raycastTarget = false; GameObject val11 = new GameObject("Label", new Type[1] { typeof(RectTransform) }); RectTransform val12 = (RectTransform)val11.transform; ((Transform)val12).SetParent((Transform)(object)val2, false); val12.anchorMin = new Vector2(0.5f, 1f); val12.anchorMax = new Vector2(0.5f, 1f); val12.pivot = new Vector2(0.5f, 0f); val12.anchoredPosition = new Vector2(0f, 2f); val12.sizeDelta = new Vector2(160f, 20f); TextMeshProUGUI val13 = CreateText(val11, 14f, (TextAlignmentOptions)514); ((Graphic)val13).color = Color.white; val.SetActive(false); return new Bar { root = val, rect = val2, group = val4, back = val7, fill = val10, fillRect = val9, label = val13 }; } private TextMeshProUGUI CreateText(GameObject go, float size, TextAlignmentOptions align) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>(); TMP_FontAsset val2 = ResolveFont(); if ((Object)(object)val2 != (Object)null) { ((TMP_Text)val).font = val2; } ((TMP_Text)val).fontSize = size; ((TMP_Text)val).alignment = align; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).text = string.Empty; return val; } private TMP_FontAsset ResolveFont() { if ((Object)(object)_font != (Object)null) { return _font; } try { _font = TMP_Settings.defaultFontAsset; } catch (Exception) { } if ((Object)(object)_font == (Object)null) { try { TMP_Text val = Object.FindAnyObjectByType<TMP_Text>(); if ((Object)(object)val != (Object)null) { _font = val.font; } } catch (Exception) { } } if ((Object)(object)_font == (Object)null) { MonsterHealthBarsPlugin.LogWarn("TMP font asset not found - damage numbers may be invisible."); } return _font; } private void UpdatePopups(float dt) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) if (dt <= 0f) { return; } float value = MonsterHealthBarsPlugin.DamageTextSize.Value; Color val = Color.Lerp(MonsterHealthBarsPlugin.BarColor, Color.white, 0.45f); for (int num = _popups.Count - 1; num >= 0; num--) { Popup popup = _popups[num]; if ((Object)(object)popup.go == (Object)null) { _popups.RemoveAt(num); } else if (popup.go.activeSelf) { popup.age += dt; Vector2 screen; float depth; if (popup.age >= popup.life) { popup.go.SetActive(false); } else if (!Project(popup.world, out screen, out depth)) { popup.go.SetActive(false); } else { float num2 = Mathf.Clamp01(popup.age / popup.life); float num3 = 1f - (1f - num2) * (1f - num2); float num4 = (popup.riseCurrent = popup.rise * num3); float num5 = Mathf.Clamp01(popup.age / 0.15f); float num6 = Mathf.Clamp01((popup.life - popup.age) / 0.5f); float num7 = Mathf.Min(num5, num6); float num8 = ((num2 < 0.12f) ? Mathf.Lerp(1.2f, 1f, num2 / 0.12f) : 1f); popup.rect.anchoredPosition = ToCanvas(screen) + popup.screenOffset + new Vector2(0f, num4); ((Transform)popup.rect).localScale = Vector3.one * num8; ((TMP_Text)popup.text).fontSize = value; ((Graphic)popup.text).color = new Color(val.r, val.g, val.b, num7); } } } } private Popup GetPopup() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _popups.Count; i++) { if (!_popups[i].go.activeSelf) { _popups[i].go.SetActive(true); return _popups[i]; } } GameObject val = new GameObject("DamagePopup", new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)_canvasRect, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(300f, 80f); TextMeshProUGUI val4 = CreateText(val, 36f, (TextAlignmentOptions)514); ((TMP_Text)val4).fontStyle = (FontStyles)1; Popup popup = new Popup { go = val, rect = val2, text = val4, life = 2f }; _popups.Add(popup); return popup; } internal static void OnDamage(EnemyHealth health, int amount) { BarsOverlay instance = Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)health == (Object)null)) { instance.MarkHit(health); if (amount > 0) { instance.SpawnDamage(health, amount); } } } private void MarkHit(EnemyHealth health) { Entry entry = FindEntryByHealth(health); if (entry == null) { EnemyParent componentInParent = ((Component)health).GetComponentInParent<EnemyParent>(); if ((Object)(object)componentInParent == (Object)null) { return; } entry = FindEntry(componentInParent) ?? AddEntry(componentInParent); } if (entry != null) { entry.lastHitTime = Time.unscaledTime; } } private void SpawnDamage(EnemyHealth health, int amount) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) if (MonsterHealthBarsPlugin.ShowDamageNumbers.Value && !((Object)(object)_cam == (Object)null) && !((Object)(object)ResolveFont() == (Object)null)) { Vector3 val = GetAnchorFor(health) + Vector3.up * MonsterHealthBarsPlugin.BarYOffset.Value; float num = Mathf.Max(1f, MonsterHealthBarsPlugin.Radius.Value); if (!(Vector3.Distance(GetPlayerPosition(), val) > num) && Project(val, out var _, out var _)) { Popup popup = GetPopup(); float num2 = Mathf.Max(0.2f, MonsterHealthBarsPlugin.DamageTextDuration.Value); float num3 = (float)(_popupCounter++ % 5 - 2) * 30f + Random.Range(-6f, 6f); popup.world = val + new Vector3(Random.Range(-0.1f, 0.1f), 0.1f, Random.Range(-0.1f, 0.1f)); popup.screenOffset = new Vector2(num3, 0f); popup.rise = MonsterHealthBarsPlugin.DamageTextRise.Value * num2; popup.riseCurrent = 0f; popup.age = 0f; popup.life = num2; ((TMP_Text)popup.text).text = amount.ToString(); popup.go.SetActive(true); } } } private Vector3 GetAnchorFor(EnemyHealth health) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Entry entry = FindEntryByHealth(health); if (entry != null) { return GetTopPoint(entry); } EnemyParent componentInParent = ((Component)health).GetComponentInParent<EnemyParent>(); if ((Object)(object)componentInParent != (Object)null) { Enemy componentInChildren = ((Component)componentInParent).GetComponentInChildren<Enemy>(true); return GetTopPoint(((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.CenterTransform != (Object)null) ? componentInChildren.CenterTransform : ((Component)health).transform, CollectColliders(((Component)componentInParent).transform), null); } return ((Component)health).transform.position + Vector3.up * 1.5f; } private Vector3 GetPlayerPosition() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) PlayerController instance = PlayerController.instance; if ((Object)(object)instance != (Object)null) { PlayerAvatar playerAvatarScript = instance.playerAvatarScript; if ((Object)(object)playerAvatarScript != (Object)null && (Object)(object)playerAvatarScript.playerTransform != (Object)null) { return playerAvatarScript.playerTransform.position; } if ((Object)(object)((Component)instance).transform != (Object)null) { return ((Component)instance).transform.position; } } if (!((Object)(object)_cam != (Object)null)) { return Vector3.zero; } return ((Component)_cam).transform.position; } private bool Project(Vector3 world, out Vector2 screen, out float depth) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0050: 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_0062: Unknown result type (might be due to invalid IL or missing references) screen = default(Vector2); depth = 0f; if ((Object)(object)_cam == (Object)null) { return false; } Vector3 val = _cam.WorldToViewportPoint(world); depth = val.z; if (val.z <= 0f) { return false; } screen = new Vector2(val.x * (float)Screen.width, val.y * (float)Screen.height); return true; } private static Vector2 ToCanvas(Vector2 screen) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) return new Vector2(screen.x - (float)Screen.width * 0.5f, screen.y - (float)Screen.height * 0.5f); } private bool HasLineOfSight(Vector3 target, Transform root) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) if ((Object)(object)_cam == (Object)null) { return true; } Vector3 position = ((Component)_cam).transform.position; Vector3 val = target - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.01f) { return true; } RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(position, val / magnitude, ref val2, magnitude - 0.3f, -1, (QueryTriggerInteraction)1)) { return true; } if ((Object)(object)((RaycastHit)(ref val2)).transform != (Object)null) { return ((RaycastHit)(ref val2)).transform.IsChildOf(root); } return false; } } internal static class HealthSync { internal const byte EventCode = 173; private static readonly Dictionary<int, int> NetHealth = new Dictionary<int, int>(); private static bool _subscribed; private static FieldRef<EnemyHealth, int> _healthCurrentRef; private static FieldRef<EnemyHealth, bool> _deadRef; private static FieldInfo _healthCurrentField; private static FieldInfo _deadField; private static EnemyDirector _lastDirector; internal static void Initialize() { try { _healthCurrentRef = AccessTools.FieldRefAccess<EnemyHealth, int>("healthCurrent"); } catch (Exception) { _healthCurrentField = AccessTools.Field(typeof(EnemyHealth), "healthCurrent"); } try { _deadRef = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead"); } catch (Exception) { _deadField = AccessTools.Field(typeof(EnemyHealth), "dead"); } if (_healthCurrentRef == null && _healthCurrentField == null) { MonsterHealthBarsPlugin.LogError("EnemyHealth.healthCurrent not found - HP will not be readable. Game version changed?"); } TrySubscribe(); } internal static void Shutdown() { TryUnsubscribe(); } internal static void TrySubscribe() { if (_subscribed) { return; } try { if (PhotonNetwork.NetworkingClient != null) { PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent; PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent; _subscribed = true; } } catch (Exception ex) { MonsterHealthBarsPlugin.LogDebug("Photon subscribe failed: " + ex.Message); } } internal static void TryUnsubscribe() { if (!_subscribed) { return; } try { if (PhotonNetwork.NetworkingClient != null) { PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent; } } catch (Exception) { } _subscribed = false; } private static void OnPhotonEvent(EventData e) { if (e.Code == 173 && e.CustomData is object[] array && array.Length >= 2 && array[0] is int key && array[1] is int value) { NetHealth[key] = value; } } internal static bool IsMaster() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch (Exception) { try { return !GameManager.Multiplayer(); } catch (Exception) { return true; } } } internal static bool IsMultiplayer() { try { return SemiFunc.IsMultiplayer(); } catch (Exception) { try { return GameManager.Multiplayer(); } catch (Exception) { return false; } } } internal static void NotifyDirector(EnemyDirector director) { if (!((Object)(object)director == (Object)(object)_lastDirector)) { _lastDirector = director; NetHealth.Clear(); } } internal static int GetMax(EnemyHealth health) { if (!((Object)(object)health == (Object)null)) { return health.health; } return 0; } internal static bool IsDead(EnemyHealth health) { if ((Object)(object)health == (Object)null) { return true; } try { if (_deadRef != null) { return _deadRef.Invoke(health); } if (_deadField != null) { return (bool)_deadField.GetValue(health); } } catch (Exception) { } return false; } internal static int GetCurrent(EnemyHealth health, int viewId) { if ((Object)(object)health == (Object)null) { return 0; } if (IsMaster()) { try { if (_healthCurrentRef != null) { return _healthCurrentRef.Invoke(health); } if (_healthCurrentField != null) { return (int)_healthCurrentField.GetValue(health); } } catch (Exception) { } return health.health; } if (viewId != 0 && NetHealth.TryGetValue(viewId, out var value)) { return value; } return health.health; } internal static void Send(int viewId, int hp) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0045: 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_0059: Expected O, but got Unknown if (!MonsterHealthBarsPlugin.SyncEnabled.Value || viewId == 0) { return; } try { if (PhotonNetwork.InRoom) { object[] obj = new object[2] { viewId, hp }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; PhotonNetwork.RaiseEvent((byte)173, (object)obj, val, val2); } } catch (Exception ex) { MonsterHealthBarsPlugin.LogDebug("RaiseEvent failed: " + ex.Message); } } internal static bool ShouldSend(ref int lastSent, ref float lastTime, int hp, float interval) { if (hp != lastSent || Time.unscaledTime - lastTime >= interval) { lastSent = hp; lastTime = Time.unscaledTime; return true; } return false; } } [HarmonyPatch(typeof(EnemyHealth), "Hurt", new Type[] { typeof(int), typeof(Vector3) })] internal static class EnemyHealthHurtPatch { private static void Prefix(EnemyHealth __instance, out int __state) { __state = HealthSync.GetCurrent(__instance, 0); } private static void Postfix(EnemyHealth __instance, int __state) { if (HealthSync.IsMaster()) { int current = HealthSync.GetCurrent(__instance, 0); int num = __state - current; if (num > 0) { BarsOverlay.OnDamage(__instance, num); } } } } [HarmonyPatch(typeof(EnemyHealth), "HurtRPC", new Type[] { typeof(int), typeof(Vector3), typeof(PhotonMessageInfo) })] internal static class EnemyHealthHurtRpcPatch { private static void Postfix(EnemyHealth __instance, int _damage) { if (!HealthSync.IsMaster()) { BarsOverlay.OnDamage(__instance, _damage); } } } [BepInPlugin("RuboMods.MonsterHealthBars", "MonsterHealthBars", "1.0.0")] public class MonsterHealthBarsPlugin : BaseUnityPlugin { public const string Guid = "RuboMods.MonsterHealthBars"; public const string Version = "1.0.0"; internal static ConfigEntry<float> Radius; internal static ConfigEntry<string> BarColorEntry; internal static ConfigEntry<float> BarWidth; internal static ConfigEntry<float> BarHeight; internal static ConfigEntry<float> BarYOffset; internal static ConfigEntry<float> MinDistanceScale; internal static ConfigEntry<bool> ShowBars; internal static ConfigEntry<bool> AlwaysShow; internal static ConfigEntry<float> HideDelay; internal static ConfigEntry<float> FadeOutDuration; internal static ConfigEntry<bool> ShowHpText; internal static ConfigEntry<bool> RequireLineOfSight; internal static ConfigEntry<bool> ShowDamageNumbers; internal static ConfigEntry<float> DamageTextSize; internal static ConfigEntry<float> DamageTextDuration; internal static ConfigEntry<float> DamageTextRise; internal static ConfigEntry<bool> SyncEnabled; internal static ConfigEntry<float> SyncInterval; internal static Color BarColor = new Color(1f, 0.16f, 0.16f, 1f); internal static readonly Color BarBackColor = new Color(0f, 0f, 0f, 0.65f); internal static MonsterHealthBarsPlugin Instance { get; private set; } internal static void Log(string message) { MonsterHealthBarsPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)message); } } internal static void LogWarn(string message) { MonsterHealthBarsPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)message); } } internal static void LogError(string message) { MonsterHealthBarsPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)message); } } internal static void LogDebug(string message) { MonsterHealthBarsPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogDebug((object)message); } } private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Expected O, but got Unknown //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Expected O, but got Unknown //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Expected O, but got Unknown //IL_03ff: Unknown result type (might be due to invalid IL or missing references) Instance = this; Radius = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "Radius", 20f, new ConfigDescription("Радиус (в метрах) вокруг игрока, в котором видны полоски HP и цифры урона.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), Array.Empty<object>())); ShowBars = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "ShowHealthBars", true, "Показывать полоски HP над монстрами."); AlwaysShow = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "AlwaysShow", false, "true — полоски видны всегда; false — только после урона, затем гаснут через HideDelay."); HideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "HideDelay", 4f, new ConfigDescription("Сколько секунд полоска остаётся после последнего удара (если AlwaysShow = false).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); FadeOutDuration = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "FadeOutDuration", 0.5f, new ConfigDescription("За сколько секунд полоска плавно исчезает.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 3f), Array.Empty<object>())); BarColorEntry = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "BarColor", "#FF2A2A", "Цвет полоски HP. Формат: #RRGGBB, #RRGGBBAA или \"R,G,B\" (0-255)."); BarWidth = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarWidth", 110f, new ConfigDescription("Ширина полоски в пикселях (при масштабе 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 600f), Array.Empty<object>())); BarHeight = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarHeight", 10f, new ConfigDescription("Толщина полоски в пикселях.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>())); BarYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarYOffset", 0.25f, new ConfigDescription("Дополнительный подъём полоски над верхней точкой модели монстра (метры).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 5f), Array.Empty<object>())); MinDistanceScale = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "MinDistanceScale", 0.65f, new ConfigDescription("Во сколько раз уменьшается полоска на краю радиуса (1 = размер не зависит от расстояния).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); ShowHpText = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "ShowHpText", false, "Показывать рядом с полоской текст \"текущее/максимум\"."); RequireLineOfSight = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "RequireLineOfSight", false, "Скрывать полоску, если монстр за стеной (дороже по производительности)."); ShowDamageNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("2. DamageNumbers", "Enabled", true, "Показывать всплывающие цифры урона рядом с монстром."); DamageTextSize = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "TextSize", 36f, new ConfigDescription("Размер цифр урона в пикселях (при масштабе 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 200f), Array.Empty<object>())); DamageTextDuration = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "Duration", 2f, new ConfigDescription("Сколько секунд цифра висит и растворяется.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>())); DamageTextRise = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "RiseSpeed", 20f, new ConfigDescription("Скорость подъёма цифры (пикселей в секунду, с замедлением к концу).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); SyncEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3. Multiplayer", "SyncHealth", true, "Хост рассылает клиентам текущее HP монстров (Photon event). Без этого клиенты видели бы только максимум."); SyncInterval = ((BaseUnityPlugin)this).Config.Bind<float>("3. Multiplayer", "HeartbeatInterval", 1f, new ConfigDescription("Как часто хост дополнительно рассылает HP (сек) даже без урона.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>())); BarColor = ParseColor(BarColorEntry.Value, new Color(1f, 0.16f, 0.16f, 1f)); BarColorEntry.SettingChanged += delegate { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) BarColor = ParseColor(BarColorEntry.Value, Color.red); }; GameObject val = new GameObject("MonsterHealthBars_Overlay"); Object.DontDestroyOnLoad((Object)val); val.AddComponent<BarsOverlay>(); HealthSync.Initialize(); try { new Harmony("RuboMods.MonsterHealthBars").PatchAll(typeof(MonsterHealthBarsPlugin).Assembly); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Harmony patch failed: " + ex)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("MonsterHealthBars v1.0.0 loaded. Radius=" + Radius.Value + "m, color=" + BarColorEntry.Value)); } private void OnDestroy() { HealthSync.Shutdown(); } internal static Color ParseColor(string value, Color fallback) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(value)) { return fallback; } value = value.Trim(); Color result = default(Color); if (value.StartsWith("#") && ColorUtility.TryParseHtmlString(value, ref result)) { return result; } string[] array = value.Split(','); if (array.Length >= 3 && float.TryParse(array[0], out var result2) && float.TryParse(array[1], out var result3) && float.TryParse(array[2], out var result4)) { float result5 = 255f; if (array.Length >= 4) { float.TryParse(array[3], out result5); } return new Color(Mathf.Clamp01(result2 / 255f), Mathf.Clamp01(result3 / 255f), Mathf.Clamp01(result4 / 255f), Mathf.Clamp01((result5 <= 1f) ? result5 : (result5 / 255f))); } Color result6 = default(Color); if (ColorUtility.TryParseHtmlString(value, ref result6)) { return result6; } return fallback; } } }