Decompiled source of betterHUDmod v1.0.3

plugins/UltrakillModTest1.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using TMPro;
using ULTRAKILL.Cheats;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("UltrakillModTest1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UltrakillModTest1")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2c7d4b1e-04d7-49d9-8ec3-4571b1b7fff2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BetterHud;

public static class PlayerDamageEvents
{
	public static event Action<int> OnHeavyDamageTaken;

	internal static void TriggerHeavyDamage(int damage)
	{
		Action<int> onHeavyDamageTaken = PlayerDamageEvents.OnHeavyDamageTaken;
		int num = ((onHeavyDamageTaken != null) ? onHeavyDamageTaken.GetInvocationList().Length : 0);
		Debug.LogError((object)$"[BetterHud][DamageEvent] TriggerHeavyDamage({damage}), listeners={num}");
		if (num == 0)
		{
			Debug.LogError((object)"[BetterHud][DamageEvent] WARNING: OnHeavyDamageTaken has no listeners!");
			return;
		}
		try
		{
			PlayerDamageEvents.OnHeavyDamageTaken(damage);
		}
		catch (Exception arg)
		{
			Debug.LogError((object)$"[BetterHud][DamageEvent] Exception while invoking event:\n{arg}");
		}
	}
}
[HarmonyPatch(typeof(NewMovement), "GetHurt")]
public static class GetHurtPatch
{
	[HarmonyPrefix]
	public static void Prefix(NewMovement __instance, ref int damage, bool invincible, bool ignoreInvincibility)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			Debug.LogError((object)"[BetterHud][GetHurt] __instance is null!");
			return;
		}
		if (__instance.dead || __instance.levelOver || !(!invincible || ((Component)__instance).gameObject.layer != 15 || ignoreInvincibility) || damage <= 0)
		{
			Debug.LogError((object)"[BetterHud][GetHurt] Ignored by original damage conditions.");
			return;
		}
		int num = damage;
		AssistController instance = MonoSingleton<AssistController>.Instance;
		if ((Object)(object)instance != (Object)null)
		{
			if (instance.majorEnabled)
			{
				num = Mathf.RoundToInt((float)damage * instance.damageTaken);
				Debug.LogError((object)("[BetterHud][GetHurt] Major Assist changed damage: " + $"{damage} -> {num}"));
			}
		}
		else
		{
			Debug.LogError((object)"[BetterHud][GetHurt] AssistController.Instance is null! Using original damage.");
		}
		if (Invincibility.Enabled)
		{
			Debug.LogError((object)"[BetterHud][GetHurt] Invincibility.Enabled = true, finalDamage forced to 0.");
			num = 0;
		}
		if (__instance.hp - num > 0 && num >= 50)
		{
			Debug.LogError((object)$"[BetterHud][GetHurt] >>> HEAVY DAMAGE DETECTED: {num} <<<");
			PlayerDamageEvents.TriggerHeavyDamage(num);
		}
	}
}
public class HeavyDamageVisualEffect : MonoBehaviour
{
	private Coroutine _effectCoroutine;

	private const float Duration = 1f;

	private void OnEnable()
	{
		PlayerDamageEvents.OnHeavyDamageTaken += HandleHeavyDamage;
		Debug.LogError((object)"[BetterHud][HeavyEffect] COMPONENT ENABLED - event subscribed.");
	}

	private void OnDisable()
	{
		PlayerDamageEvents.OnHeavyDamageTaken -= HandleHeavyDamage;
		Debug.LogError((object)"[BetterHud][HeavyEffect] COMPONENT DISABLED - event unsubscribed.");
		if (_effectCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(_effectCoroutine);
			_effectCoroutine = null;
		}
		ResetShaderValues();
		NewMovement instance = MonoSingleton<NewMovement>.Instance;
		if ((Object)(object)instance == (Object)null || !instance.dead)
		{
			SetDeathEffect(enabled: false);
		}
		else
		{
			Debug.LogError((object)"[BetterHud][HeavyEffect] Player is dead, leaving DeathEffect control to original DeathSequence.");
		}
	}

	private void HandleHeavyDamage(int damage)
	{
		Debug.LogError((object)$"[BetterHud][HeavyEffect] HANDLE HEAVY DAMAGE: {damage}");
		if (_effectCoroutine != null)
		{
			Debug.LogError((object)"[BetterHud][HeavyEffect] Previous effect coroutine found. Restarting.");
			((MonoBehaviour)this).StopCoroutine(_effectCoroutine);
			_effectCoroutine = null;
		}
		_effectCoroutine = ((MonoBehaviour)this).StartCoroutine(DamageEffectRoutine(damage));
	}

	private IEnumerator DamageEffectRoutine(int damage)
	{
		Debug.LogError((object)$"[BetterHud][HeavyEffect] EFFECT START | damage={damage}");
		float elapsed = 0f;
		SetDeathEffect(enabled: true);
		Shader.SetGlobalFloat("_Sharpness", 1f);
		Shader.SetGlobalFloat("_Deathness", 1f);
		Debug.LogError((object)"[BetterHud][HeavyEffect] Shader values initialized: _Sharpness=1, _Deathness=1");
		float nextLogTime = 0.5f;
		while (elapsed < 1f)
		{
			NewMovement player = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)player != (Object)null && player.dead)
			{
				Debug.LogError((object)"[BetterHud][HeavyEffect] PLAYER DIED DURING EFFECT. Stopping custom effect without disabling original DeathEffect.");
				ResetShaderValues();
				_effectCoroutine = null;
				yield break;
			}
			elapsed += Time.unscaledDeltaTime;
			float progress = Mathf.Clamp01(elapsed / 1f);
			float intensity = Mathf.Lerp(1f, 0f, progress);
			Shader.SetGlobalFloat("_Sharpness", intensity);
			Shader.SetGlobalFloat("_Deathness", intensity);
			if (elapsed >= nextLogTime)
			{
				Debug.LogError((object)($"[BetterHud][HeavyEffect] t={elapsed:F2}/{1f:F2}, " + $"progress={progress:F2}, " + $"intensity={intensity:F2}"));
				nextLogTime += 0.5f;
			}
			yield return null;
		}
		ResetShaderValues();
		SetDeathEffect(enabled: false);
		_effectCoroutine = null;
		Debug.LogError((object)"[BetterHud][HeavyEffect] EFFECT FINISHED.");
	}

	private void SetDeathEffect(bool enabled)
	{
		PostProcessV2_Handler instance = MonoSingleton<PostProcessV2_Handler>.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			Debug.LogError((object)($"[BetterHud][HeavyEffect] Cannot set DeathEffect({enabled}): " + "PostProcessV2_Handler.Instance is null!"));
			return;
		}
		instance.DeathEffect(enabled);
		Debug.LogError((object)$"[BetterHud][HeavyEffect] DeathEffect({enabled}) called.");
	}

	private void ResetShaderValues()
	{
		Shader.SetGlobalFloat("_Sharpness", 0f);
		Shader.SetGlobalFloat("_Deathness", 0f);
		Debug.LogError((object)"[BetterHud][HeavyEffect] Shader values reset to 0.");
	}
}
public class Trackpanel : MonoBehaviour
{
	private const string BUNDLE_NAME = "trackertabel";

	private readonly HashSet<int> debuggedEnemies = new HashSet<int>();

	private const string PREFAB_NAME = "MainTrackerPanel";

	private const string TARGET_CANVAS_NAME = "Canvas";

	private static AssetBundle loadedBundle;

	private static GameObject trackerPrefab;

	private readonly Dictionary<EnemyIdentifier, GameObject> activeTrackers = new Dictionary<EnemyIdentifier, GameObject>();

	private readonly List<EnemyIdentifier> cleanupBuffer = new List<EnemyIdentifier>();

	private Canvas targetCanvas;

	private readonly HashSet<string> lastEnemyNames = new HashSet<string>();

	private string GetHierarchyPath(Transform target)
	{
		if ((Object)(object)target == (Object)null)
		{
			return "<null>";
		}
		string text = ((Object)target).name;
		while ((Object)(object)target.parent != (Object)null)
		{
			target = target.parent;
			text = ((Object)target).name + "/" + text;
		}
		return text;
	}

	private void DebugEnemy(EnemyIdentifier enemy)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)((Component)enemy).gameObject).GetInstanceID();
		if (debuggedEnemies.Contains(instanceID))
		{
			return;
		}
		debuggedEnemies.Add(instanceID);
		Debug.Log((object)"[TrackerPanel] ===============================");
		Debug.Log((object)("[TrackerPanel] EnemyIdentifier: " + ((Object)enemy).name));
		Debug.Log((object)("[TrackerPanel] GameObject: " + ((Object)((Component)enemy).gameObject).name));
		Debug.Log((object)$"[TrackerPanel] InstanceID: {instanceID}");
		Debug.Log((object)$"[TrackerPanel] Health: {enemy.health}");
		Debug.Log((object)$"[TrackerPanel] Dead: {enemy.dead}");
		Debug.Log((object)$"[TrackerPanel] Active: {((Component)enemy).gameObject.activeInHierarchy}");
		Debug.Log((object)("[TrackerPanel] Hierarchy: " + GetHierarchyPath(((Component)enemy).transform)));
		Component[] components = ((Component)enemy).gameObject.GetComponents<Component>();
		foreach (Component val in components)
		{
			if ((Object)(object)val != (Object)null)
			{
				Debug.Log((object)("[TrackerPanel] Component: " + ((object)val).GetType().Name));
			}
		}
		Component[] componentsInChildren = ((Component)enemy).GetComponentsInChildren<Component>(true);
		foreach (Component val2 in componentsInChildren)
		{
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.gameObject != (Object)(object)((Component)enemy).gameObject)
			{
				Debug.Log((object)("[TrackerPanel] CHILD: " + GetHierarchyPath(val2.transform) + " -> " + ((object)val2).GetType().Name));
			}
		}
		Debug.Log((object)"[TrackerPanel] ===============================");
	}

	private void Awake()
	{
		Debug.Log((object)"[TrackerPanel] Awake");
		LoadAssetBundle();
		SceneManager.sceneLoaded += OnSceneLoaded;
		FindAndSetupCanvas();
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		ClearAllTrackers();
	}

	private void Update()
	{
		if ((Object)(object)targetCanvas == (Object)null)
		{
			FindAndSetupCanvas();
			if ((Object)(object)targetCanvas == (Object)null)
			{
				return;
			}
		}
		EnemyTracker instance = MonoSingleton<EnemyTracker>.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		List<EnemyIdentifier> currentEnemies = instance.GetCurrentEnemies();
		if (currentEnemies != null)
		{
			int count = currentEnemies.Count;
			for (int i = 0; i < count; i++)
			{
				EnemyIdentifier val = currentEnemies[i];
				DebugEnemy(val);
				if (IsValidEnemy(val) && !activeTrackers.ContainsKey(val))
				{
					CreateTracker(val);
				}
			}
		}
		cleanupBuffer.Clear();
		foreach (KeyValuePair<EnemyIdentifier, GameObject> activeTracker in activeTrackers)
		{
			EnemyIdentifier key = activeTracker.Key;
			GameObject value = activeTracker.Value;
			if (!IsValidEnemy(key) || (Object)(object)value == (Object)null)
			{
				cleanupBuffer.Add(key);
			}
		}
		int count2 = cleanupBuffer.Count;
		for (int j = 0; j < count2; j++)
		{
			EnemyIdentifier key2 = cleanupBuffer[j];
			if (activeTrackers.TryGetValue(key2, out var value2))
			{
				if ((Object)(object)value2 != (Object)null)
				{
					Object.Destroy((Object)(object)value2);
				}
				activeTrackers.Remove(key2);
			}
		}
	}

	private void LoadAssetBundle()
	{
		if ((Object)(object)trackerPrefab != (Object)null)
		{
			return;
		}
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string directoryName = Path.GetDirectoryName(executingAssembly.Location);
		string text = Path.Combine(directoryName, "trackertabel");
		if (File.Exists(text))
		{
			loadedBundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)loadedBundle != (Object)null)
			{
				Debug.Log((object)"[TrackerPanel] Bundle loaded: trackertabel");
			}
		}
		if ((Object)(object)loadedBundle == (Object)null)
		{
			Debug.LogError((object)"[TrackerPanel] Failed to load AssetBundle: trackertabel");
			return;
		}
		trackerPrefab = loadedBundle.LoadAsset<GameObject>("MainTrackerPanel");
		if ((Object)(object)trackerPrefab == (Object)null)
		{
			Debug.LogError((object)"[TrackerPanel] Prefab not found: MainTrackerPanel");
		}
		else
		{
			Debug.Log((object)("[TrackerPanel] Prefab loaded: " + ((Object)trackerPrefab).name));
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		ClearAllTrackers();
		FindAndSetupCanvas();
	}

	private void FindAndSetupCanvas()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		string currentScene = SceneHelper.CurrentScene;
		if (currentScene == "Main Menu" || currentScene == "Bootstrap")
		{
			targetCanvas = null;
			return;
		}
		Scene activeScene = SceneManager.GetActiveScene();
		GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
		foreach (GameObject val in rootGameObjects)
		{
			if (!(((Object)val).name != "Canvas"))
			{
				Canvas component = val.GetComponent<Canvas>();
				if (!((Object)(object)component == (Object)null))
				{
					targetCanvas = component;
					Debug.Log((object)("[TrackerPanel] Target Canvas found in active scene: " + ((Scene)(ref activeScene)).name));
					break;
				}
			}
		}
	}

	private void CreateTracker(EnemyIdentifier enemy)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return;
		}
		if ((Object)(object)trackerPrefab == (Object)null)
		{
			Debug.LogError((object)"[TrackerPanel] trackerPrefab is null");
		}
		else
		{
			if ((Object)(object)targetCanvas == (Object)null)
			{
				return;
			}
			Enemy component = ((Component)enemy).GetComponent<Enemy>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)("[TrackerPanel] SKIPPING '" + ((Object)enemy).name + "' - Enemy component not found. Hierarchy: " + GetHierarchyPath(((Component)enemy).transform)));
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(trackerPrefab, ((Component)targetCanvas).transform);
			val.transform.SetAsFirstSibling();
			EnemyTrackerUI enemyTrackerUI = val.GetComponent<EnemyTrackerUI>();
			if ((Object)(object)enemyTrackerUI == (Object)null)
			{
				enemyTrackerUI = val.AddComponent<EnemyTrackerUI>();
			}
			enemyTrackerUI.Initialize(enemy);
			activeTrackers.Add(enemy, val);
		}
	}

	private bool IsValidEnemy(EnemyIdentifier enemy)
	{
		return (Object)(object)enemy != (Object)null && !enemy.dead && enemy.health > 0f && ((Component)enemy).gameObject.activeInHierarchy;
	}

	private void ClearAllTrackers()
	{
		foreach (KeyValuePair<EnemyIdentifier, GameObject> activeTracker in activeTrackers)
		{
			if ((Object)(object)activeTracker.Value != (Object)null)
			{
				Object.Destroy((Object)(object)activeTracker.Value);
			}
		}
		activeTrackers.Clear();
	}
}
public class EnemyTrackerUI : MonoBehaviour
{
	private const float MIN_ASPECT_RATIO = 0.05f;

	private const float MAX_ASPECT_RATIO = 20f;

	private const float MIN_SCREEN_SIZE = 0.01f;

	private EnemyIdentifier enemy;

	private Enemy enemyComponent;

	private Collider enemyCollider;

	private RectTransform rectTransform;

	private Camera mainCamera;

	private RectTransform leftFiller;

	private RectTransform rightFiller;

	private Image leftFillerImage;

	private Image rightFillerImage;

	private float enemyHeightOffset;

	private float enemyAspectRatio = 1f;

	private bool aspectRatioInitialized = false;

	private static readonly Color NORMAL_FILLER_COLOR = new Color(0f, 1f, 0f, 1f);

	private static readonly Color INVINCIBLE_FILLER_COLOR = new Color(0f, 1f, 1f, 1f);

	private void UpdateInvincibilityColor()
	{
		//IL_002a: 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_002f: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemyComponent == (Object)null)
		{
			return;
		}
		Color color = (enemy.blessed ? INVINCIBLE_FILLER_COLOR : NORMAL_FILLER_COLOR);
		if ((Object)(object)leftFiller != (Object)null)
		{
			Image component = ((Component)leftFiller).GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				((Graphic)component).color = color;
			}
		}
		if ((Object)(object)rightFiller != (Object)null)
		{
			Image component2 = ((Component)rightFiller).GetComponent<Image>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Graphic)component2).color = color;
			}
		}
	}

	public void Initialize(EnemyIdentifier targetEnemy)
	{
		//IL_0218: 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_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		enemy = targetEnemy;
		rectTransform = ((Component)this).GetComponent<RectTransform>();
		if ((Object)(object)enemy == (Object)null)
		{
			Debug.LogError((object)"[TrackerPanel] Initialize received null enemy");
			return;
		}
		enemyComponent = ((Component)targetEnemy).GetComponent<Enemy>();
		if ((Object)(object)enemyComponent == (Object)null)
		{
			Debug.LogError((object)("[TrackerPanel] Enemy component NOT FOUND on " + ((Object)((Component)targetEnemy).gameObject).name));
		}
		if (((Object)targetEnemy).name.IndexOf("Mass", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			Transform val = ((Component)targetEnemy).transform.Find("scorpionboss3 (1)/Armature/spine2");
			if ((Object)(object)val != (Object)null)
			{
				enemyCollider = (Collider)(object)((Component)val).GetComponent<SphereCollider>();
			}
			if ((Object)(object)enemyCollider == (Object)null)
			{
				enemyCollider = (Collider)(object)((Component)targetEnemy).GetComponentInChildren<SphereCollider>();
			}
		}
		Bounds bounds;
		if ((Object)(object)enemyCollider == (Object)null)
		{
			enemyCollider = ((Component)enemy).GetComponent<Collider>();
			if ((Object)(object)enemyCollider != (Object)null)
			{
				bounds = enemyCollider.bounds;
				if (((Bounds)(ref bounds)).size == Vector3.zero)
				{
					Collider[] componentsInChildren = ((Component)enemy).GetComponentsInChildren<Collider>();
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						bounds = componentsInChildren[i].bounds;
						if (((Bounds)(ref bounds)).size != Vector3.zero)
						{
							enemyCollider = componentsInChildren[i];
							break;
						}
					}
				}
			}
		}
		if ((Object)(object)enemyCollider == (Object)null)
		{
			Debug.LogWarning((object)("[TrackerPanel] No collider found for " + ((Object)enemy).name + ". Skipping tracker initialization."));
			return;
		}
		string[] obj = new string[6]
		{
			"[TrackerPanel] ",
			((Object)enemy).name,
			" Collider = ",
			((object)enemyCollider).GetType().Name,
			", ",
			null
		};
		bounds = enemyCollider.bounds;
		obj[5] = $"Bounds = {((Bounds)(ref bounds)).size}";
		Debug.Log((object)string.Concat(obj));
		if ((Object)(object)enemyCollider != (Object)null)
		{
			Bounds bounds2 = enemyCollider.bounds;
			enemyHeightOffset = (((Bounds)(ref bounds2)).center - ((Component)enemy).transform.position).y + ((Bounds)(ref bounds2)).extents.y;
		}
		Transform val2 = ((Component)this).transform.Find("LeftBorder");
		Transform val3 = ((Component)this).transform.Find("RightBorder");
		if ((Object)(object)val2 != (Object)null)
		{
			ref RectTransform reference = ref leftFiller;
			Transform obj2 = val2.Find("LeftFiller");
			reference = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
		}
		else
		{
			Debug.LogError((object)("[TrackerPanel] LeftBorder NOT FOUND on tracker prefab. Tracker: " + ((Object)((Component)this).gameObject).name));
		}
		if ((Object)(object)val3 != (Object)null)
		{
			ref RectTransform reference2 = ref rightFiller;
			Transform obj3 = val3.Find("RightFiller");
			reference2 = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
		}
		else
		{
			Debug.LogError((object)("[TrackerPanel] RightBorder NOT FOUND on tracker prefab. Tracker: " + ((Object)((Component)this).gameObject).name));
		}
	}

	private void UpdateHealthFillers()
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemyComponent == (Object)null)
		{
			return;
		}
		if (enemyComponent.originalHealth <= 0f)
		{
			Debug.LogError((object)$"[TrackerPanel] Invalid originalHealth for {((Object)enemy).name}: {enemyComponent.originalHealth}");
			return;
		}
		float y = Mathf.Clamp01(enemyComponent.health / enemyComponent.originalHealth);
		if ((Object)(object)leftFiller != (Object)null)
		{
			Vector2 anchorMax = leftFiller.anchorMax;
			anchorMax.y = y;
			leftFiller.anchorMax = anchorMax;
		}
		if ((Object)(object)rightFiller != (Object)null)
		{
			Vector2 anchorMax2 = rightFiller.anchorMax;
			anchorMax2.y = y;
			rightFiller.anchorMax = anchorMax2;
		}
	}

	private void LateUpdate()
	{
		//IL_00e3: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: 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)
		//IL_010b: 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_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemy == (Object)null || enemy.dead || enemy.health <= 0f || (Object)(object)((Component)enemy).transform == (Object)null)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		UpdateInvincibilityColor();
		UpdateHealthFillers();
		if ((Object)(object)rectTransform == (Object)null)
		{
			return;
		}
		if ((Object)(object)mainCamera == (Object)null)
		{
			if ((Object)(object)MonoSingleton<CameraController>.Instance != (Object)null)
			{
				mainCamera = MonoSingleton<CameraController>.Instance.cam;
			}
			else
			{
				mainCamera = Camera.main;
			}
			if ((Object)(object)mainCamera == (Object)null)
			{
				return;
			}
		}
		Vector3 val = ((Component)enemy).transform.position + Vector3.up * (enemyHeightOffset * 0.5f);
		Vector3 screenPoint = mainCamera.WorldToScreenPoint(val);
		ApplyPostProcessCorrection(ref screenPoint);
		if (screenPoint.z < 0f)
		{
			((Transform)rectTransform).position = new Vector3(-9999f, -9999f, 0f);
			return;
		}
		((Transform)rectTransform).position = screenPoint;
		UpdateTrackerSize();
	}

	private void UpdateTrackerSize()
	{
		//IL_001e: 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_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_0035: 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_003d: 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_0049: 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_0054: 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_0061: 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_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_007f: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00ae: 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_00bb: 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_00c7: 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_00d3: 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)
		//IL_00df: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: 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_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: 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_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: 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_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)enemyCollider == (Object)null)
		{
			return;
		}
		Bounds bounds = enemyCollider.bounds;
		Vector3[] array = (Vector3[])(object)new Vector3[8];
		Vector3 min = ((Bounds)(ref bounds)).min;
		Vector3 max = ((Bounds)(ref bounds)).max;
		array[0] = new Vector3(min.x, min.y, min.z);
		array[1] = new Vector3(min.x, min.y, max.z);
		array[2] = new Vector3(min.x, max.y, min.z);
		array[3] = new Vector3(min.x, max.y, max.z);
		array[4] = new Vector3(max.x, min.y, min.z);
		array[5] = new Vector3(max.x, min.y, max.z);
		array[6] = new Vector3(max.x, max.y, min.z);
		array[7] = new Vector3(max.x, max.y, max.z);
		float num = float.MaxValue;
		float num2 = float.MinValue;
		float num3 = float.MaxValue;
		float num4 = float.MinValue;
		bool flag = false;
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 screenPoint = mainCamera.WorldToScreenPoint(array[i]);
			if (!(screenPoint.z < 0f))
			{
				ApplyPostProcessCorrection(ref screenPoint);
				if (screenPoint.x < num)
				{
					num = screenPoint.x;
				}
				if (screenPoint.x > num2)
				{
					num2 = screenPoint.x;
				}
				if (screenPoint.y < num3)
				{
					num3 = screenPoint.y;
				}
				if (screenPoint.y > num4)
				{
					num4 = screenPoint.y;
				}
				flag = true;
			}
		}
		if (!flag)
		{
			return;
		}
		float num5 = num2 - num;
		float num6 = num4 - num3;
		if (num5 <= 0.01f || num6 <= 0.01f)
		{
			return;
		}
		if (!aspectRatioInitialized)
		{
			float num7 = num5 / num6;
			if (num7 >= 0.05f && num7 <= 20f)
			{
				enemyAspectRatio = num7;
				aspectRatioInitialized = true;
				Debug.Log((object)$"[TrackerPanel] Aspect ratio initialized for {((Object)enemy).name}: {enemyAspectRatio:F3}");
			}
			else
			{
				enemyAspectRatio = 1f;
				aspectRatioInitialized = true;
				Debug.LogWarning((object)$"[TrackerPanel] Invalid aspect ratio for {((Object)enemy).name}: {num7:F3}. Using 1:1.");
			}
		}
		float num8 = Mathf.Min(num6, 700f);
		float num9 = Mathf.Min(num5, 700f * enemyAspectRatio);
		if (!(num9 <= 0f) && !(num8 <= 0f))
		{
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, num9);
			rectTransform.SetSizeWithCurrentAnchors((Axis)1, num8);
		}
	}

	private void ApplyPostProcessCorrection(ref Vector3 screenPoint)
	{
		if ((Object)(object)MonoSingleton<PostProcessV2_Handler>.Instance != (Object)null)
		{
			int privateField = GetPrivateField<int>(MonoSingleton<PostProcessV2_Handler>.Instance, "width");
			int privateField2 = GetPrivateField<int>(MonoSingleton<PostProcessV2_Handler>.Instance, "height");
			if (privateField > 0 && privateField2 > 0)
			{
				screenPoint.x *= (float)Screen.width / (float)privateField;
				screenPoint.y *= (float)Screen.height / (float)privateField2;
			}
		}
	}

	private T GetPrivateField<T>(object instance, string fieldName)
	{
		if (instance == null)
		{
			return default(T);
		}
		FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			return default(T);
		}
		return (T)field.GetValue(instance);
	}
}
[BepInPlugin("betterhud", "BetterHud", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
	[Serializable]
	private class StarterPanelConfig
	{
		public string[] texts;
	}

	private const string BundleName = "myui2";

	private const string PrefabName = "MyHUD";

	private const string UIDllName = "UltrakillUnityPrefab.dll";

	private Harmony _harmony;

	private const bool StarterPanelRandom = true;

	private const int StarterPanelTextIndex = 0;

	private AssetBundle _bundle;

	private GameObject _hudInstance;

	private Image _fillerImage;

	private TMP_Text _starterPanelText;

	private static string ModFolder => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

	private void Awake()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] StartePanel is awake!");
		try
		{
			_harmony = new Harmony("betterhudmod");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[BetterHud][Harmony] PatchAll SUCCESS!");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[BetterHud][Harmony] PatchAll FAILED:\n{arg}");
		}
		LoadUIDll();
		PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Combine(PrefsManager.onPrefChanged, new Action<string, object>(OnPreferenceChanged));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] Subscribed to PrefsManager.onPrefChanged");
		((Component)this).gameObject.AddComponent<HeavyDamageVisualEffect>();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[BetterHud][HeavyEffect] HeavyDamageVisualEffect component added!");
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Remove(PrefsManager.onPrefChanged, new Action<string, object>(OnPreferenceChanged));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] Unsubscribed from PrefsManager.onPrefChanged");
		try
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[BetterHud][Harmony] Harmony patches removed.");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[BetterHud][Harmony] Failed to unpatch:\n{arg}");
		}
		CleanupHUDReferences();
		UnloadAssetBundle();
	}

	private void LoadUIDll()
	{
		string text = Path.Combine(ModFolder, "UltrakillUnityPrefab.dll");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[StartPanel] Looking for UI DLL: " + text));
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[StartPanel] UI DLL not found: " + text));
			return;
		}
		try
		{
			Assembly.LoadFrom(text);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] UltrakillUnityPrefab.dll successfully loaded!");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[StartPanel] Failed to load UI DLL: {arg}");
		}
	}

	private void CleanupHUDReferences()
	{
		if ((Object)(object)_hudInstance != (Object)null)
		{
			Object.Destroy((Object)(object)_hudInstance);
			_hudInstance = null;
		}
		_fillerImage = null;
		_starterPanelText = null;
	}

	private void UnloadAssetBundle()
	{
		if ((Object)(object)_bundle != (Object)null)
		{
			_bundle.Unload(false);
			_bundle = null;
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		string currentScene = SceneHelper.CurrentScene;
		((BaseUnityPlugin)this).Logger.LogInfo((object)currentScene);
		if (!IsIgnoredScene(currentScene))
		{
			SpawnTrackerPanel();
			if (!((Object)(object)_hudInstance != (Object)null) && TryFindGunCanvas(out var gunCanvas))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] GunCanvas found!");
				((MonoBehaviour)this).StartCoroutine(LoadHUDCoroutine(gunCanvas));
			}
		}
	}

	private bool IsIgnoredScene(string sceneName)
	{
		return sceneName == "Main Menu" || sceneName == "Intro" || sceneName == "Bootstrap";
	}

	private void SpawnTrackerPanel()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		GameObject val = new GameObject("TrackerPanelScript");
		val.AddComponent<Trackpanel>();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[TrackerPanel] Tracker Panel script loaded!");
	}

	private bool TryFindGunCanvas(out GameObject gunCanvas)
	{
		gunCanvas = null;
		GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
		GameObject[] array2 = array;
		foreach (GameObject val in array2)
		{
			if ((Object)(object)val != (Object)null && ((Object)val).name == "GunCanvas")
			{
				gunCanvas = val;
				return true;
			}
		}
		return false;
	}

	private void OnPreferenceChanged(string key, object value)
	{
		if (!(key != "hudBackgroundOpacity"))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[StartPanel] hudBackgroundOpacity changed: {value}");
			if (value is float opacity)
			{
				UpdateFillerOpacity(opacity);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"[StartPanel] hudBackgroundOpacity has unexpected type: {value?.GetType()}");
			}
		}
	}

	private IEnumerator LoadHUDCoroutine(GameObject gunCanvas)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] Waiting 1 second before loading MyHUD...");
		yield return (object)new WaitForSeconds(1f);
		if ((Object)(object)gunCanvas == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] GunCanvas became null during the delay!");
		}
		else
		{
			if (!TryEnsureBundleLoaded())
			{
				yield break;
			}
			GameObject prefab = _bundle.LoadAsset<GameObject>("MyHUD");
			if ((Object)(object)prefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Prefab 'MyHUD' not found in AssetBundle!");
				yield break;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] MyHUD prefab found!");
			if (TryInstantiateHUD(prefab, gunCanvas))
			{
				BindUIComponents();
				_hudInstance.SetActive(true);
				UpdateFillerOpacityFromPrefs();
				LoadStarterPanelText();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] MyHUD successfully added to GunCanvas!");
			}
		}
	}

	private bool TryEnsureBundleLoaded()
	{
		if ((Object)(object)_bundle != (Object)null)
		{
			return true;
		}
		string text = Path.Combine(ModFolder, "myui2");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[StartPanel] Looking for AssetBundle: " + text));
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[StartPanel] AssetBundle not found: " + text));
			return false;
		}
		_bundle = AssetBundle.LoadFromFile(text);
		if ((Object)(object)_bundle == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Failed to load AssetBundle!");
			return false;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] AssetBundle successfully loaded!");
		return true;
	}

	private bool TryInstantiateHUD(GameObject prefab, GameObject parentCanvas)
	{
		try
		{
			_hudInstance = Object.Instantiate<GameObject>(prefab);
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[StartPanel] Failed to instantiate MyHUD: {arg}");
			return false;
		}
		if ((Object)(object)_hudInstance == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] MyHUD instance is null!");
			return false;
		}
		RectTransform component = _hudInstance.GetComponent<RectTransform>();
		if ((Object)(object)component == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] MyHUD does not have a RectTransform!");
			Object.Destroy((Object)(object)_hudInstance);
			_hudInstance = null;
			return false;
		}
		((Transform)component).SetParent(parentCanvas.transform, false);
		return true;
	}

	private void BindUIComponents()
	{
		Transform val = _hudInstance.transform.Find("Filler");
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Filler not found inside MyHUD!");
			return;
		}
		_fillerImage = ((Component)val).GetComponent<Image>();
		if ((Object)(object)_fillerImage == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Filler does not have an Image component!");
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] Filler Image found!");
		}
		Transform val2 = val.Find("Viewport/Content/Text");
		if ((Object)(object)val2 == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Text not found at Filler/Viewport/Content/Text!");
			return;
		}
		_starterPanelText = ((Component)val2).GetComponent<TMP_Text>();
		if ((Object)(object)_starterPanelText == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] Text does not have a TMP_Text component!");
		}
		else
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[StartPanel] TextMeshPro component found!");
		}
	}

	private void UpdateFillerOpacity(float opacity)
	{
		//IL_004a: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_fillerImage == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[StartPanel] FillerImage is null, cannot update opacity!");
			return;
		}
		if (opacity > 10f)
		{
			opacity -= 10f;
		}
		float num = opacity / 100f;
		Color color = ((Graphic)_fillerImage).color;
		color.a = num;
		((Graphic)_fillerImage).color = color;
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"[StartPanel] FillerImage alpha updated: {num}");
	}

	private void UpdateFillerOpacityFromPrefs()
	{
		if (!((Object)(object)_fillerImage == (Object)null))
		{
			float opacity = MonoSingleton<PrefsManager>.Instance.GetFloat("hudBackgroundOpacity", 50f);
			UpdateFillerOpacity(opacity);
		}
	}

	private void LoadStarterPanelText()
	{
		StarterPanelConfig config;
		string text;
		if ((Object)(object)_starterPanelText == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] StarterPanel TMP_Text is null!");
		}
		else if (TryLoadStarterConfig(out config) && TrySelectText(config, out text))
		{
			_starterPanelText.text = text;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[StartPanel] StarterPanel text set: \"" + text + "\""));
		}
	}

	private bool TryLoadStarterConfig(out StarterPanelConfig config)
	{
		config = null;
		string text = Path.Combine(ModFolder, "Config", "StarterPanel.json");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[StartPanel] Looking for StarterPanel.json: " + text));
		if (!File.Exists(text))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[StartPanel] StarterPanel.json not found: " + text));
			return false;
		}
		try
		{
			string text2 = File.ReadAllText(text);
			config = JsonUtility.FromJson<StarterPanelConfig>(text2);
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[StartPanel] Failed to read/parse StarterPanel.json: {arg}");
			return false;
		}
		if (config == null || config.texts == null || config.texts.Length == 0)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[StartPanel] StarterPanel.json is invalid or contains no texts!");
			return false;
		}
		return true;
	}

	private bool TrySelectText(StarterPanelConfig config, out string text)
	{
		text = null;
		bool flag = true;
		int num = Random.Range(0, config.texts.Length);
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"[StartPanel] StarterPanelRandom = true, selected index: {num}");
		text = config.texts[num];
		return true;
	}
}

plugins/UltrakillUnityPrefab.dll

Decompiled 20 hours ago
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BetterHud;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("UltrakillUnityPrefab")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UltrakillUnityPrefab")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3d5cf763-b102-46a5-9f37-ac76af31d7fe")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
public class SimpleTypewriter : MonoBehaviour
{
	[Header("UI")]
	[SerializeField]
	private GameObject myUI;

	[SerializeField]
	private GameObject filler;

	[SerializeField]
	private GameObject viewport;

	[SerializeField]
	private GameObject content;

	[SerializeField]
	private TMP_Text textComponent;

	[SerializeField]
	private ScrollRect scrollRect;

	[Header("Анимация текста")]
	[SerializeField]
	private float timeBetweenChars = 0.03f;

	[Header("Исчезновение Content")]
	[SerializeField]
	private float delayBeforeDisappear = 2f;

	[Header("Анимация закрытия MyUI")]
	[SerializeField]
	private BetterUIHudOpenEffect openEffect;

	private string fullText;

	private Coroutine typingCoroutine;

	private RectTransform contentTransform;

	private RectTransform viewportTransform;

	private Vector2 initialContentSize;

	private void Awake()
	{
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Expected O, but got Unknown
		textComponent.text = "";
		((MonoBehaviour)this).StartCoroutine(WaitForText());
		if ((Object)(object)textComponent == (Object)null)
		{
			textComponent = ((Component)this).GetComponent<TMP_Text>();
		}
		if ((Object)(object)scrollRect == (Object)null)
		{
			scrollRect = ((Component)this).GetComponentInParent<ScrollRect>();
		}
		if ((Object)(object)content == (Object)null)
		{
			content = (((Object)(object)((Component)this).transform.parent != (Object)null) ? ((Component)((Component)this).transform.parent).gameObject : null);
		}
		if ((Object)(object)content != (Object)null)
		{
			contentTransform = content.GetComponent<RectTransform>();
			if ((Object)(object)contentTransform != (Object)null)
			{
				initialContentSize = contentTransform.sizeDelta;
			}
		}
		if ((Object)(object)scrollRect != (Object)null && (Object)(object)scrollRect.viewport != (Object)null)
		{
			viewportTransform = scrollRect.viewport;
		}
		if ((Object)(object)myUI == (Object)null)
		{
			Transform val = ((Component)this).transform;
			while ((Object)(object)val.parent != (Object)null)
			{
				val = val.parent;
			}
			myUI = ((Component)val).gameObject;
		}
		if ((Object)(object)openEffect == (Object)null && (Object)(object)myUI != (Object)null)
		{
			openEffect = myUI.GetComponent<BetterUIHudOpenEffect>();
		}
		if ((Object)(object)viewport == (Object)null && (Object)(object)scrollRect != (Object)null && (Object)(object)scrollRect.viewport != (Object)null)
		{
			viewport = ((Component)scrollRect.viewport).gameObject;
		}
		if ((Object)(object)filler == (Object)null && (Object)(object)viewport != (Object)null && (Object)(object)viewport.transform.parent != (Object)null)
		{
			filler = ((Component)viewport.transform.parent).gameObject;
		}
		if ((Object)(object)openEffect != (Object)null)
		{
			openEffect.onAnimationComplete.AddListener(new UnityAction(StartTypingAfterOpen));
		}
	}

	private void OnDestroy()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		if ((Object)(object)openEffect != (Object)null)
		{
			openEffect.onAnimationComplete.RemoveListener(new UnityAction(StartTypingAfterOpen));
		}
	}

	private void StartTypingAfterOpen()
	{
		if ((Object)(object)textComponent == (Object)null)
		{
			Debug.LogError((object)"[SimpleTypewriter] StartTypingAfterOpen(): textComponent не найден.");
		}
		else
		{
			StartTyping(textComponent.text);
		}
	}

	public void StartTyping(string textToType)
	{
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		if (typingCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(typingCoroutine);
		}
		if ((Object)(object)myUI != (Object)null)
		{
			myUI.SetActive(true);
		}
		if ((Object)(object)filler != (Object)null)
		{
			filler.SetActive(true);
		}
		if ((Object)(object)viewport != (Object)null)
		{
			viewport.SetActive(true);
		}
		if ((Object)(object)content != (Object)null)
		{
			content.SetActive(true);
			if ((Object)(object)contentTransform != (Object)null)
			{
				contentTransform.sizeDelta = initialContentSize;
			}
		}
		if ((Object)(object)textComponent != (Object)null)
		{
			((Component)textComponent).gameObject.SetActive(true);
		}
		if ((Object)(object)scrollRect != (Object)null)
		{
			scrollRect.StopMovement();
			scrollRect.verticalNormalizedPosition = 1f;
		}
		fullText = textToType;
		typingCoroutine = ((MonoBehaviour)this).StartCoroutine(TypeTextAndShrink());
	}

	private IEnumerator TypeTextAndShrink()
	{
		if ((Object)(object)textComponent == (Object)null)
		{
			Debug.LogError((object)"[SimpleTypewriter] TypeTextAndShrink(): textComponent не найден.");
			yield break;
		}
		textComponent.text = fullText;
		textComponent.maxVisibleCharacters = 0;
		textComponent.ForceMeshUpdate(false, false);
		Canvas.ForceUpdateCanvases();
		for (int i = 0; i <= fullText.Length; i++)
		{
			textComponent.maxVisibleCharacters = i;
			textComponent.ForceMeshUpdate(false, false);
			UpdateContentAndScroll();
			yield return (object)new WaitForSeconds(timeBetweenChars);
		}
		yield return (object)new WaitForSeconds(delayBeforeDisappear);
		textComponent.text = "";
		textComponent.maxVisibleCharacters = 0;
		textComponent.ForceMeshUpdate(false, false);
		Canvas.ForceUpdateCanvases();
		if ((Object)(object)content != (Object)null)
		{
			content.SetActive(false);
		}
		if ((Object)(object)openEffect != (Object)null)
		{
			openEffect.Reverse();
		}
		else if ((Object)(object)myUI != (Object)null)
		{
			myUI.SetActive(false);
		}
		typingCoroutine = null;
	}

	private void UpdateContentAndScroll()
	{
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: 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_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)textComponent == (Object)null)
		{
			Debug.LogError((object)"[SimpleTypewriter] UpdateContentAndScroll(): textComponent не найден.");
			return;
		}
		if ((Object)(object)contentTransform == (Object)null)
		{
			Debug.LogError((object)"[SimpleTypewriter] UpdateContentAndScroll(): contentTransform не найден.");
			return;
		}
		if ((Object)(object)scrollRect == (Object)null)
		{
			Debug.LogError((object)"[SimpleTypewriter] UpdateContentAndScroll(): scrollRect не найден.");
			return;
		}
		if ((Object)(object)viewportTransform == (Object)null)
		{
			viewportTransform = scrollRect.viewport;
			if ((Object)(object)viewportTransform == (Object)null)
			{
				Debug.LogError((object)"[SimpleTypewriter] UpdateContentAndScroll(): viewportTransform не найден.");
				return;
			}
		}
		textComponent.ForceMeshUpdate(false, false);
		Canvas.ForceUpdateCanvases();
		LayoutRebuilder.ForceRebuildLayoutImmediate(contentTransform);
		float preferredHeight = textComponent.preferredHeight;
		Rect rect = viewportTransform.rect;
		float height = ((Rect)(ref rect)).height;
		float num = Mathf.Max(preferredHeight, height);
		Vector2 sizeDelta = contentTransform.sizeDelta;
		sizeDelta.y = num;
		contentTransform.sizeDelta = sizeDelta;
		Canvas.ForceUpdateCanvases();
		LayoutRebuilder.ForceRebuildLayoutImmediate(contentTransform);
		rect = viewportTransform.rect;
		if (num > ((Rect)(ref rect)).height)
		{
			contentTransform.anchorMin = new Vector2(0f, 0f);
			contentTransform.anchorMax = new Vector2(1f, 0f);
			contentTransform.pivot = new Vector2(0.5f, 0f);
			textComponent.alignment = (TextAlignmentOptions)1025;
			scrollRect.verticalNormalizedPosition = 0f;
		}
		else
		{
			scrollRect.verticalNormalizedPosition = 1f;
		}
		scrollRect.StopMovement();
	}

	private IEnumerator WaitForText()
	{
		while (string.IsNullOrEmpty(textComponent.text))
		{
			yield return null;
		}
		Debug.Log((object)("[SimpleTypewriter] Text received: '" + textComponent.text + "'"));
		if ((Object)(object)openEffect != (Object)null)
		{
			openEffect.onAnimationComplete.AddListener(new UnityAction(StartTypingAfterOpen));
			Debug.Log((object)"[SimpleTypewriter] Subscribed to onAnimationComplete.");
		}
		else
		{
			Debug.LogError((object)"[SimpleTypewriter] WaitForText(): openEffect не найден.");
		}
	}
}
namespace BetterHud;

public class BetterUIHudOpenEffect : MonoBehaviour
{
	[Header("UI hierarchy")]
	[SerializeField]
	private RectTransform myUI;

	[SerializeField]
	private RectTransform filler;

	[SerializeField]
	private RectTransform viewport;

	[SerializeField]
	private RectTransform content;

	private RectTransform tran;

	[HideInInspector]
	public Vector2 originalDimensions;

	[HideInInspector]
	public Vector2 targetDimensions;

	[HideInInspector]
	public bool gotValues;

	public bool animating;

	public float speed = 30f;

	[HideInInspector]
	public float originalSpeed;

	public bool skip;

	public bool reverse;

	public bool YFirst;

	public bool dontUseScale;

	public UnityEvent onAnimationComplete;

	private void Awake()
	{
		Initialize();
	}

	private void Initialize()
	{
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)tran == (Object)null)
		{
			tran = ((Component)this).GetComponent<RectTransform>();
		}
		if ((Object)(object)tran == (Object)null)
		{
			Debug.LogError((object)("[BetterUIHudOpenEffect] Не найден RectTransform на " + ((Object)((Component)this).gameObject).name));
			return;
		}
		if ((Object)(object)myUI == (Object)null)
		{
			myUI = tran;
		}
		if ((Object)(object)filler == (Object)null && ((Transform)myUI).childCount > 0)
		{
			ref RectTransform reference = ref filler;
			Transform child = ((Transform)myUI).GetChild(0);
			reference = (RectTransform)(object)((child is RectTransform) ? child : null);
		}
		if ((Object)(object)viewport == (Object)null && (Object)(object)filler != (Object)null && ((Transform)filler).childCount > 0)
		{
			ref RectTransform reference2 = ref viewport;
			Transform child2 = ((Transform)filler).GetChild(0);
			reference2 = (RectTransform)(object)((child2 is RectTransform) ? child2 : null);
		}
		if ((Object)(object)content == (Object)null && (Object)(object)viewport != (Object)null && ((Transform)viewport).childCount > 0)
		{
			ref RectTransform reference3 = ref content;
			Transform child3 = ((Transform)viewport).GetChild(0);
			reference3 = (RectTransform)(object)((child3 is RectTransform) ? child3 : null);
		}
		if (!gotValues)
		{
			originalDimensions = (Vector2)(dontUseScale ? tran.sizeDelta : new Vector2(((Transform)tran).localScale.x, ((Transform)tran).localScale.y));
			targetDimensions = originalDimensions;
			originalSpeed = speed;
			gotValues = true;
		}
	}

	private void OnEnable()
	{
		ResetValues();
	}

	private void Update()
	{
		//IL_0033: 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_006a: 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_0206: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
		if (!animating)
		{
			return;
		}
		float num = (dontUseScale ? (tran.sizeDelta.x / originalDimensions.x) : ((Transform)tran).localScale.x);
		float num2 = (dontUseScale ? (tran.sizeDelta.y / originalDimensions.y) : ((Transform)tran).localScale.y);
		if (!skip)
		{
			if (YFirst && !Mathf.Approximately(num2, targetDimensions.y))
			{
				num2 = Mathf.MoveTowards(num2, targetDimensions.y, Time.unscaledDeltaTime * (Mathf.Abs(targetDimensions.y - num2) + 0.1f) * speed);
			}
			else if (!Mathf.Approximately(num, targetDimensions.x))
			{
				num = Mathf.MoveTowards(num, targetDimensions.x, Time.unscaledDeltaTime * (Mathf.Abs(targetDimensions.x - num) + 0.1f) * speed);
			}
			else if (!Mathf.Approximately(num2, targetDimensions.y))
			{
				num2 = Mathf.MoveTowards(num2, targetDimensions.y, Time.unscaledDeltaTime * (Mathf.Abs(targetDimensions.y - num2) + 0.1f) * speed);
			}
		}
		else
		{
			num = targetDimensions.x;
			num2 = targetDimensions.y;
		}
		if (dontUseScale)
		{
			tran.sizeDelta = new Vector2(num * originalDimensions.x, num2 * originalDimensions.y);
		}
		else
		{
			((Transform)tran).localScale = new Vector3(num, num2, ((Transform)tran).localScale.z);
		}
		if (Mathf.Approximately(num, targetDimensions.x) && Mathf.Approximately(num2, targetDimensions.y))
		{
			animating = false;
			UnityEvent obj = onAnimationComplete;
			if (obj != null)
			{
				obj.Invoke();
			}
			if (reverse)
			{
				((Component)myUI).gameObject.SetActive(false);
			}
		}
	}

	public Vector2 GetOriginalDimensions()
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Initialize();
		return originalDimensions;
	}

	public void Force()
	{
		Initialize();
	}

	public void ResetValues()
	{
		ResetValues(null);
	}

	public void ResetValues(Vector2? inheritedOriginalDimensions)
	{
		//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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		Initialize();
		if (inheritedOriginalDimensions.HasValue)
		{
			originalDimensions = inheritedOriginalDimensions.Value;
			gotValues = true;
		}
		speed = originalSpeed;
		if (skip)
		{
			return;
		}
		if (reverse)
		{
			Reverse(speed);
			return;
		}
		targetDimensions = originalDimensions;
		if (dontUseScale)
		{
			tran.sizeDelta = originalDimensions;
		}
		else
		{
			((Transform)tran).localScale = new Vector3(0.05f, 0.05f, ((Transform)tran).localScale.z);
		}
		animating = true;
	}

	public void Reverse(float newSpeed = 10f)
	{
		//IL_0013: 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)
		Initialize();
		targetDimensions = new Vector2(1f, 0f);
		speed = newSpeed;
		reverse = true;
		animating = true;
	}
}