Decompiled source of Crossover v1.0.0

plugins\Crossover.dll

Decompiled 19 hours ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
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("Crossover")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+bde1bfeb7ae7cc5ed6b76bb8e48c2a27ed934b99")]
[assembly: AssemblyProduct("Crossover")]
[assembly: AssemblyTitle("Crossover")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Crossover
{
	public class ConfigManager
	{
		public static PluginConfigurator config;

		public static BoolField Enable;

		public static ColorField AccentColor;

		public static FloatField StartScale;

		public static FloatField EndScale;

		public static FloatField EnemyHealthThreshold;

		public static FloatSliderField CrossMarkOpacity;

		public static void Initialize()
		{
		}

		static ConfigManager()
		{
			//IL_0048: 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_006d: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			config = PluginConfigurator.Create("Crossover", "com.github.end-4.crossover");
			string text = Path.Combine(Plugin.workingDir, "icon.png");
			if (File.Exists(text))
			{
				config.SetIconWithURL(text);
			}
			new ConfigHeader(config.rootPanel, "", 10);
			Enable = new BoolField(config.rootPanel, "Enable death crosses", "enable", true);
			AccentColor = new ColorField(config.rootPanel, "Cross accent color", "accentColor", new Color(73f / 85f, 0.11764706f, 19f / 85f));
			StartScale = new FloatField(config.rootPanel, "Cross starting scale", "startScale", 2f);
			EndScale = new FloatField(config.rootPanel, "Cross ending scale", "endScale", 0.35f);
			EnemyHealthThreshold = new FloatField(config.rootPanel, "Enemy health threshold", "enemyHealthThreshold", 0f);
			CrossMarkOpacity = new FloatSliderField(config.rootPanel, "Cross mark opacity", "crossMarkOpacity", new Tuple<float, float>(0f, 1f), 1f);
		}
	}
	public class CrossBehavior : MonoBehaviour
	{
		private enum State
		{
			Hidden,
			Marking
		}

		public float markLifetime = 0.4f;

		public float scalingDuration = 0.1333f;

		public float startScale = 1f;

		public float endScale = 0.2f;

		public Tuple<float, Color>[] colorSteps = new Tuple<float, Color>[5]
		{
			Tuple.Create<float, Color>(0f, Color.white),
			Tuple.Create<float, Color>(0.0333f, Color.black),
			Tuple.Create<float, Color>(0.0667f, Color.white),
			Tuple.Create<float, Color>(0.1333f, Color.black),
			Tuple.Create<float, Color>(0.2f, Color.red)
		};

		public EnemyIdentifier enemy;

		private CanvasGroup canvasGroup;

		private float enemyHeight;

		private RectTransform rectTransform;

		private Image frontLayerImage;

		private State state;

		private float startMarkTime;

		private Vector3 targetPoint;

		private Vector3 lastEnemyPosition = Vector3.zero;

		private float scaleDiff => startScale - endScale;

		private void Awake()
		{
			//IL_003e: 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)
			canvasGroup = ((Component)this).GetComponent<CanvasGroup>();
			frontLayerImage = ((Component)((Component)this).transform.Find("DeathCrossFrontLayer")).gameObject.GetComponent<Image>();
			Image component = ((Component)this).gameObject.GetComponent<Image>();
			((Graphic)component).color = ConfigManager.AccentColor.value;
			colorSteps[^1] = Tuple.Create<float, Color>(colorSteps[^1].Item1, ((Graphic)component).color);
			startScale = ConfigManager.StartScale.value;
			endScale = ConfigManager.EndScale.value;
		}

		private void Start()
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			ref RectTransform reference = ref rectTransform;
			Transform transform = ((Component)this).transform;
			reference = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Collider component = ((Component)enemy).GetComponent<Collider>();
			Bounds bounds = component.bounds;
			float y = (((Bounds)(ref bounds)).center - ((Component)enemy).transform.position).y;
			bounds = component.bounds;
			enemyHeight = y + ((Bounds)(ref bounds)).extents.y;
		}

		private float Curve(float x)
		{
			float num = Math.Clamp(x, 0f, 1f);
			float num2 = 1f - num;
			return 1f - num2 * num2 * num2;
		}

		private Vector3 GetMarkPosition()
		{
			//IL_0038: 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_004e: 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_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)
			if ((Object)(object)enemy != (Object)null && (Object)(object)((Component)enemy).transform != (Object)null)
			{
				lastEnemyPosition = ((Component)enemy).transform.position;
			}
			return lastEnemyPosition + enemyHeight / 2f * Vector3.up;
		}

		private void UpdateTargetPoint()
		{
			//IL_000c: 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)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			targetPoint = MonoSingleton<CameraController>.Instance.cam.WorldToScreenPoint(GetMarkPosition());
			int privateField = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("width");
			int privateField2 = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("height");
			targetPoint.x *= Screen.width;
			targetPoint.y *= Screen.height;
			targetPoint.x /= privateField;
			targetPoint.y /= privateField2;
			((Transform)rectTransform).position = targetPoint;
		}

		private void UpdateColor(float elapsedTime)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			int i = 0;
			if (!(elapsedTime < 0f))
			{
				for (; i < colorSteps.Length && elapsedTime >= colorSteps[i].Item1; i++)
				{
				}
				((Graphic)frontLayerImage).color = colorSteps[i - 1].Item2;
			}
		}

		private void SetScale(float newScale)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			((Transform)rectTransform).localScale = new Vector3(newScale, newScale, newScale);
		}

		private void UpdateScale(float percentage)
		{
			float scale = startScale - Curve(percentage) * scaleDiff;
			SetScale(scale);
		}

		private void Update()
		{
			if (state == State.Hidden && ((Object)(object)enemy == (Object)null || enemy.health <= 0f))
			{
				state = State.Marking;
				startMarkTime = Time.time;
				canvasGroup.alpha = ConfigManager.CrossMarkOpacity.value;
			}
			if (state != 0)
			{
				float num = Time.time - startMarkTime;
				UpdateColor(num);
				UpdateScale(num / scalingDuration);
				UpdateTargetPoint();
				if (Time.time - startMarkTime >= markLifetime)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
		}
	}
	[BepInPlugin("com.github.end-4.crossover", "Crossover", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource? Log;

		public static string workingPath = Assembly.GetExecutingAssembly().Location;

		public static string workingDir = Path.GetDirectoryName(workingPath);

		public const string PluginGUID = "com.github.end-4.crossover";

		public const string PluginName = "Crossover";

		public const string PluginVersion = "1.0.0";

		internal static GameObject DeathCrossPrefab;

		internal static GameObject DeathCrossCanvasPrefab;

		internal static GameObject DeathCrossCanvas;

		private static readonly string BundlePath = Path.Combine(workingDir, "assets", "crossover.bundle");

		private void LoadObjects()
		{
			AssetBundle obj = AssetBundle.LoadFromFile(BundlePath);
			if ((Object)(object)obj == (Object)null)
			{
				Log.LogError((object)"Couldn't load asset bundle");
			}
			DeathCrossPrefab = obj.LoadAsset<GameObject>("DeathCross");
			DeathCrossCanvasPrefab = obj.LoadAsset<GameObject>("DeathCrossCanvas");
			DeathCrossCanvas = Object.Instantiate<GameObject>(DeathCrossCanvasPrefab);
			Object.DontDestroyOnLoad((Object)(object)DeathCrossCanvas);
			((Object)DeathCrossCanvas).hideFlags = (HideFlags)61;
		}

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigManager.Initialize();
			LoadObjects();
			new Harmony("Crossover").PatchAll();
			Log.LogInfo((object)"Crossover loaded!");
		}
	}
	internal static class Utils
	{
		public static T GetPrivateField<T>(this object obj, string field)
		{
			Type type = obj.GetType();
			if (type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic) == null)
			{
				throw new ArgumentException("The field " + field + " does not exist in target class " + type.Name + "!");
			}
			return (T)type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
		}
	}
}
namespace Crossover.Patches
{
	[HarmonyPatch(typeof(EnemyIdentifier))]
	public class EnemyPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void EnemySpawned(EnemyIdentifier __instance)
		{
			if (ConfigManager.Enable.value && !(__instance.health < ConfigManager.EnemyHealthThreshold.value))
			{
				GameObject obj = Object.Instantiate<GameObject>(Plugin.DeathCrossPrefab, Plugin.DeathCrossCanvas.transform);
				obj.GetComponent<CanvasGroup>().alpha = 0f;
				obj.AddComponent<CrossBehavior>().enemy = __instance;
			}
		}
	}
}