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(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[] colorSteps = new Tuple[5] { Tuple.Create(0f, Color.white), Tuple.Create(0.0333f, Color.black), Tuple.Create(0.0667f, Color.white), Tuple.Create(0.1333f, Color.black), Tuple.Create(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(); frontLayerImage = ((Component)((Component)this).transform.Find("DeathCrossFrontLayer")).gameObject.GetComponent(); Image component = ((Component)this).gameObject.GetComponent(); ((Graphic)component).color = ConfigManager.AccentColor.value; colorSteps[^1] = Tuple.Create(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(); 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.Instance.cam.WorldToScreenPoint(GetMarkPosition()); int privateField = MonoSingleton.Instance.GetPrivateField("width"); int privateField2 = MonoSingleton.Instance.GetPrivateField("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("DeathCross"); DeathCrossCanvasPrefab = obj.LoadAsset("DeathCrossCanvas"); DeathCrossCanvas = Object.Instantiate(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(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(Plugin.DeathCrossPrefab, Plugin.DeathCrossCanvas.transform); obj.GetComponent().alpha = 0f; obj.AddComponent().enemy = __instance; } } } }