Decompiled source of PlatinumCoin v1.0.0

BepInEx/plugins/PlatinumCoin.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("PlatinumCoin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PlatinumCoin")]
[assembly: AssemblyTitle("PlatinumCoin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PlatinumCoin
{
	[BepInPlugin("clippton.ultrakill.platinumcoin", "PlatinumCoin", "1.0.0")]
	public sealed class Main : BaseUnityPlugin
	{
		public const string PluginGuid = "clippton.ultrakill.platinumcoin";

		public const string PluginName = "PlatinumCoin";

		public const string PluginVersion = "1.0.0";

		internal static ConfigEntry<int> ProtectedHitCount;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			ProtectedHitCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ProtectedHitCount", 3, "How many ricoshots a coin survives before being destroyed normally. Set to 0 for vanilla behavior.");
			harmony = new Harmony("clippton.ultrakill.platinumcoin");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"PlatinumCoin 1.0.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			CoinProtection.Clear();
		}
	}
	internal static class CoinProtection
	{
		private static readonly Dictionary<int, int> RemainingHits = new Dictionary<int, int>();

		private static readonly FieldInfo ColsField = AccessTools.Field(typeof(Coin), "cols");

		private static readonly FieldInfo ScolField = AccessTools.Field(typeof(Coin), "scol");

		private static readonly FieldInfo CheckingSpeedField = AccessTools.Field(typeof(Coin), "checkingSpeed");

		private static readonly FieldInfo TimeToDeleteField = AccessTools.Field(typeof(Coin), "timeToDelete");

		private static readonly FieldInfo CurrentChargeField = AccessTools.Field(typeof(Coin), "currentCharge");

		private static readonly FieldInfo AltBeamField = AccessTools.Field(typeof(Coin), "altBeam");

		private static readonly FieldInfo PendingBeamHitsField = AccessTools.Field(typeof(Coin), "pendingBeamHits");

		public static void Clear()
		{
			RemainingHits.Clear();
		}

		public static void Reset(Coin coin)
		{
			if ((Object)(object)coin != (Object)null)
			{
				RemainingHits.Remove(((Object)coin).GetInstanceID());
			}
		}

		public static bool TryConsumeSave(Coin coin)
		{
			if ((Object)(object)coin == (Object)null)
			{
				return false;
			}
			int num = Mathf.Max(0, Main.ProtectedHitCount.Value);
			if (num == 0)
			{
				Reset(coin);
				return false;
			}
			int instanceID = ((Object)coin).GetInstanceID();
			if (!RemainingHits.TryGetValue(instanceID, out var value))
			{
				value = num;
			}
			if (value <= 0)
			{
				return false;
			}
			RemainingHits[instanceID] = value - 1;
			return true;
		}

		public static void ReviveAfterRicoshot(Coin coin)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)coin == (Object)null)
			{
				return;
			}
			((Component)coin).gameObject.SetActive(true);
			coin.shot = false;
			coin.shotByEnemy = false;
			coin.hitPoint = Vector3.zero;
			coin.hitTimes = 1;
			coin.ccc = null;
			SetPrivateField(CheckingSpeedField, coin, true);
			SetPrivateField(TimeToDeleteField, coin, 1f);
			SetPrivateField(CurrentChargeField, coin, null);
			SetPrivateField(AltBeamField, coin, null);
			object value = PendingBeamHitsField.GetValue(coin);
			(value?.GetType().GetMethod("Clear"))?.Invoke(value, null);
			if (ColsField.GetValue(coin) is Collider[] array)
			{
				Collider[] array2 = array;
				foreach (Collider val in array2)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.enabled = true;
					}
				}
			}
			object? value2 = ScolField.GetValue(coin);
			SphereCollider val2 = (SphereCollider)((value2 is SphereCollider) ? value2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				((Collider)val2).enabled = true;
				val2.radius = 0.5f;
			}
			if ((Object)(object)coin.rb != (Object)null)
			{
				coin.rb.isKinematic = false;
				coin.rb.velocity = Vector3.up * 8f;
				coin.rb.angularVelocity = Random.insideUnitSphere * 20f;
				PhysicsExtensions.SetGravityMode(coin.rb, true);
			}
			TrailRenderer component = ((Component)coin).GetComponent<TrailRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.Clear();
				((Renderer)component).enabled = true;
			}
			((MonoBehaviour)coin).CancelInvoke("ReflectRevolver");
			((MonoBehaviour)coin).CancelInvoke("GetDeleted");
			((MonoBehaviour)coin).Invoke("GetDeleted", 5f);
			MonoSingleton<CoinTracker>.Instance.AddCoin(coin);
		}

		private static void SetPrivateField(FieldInfo field, object instance, object value)
		{
			if (field != null)
			{
				field.SetValue(instance, value);
			}
		}
	}
	[HarmonyPatch(typeof(Coin))]
	internal static class CoinPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix(Coin __instance)
		{
			CoinProtection.Reset(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("ReflectRevolver")]
		private static void ReflectRevolverPostfix(Coin __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Component)__instance).gameObject.activeSelf && CoinProtection.TryConsumeSave(__instance))
			{
				CoinProtection.ReviveAfterRicoshot(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetDeleted")]
		private static void GetDeletedPrefix(Coin __instance)
		{
			CoinProtection.Reset(__instance);
		}
	}
}