using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Auuueser.EnemyHealthBars.Configuration; using Auuueser.EnemyHealthBars.Core.Configuration; using Auuueser.EnemyHealthBars.Core.Domain; using Auuueser.EnemyHealthBars.Core.GameData; using Auuueser.EnemyHealthBars.Core.Presentation; using Auuueser.EnemyHealthBars.Game; using Auuueser.EnemyHealthBars.Presentation; using Auuueser.EnemyHealthBars.Runtime; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; 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("EnemyHealthBar")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+acb061bd561295755ea67507eed9dd688145cd1f")] [assembly: AssemblyProduct("EnemyHealthBar")] [assembly: AssemblyTitle("EnemyHealthBar")] [assembly: AssemblyVersion("1.0.0.0")] 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; } } } namespace Auuueser.EnemyHealthBars { [BepInPlugin("auuueser.lethalcompany.enemyhealthbar", "Enemy Health Bar", "0.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("Lethal Company.exe")] public sealed class Plugin : BaseUnityPlugin { private HealthBarRuntime? runtime; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; ConfigLanguage language = ChineseProjectLanguageDetector.Detect(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); ModConfig config = ModConfig.Bind(((BaseUnityPlugin)this).Config, language); if (LethalConfigIntegration.IsAvailable()) { LethalConfigIntegration.Register(config, ((BaseUnityPlugin)this).Logger); } runtime = HealthBarRuntime.Start(config, ((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Enemy Health Bar 0.0.1 loaded."); } private void OnDestroy() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin component destroyed; runtime remains active."); } } internal static class PluginInfo { public const string PluginGuid = "auuueser.lethalcompany.enemyhealthbar"; public const string PluginName = "Enemy Health Bar"; public const string PluginVersion = "0.0.1"; } } namespace Auuueser.EnemyHealthBars.Runtime { internal sealed class EnemyHealthBarController : MonoBehaviour { private struct DiagnosticScanCounts { public static readonly DiagnosticScanCounts Empty; public int Spawned; public int Readable; public int Shown; public int Active; public int RejectedMissingEnemy; public int RejectedMissingEnemyType; public int RejectedCannotDie; public int HiddenDead; public int HiddenZeroHealth; public int HiddenFull; public int HiddenDistance; } private readonly EnemyHealthTracker tracker = new EnemyHealthTracker(); private readonly EnemyHealthReader healthReader = new EnemyHealthReader(); private readonly EnemyMaxHealthResolver maxHealthResolver = new EnemyMaxHealthResolver(); private readonly HashSet activeEnemyIds = new HashSet(); private ModConfig? config; private ManualLogSource? logger; private RoundManagerEnemySource? enemySource; private LocalPlayerCameraProvider? cameraProvider; private EnemyHealthBarPresenter? presenter; private float nextScanTime; private float nextDiagnosticLogTime; private float nextDebugHeartbeatLogTime; private int observedSettingsVersion; public void Initialize(ModConfig config, ManualLogSource logger, RoundManagerEnemySource enemySource, LocalPlayerCameraProvider cameraProvider, EnemyHealthBarPresenter presenter) { this.config = config; this.logger = logger; this.enemySource = enemySource; this.cameraProvider = cameraProvider; this.presenter = presenter; observedSettingsVersion = config.SettingsVersion; } public void SetEnabled(bool enabled) { ((Behaviour)this).enabled = enabled; ((Component)this).gameObject.SetActive(enabled); } private void Update() { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (config == null || enemySource == null || cameraProvider == null || presenter == null) { return; } config.ReloadIfChangedOnDisk(Time.unscaledTime); if (observedSettingsVersion != config.SettingsVersion) { observedSettingsVersion = config.SettingsVersion; presenter.RefreshStyle(); } if (!config.Enabled) { presenter.Clear(); LogDiagnosticsIfDue(DiagnosticScanCounts.Empty, null, "Disabled"); LogDebugHeartbeatIfDue(null); return; } Camera activeCamera = cameraProvider.GetActiveCamera(); if ((Object)(object)activeCamera == (Object)null) { presenter.Clear(); LogDiagnosticsIfDue(DiagnosticScanCounts.Empty, null, "No active camera"); LogDebugHeartbeatIfDue(null); return; } Quaternion billboardRotation = HealthBarBillboard.CalculateRotation(activeCamera); UpdateDebugTestBar(activeCamera, billboardRotation); LogDebugHeartbeatIfDue(activeCamera); bool flag = false; if (Time.unscaledTime >= nextScanTime) { nextScanTime = Time.unscaledTime + config.ScanInterval; RefreshEnemies(activeCamera, billboardRotation); flag = true; } if (!flag) { presenter.UpdateActive(activeCamera, billboardRotation); } } private void OnDestroy() { presenter?.Clear(); } private void RefreshEnemies(Camera camera, Quaternion billboardRotation) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) if (config == null || enemySource == null || presenter == null) { return; } activeEnemyIds.Clear(); HealthBarVisibilityRules val = config.CreateVisibilityRules(); Vector3 position = ((Component)camera).transform.position; List spawnedEnemies = enemySource.GetSpawnedEnemies(); if (spawnedEnemies == null) { tracker.KeepOnly((ISet)activeEnemyIds); presenter.HideMissing(activeEnemyIds); LogDiagnosticsIfDue(DiagnosticScanCounts.Empty, camera, "SpawnedEnemies unavailable"); return; } DiagnosticScanCounts diagnosticScanCounts = default(DiagnosticScanCounts); diagnosticScanCounts.Spawned = spawnedEnemies.Count; DiagnosticScanCounts counts = diagnosticScanCounts; for (int i = 0; i < spawnedEnemies.Count; i++) { EnemyAI val2 = spawnedEnemies[i]; if ((Object)(object)val2 == (Object)null) { counts.RejectedMissingEnemy++; continue; } if (!healthReader.TryRead(val2, config.ShowInvulnerableEnemies, maxHealthResolver, out var sample, out var failure)) { AddReadFailure(ref counts, failure); continue; } counts.Readable++; activeEnemyIds.Add(((EnemyHealthSample)(ref sample)).EnemyId); EnemyHealthSnapshot val3 = tracker.Track(sample, config.MaxHealthMode); if (((EnemyHealthSnapshot)(ref val3)).IsDead) { counts.HiddenDead++; presenter.Hide(((EnemyHealthSample)(ref sample)).EnemyId); continue; } if (((EnemyHealthSnapshot)(ref val3)).CurrentHealth <= 0 || ((EnemyHealthSnapshot)(ref val3)).MaxHealth <= 0) { counts.HiddenZeroHealth++; presenter.Hide(((EnemyHealthSample)(ref sample)).EnemyId); continue; } if (!config.ShowFullHealthEnemies && ((EnemyHealthSnapshot)(ref val3)).IsFullHealth) { counts.HiddenFull++; presenter.Hide(((EnemyHealthSample)(ref sample)).EnemyId); continue; } Vector3 worldPosition = presenter.GetWorldPosition(val2); Vector3 val4 = position - worldPosition; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (!((HealthBarVisibilityRules)(ref val)).ShouldShowBySquaredDistance(val3, sqrMagnitude)) { counts.HiddenDistance++; presenter.Hide(((EnemyHealthSample)(ref sample)).EnemyId); } else { counts.Shown++; presenter.ShowOrUpdate(val2, val3, worldPosition, camera, billboardRotation); } } tracker.KeepOnly((ISet)activeEnemyIds); presenter.HideMissing(activeEnemyIds); counts.Active = presenter.ActiveCount; LogDiagnosticsIfDue(counts, camera, "scan"); } private void LogDiagnosticsIfDue(DiagnosticScanCounts counts, Camera? camera, string source) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (config != null && logger != null && config.DiagnosticsEnabled && !(Time.unscaledTime < nextDiagnosticLogTime)) { nextDiagnosticLogTime = Time.unscaledTime + config.DiagnosticsLogInterval; string text = (((Object)(object)camera != (Object)null) ? $"{((Object)camera).name}@{FormatVector(((Component)camera).transform.position)} mask={camera.cullingMask}" : "none"); string arg = maxHealthResolver.FormatUnresolvedNamesForDiagnostics(5); logger.LogInfo((object)($"Diagnostics {source}: camera={text}, spawned={counts.Spawned}, readable={counts.Readable}, shown={counts.Shown}, active={counts.Active}, " + $"rejectedNull={counts.RejectedMissingEnemy}, rejectedNoType={counts.RejectedMissingEnemyType}, rejectedCannotDie={counts.RejectedCannotDie}, " + $"hiddenDead={counts.HiddenDead}, hiddenZeroHp={counts.HiddenZeroHealth}, hiddenFull={counts.HiddenFull}, hiddenDistance={counts.HiddenDistance}, " + $"unresolvedMaxHealth={maxHealthResolver.UnresolvedCount}, unresolvedNames={arg}")); } } private void UpdateDebugTestBar(Camera camera, Quaternion billboardRotation) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (config != null && presenter != null) { if (config.DebugShowTestBar) { presenter.ShowDebugTestBar(camera, billboardRotation); } else { presenter.HideDebugTestBar(); } } } private void LogDebugHeartbeatIfDue(Camera? camera) { if (config != null && logger != null && presenter != null && config.DiagnosticsEnabled && !(Time.unscaledTime < nextDebugHeartbeatLogTime)) { nextDebugHeartbeatLogTime = Time.unscaledTime + config.DiagnosticsLogInterval; string text = (((Object)(object)camera != (Object)null) ? ((Object)camera).name : "none"); logger.LogInfo((object)$"Debug heartbeat: enabled={config.Enabled}, camera='{text}', active={presenter.ActiveCount}, testBar={presenter.DebugTestBarVisible}"); } } private static void AddReadFailure(ref DiagnosticScanCounts counts, EnemyHealthReadFailure failure) { switch (failure) { case EnemyHealthReadFailure.MissingEnemy: counts.RejectedMissingEnemy++; break; case EnemyHealthReadFailure.MissingEnemyType: counts.RejectedMissingEnemyType++; break; case EnemyHealthReadFailure.CannotDie: counts.RejectedCannotDie++; break; } } private static string FormatVector(Vector3 value) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"({value.x:0.0},{value.y:0.0},{value.z:0.0})"; } } internal sealed class HealthBarRuntime : IDisposable { private static GameObject? runtimeObject; private static EnemyHealthBarController? runtimeController; private readonly GameObject host; private HealthBarRuntime(GameObject host) { this.host = host; } public static HealthBarRuntime Start(ModConfig config, ManualLogSource logger) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)runtimeObject == (Object)null) { runtimeObject = new GameObject("EnemyHealthBars.Runtime"); ((Object)runtimeObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)runtimeObject); } else if (!runtimeObject.activeSelf) { runtimeObject.SetActive(true); } GameObject val = runtimeObject; runtimeController = val.GetComponent(); if ((Object)(object)runtimeController == (Object)null) { EnemyHealthBarPresenter presenter = new EnemyHealthBarPresenter(config, val.transform); runtimeController = val.AddComponent(); runtimeController.Initialize(config, logger, new RoundManagerEnemySource(), new LocalPlayerCameraProvider(), presenter); logger.LogInfo((object)"Runtime controller active."); } else { runtimeController.SetEnabled(enabled: true); logger.LogInfo((object)"Runtime controller active."); } return new HealthBarRuntime(val); } public void Dispose() { if ((Object)(object)host != (Object)null) { Object.Destroy((Object)(object)host); } } } } namespace Auuueser.EnemyHealthBars.Presentation { internal sealed class EnemyHealthBarPresenter { private sealed class ActiveHealthBar { public EnemyAI Enemy { get; set; } public EnemyHealthSnapshot Snapshot { get; set; } public HealthBarView View { get; } public ActiveHealthBar(EnemyAI enemy, HealthBarView view) { Enemy = enemy; View = view; } } private readonly ModConfig config; private readonly HealthBarPool pool; private readonly HealthBarTargetResolver targetResolver = new HealthBarTargetResolver(); private readonly Dictionary activeBars = new Dictionary(); private readonly List removeBuffer = new List(); private HealthBarView? debugTestBar; public int ActiveCount => activeBars.Count; public bool DebugTestBarVisible => debugTestBar != null; public EnemyHealthBarPresenter(ModConfig config, Transform parent) { this.config = config; pool = new HealthBarPool(config, parent); } public void ShowOrUpdate(EnemyAI enemy, EnemyHealthSnapshot snapshot, Vector3 worldPosition, Camera camera, Quaternion billboardRotation) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!activeBars.TryGetValue(((EnemyHealthSnapshot)(ref snapshot)).EnemyId, out ActiveHealthBar value)) { value = new ActiveHealthBar(enemy, pool.Get()); activeBars.Add(((EnemyHealthSnapshot)(ref snapshot)).EnemyId, value); } value.Enemy = enemy; value.Snapshot = snapshot; value.View.SetHealth(snapshot); value.View.SetWorldPosition(worldPosition, camera, billboardRotation); value.View.SetVisible(visible: true); } public void Hide(int enemyId) { if (activeBars.TryGetValue(enemyId, out ActiveHealthBar value)) { activeBars.Remove(enemyId); pool.Release(value.View); } } public void HideMissing(ISet activeEnemyIds) { removeBuffer.Clear(); foreach (KeyValuePair activeBar in activeBars) { if (!activeEnemyIds.Contains(activeBar.Key)) { removeBuffer.Add(activeBar.Key); } } foreach (int item in removeBuffer) { Hide(item); } } public void RefreshStyle() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) HealthBarStyle style = HealthBarStyle.FromConfig(config); pool.RefreshStyle(style); debugTestBar?.ApplyStyle(style); foreach (KeyValuePair activeBar in activeBars) { activeBar.Value.View.ApplyStyle(style); activeBar.Value.View.SetHealth(activeBar.Value.Snapshot); } } public void ShowDebugTestBar(Camera camera, Quaternion billboardRotation) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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) if (debugTestBar == null) { debugTestBar = pool.Get(); debugTestBar.SetVisible(visible: true); } Vector3 worldPosition = ((Component)camera).transform.position + ((Component)camera).transform.forward * 2.25f - ((Component)camera).transform.up * 0.35f; debugTestBar.SetVisible(visible: true); debugTestBar.SetHealth(new EnemyHealthSnapshot(-1, "Test enemy", 13, 20, false)); debugTestBar.SetWorldPosition(worldPosition, camera, billboardRotation); } public void HideDebugTestBar() { if (debugTestBar != null) { pool.Release(debugTestBar); debugTestBar = null; } } public void UpdateActive(Camera camera, Quaternion billboardRotation) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) removeBuffer.Clear(); foreach (KeyValuePair activeBar in activeBars) { ActiveHealthBar value = activeBar.Value; if ((Object)(object)value.Enemy == (Object)null) { removeBuffer.Add(activeBar.Key); continue; } Vector3 worldPosition = targetResolver.GetWorldPosition(value.Enemy, config.VerticalOffset, config.DisplayMode); value.View.SetWorldPosition(worldPosition, camera, billboardRotation); } foreach (int item in removeBuffer) { Hide(item); } } public void Clear() { HideDebugTestBar(); removeBuffer.Clear(); foreach (int key in activeBars.Keys) { removeBuffer.Add(key); } foreach (int item in removeBuffer) { Hide(item); } } public Vector3 GetWorldPosition(EnemyAI enemy) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) return targetResolver.GetWorldPosition(enemy, config.VerticalOffset, config.DisplayMode); } } internal sealed class HealthBarBillboard : MonoBehaviour { public void SetCamera(Camera? camera) { } public void ApplyRotation(Quaternion rotation) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.rotation = rotation; } public static Quaternion CalculateRotation(Camera camera) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)camera).transform; Vector3 forward = transform.forward; Vector3 up = transform.up; if (forward == Vector3.zero || up == Vector3.zero) { return Quaternion.identity; } return Quaternion.LookRotation(forward, up); } } internal sealed class HealthBarPool { private readonly ModConfig config; private readonly Transform parent; private readonly Stack pooledViews = new Stack(); private HealthBarStyle currentStyle; public HealthBarPool(ModConfig config, Transform parent) { this.config = config; this.parent = parent; currentStyle = HealthBarStyle.FromConfig(config); } public HealthBarView Get() { if (pooledViews.Count > 0) { HealthBarView healthBarView = pooledViews.Pop(); healthBarView.ApplyStyle(currentStyle); return healthBarView; } return HealthBarView.Create(parent, currentStyle); } public void Release(HealthBarView view) { view.SetVisible(visible: false); pooledViews.Push(view); } public void RefreshStyle(HealthBarStyle style) { currentStyle = style; foreach (HealthBarView pooledView in pooledViews) { pooledView.ApplyStyle(style); } } } internal sealed class HealthBarStyle { private const float PixelUnitScale = 140f; private const float WorldScaleMultiplier = 0.012f; public float Width { get; } public float Height { get; } public float WorldScale { get; } public HealthBarDisplayMode DisplayMode { get; } public bool ShowHealthNumbers { get; } public HealthTextFormat HealthTextFormat { get; } public bool ShowEnemyName { get; } public float SideBarWidth { get; } public float SideBarHeight { get; } public float SideBarHorizontalOffset { get; } public Color BackgroundColor { get; } = new Color(0.02f, 0.02f, 0.02f, 0.78f); public Color FillColor { get; } = new Color(0.78f, 0.08f, 0.07f, 0.92f); public Color BorderColor { get; } = new Color(0f, 0f, 0f, 0.95f); public Color TextColor { get; } = new Color(0.96f, 0.96f, 0.96f, 1f); private HealthBarStyle(float width, float height, float worldScale, HealthBarDisplayMode displayMode, bool showHealthNumbers, HealthTextFormat healthTextFormat, bool showEnemyName, float sideBarWidth, float sideBarHeight, float sideBarHorizontalOffset) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a8: 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) Width = width; Height = height; WorldScale = worldScale; DisplayMode = displayMode; ShowHealthNumbers = showHealthNumbers; HealthTextFormat = healthTextFormat; ShowEnemyName = showEnemyName; SideBarWidth = sideBarWidth; SideBarHeight = sideBarHeight; SideBarHorizontalOffset = sideBarHorizontalOffset; } public static HealthBarStyle FromConfig(ModConfig config) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) return new HealthBarStyle(config.BarWidth * 140f, config.BarHeight * 140f, config.WorldScale * 0.012f, config.DisplayMode, config.ShowHealthNumbers, config.HealthTextFormat, config.ShowEnemyName, config.SideBarWidth * 140f, config.SideBarHeight * 140f, config.SideBarHorizontalOffset * 140f); } } internal sealed class HealthBarTargetResolver { public Vector3 GetWorldPosition(EnemyAI enemy, float verticalOffset, HealthBarDisplayMode displayMode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if ((int)displayMode == 1) { return GetVerticalSideWorldPosition(enemy, verticalOffset); } if (TryGetMaskedStableAnchor(enemy, out var anchor)) { return anchor + Vector3.up * verticalOffset; } if (TryGetRendererBounds(enemy, out var bounds)) { float num = (((Object)(object)enemy.eye != (Object)null) ? Mathf.Max(enemy.eye.position.y, ((Bounds)(ref bounds)).max.y) : ((Bounds)(ref bounds)).max.y); return new Vector3(((Bounds)(ref bounds)).center.x, num + verticalOffset, ((Bounds)(ref bounds)).center.z); } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position + Vector3.up * verticalOffset; } return ((Component)enemy).transform.position + Vector3.up * (1.5f + verticalOffset); } private static Vector3 GetVerticalSideWorldPosition(EnemyAI enemy, float verticalOffset) { //IL_0012: 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_001f: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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) float num = verticalOffset * 0.25f; if (TryGetMaskedStableAnchor(enemy, out var anchor)) { return anchor + Vector3.up * (num - 0.35f); } if (TryGetRendererBounds(enemy, out var bounds)) { return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y + num, ((Bounds)(ref bounds)).center.z); } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position + Vector3.up * (num - 0.35f); } return ((Component)enemy).transform.position + Vector3.up * (1f + num); } private static bool TryGetMaskedStableAnchor(EnemyAI enemy, out Vector3 anchor) { //IL_0001: 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) anchor = default(Vector3); if (!(enemy is MaskedPlayerEnemy)) { return false; } Transform radarHeadTransform = enemy.GetRadarHeadTransform(); if ((Object)(object)radarHeadTransform == (Object)null) { return false; } anchor = radarHeadTransform.position; return true; } private static bool TryGetRendererBounds(EnemyAI enemy, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; if (enemy.skinnedMeshRenderers != null) { SkinnedMeshRenderer[] skinnedMeshRenderers = enemy.skinnedMeshRenderers; for (int i = 0; i < skinnedMeshRenderers.Length; i++) { flag = EncapsulateRendererBounds((Renderer?)(object)skinnedMeshRenderers[i], ref bounds, flag); } } if (enemy.meshRenderers != null) { MeshRenderer[] meshRenderers = enemy.meshRenderers; for (int i = 0; i < meshRenderers.Length; i++) { flag = EncapsulateRendererBounds((Renderer?)(object)meshRenderers[i], ref bounds, flag); } } return flag; } private static bool EncapsulateRendererBounds(Renderer? renderer, ref Bounds bounds, bool hasBounds) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return hasBounds; } if (!hasBounds) { bounds = renderer.bounds; return true; } ((Bounds)(ref bounds)).Encapsulate(renderer.bounds); return true; } } internal sealed class HealthBarView { private const float FillPadding = 1f; private const float SideTextPadding = 6f; private const float TextFontSize = 18f; private static TMP_FontAsset? resolvedTextFont; private static bool textFontResolved; private readonly GameObject gameObject; private readonly RectTransform root; private readonly Image backgroundImage; private readonly Image fillImage; private readonly Outline border; private readonly RectTransform backgroundRect; private readonly RectTransform fillRect; private readonly TextMeshProUGUI healthText; private readonly RectTransform textRect; private readonly Canvas worldCanvas; private readonly HealthBarBillboard billboard; private Camera? lastAppliedCanvasCamera; private HealthBarStyle currentStyle; private int lastTextCurrentHealth = int.MinValue; private int lastTextMaxHealth = int.MinValue; private HealthTextFormat lastTextFormat = (HealthTextFormat)(-1); private HealthBarDisplayMode lastDisplayMode = (HealthBarDisplayMode)(-1); private HealthBarDisplayMode lastFillDisplayMode = (HealthBarDisplayMode)(-1); private float lastFillFraction = -1f; private bool lastShowEnemyName; private string? lastDisplayName; private HealthBarView(GameObject gameObject, RectTransform root, Image backgroundImage, Image fillImage, Outline border, RectTransform backgroundRect, RectTransform fillRect, TextMeshProUGUI healthText, RectTransform textRect, Canvas worldCanvas, HealthBarBillboard billboard, HealthBarStyle style) { //IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references) this.gameObject = gameObject; this.root = root; this.backgroundImage = backgroundImage; this.fillImage = fillImage; this.border = border; this.backgroundRect = backgroundRect; this.fillRect = fillRect; this.healthText = healthText; this.textRect = textRect; this.worldCanvas = worldCanvas; this.billboard = billboard; currentStyle = style; } public static HealthBarView Create(Transform parent, HealthBarStyle style) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_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_007f: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00d2: Expected O, but got Unknown GameObject val = new GameObject("EnemyHealthBar"); val.transform.SetParent(parent, false); HealthBarBillboard healthBarBillboard = val.AddComponent(); RectTransform parent2 = val.AddComponent(); Canvas val2 = val.AddComponent(); val2.renderMode = (RenderMode)2; val2.overrideSorting = true; val2.sortingOrder = 500; val.AddComponent(); Image val3 = CreateImage("Background", (Transform)(object)parent2, style.BackgroundColor); RectTransform component = ((Component)val3).GetComponent(); Outline val4 = ((Component)val3).gameObject.AddComponent(); Image val5 = CreateImage("Fill", ((Component)val3).transform, style.FillColor); RectTransform component2 = ((Component)val5).GetComponent(); TextMeshProUGUI val6 = CreateHealthText((Transform)(object)parent2, style.TextColor); RectTransform component3 = ((Component)val6).GetComponent(); SetLayerRecursively(val, ((Component)parent).gameObject.layer); HealthBarView healthBarView = new HealthBarView(val, parent2, val3, val5, val4, component, component2, val6, component3, val2, healthBarBillboard, style); healthBarView.ApplyStyle(style); healthBarView.SetVisible(visible: false); return healthBarView; } public void ApplyStyle(HealthBarStyle style) { //IL_000d: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0065: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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: Invalid comparison between Unknown and I4 //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Invalid comparison between Unknown and I4 currentStyle = style; ((Transform)root).localScale = Vector3.one * style.WorldScale; ((Graphic)backgroundImage).color = style.BackgroundColor; ((Shadow)border).effectColor = style.BorderColor; ((Shadow)border).effectDistance = new Vector2(1f, -1f); ((Graphic)fillImage).color = style.FillColor; ((Graphic)healthText).color = style.TextColor; ((TMP_Text)healthText).fontSize = 18f; ((Component)healthText).gameObject.SetActive(ShouldShowText(style)); HealthBarDisplayMode displayMode = style.DisplayMode; if ((int)displayMode != 1) { if ((int)displayMode == 2) { ApplyNumbersOnlyLayout(style); } else { ApplyHorizontalLayout(style); } } else { ApplyVerticalSideLayout(style); } ResetTextCache(); } public void SetFill(float fraction) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0092: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (fraction < 0f) { fraction = 0f; } else if (fraction > 1f) { fraction = 1f; } if (lastFillFraction == fraction && lastFillDisplayMode == currentStyle.DisplayMode) { return; } if ((int)currentStyle.DisplayMode == 2) { SetActiveIfChanged(((Component)backgroundImage).gameObject, active: false); lastFillFraction = fraction; lastFillDisplayMode = currentStyle.DisplayMode; return; } SetActiveIfChanged(((Component)backgroundImage).gameObject, active: true); if ((int)currentStyle.DisplayMode == 1) { fillRect.SetSizeWithCurrentAnchors((Axis)1, Mathf.Lerp(0f, Mathf.Max(0f, currentStyle.SideBarHeight - 2f), fraction)); lastFillFraction = fraction; lastFillDisplayMode = currentStyle.DisplayMode; } else { fillRect.SetSizeWithCurrentAnchors((Axis)0, Mathf.Lerp(0f, Mathf.Max(0f, currentStyle.Width - 2f), fraction)); lastFillFraction = fraction; lastFillDisplayMode = currentStyle.DisplayMode; } } public void SetHealth(EnemyHealthSnapshot snapshot) { //IL_00c9: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) SetFill(((EnemyHealthSnapshot)(ref snapshot)).HealthFraction); if (!ShouldShowText(currentStyle)) { if (((TMP_Text)healthText).text.Length > 0) { ((TMP_Text)healthText).text = string.Empty; } return; } string text = ((EnemyHealthSnapshot)(ref snapshot)).DisplayName ?? string.Empty; if (lastTextCurrentHealth != ((EnemyHealthSnapshot)(ref snapshot)).CurrentHealth || lastTextMaxHealth != ((EnemyHealthSnapshot)(ref snapshot)).MaxHealth || lastTextFormat != currentStyle.HealthTextFormat || lastDisplayMode != currentStyle.DisplayMode || lastShowEnemyName != currentStyle.ShowEnemyName || !(lastDisplayName == text)) { string text2 = HealthTextFormatter.Format(((EnemyHealthSnapshot)(ref snapshot)).CurrentHealth, ((EnemyHealthSnapshot)(ref snapshot)).MaxHealth, currentStyle.HealthTextFormat); if (currentStyle.ShowEnemyName && text.Length > 0) { text2 = text + " " + text2; } ((TMP_Text)healthText).text = text2; lastTextCurrentHealth = ((EnemyHealthSnapshot)(ref snapshot)).CurrentHealth; lastTextMaxHealth = ((EnemyHealthSnapshot)(ref snapshot)).MaxHealth; lastTextFormat = currentStyle.HealthTextFormat; lastDisplayMode = currentStyle.DisplayMode; lastShowEnemyName = currentStyle.ShowEnemyName; lastDisplayName = text; } } public void SetWorldPosition(Vector3 worldPosition, Camera camera, Quaternion billboardRotation) { //IL_0006: 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) ((Transform)root).position = worldPosition; ApplyCanvasCamera(camera); billboard.ApplyRotation(billboardRotation); } public void SetVisible(bool visible) { SetActiveIfChanged(gameObject, visible); } private void ApplyHorizontalLayout(HealthBarStyle style) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) root.sizeDelta = new Vector2(style.Width, style.Height); SetActiveIfChanged(((Component)backgroundImage).gameObject, active: true); SetRect(backgroundRect, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(style.Width, style.Height)); SetRect(fillRect, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(1f, 0f), new Vector2(0f, Mathf.Max(0f, style.Height - 2f))); fillRect.pivot = new Vector2(0f, 0.5f); fillRect.SetSizeWithCurrentAnchors((Axis)0, 0f); SetFullTextRect(); } private void ApplyVerticalSideLayout(HealthBarStyle style) { //IL_005f: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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) float verticalSideTextWidth = GetVerticalSideTextWidth(style); float num = Mathf.Abs(style.SideBarHorizontalOffset) + style.SideBarWidth * 0.5f + 6f + verticalSideTextWidth; float num2 = Mathf.Max(style.Width, num * 2f); float num3 = Mathf.Max(style.SideBarHeight, Mathf.Max(style.Height, 24f)); root.sizeDelta = new Vector2(num2, num3); SetActiveIfChanged(((Component)backgroundImage).gameObject, active: true); SetRect(backgroundRect, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(style.SideBarHorizontalOffset, 0f), new Vector2(style.SideBarWidth, style.SideBarHeight)); SetRect(fillRect, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 1f), new Vector2(Mathf.Max(0f, style.SideBarWidth - 2f), 0f)); fillRect.pivot = new Vector2(0.5f, 0f); fillRect.SetSizeWithCurrentAnchors((Axis)1, 0f); SetVerticalSideTextRect(style); } private void ApplyNumbersOnlyLayout(HealthBarStyle style) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) root.sizeDelta = new Vector2(style.Width, Mathf.Max(style.Height, 24f)); SetActiveIfChanged(((Component)backgroundImage).gameObject, active: false); SetFullTextRect(); } private static Image CreateImage(string name, Transform parent, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.AddComponent(); val.AddComponent(); Image obj = val.AddComponent(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private static TextMeshProUGUI CreateHealthText(Transform parent, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HealthText"); val.transform.SetParent(parent, false); val.AddComponent(); val.AddComponent(); TextMeshProUGUI val2 = val.AddComponent(); ((TMP_Text)val2).text = string.Empty; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).enableWordWrapping = false; ((TMP_Text)val2).enableAutoSizing = true; ((TMP_Text)val2).fontSizeMin = 10f; ((TMP_Text)val2).fontSizeMax = 18f; ((TMP_Text)val2).overflowMode = (TextOverflowModes)1; ((TMP_Text)val2).fontStyle = (FontStyles)1; ((TMP_Text)val2).fontSize = 18f; ((Graphic)val2).color = color; TMP_FontAsset val3 = ResolveTextFont(); if ((Object)(object)val3 != (Object)null) { ((TMP_Text)val2).font = val3; } return val2; } private static TMP_FontAsset? ResolveTextFont() { if (textFontResolved) { return resolvedTextFont; } textFontResolved = true; resolvedTextFont = TMP_Settings.defaultFontAsset; if ((Object)(object)resolvedTextFont != (Object)null) { return resolvedTextFont; } Font builtinResource = Resources.GetBuiltinResource("Arial.ttf"); if ((Object)(object)builtinResource != (Object)null) { resolvedTextFont = TMP_FontAsset.CreateFontAsset(builtinResource); } return resolvedTextFont; } private void SetFullTextRect() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) textRect.anchorMin = Vector2.zero; textRect.anchorMax = Vector2.one; textRect.pivot = new Vector2(0.5f, 0.5f); textRect.offsetMin = Vector2.zero; textRect.offsetMax = Vector2.zero; ((TMP_Text)healthText).alignment = (TextAlignmentOptions)514; } private void SetVerticalSideTextRect(HealthBarStyle style) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) float num = ((style.SideBarHorizontalOffset >= 0f) ? 1f : (-1f)); float verticalSideTextWidth = GetVerticalSideTextWidth(style); float num2 = Mathf.Max(style.SideBarHeight, 24f); float num3 = style.SideBarHorizontalOffset + num * style.SideBarWidth * 0.5f + num * (6f + verticalSideTextWidth * 0.5f); SetRect(textRect, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(num3, 0f), new Vector2(verticalSideTextWidth, num2)); ((TMP_Text)healthText).alignment = (TextAlignmentOptions)((num > 0f) ? 513 : 516); } private static float GetVerticalSideTextWidth(HealthBarStyle style) { return Mathf.Max(style.Width, 72f); } private static void SetRect(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 sizeDelta) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = anchorMin; rect.anchorMax = anchorMax; rect.pivot = new Vector2(0.5f, 0.5f); rect.anchoredPosition = anchoredPosition; rect.sizeDelta = sizeDelta; } private static bool ShouldShowText(HealthBarStyle style) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if (!style.ShowHealthNumbers) { return (int)style.DisplayMode == 2; } return true; } private void ResetTextCache() { //IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references) lastTextCurrentHealth = int.MinValue; lastTextMaxHealth = int.MinValue; lastTextFormat = (HealthTextFormat)(-1); lastDisplayMode = (HealthBarDisplayMode)(-1); lastFillDisplayMode = (HealthBarDisplayMode)(-1); lastFillFraction = -1f; lastShowEnemyName = false; lastDisplayName = null; } private void ApplyCanvasCamera(Camera camera) { billboard.SetCamera(camera); if (!((Object)(object)lastAppliedCanvasCamera == (Object)(object)camera) || !((Object)(object)worldCanvas.worldCamera == (Object)(object)camera)) { worldCanvas.worldCamera = camera; lastAppliedCanvasCamera = camera; } } private static void SetLayerRecursively(GameObject target, int layer) { target.layer = layer; Transform transform = target.transform; for (int i = 0; i < transform.childCount; i++) { SetLayerRecursively(((Component)transform.GetChild(i)).gameObject, layer); } } private static void SetActiveIfChanged(GameObject target, bool active) { if (target.activeSelf != active) { target.SetActive(active); } } } } namespace Auuueser.EnemyHealthBars.Game { internal enum EnemyHealthReadFailure { None, MissingEnemy, MissingEnemyType, CannotDie } internal sealed class EnemyHealthReader { public bool TryRead(EnemyAI? enemy, bool includeInvulnerableEnemies, EnemyMaxHealthResolver maxHealthResolver, out EnemyHealthSample sample, out EnemyHealthReadFailure failure) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) sample = default(EnemyHealthSample); failure = EnemyHealthReadFailure.None; if ((Object)(object)enemy == (Object)null) { failure = EnemyHealthReadFailure.MissingEnemy; return false; } if ((Object)(object)enemy.enemyType == (Object)null) { failure = EnemyHealthReadFailure.MissingEnemyType; return false; } if (!includeInvulnerableEnemies && !enemy.enemyType.canDie) { failure = EnemyHealthReadFailure.CannotDie; return false; } int instanceID = ((Object)enemy).GetInstanceID(); string text = ResolveDisplayName(enemy); int num = maxHealthResolver.Resolve(enemy, text); sample = new EnemyHealthSample(instanceID, text, enemy.enemyHP, num, enemy.isEnemyDead); return true; } private static string ResolveDisplayName(EnemyAI enemy) { EnemyType enemyType = enemy.enemyType; if ((Object)(object)enemyType != (Object)null && !string.IsNullOrWhiteSpace(enemyType.enemyName)) { return enemyType.enemyName; } if (!string.IsNullOrWhiteSpace(((Object)enemy).name)) { return ((Object)enemy).name; } return "Enemy"; } } internal sealed class EnemyMaxHealthResolver { private readonly EnemyMaxHealthLookup maxHealthLookup = new EnemyMaxHealthLookup(EnemyHealthDefaults.Items); public int UnresolvedCount => maxHealthLookup.UnresolvedCount; public int Resolve(EnemyAI enemy, string displayName) { string cacheKey = ResolveCacheKey(enemy, displayName); int baseMaxHealth = ResolveBaseMaxHealth(enemy, cacheKey); return ResolveSpecialMaxHealth(enemy, baseMaxHealth); } public string FormatUnresolvedNamesForDiagnostics(int maxNames) { return maxHealthLookup.FormatUnresolvedNamesForDiagnostics(maxNames); } private int ResolveBaseMaxHealth(EnemyAI enemy, string cacheKey) { int result = default(int); if (maxHealthLookup.TryGetStrictMaxHealth(cacheKey, ref result)) { return result; } if (maxHealthLookup.IsUnresolved(cacheKey)) { return 0; } return maxHealthLookup.StoreResolvedStrictMaxHealth(cacheKey, ResolveFromPrefab(enemy)); } private static int ResolveSpecialMaxHealth(EnemyAI enemy, int baseMaxHealth) { if (enemy is ButlerEnemyAI) { int num = ((!((Object)(object)StartOfRound.Instance != (Object)null)) ? 1 : StartOfRound.Instance.connectedPlayersAmount); return EnemySpecialMaxHealthRules.ResolveButlerMaxHealth(baseMaxHealth, num); } if (enemy is CaveDwellerAI) { return EnemySpecialMaxHealthRules.ResolveManeaterMaxHealth(baseMaxHealth, enemy.currentBehaviourStateIndex); } return baseMaxHealth; } private static string ResolveCacheKey(EnemyAI enemy, string displayName) { EnemyType enemyType = enemy.enemyType; if ((Object)(object)enemyType != (Object)null && !string.IsNullOrWhiteSpace(enemyType.enemyName)) { return enemyType.enemyName; } if (!string.IsNullOrWhiteSpace(displayName)) { return displayName; } if (!string.IsNullOrWhiteSpace(((Object)enemy).name)) { return ((Object)enemy).name; } return string.Empty; } private static int ResolveFromPrefab(EnemyAI enemy) { EnemyType enemyType = enemy.enemyType; if ((Object)(object)enemyType == (Object)null || (Object)(object)enemyType.enemyPrefab == (Object)null) { return 0; } EnemyAI val = default(EnemyAI); if (!enemyType.enemyPrefab.TryGetComponent(ref val)) { return 0; } if (val.enemyHP <= 0) { return 0; } return val.enemyHP; } } internal sealed class LocalPlayerCameraProvider { public Camera? GetActiveCamera() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.localPlayerController != (Object)null && IsUsable(instance.localPlayerController.gameplayCamera)) { return instance.localPlayerController.gameplayCamera; } if (IsUsable(instance.activeCamera)) { return instance.activeCamera; } if (IsUsable(instance.spectateCamera)) { return instance.spectateCamera; } } HUDManager instance2 = HUDManager.Instance; if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.localPlayer != (Object)null && IsUsable(instance2.localPlayer.gameplayCamera)) { return instance2.localPlayer.gameplayCamera; } if (!((Object)(object)Camera.main != (Object)null)) { return Camera.current; } return Camera.main; } private static bool IsUsable(Camera? camera) { if ((Object)(object)camera != (Object)null) { return ((Behaviour)camera).isActiveAndEnabled; } return false; } } internal sealed class RoundManagerEnemySource { public List? GetSpawnedEnemies() { RoundManager instance = RoundManager.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.SpawnedEnemies; } } } namespace Auuueser.EnemyHealthBars.Configuration { internal static class ChineseProjectLanguageDetector { public static ConfigLanguage Detect(ConfigFile config, ManualLogSource logger) { if (!DetectLoadedPlugin(logger) && !DetectExistingConfig(config, logger) && !DetectManifestNearConfig(config, logger)) { return (ConfigLanguage)0; } return (ConfigLanguage)1; } private static bool DetectLoadedPlugin(ManualLogSource logger) { foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { PluginInfo value = pluginInfo.Value; if (value != null && value.Metadata != null && ChineseProjectDetection.IsChineseProjectPlugin(value.Metadata.GUID, value.Metadata.Name, value.Location)) { logger.LogInfo((object)("LC Chinese Project detected from plugin '" + value.Metadata.GUID + "'. Using Chinese config text.")); return true; } } return false; } private static bool DetectExistingConfig(ConfigFile config, ManualLogSource logger) { if (!File.Exists(config.ConfigFilePath)) { return false; } try { if (!ChineseProjectDetection.ContainsChineseConfigSections(File.ReadAllText(config.ConfigFilePath))) { return false; } logger.LogInfo((object)"Existing Chinese config sections detected. Using Chinese config text."); return true; } catch (Exception ex) { logger.LogWarning((object)("Could not inspect existing config language: " + ex.Message)); return false; } } private static bool DetectManifestNearConfig(ConfigFile config, ManualLogSource logger) { string directoryName = Path.GetDirectoryName(config.ConfigFilePath); if (string.IsNullOrEmpty(directoryName)) { return false; } DirectoryInfo parent = Directory.GetParent(directoryName); if (parent == null) { return false; } string path = Path.Combine(parent.FullName, "plugins"); if (!Directory.Exists(path)) { return false; } try { string[] files = Directory.GetFiles(path, "manifest.json", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { if (ChineseProjectDetection.ContainsChineseProjectManifestText(File.ReadAllText(files[i]))) { logger.LogInfo((object)("LC Chinese Project manifest detected at '" + files[i] + "'. Using Chinese config text.")); return true; } } } catch (Exception ex) { logger.LogWarning((object)("Could not inspect plugin manifests for config language: " + ex.Message)); } return false; } } internal static class LethalConfigIntegration { private const string PluginGuid = "ainavt.lc.lethalconfig"; public static bool IsAvailable() { return Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"); } public static void Register(ModConfig config, ManualLogSource logger) { try { ConfigTexts texts = config.Texts; LethalConfigManager.SetModDescription(texts.ModDescription); AddBool(config.EnabledEntry, texts.EnabledName, texts.GeneralSection, texts.EnabledDescription); AddBool(config.ShowInvulnerableEnemiesEntry, texts.ShowInvulnerableEnemiesName, texts.VisibilitySection, texts.ShowInvulnerableEnemiesDescription); AddEnum(config.MaxHealthModeEntry, texts.MaxHealthModeName, texts.VisibilitySection, texts.MaxHealthModeDescription); AddFloat(config.MaxDistanceEntry, texts.MaxDistanceName, texts.VisibilitySection, texts.MaxDistanceDescription); AddFloat(config.ScanIntervalEntry, texts.ScanIntervalName, texts.PerformanceSection, texts.ScanIntervalDescription); AddFloat(config.VerticalOffsetEntry, texts.VerticalOffsetName, texts.LayoutSection, texts.VerticalOffsetDescription); AddFloat(config.BarWidthEntry, texts.BarWidthName, texts.LayoutSection, texts.BarWidthDescription); AddFloat(config.BarHeightEntry, texts.BarHeightName, texts.LayoutSection, texts.BarHeightDescription); AddFloat(config.WorldScaleEntry, texts.WorldScaleName, texts.LayoutSection, texts.WorldScaleDescription); AddEnum(config.DisplayModeEntry, texts.DisplayModeName, texts.LayoutSection, texts.DisplayModeDescription); AddBool(config.ShowHealthNumbersEntry, texts.ShowHealthNumbersName, texts.LayoutSection, texts.ShowHealthNumbersDescription); AddEnum(config.HealthTextFormatEntry, texts.HealthTextFormatName, texts.LayoutSection, texts.HealthTextFormatDescription); AddBool(config.ShowEnemyNameEntry, texts.ShowEnemyNameName, texts.LayoutSection, texts.ShowEnemyNameDescription); AddFloat(config.SideBarWidthEntry, texts.SideBarWidthName, texts.LayoutSection, texts.SideBarWidthDescription); AddFloat(config.SideBarHeightEntry, texts.SideBarHeightName, texts.LayoutSection, texts.SideBarHeightDescription); AddFloat(config.SideBarHorizontalOffsetEntry, texts.SideBarHorizontalOffsetName, texts.LayoutSection, texts.SideBarHorizontalOffsetDescription); AddBool(config.DebugEnabledEntry, texts.DebugEnabledName, texts.DebugSection, texts.DebugEnabledDescription); AddBool(config.DebugShowFullHealthEnemiesEntry, texts.DebugShowFullHealthEnemiesName, texts.DebugSection, texts.DebugShowFullHealthEnemiesDescription); AddBool(config.DebugDiagnosticsEnabledEntry, texts.DebugDiagnosticsEnabledName, texts.DebugSection, texts.DebugDiagnosticsEnabledDescription); AddFloat(config.DebugDiagnosticsLogIntervalEntry, texts.DebugDiagnosticsLogIntervalName, texts.DebugSection, texts.DebugDiagnosticsLogIntervalDescription); AddBool(config.DebugShowTestBarEntry, texts.DebugShowTestBarName, texts.DebugSection, texts.DebugShowTestBarDescription); logger.LogInfo((object)"Registered localized LethalConfig entries."); } catch (Exception ex) { logger.LogWarning((object)("Could not register LethalConfig entries: " + ex.Message)); } } private static void AddBool(ConfigEntry entry, string name, string section, string description) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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_002d: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)entry); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(entry, new BoolCheckBoxOptions { Name = name, Section = section, Description = description, RequiresRestart = false })); } private static void AddFloat(ConfigEntry entry, string name, string section, string description) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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_002d: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)entry); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(entry, new FloatInputFieldOptions { Name = name, Section = section, Description = description, RequiresRestart = false })); } private static void AddEnum(ConfigEntry entry, string name, string section, string description) where T : Enum { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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_002d: Expected O, but got Unknown LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)entry); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem(entry, new EnumDropDownOptions { Name = name, Section = section, Description = description, RequiresRestart = false })); } } internal sealed class ModConfig { private const float ConfigFilePollInterval = 0.5f; private readonly ConfigFile configFile; private readonly string configFilePath; private readonly ConfigEntry enabled; private readonly ConfigEntry showInvulnerableEnemies; private readonly ConfigEntry maxHealthMode; private readonly ConfigEntry maxDistance; private readonly ConfigEntry scanInterval; private readonly ConfigEntry verticalOffset; private readonly ConfigEntry barWidth; private readonly ConfigEntry barHeight; private readonly ConfigEntry worldScale; private readonly ConfigEntry displayMode; private readonly ConfigEntry showHealthNumbers; private readonly ConfigEntry healthTextFormat; private readonly ConfigEntry showEnemyName; private readonly ConfigEntry sideBarWidth; private readonly ConfigEntry sideBarHeight; private readonly ConfigEntry sideBarHorizontalOffset; private readonly ConfigEntry debugEnabled; private readonly ConfigEntry debugShowFullHealthEnemies; private readonly ConfigEntry debugDiagnosticsEnabled; private readonly ConfigEntry debugDiagnosticsLogInterval; private readonly ConfigEntry debugShowTestBar; private DateTime lastConfigWriteTimeUtc; private float nextConfigFilePollTime; public ConfigLanguage Language { get; } public ConfigTexts Texts { get; } public int SettingsVersion { get; private set; } public bool Enabled => enabled.Value; public bool ShowInvulnerableEnemies => showInvulnerableEnemies.Value; public MaxHealthMode MaxHealthMode => maxHealthMode.Value; public bool DebugEnabled => debugEnabled.Value; public bool DiagnosticsEnabled { get { if (DebugEnabled) { return debugDiagnosticsEnabled.Value; } return false; } } public bool ShowFullHealthEnemies { get { if (DebugEnabled) { return debugShowFullHealthEnemies.Value; } return false; } } public bool DebugShowTestBar { get { if (DebugEnabled) { return debugShowTestBar.Value; } return false; } } public float DiagnosticsLogInterval { get { if (!(debugDiagnosticsLogInterval.Value < 1f)) { return debugDiagnosticsLogInterval.Value; } return 1f; } } public float ScanInterval { get { if (!(scanInterval.Value < 0.02f)) { return scanInterval.Value; } return 0.02f; } } public float VerticalOffset => verticalOffset.Value; public float BarWidth { get { if (!(barWidth.Value < 0.1f)) { return barWidth.Value; } return 0.1f; } } public float BarHeight { get { if (!(barHeight.Value < 0.03f)) { return barHeight.Value; } return 0.03f; } } public float WorldScale { get { if (!(worldScale.Value < 0.01f)) { return worldScale.Value; } return 0.01f; } } public HealthBarDisplayMode DisplayMode => displayMode.Value; public bool ShowHealthNumbers => showHealthNumbers.Value; public HealthTextFormat HealthTextFormat => healthTextFormat.Value; public bool ShowEnemyName => showEnemyName.Value; public float SideBarWidth { get { if (!(sideBarWidth.Value < 0.03f)) { return sideBarWidth.Value; } return 0.03f; } } public float SideBarHeight { get { if (!(sideBarHeight.Value < 0.1f)) { return sideBarHeight.Value; } return 0.1f; } } public float SideBarHorizontalOffset => sideBarHorizontalOffset.Value; internal ConfigEntry EnabledEntry => enabled; internal ConfigEntry ShowInvulnerableEnemiesEntry => showInvulnerableEnemies; internal ConfigEntry MaxHealthModeEntry => maxHealthMode; internal ConfigEntry MaxDistanceEntry => maxDistance; internal ConfigEntry ScanIntervalEntry => scanInterval; internal ConfigEntry VerticalOffsetEntry => verticalOffset; internal ConfigEntry BarWidthEntry => barWidth; internal ConfigEntry BarHeightEntry => barHeight; internal ConfigEntry WorldScaleEntry => worldScale; internal ConfigEntry DisplayModeEntry => displayMode; internal ConfigEntry ShowHealthNumbersEntry => showHealthNumbers; internal ConfigEntry HealthTextFormatEntry => healthTextFormat; internal ConfigEntry ShowEnemyNameEntry => showEnemyName; internal ConfigEntry SideBarWidthEntry => sideBarWidth; internal ConfigEntry SideBarHeightEntry => sideBarHeight; internal ConfigEntry SideBarHorizontalOffsetEntry => sideBarHorizontalOffset; internal ConfigEntry DebugEnabledEntry => debugEnabled; internal ConfigEntry DebugShowFullHealthEnemiesEntry => debugShowFullHealthEnemies; internal ConfigEntry DebugDiagnosticsEnabledEntry => debugDiagnosticsEnabled; internal ConfigEntry DebugDiagnosticsLogIntervalEntry => debugDiagnosticsLogInterval; internal ConfigEntry DebugShowTestBarEntry => debugShowTestBar; private ModConfig(ConfigFile config, ConfigLanguage language) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) configFile = config; configFilePath = config.ConfigFilePath; Language = language; Texts = ConfigTextCatalog.Get(language); enabled = config.Bind(Texts.GeneralSection, "Enabled", true, Texts.EnabledDescription); showInvulnerableEnemies = config.Bind(Texts.VisibilitySection, "ShowInvulnerableEnemies", false, Texts.ShowInvulnerableEnemiesDescription); maxHealthMode = config.Bind(Texts.VisibilitySection, "MaxHealthMode", (MaxHealthMode)2, Texts.MaxHealthModeDescription); maxDistance = config.Bind(Texts.VisibilitySection, "MaxDistance", 35f, Texts.MaxDistanceDescription); scanInterval = config.Bind(Texts.PerformanceSection, "ScanInterval", 0.2f, Texts.ScanIntervalDescription); verticalOffset = config.Bind(Texts.LayoutSection, "VerticalOffset", 0.45f, Texts.VerticalOffsetDescription); barWidth = config.Bind(Texts.LayoutSection, "BarWidth", 1.25f, Texts.BarWidthDescription); barHeight = config.Bind(Texts.LayoutSection, "BarHeight", 0.14f, Texts.BarHeightDescription); worldScale = config.Bind(Texts.LayoutSection, "WorldScale", 0.7f, Texts.WorldScaleDescription); displayMode = config.Bind(Texts.LayoutSection, "DisplayMode", (HealthBarDisplayMode)0, Texts.DisplayModeDescription); showHealthNumbers = config.Bind(Texts.LayoutSection, "ShowHealthNumbers", true, Texts.ShowHealthNumbersDescription); healthTextFormat = config.Bind(Texts.LayoutSection, "HealthTextFormat", (HealthTextFormat)0, Texts.HealthTextFormatDescription); showEnemyName = config.Bind(Texts.LayoutSection, "ShowEnemyName", false, Texts.ShowEnemyNameDescription); sideBarWidth = config.Bind(Texts.LayoutSection, "SideBarWidth", 0.14f, Texts.SideBarWidthDescription); sideBarHeight = config.Bind(Texts.LayoutSection, "SideBarHeight", 0.55f, Texts.SideBarHeightDescription); sideBarHorizontalOffset = config.Bind(Texts.LayoutSection, "SideBarHorizontalOffset", 0.55f, Texts.SideBarHorizontalOffsetDescription); debugEnabled = config.Bind(Texts.DebugSection, "Enabled", false, Texts.DebugEnabledDescription); debugShowFullHealthEnemies = config.Bind(Texts.DebugSection, "ShowFullHealthEnemies", false, Texts.DebugShowFullHealthEnemiesDescription); debugDiagnosticsEnabled = config.Bind(Texts.DebugSection, "DiagnosticsEnabled", false, Texts.DebugDiagnosticsEnabledDescription); debugDiagnosticsLogInterval = config.Bind(Texts.DebugSection, "DiagnosticsLogInterval", 3f, Texts.DebugDiagnosticsLogIntervalDescription); debugShowTestBar = config.Bind(Texts.DebugSection, "ShowTestBar", false, Texts.DebugShowTestBarDescription); config.SettingChanged += OnConfigChanged; config.ConfigReloaded += OnConfigReloaded; config.Save(); RefreshLastWriteTime(); } public static ModConfig Bind(ConfigFile config, ConfigLanguage language) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return new ModConfig(config, language); } public HealthBarVisibilityRules CreateVisibilityRules() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) return new HealthBarVisibilityRules(ShowFullHealthEnemies, maxDistance.Value); } public void ReloadIfChangedOnDisk(float currentTime) { if (!(currentTime < nextConfigFilePollTime) && File.Exists(configFilePath)) { nextConfigFilePollTime = currentTime + 0.5f; if (!(File.GetLastWriteTimeUtc(configFilePath) <= lastConfigWriteTimeUtc)) { configFile.Reload(); RefreshLastWriteTime(); } } } private void OnConfigChanged(object sender, SettingChangedEventArgs args) { SettingsVersion++; RefreshLastWriteTime(); } private void OnConfigReloaded(object sender, EventArgs args) { SettingsVersion++; RefreshLastWriteTime(); } private void RefreshLastWriteTime() { if (File.Exists(configFilePath)) { lastConfigWriteTimeUtc = File.GetLastWriteTimeUtc(configFilePath); } } } }