Decompiled source of FeedbackersForEveryone v0.0.0

FeedbackersForEveryone.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Nyxpiri.ULTRAKILL.NyxLib;
using ULTRAKILL.Portal;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Nyxpiri.ULTRAKILL.FeedbackersForEveryone;

public static class Assets
{
	public static AssetReference ParryFlashPrefab { get; private set; }

	public static GameObject EnemyRevolverBullet { get; private set; }

	public static GameObject EnemyRevolverAltBullet { get; private set; }

	internal static void Initialize()
	{
		LevelQuickLoader.AddQuickLoadLevel("uk_construct");
		Assets.EnableExplosionsPicking();
		Assets.EnableProjectilePicking();
		Assets.AddAssetPicker<SwordsMachine>((Func<SwordsMachine, bool>)delegate(SwordsMachine sm)
		{
			ParryFlashPrefab = sm.gunFlash;
			return true;
		});
		Assets.AddAssetPicker<EnemyRevolver>((Func<EnemyRevolver, bool>)delegate(EnemyRevolver revolver)
		{
			EnemyRevolverBullet = Object.Instantiate<GameObject>(revolver.bullet);
			EnemyRevolverBullet.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)EnemyRevolverBullet);
			EnemyRevolverAltBullet = Object.Instantiate<GameObject>(revolver.altBullet);
			EnemyRevolverAltBullet.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)EnemyRevolverAltBullet);
			return true;
		});
	}
}
internal static class Log
{
	private static ManualLogSource _logger;

	public static void Initialize(ManualLogSource logger)
	{
		Assert.IsNull((object)_logger, "Log.Initialize called when _logger wasn't null?");
		_logger = logger;
	}

	public static void Fatal(object data)
	{
		_logger.LogFatal(data);
	}

	public static void Error(object data)
	{
		_logger.LogError(data);
	}

	public static void Warning(object data)
	{
		_logger.LogWarning(data);
	}

	public static void Message(object data)
	{
		_logger.LogMessage(data);
	}

	public static void Info(object data)
	{
		_logger.LogInfo(data);
	}

	public static void Debug(object data)
	{
		_logger.LogDebug(data);
	}
}
public static class EnemyFeedbackerEnemyComponentsExtension
{
	public static EnemyFeedbacker GetFeedbacker(this EnemyComponents enemy)
	{
		return enemy.GetMonoByIndex<EnemyFeedbacker>(EnemyFeedbacker.MonoRegistrarIndex);
	}
}
public class EnemyFeedbacker : MonoBehaviour
{
	private struct QueuedParry
	{
		public Action<Vector3> ParryAction;

		public FixedTimeStamp InitTime;

		public Vector3 PosAtTheTime;
	}

	private EnemyComponents _eadd = null;

	public FixedTimeStamp LastParryTimestamp;

	private static FieldInfo timeControllerParryLightFi = typeof(TimeController).GetField("parryLight", BindingFlags.Instance | BindingFlags.NonPublic);

	private List<QueuedParry> _queuedParries = new List<QueuedParry>(2);

	private EnemyType _enemyType = (EnemyType)10;

	public bool Enabled => Cheats.IsCheatEnabled("nyxpiri.feedbackers-for-everyone");

	public bool ReadyToParry => ((FixedTimeStamp)(ref LastParryTimestamp)).TimeSince >= (double)ParryCooldown && Stamina >= ParryCost && Enabled;

	public float ParryCost => (float)Options.ParryStaminaCost[_enemyType].Value * Options.StaminaCostScalar.Value;

	public float ParryCooldown => (float)Options.MinParryCooldowns[_enemyType].Value * Options.MinParryCooldownScalar.Value;

	public float Stamina { get; private set; } = 0f;


	public static int MonoRegistrarIndex { get; private set; }

	public void QueueParry(Action<Vector3> parryAction)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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)
		FixedTimeStamp initTime = default(FixedTimeStamp);
		((FixedTimeStamp)(ref initTime)).UpdateToNow();
		_queuedParries.Add(new QueuedParry
		{
			ParryAction = parryAction,
			InitTime = initTime,
			PosAtTheTime = ((Component)this).transform.position
		});
	}

	protected void Awake()
	{
		_eadd = ((Component)this).GetComponent<EnemyComponents>();
		Assert.IsNotNull((Object)(object)_eadd, "");
	}

	public bool CanParry(ProjectileBoostTracker boostTracker, double parryability)
	{
		//IL_0063: 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)
		if (!ReadyToParry)
		{
			return false;
		}
		double num = ((boostTracker.NumBoosts != 0 && (boostTracker.NumEnemyBoosts != 0 || !boostTracker.IsPlayerSourced)) ? (Options.MultiHitParrySkills[_enemyType].Value * (double)Options.MultiHitSkillScalar.Value) : (Options.FirstHitParrySkills[_enemyType].Value * (double)Options.FirstHitSkillScalar.Value));
		if (num - (1.0 - parryability) > 0.0)
		{
			return true;
		}
		return false;
	}

	public void ParryEffect(Vector3 fromPoint)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: 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_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		Assert.IsTrue(ReadyToParry, "EnemyFeedbacker.ParryEffect called when not ReadyToParry?");
		if (Options.HitstopOnEnemyParry.Value)
		{
			TimeScale.Controller.ParryFlash();
		}
		GameObject val = Object.Instantiate<GameObject>((GameObject)timeControllerParryLightFi.GetValue(TimeScale.Controller), fromPoint, Quaternion.identity, ((Component)this).transform);
		AudioSource componentInChildren = val.GetComponentInChildren<AudioSource>();
		AudioSource componentInChildren2 = val.GetComponentInChildren<AudioSource>();
		componentInChildren2.volume *= Options.EnemyParrySoundScalar.Value;
		val.GetComponent<RemoveOnTime>().time = 0.065f;
		AudioSourceExtensions.SetPitch(componentInChildren, AudioSourceExtensions.GetPitch(componentInChildren) * 1.25f);
		GameObject obj = AddressablesExtensions.ToAsset(Assets.ParryFlashPrefab);
		Vector3 val2 = MonoSingleton<NewMovement>.Instance.HeadPosition - fromPoint;
		GameObject val3 = Object.Instantiate<GameObject>(obj, fromPoint, Quaternion.LookRotation(((Vector3)(ref val2)).normalized), Options.ParryFollowsEnemy.Value ? ((Component)this).transform : null);
		val3.transform.localScale = new Vector3(1f / val3.transform.lossyScale.x, 1f / val3.transform.lossyScale.y, 1f / val3.transform.lossyScale.z);
		Transform transform = val3.transform;
		transform.localScale *= 1.5f;
		Stamina -= ParryCost;
		((FixedTimeStamp)(ref LastParryTimestamp)).UpdateToNow();
	}

	public void ParryFinishEffect(Vector3 fromPoint)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_008a: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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_00d4: 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_0100: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>((GameObject)timeControllerParryLightFi.GetValue(TimeScale.Controller), fromPoint, Quaternion.identity, ((Component)this).transform);
		AudioSource componentInChildren = val.GetComponentInChildren<AudioSource>();
		componentInChildren.time = 0.05f;
		componentInChildren.volume *= Options.EnemyParrySoundScalar.Value * 0.5f;
		AudioSourceExtensions.SetPitch(componentInChildren, AudioSourceExtensions.GetPitch(componentInChildren) * 1.25f);
		val.GetComponent<RemoveOnTime>().time = Options.EnemyParryDelay.Value;
		GameObject obj = AddressablesExtensions.ToAsset(Assets.ParryFlashPrefab);
		Vector3 val2 = MonoSingleton<NewMovement>.Instance.HeadPosition - fromPoint;
		GameObject val3 = Object.Instantiate<GameObject>(obj, fromPoint, Quaternion.LookRotation(((Vector3)(ref val2)).normalized), Options.ParryFollowsEnemy.Value ? ((Component)this).transform : null);
		val3.transform.localScale = new Vector3(1f / val3.transform.lossyScale.x, 1f / val3.transform.lossyScale.y, 1f / val3.transform.lossyScale.z);
		Transform transform = val3.transform;
		transform.localScale *= 3f;
	}

	protected void Start()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Invalid comparison between Unknown and I4
		//IL_003a: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		_enemyType = _eadd.Eid.enemyType;
		if ((int)_enemyType == 8)
		{
			V2 component = ((Component)this).GetComponent<V2>();
			if (component.secondEncounter)
			{
				_enemyType = (EnemyType)22;
			}
		}
		CancerousRodent component2 = ((Component)this).GetComponent<CancerousRodent>();
		if ((Object)(object)component2 != (Object)null)
		{
			if (component2.harmless)
			{
				_enemyType = (EnemyType)23;
			}
			else
			{
				_enemyType = (EnemyType)24;
			}
		}
	}

	protected void Update()
	{
	}

	protected void FixedUpdate()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: 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)
		Stamina = Mathf.MoveTowards(Stamina, 1f, Time.fixedDeltaTime * (float)Options.ParryStaminaRechargeRate[_enemyType].Value * Options.StaminaRechargeRateScalar.Value);
		for (int i = 0; i < _queuedParries.Count; i++)
		{
			QueuedParry queuedParry = _queuedParries[i];
			float value = Options.EnemyParryDelay.Value;
			if (!(((FixedTimeStamp)(ref queuedParry.InitTime)).TimeSince < (double)value))
			{
				_queuedParries.RemoveAt(i);
				i--;
				queuedParry.ParryAction?.Invoke(Options.ParryFollowsEnemy.Value ? (((Component)this).transform.position - queuedParry.PosAtTheTime) : Vector3.zero);
			}
		}
	}

	protected void OnDestroy()
	{
	}

	public Vector3 SolveParryForce(Vector3 projectilePosition, Vector3 projectileVelocity)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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_0038: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: 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_0087: 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)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		NewMovement instance = MonoSingleton<NewMovement>.Instance;
		Vector3 headPosition = instance.HeadPosition;
		Vector3 travellerVelocity = instance.travellerVelocity;
		Vector3 val = headPosition - projectilePosition;
		Vector3 normalized = ((Vector3)(ref val)).normalized;
		Vector3 val2 = Vector3.Project(travellerVelocity, normalized);
		float magnitude = ((Vector3)(ref val2)).magnitude;
		Vector3 normalized2 = ((Vector3)(ref val2)).normalized;
		val = headPosition - projectilePosition;
		float num = magnitude * ((Vector3.Distance(normalized2, ((Vector3)(ref val)).normalized) > 0.5f) ? (-1f) : 1f);
		Vector3 val3 = travellerVelocity - Vector3.Project(travellerVelocity, normalized);
		float num2 = ((Vector3)(ref projectileVelocity)).magnitude + num;
		float num3 = Vector3.Distance(projectilePosition, headPosition + val3);
		val = headPosition + val3 * (num3 / num2) - projectilePosition;
		return ((Vector3)(ref val)).normalized;
	}

	internal static void Initialize()
	{
		MonoRegistrarIndex = EnemyComponents.MonoRegistrar.Register<EnemyFeedbacker>();
	}
}
public static class Cheats
{
	public const string FeedbackersForEveryone = "nyxpiri.feedbackers-for-everyone";
}
[BepInPlugin("nyxpiri.ultrakill.feedbackers-for-everyone", "Feedbackers for Everyone", "0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInProcess("ULTRAKILL.exe")]
public class FeedbackersForEveryone : BaseUnityPlugin
{
	protected void Awake()
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		Log.Initialize(((BaseUnityPlugin)this).Logger);
		Options.Config = ((BaseUnityPlugin)this).Config;
		Options.Initialize();
		EnemyFeedbacker.Initialize();
		ParryabilityTracker.Initialize();
		CannonballPatches.Initialize();
		CoinPatches.Initialize();
		GrenadePatches.Initialize();
		NailPatches.Initialize();
		ProjectilePatches.Initialize();
		PunchPatches.Initialize();
		RevolverBeamPatches.Initialize();
		Assets.Initialize();
		Harmony.CreateAndPatchAll(((object)this).GetType().Assembly, (string)null);
		Assets.EnableProjectilePicking();
		Cheats.ReadyForCheatRegistration += new ReadyForCheatRegistrationEventHandler(RegisterCheats);
		if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}

	private void RegisterCheats(CheatsManager cheatsManager)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		cheatsManager.RegisterCheat((ICheat)new ToggleCheat("Feedbackers for Everyone!", "nyxpiri.feedbackers-for-everyone", (Action<ToggleCheat>)delegate
		{
		}, (Action<ToggleCheat, CheatsManager>)delegate
		{
		}), "FAIRNESS AND EQUALITY");
	}

	protected void OnApplicationFocus(bool hasFocus)
	{
		if (hasFocus)
		{
			((BaseUnityPlugin)this).Config.Reload();
		}
	}

	protected void Start()
	{
	}

	protected void Update()
	{
	}

	protected void LateUpdate()
	{
	}
}
public static class Options
{
	public static ConfigEntry<bool> HitstopOnEnemyParry = null;

	public static ConfigEntry<bool> ParryFollowsEnemy = null;

	public static ConfigEntry<float> EnemyParryDelay = null;

	public static ConfigEntry<float> EnemyParrySoundScalar = null;

	public static ConfigEntry<string> ParryProsString = null;

	public static Dictionary<EnemyType, ConfigEntry<double>> ParryStaminaCost = new Dictionary<EnemyType, ConfigEntry<double>>(64);

	public static Dictionary<EnemyType, ConfigEntry<double>> ParryStaminaRechargeRate = new Dictionary<EnemyType, ConfigEntry<double>>(64);

	public static Dictionary<EnemyType, ConfigEntry<double>> MinParryCooldowns = new Dictionary<EnemyType, ConfigEntry<double>>(64);

	public static Dictionary<EnemyType, ConfigEntry<double>> FirstHitParrySkills = new Dictionary<EnemyType, ConfigEntry<double>>(64);

	public static Dictionary<EnemyType, ConfigEntry<double>> MultiHitParrySkills = new Dictionary<EnemyType, ConfigEntry<double>>(64);

	public static ConfigEntry<float> FirstHitSkillScalar = null;

	public static ConfigEntry<float> MultiHitSkillScalar = null;

	public static ConfigEntry<float> MinParryCooldownScalar = null;

	public static ConfigEntry<float> StaminaRechargeRateScalar = null;

	public static ConfigEntry<float> StaminaCostScalar = null;

	public static ConfigEntry<bool> ShotCoinsParryable = null;

	public static ConfigEntry<bool> PunchedCoinsParryable = null;

	public static ConfigEntry<bool> BeamsParryable = null;

	public static ConfigEntry<bool> GrenadesParryable = null;

	public static ConfigEntry<bool> PlayerProjectilesParryable = null;

	public static ConfigEntry<bool> CannonballsParryable = null;

	public static ConfigEntry<bool> SawsParryable = null;

	internal static ConfigFile Config = null;

	public static void Initialize()
	{
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Invalid comparison between Unknown and I4
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Invalid comparison between Unknown and I4
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Invalid comparison between Unknown and I4
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0404: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Invalid comparison between Unknown and I4
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Expected I4, but got Unknown
		HitstopOnEnemyParry = Config.Bind<bool>("Preferences", "HitstopOnEnemyParry", false, (ConfigDescription)null);
		EnemyParryDelay = Config.Bind<float>("Balance", "EnemyParryDelay", 0.3f, (ConfigDescription)null);
		ParryFollowsEnemy = Config.Bind<bool>("Balance", "ParryFollowsEnemy", true, (ConfigDescription)null);
		EnemyParrySoundScalar = Config.Bind<float>("Preference.Audio", "EnemyParrySoundScalar", 4f, (ConfigDescription)null);
		ShotCoinsParryable = Config.Bind<bool>("Balance", "ShotCoinsParryable", true, (ConfigDescription)null);
		PunchedCoinsParryable = Config.Bind<bool>("Balance", "PunchedCoinsParryable", true, (ConfigDescription)null);
		BeamsParryable = Config.Bind<bool>("Balance", "BeamsParryable", true, (ConfigDescription)null);
		GrenadesParryable = Config.Bind<bool>("Balance", "GrenadesParryable", true, (ConfigDescription)null);
		PlayerProjectilesParryable = Config.Bind<bool>("Balance", "PlayerProjectilesParryable", true, (ConfigDescription)null);
		CannonballsParryable = Config.Bind<bool>("Balance", "CannonballsParryable", true, (ConfigDescription)null);
		SawsParryable = Config.Bind<bool>("Balance", "SawsParryable", true, (ConfigDescription)null);
		FirstHitSkillScalar = Config.Bind<float>("Balance", "FirstHitSkillScalar", 1f, (ConfigDescription)null);
		MultiHitSkillScalar = Config.Bind<float>("Balance", "MultiHitSkillScalar", 1f, (ConfigDescription)null);
		MinParryCooldownScalar = Config.Bind<float>("Balance", "MinParryCooldownScalar", 1f, (ConfigDescription)null);
		StaminaRechargeRateScalar = Config.Bind<float>("Balance", "StaminaRechargeRateScalar", 1f, (ConfigDescription)null);
		StaminaCostScalar = Config.Bind<float>("Balance", "StaminaCostScalar", 1f, (ConfigDescription)null);
		foreach (object value in Enum.GetValues(typeof(EnemyType)))
		{
			double num = 0.5;
			double num2 = 0.75;
			double num3 = 0.4;
			double num4 = 0.175;
			double num5 = 0.1;
			EnemyType val = (EnemyType)value;
			EnemyType val2 = val;
			if ((int)val2 <= 24)
			{
				if ((int)val2 != 8)
				{
					switch (val2 - 18)
					{
					case 4:
						num2 = 1.01;
						num = 0.75;
						break;
					case 0:
						num2 = 1.01;
						num = 0.75;
						break;
					case 5:
						num2 = 1.01;
						num = 0.85;
						num4 = 0.30000001192092896;
						break;
					case 6:
						num2 = 1.01;
						num = 0.5;
						num4 = 0.20000000298023224;
						break;
					}
				}
				else
				{
					num2 = 0.8;
					num = 0.75;
				}
			}
			else if ((int)val2 != 28)
			{
				if ((int)val2 == 29)
				{
					num2 = 1.01;
					num = 0.75;
				}
			}
			else
			{
				num2 = 1.01;
				num = 0.5;
			}
			FirstHitParrySkills[(EnemyType)value] = Config.Bind<double>($"Balance.{value}", "FirstHitSkill", num2, $"Sets how good {value} is/are at parrying on first contact with an enemy");
			MultiHitParrySkills[(EnemyType)value] = Config.Bind<double>($"Balance.{value}", "MultiHitSkill", num, $"Sets how good {value} is/are at parrying past the first contact with an enemy");
			MinParryCooldowns[(EnemyType)value] = Config.Bind<double>($"Balance.{value}", "MinParryCooldown", num5, (ConfigDescription)null);
			ParryStaminaRechargeRate[(EnemyType)value] = Config.Bind<double>($"Balance.{value}", "ParryStaminaRechargeRate", num4, (ConfigDescription)null);
			ParryStaminaCost[(EnemyType)value] = Config.Bind<double>($"Balance.{value}", "ParryStaminaCost", num3, (ConfigDescription)null);
		}
		Config.ConfigReloaded += OnConfigReload;
	}

	private static void OnConfigReload(object sender, EventArgs e)
	{
	}
}
public static class ParryabilityTracker
{
	private class ParryabilityInfo
	{
		private struct TimestampsQueue
		{
			private string _debugName;

			private List<double> _averageDiffs;

			private Queue<FixedTimeStamp> _queue;

			private FixedTimeStamp _decayTimestamp;

			private FixedTimeStamp _LastEnqueueTimestamp;

			private float _decayTime;

			public float BestDiffDist { get; private set; }

			public static double MaxDecayTime => 20.0;

			internal bool CanPeek => _queue.Count > 0;

			internal void Init(string debugName)
			{
				_debugName = debugName;
				_queue = new Queue<FixedTimeStamp>(QueueCap);
				((FixedTimeStamp)(ref _decayTimestamp)).UpdateToNow();
				_averageDiffs = new List<double>(QueueCap - 1);
				UpdateDecayTime();
				UpdateBestDiffDist();
			}

			internal FixedTimeStamp Peek()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				return _queue.Peek();
			}

			internal void EnqueueNew()
			{
				//IL_0044: 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_003b: Unknown result type (might be due to invalid IL or missing references)
				if (!(((FixedTimeStamp)(ref _LastEnqueueTimestamp)).TimeSince < 0.25))
				{
					if (_queue.Count == QueueCap)
					{
						_queue.Dequeue();
					}
					FixedTimeStamp item = default(FixedTimeStamp);
					((FixedTimeStamp)(ref item)).UpdateToNow();
					_queue.Enqueue(item);
					((FixedTimeStamp)(ref _decayTimestamp)).UpdateToNow();
					UpdateDecayTime();
					UpdateBestDiffDist();
					((FixedTimeStamp)(ref _LastEnqueueTimestamp)).UpdateToNow();
				}
			}

			private void UpdateBestDiffDist()
			{
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				if (_queue.Count <= 2)
				{
					BestDiffDist = 10000f;
					Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.TimestampsQueue.UpdateBestDiffDist ended with a BestDiffDist of {BestDiffDist} (based on queue being small)");
					return;
				}
				double? num = null;
				double num2 = 0.0;
				double num3 = 0.0;
				_averageDiffs.Clear();
				FixedTimeStamp? val = null;
				BestDiffDist = 0f;
				foreach (FixedTimeStamp item in _queue.Reverse())
				{
					FixedTimeStamp current = item;
					if (!val.HasValue)
					{
						val = current;
						continue;
					}
					FixedTimeStamp value = val.Value;
					num2 = (((FixedTimeStamp)(ref value)).TimeStamp - ((FixedTimeStamp)(ref current)).TimeStamp).Value;
					double valueOrDefault = num.GetValueOrDefault();
					if (!num.HasValue)
					{
						valueOrDefault = num2;
						num = valueOrDefault;
					}
					num3 += num2;
					_averageDiffs.Add(num3);
					val = current;
				}
				double num4 = double.PositiveInfinity;
				int num5 = -1;
				for (int i = 1; i < _averageDiffs.Count; i++)
				{
					_averageDiffs[i] /= i + 1;
					double num6 = _averageDiffs[i];
					double num7 = Math.Abs(num6 - num.Value);
					if (num7 < num4)
					{
						num4 = num7;
						num5 = i;
					}
				}
				BestDiffDist = (float)num4;
				Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.TimestampsQueue.UpdateBestDiffDist ended with a BestDiffDist of {BestDiffDist}, and a lowestDistI of {num5}. _queue.Count: {_queue.Count}");
			}

			internal void FixedUpdate()
			{
				if (_queue.Count != 0 && ((FixedTimeStamp)(ref _decayTimestamp)).TimeSince > (double)_decayTime)
				{
					Decay();
				}
			}

			private void Decay()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (_queue.Count != 0)
				{
					((FixedTimeStamp)(ref _decayTimestamp)).UpdateToNow();
					_queue.Dequeue();
					UpdateBestDiffDist();
				}
			}

			private void UpdateDecayTime()
			{
				//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_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
				_decayTime = 0f;
				if (_queue.Count <= 2)
				{
					_decayTime = (float)MaxDecayTime;
					return;
				}
				FixedTimeStamp? val = null;
				foreach (FixedTimeStamp item in _queue)
				{
					FixedTimeStamp current = item;
					if (!val.HasValue)
					{
						val = current;
						continue;
					}
					float decayTime = _decayTime;
					double? timeStamp = ((FixedTimeStamp)(ref current)).TimeStamp;
					FixedTimeStamp value = val.Value;
					_decayTime = decayTime + (float)(timeStamp - ((FixedTimeStamp)(ref value)).TimeStamp).Value;
					val = current;
				}
				_decayTime /= _queue.Count - 1;
				_decayTime *= 2f;
				_decayTime = Mathf.Clamp(_decayTime, 1f, (float)MaxDecayTime);
				Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.TimestampsQueue.UpdateDecayTime ended with a _decayTime of {_decayTime}, _queue.Count: {_queue.Count}");
			}
		}

		private string _debugName;

		private TimestampsQueue _creationStartTimestamps;

		private TimestampsQueue _creationProgressTimestamps;

		private TimestampsQueue _contactTimestamps;

		public static int QueueCap => 10;

		public double NotifyContact()
		{
			_contactTimestamps.EnqueueNew();
			Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.NotifyContact called and is giving a bestDiffDist of {_contactTimestamps.BestDiffDist}");
			return _contactTimestamps.BestDiffDist;
		}

		public double NotifyCreationProgress()
		{
			_creationProgressTimestamps.EnqueueNew();
			Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.NotifyCreationProgress called and is giving a bestDiffDist of {_creationProgressTimestamps.BestDiffDist}");
			return _creationProgressTimestamps.BestDiffDist;
		}

		public double NotifyCreationStart()
		{
			_creationStartTimestamps.EnqueueNew();
			Log.Debug($"{_debugName}:ParryabilityTracker.ParryabilityInfo.NotifyCreationStart called and is giving a bestDiffDist of {_creationStartTimestamps.BestDiffDist}");
			return _creationStartTimestamps.BestDiffDist;
		}

		internal void FixedUpdate()
		{
			_creationStartTimestamps.FixedUpdate();
			_creationProgressTimestamps.FixedUpdate();
			_contactTimestamps.FixedUpdate();
		}

		internal ParryabilityInfo(string debugName)
		{
			_debugName = debugName;
			_creationStartTimestamps = default(TimestampsQueue);
			_creationStartTimestamps.Init(_debugName + ".creationStartTimestamps");
			_creationProgressTimestamps = default(TimestampsQueue);
			_creationProgressTimestamps.Init(_debugName + ".creationProgressTimestamps");
			_contactTimestamps = default(TimestampsQueue);
			_contactTimestamps.Init(_debugName + ".contactTimestamps");
		}
	}

	private static Dictionary<int, ParryabilityInfo> _attackParryabilitysDict = new Dictionary<int, ParryabilityInfo>(256);

	private static List<ParryabilityInfo> _parryabilitys = new List<ParryabilityInfo>(256);

	public static void Initialize()
	{
		ScenesEvents.OnSceneWasLoaded = (Action<Scene, string>)Delegate.Combine(ScenesEvents.OnSceneWasLoaded, new Action<Scene, string>(OnSceneLoad));
		UpdateEvents.OnFixedUpdate = (Action)Delegate.Combine(UpdateEvents.OnFixedUpdate, new Action(FixedUpdate));
	}

	private static void FixedUpdate()
	{
		for (int i = 0; i < _parryabilitys.Count; i++)
		{
			_parryabilitys[i].FixedUpdate();
		}
	}

	public static double NotifyContact(int hash)
	{
		ParryabilityInfo orMakeParryability = GetOrMakeParryability(hash);
		Log.Debug($"ParryabilityTracker.NotifyContact called with hash {hash}");
		return orMakeParryability.NotifyContact();
	}

	public static double NotifyCreationProgress(int hash)
	{
		ParryabilityInfo orMakeParryability = GetOrMakeParryability(hash);
		Log.Debug($"ParryabilityTracker.NotifyCreationProgress called with hash {hash}");
		return orMakeParryability.NotifyCreationProgress();
	}

	public static double NotifyCreationStart(int hash)
	{
		ParryabilityInfo orMakeParryability = GetOrMakeParryability(hash);
		Log.Debug($"ParryabilityTracker.NotifyCreationStart called with hash {hash}");
		return orMakeParryability.NotifyCreationStart();
	}

	private static ParryabilityInfo GetOrMakeParryability(int hash)
	{
		if (!_attackParryabilitysDict.TryGetValue(hash, out var value))
		{
			value = new ParryabilityInfo($"{hash}");
			_attackParryabilitysDict.Add(hash, value);
			_parryabilitys.Add(value);
		}
		return value;
	}

	private static void OnSceneLoad(Scene sceneIdx, string sceneName)
	{
		_attackParryabilitysDict.Clear();
		_parryabilitys.Clear();
	}
}
public static class CannonballPatches
{
	private static readonly FieldInfo _checkingForBreakFi = AccessTools.Field(typeof(Cannonball), "checkingForBreak");

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		CannonballEvents.PreCannonballStart += new PreCannonballStartEventHandler(PreCannonballStart);
		CannonballEvents.PreCannonballCollide += new PreCannonballCollideEventHandler(PreCannonballCollide);
		CannonballEvents.PreCannonballLaunch += new PreCannonballLaunchEventHandler(PreCannonballLaunch);
	}

	private static void PreCannonballLaunch(EventMethodCanceler canceler, Cannonball cannonball)
	{
		Log.Debug($"PreCannonballLaunch called on {cannonball}");
		((Component)cannonball).GetComponent<ProjectileBoostTracker>().IncrementPlayerBoosts();
	}

	private static void PreCannonballCollide(EventMethodCanceler canceler, Cannonball cannonball, Collider other)
	{
		//IL_034c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
		Log.Debug($"PreCannonballCollide called on {cannonball}");
		Collider component = ((Component)cannonball).GetComponent<Collider>();
		ProjectileBoostTracker boostTracker = ((Component)cannonball).GetComponent<ProjectileBoostTracker>();
		if (!Options.CannonballsParryable.Value)
		{
			return;
		}
		Action action = delegate
		{
			if (boostTracker.NumPlayerBoosts != 0 && boostTracker.NumEnemyBoosts != 0)
			{
				MonoSingleton<StyleHUD>.Instance.AddPoints(10, "<color=#00c3ff>VOLLEYBALL</color>", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
			}
		};
		NewMovement val = default(NewMovement);
		if (((Component)other).TryGetComponent<NewMovement>(ref val) && !boostTracker.LastBoostedByPlayer && boostTracker.HasBeenBoosted)
		{
			cannonball.Explode();
		}
		else
		{
			if ((cannonball.launched || cannonball.canBreakBeforeLaunched) && !other.isTrigger && (LayerMaskDefaults.IsMatchingLayer(((Component)other).gameObject.layer, (LMD)1) || (cannonball.launched && ((Component)other).gameObject.layer == 0 && (!((Component)other).gameObject.CompareTag("Player") || !component.isTrigger))))
			{
				return;
			}
			bool flag = (bool)_checkingForBreakFi.GetValue(cannonball);
			EnemyIdentifierIdentifier val2 = default(EnemyIdentifierIdentifier);
			if ((!cannonball.launched && !cannonball.physicsCannonball) || (((Component)other).gameObject.layer != 10 && ((Component)other).gameObject.layer != 11 && ((Component)other).gameObject.layer != 12) || flag || !(Object.op_Implicit((Object)(object)other.attachedRigidbody) ? ((Component)other.attachedRigidbody).TryGetComponent<EnemyIdentifierIdentifier>(ref val2) : ((Component)other).TryGetComponent<EnemyIdentifierIdentifier>(ref val2)) || (Object)(object)val2.eid == (Object)null)
			{
				return;
			}
			EnemyComponents enemy = ((Component)val2.eid).GetComponent<EnemyComponents>();
			Assert.IsNotNull((Object)(object)enemy, "");
			if (enemy.Eid.Dead)
			{
				return;
			}
			EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
			if (!feedbacker.Enabled)
			{
				action();
				return;
			}
			if ((Object)(object)boostTracker.SafeEid == (Object)(object)enemy.Eid)
			{
				((EventMethodCanceler)(ref canceler)).CancelMethod();
				return;
			}
			double parryability = boostTracker.NotifyContact();
			boostTracker.MarkCannotBeEnemyParried();
			if (!feedbacker.ReadyToParry)
			{
				action();
				return;
			}
			if (!feedbacker.CanParry(boostTracker, parryability))
			{
				action();
				return;
			}
			boostTracker.IncrementEnemyBoost();
			feedbacker.ParryEffect(((Component)cannonball).transform.position);
			((Component)cannonball).gameObject.SetActive(false);
			boostTracker.IgnoreColliders = enemy.Colliders;
			boostTracker.SafeEid = enemy.Eid;
			cannonball.hitEnemies.Add(enemy.Eid);
			Vector3 velocity = cannonball.Rigidbody.velocity;
			float cannonballSpeed = ((Vector3)(ref velocity)).magnitude;
			feedbacker.QueueParry(delegate(Vector3 offset)
			{
				//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_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//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_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				Transform transform = ((Component)cannonball.Rigidbody).transform;
				transform.position += offset;
				feedbacker.ParryFinishEffect(((Component)cannonball).transform.position);
				((Component)cannonball).gameObject.SetActive(true);
				Vector3 val3 = enemy.GetFeedbacker().SolveParryForce(((Component)cannonball).transform.position, cannonball.Rigidbody.velocity);
				cannonball.Rigidbody.velocity = val3 * cannonballSpeed;
				((Component)cannonball.Rigidbody).transform.rotation = Quaternion.LookRotation(val3);
			});
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			Physics.IgnoreCollision(((Component)cannonball).GetComponent<Collider>(), (Collider)(object)instance.playerCollider, false);
			((EventMethodCanceler)(ref canceler)).CancelMethod();
		}
	}

	private static void PreCannonballStart(EventMethodCanceler canceler, Cannonball cannonball)
	{
		Log.Debug($"PreCannonballStart called on {cannonball}");
		ComponentExtensions.GetOrAddComponent<ProjectileBoostTracker>((Component)(object)cannonball);
	}
}
public static class CoinPatches
{
	[HarmonyPatch(typeof(Coin), "SpawnBeam")]
	private static class CoinSpawnBeamPatch
	{
		public static void Prefix(Coin __instance)
		{
			ProjectileBoostTracker orAddComponent = GameObjectExtensions.GetOrAddComponent<ProjectileBoostTracker>(__instance.refBeam);
			orAddComponent.CopyFrom(((Component)__instance).GetComponent<ProjectileBoostTracker>());
		}
	}

	[HarmonyPatch(typeof(Coin), "ReflectRevolver")]
	private static class CoinReflectRevolverPatch
	{
		private static EventMethodCancellationTracker _cancellationTracker = new EventMethodCancellationTracker();

		private static Coin _currentCoin = null;

		private static void DeliverDamageReplacement(EnemyIdentifier eid, GameObject target, Vector3 force, Vector3 hitPoint, float multiplier, bool tryForExplode, float critMultiplier = 0f, GameObject sourceWeapon = null, bool ignoreTotalDamageTakenMultiplier = false, bool fromExplosion = false)
		{
			//IL_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug($"DeliverDamageReplacement called on {_currentCoin}");
			Action action = delegate
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				eid.DeliverDamage(target, force, hitPoint, multiplier, tryForExplode, critMultiplier, sourceWeapon, ignoreTotalDamageTakenMultiplier, fromExplosion);
			};
			if (!Options.ShotCoinsParryable.Value)
			{
				action();
				return;
			}
			if (!Cheats.Enabled)
			{
				action();
				return;
			}
			Coin currentCoin = _currentCoin;
			ProjectileBoostTracker component = ((Component)currentCoin).GetComponent<ProjectileBoostTracker>();
			double parryability = component.NotifyContact();
			EnemyComponents enemy = ((Component)eid).GetComponent<EnemyComponents>();
			Assert.IsNotNull((Object)(object)enemy, "");
			if (enemy.Eid.Dead)
			{
				action();
				return;
			}
			EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
			if (!feedbacker.CanParry(component, parryability))
			{
				action();
				return;
			}
			if (!feedbacker.Enabled)
			{
				action();
				return;
			}
			if (!feedbacker.ReadyToParry)
			{
				action();
				return;
			}
			feedbacker.ParryEffect(hitPoint);
			MeshFilter componentInChildren = ((Component)currentCoin).GetComponentInChildren<MeshFilter>();
			MeshRenderer componentInChildren2 = ((Component)currentCoin).GetComponentInChildren<MeshRenderer>();
			GameObject counterBeamGo = Object.Instantiate<GameObject>(Assets.EnemyRevolverBullet);
			Projectile counterBeam = counterBeamGo.GetComponent<Projectile>();
			ProjectileBoostTracker counterBeamBoostTracker = GameObjectExtensions.GetOrAddComponent<ProjectileBoostTracker>(counterBeamGo);
			((Component)counterBeam).GetComponentInChildren<MeshFilter>().mesh = componentInChildren.mesh;
			((Renderer)((Component)counterBeam).GetComponentInChildren<MeshRenderer>()).material = ((Renderer)componentInChildren2).material;
			counterBeamBoostTracker.CopyFrom(component);
			counterBeamBoostTracker.IncrementEnemyBoost();
			float coinPower = currentCoin.power;
			feedbacker.QueueParry(delegate(Vector3 offset)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				feedbacker.ParryFinishEffect(hitPoint + offset);
				Vector3 val = feedbacker.SolveParryForce(hitPoint + offset, ((Component)counterBeam).transform.rotation * Vector3.forward * counterBeam.speed);
				counterBeamGo.transform.position = hitPoint + offset;
				counterBeamGo.transform.rotation = Quaternion.LookRotation(val);
				counterBeamGo.SetActive(true);
				IReadOnlyList<Collider> colliders = enemy.Colliders;
				counterBeamBoostTracker.IgnoreColliders = colliders;
				counterBeamBoostTracker.SafeEid = eid;
				counterBeamBoostTracker.SetTempSafeEnemyType(enemy.Eid.enemyType);
				counterBeam.playerBullet = true;
				counterBeam.damage = coinPower * 5f;
				counterBeam.enemyDamageMultiplier = 0.2f;
			});
			Object.Destroy((Object)(object)((Component)currentCoin).gameObject);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instr in instructions)
			{
				if (CodeInstructionExtensions.Calls(instr, typeof(EnemyIdentifier).GetMethod("DeliverDamage")))
				{
					instr.operand = typeof(CoinReflectRevolverPatch).GetMethod("DeliverDamageReplacement", BindingFlags.Static | BindingFlags.NonPublic);
				}
				yield return instr;
			}
		}

		public static void Prefix(Coin __instance)
		{
			_currentCoin = __instance;
			FieldInfo field = typeof(Coin).GetField("altBeam", BindingFlags.Instance | BindingFlags.NonPublic);
			object? value = field.GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				val.GetComponent<ProjectileBoostTracker>().CopyFrom(((Component)__instance).GetComponent<ProjectileBoostTracker>());
			}
		}

		public static void Postfix(Coin __instance)
		{
			_currentCoin = null;
		}
	}

	[HarmonyPatch(typeof(Coin), "Punchflection")]
	private static class CoinPunchflectionPatch
	{
		private static EventMethodCancellationTracker _cancellationTracker = new EventMethodCancellationTracker();

		private static Coin _currentCoin = null;

		private static void DeliverDamageReplacement(EnemyIdentifier eid, GameObject target, Vector3 force, Vector3 hitPoint, float multiplier, bool tryForExplode, float critMultiplier = 0f, GameObject sourceWeapon = null, bool ignoreTotalDamageTakenMultiplier = false, bool fromExplosion = false)
		{
			//IL_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			Log.Debug($"Punchflection.DeliverDamageReplacement called on {_currentCoin}");
			Action action = delegate
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				eid.DeliverDamage(target, force, hitPoint, multiplier, tryForExplode, critMultiplier, sourceWeapon, ignoreTotalDamageTakenMultiplier, fromExplosion);
			};
			if (!Options.PunchedCoinsParryable.Value)
			{
				action();
				return;
			}
			if (!Cheats.Enabled)
			{
				action();
				return;
			}
			Coin currentCoin = _currentCoin;
			ProjectileBoostTracker component = ((Component)currentCoin).GetComponent<ProjectileBoostTracker>();
			component.CoinPunched = true;
			double parryability = component.NotifyContact();
			EnemyComponents enemy = ((Component)eid).GetComponent<EnemyComponents>();
			Assert.IsNotNull((Object)(object)enemy, "");
			if (enemy.Eid.Dead)
			{
				action();
				return;
			}
			EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
			if (!feedbacker.CanParry(component, parryability))
			{
				action();
				return;
			}
			if (!feedbacker.Enabled)
			{
				action();
				return;
			}
			if (!feedbacker.ReadyToParry)
			{
				action();
				return;
			}
			feedbacker.ParryEffect(hitPoint);
			float coinPower = currentCoin.power;
			MeshFilter componentInChildren = ((Component)currentCoin).GetComponentInChildren<MeshFilter>();
			MeshRenderer componentInChildren2 = ((Component)currentCoin).GetComponentInChildren<MeshRenderer>();
			GameObject counterBeamGo = Object.Instantiate<GameObject>(Assets.EnemyRevolverBullet);
			Projectile counterBeam = counterBeamGo.GetComponent<Projectile>();
			ProjectileBoostTracker counterBeamBoostTracker = GameObjectExtensions.GetOrAddComponent<ProjectileBoostTracker>(counterBeamGo);
			((Component)counterBeam).GetComponentInChildren<MeshFilter>().mesh = componentInChildren.mesh;
			((Renderer)((Component)counterBeam).GetComponentInChildren<MeshRenderer>()).material = ((Renderer)componentInChildren2).material;
			counterBeamBoostTracker.CopyFrom(component);
			counterBeamBoostTracker.IncrementEnemyBoost();
			feedbacker.QueueParry(delegate(Vector3 offset)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				feedbacker.ParryFinishEffect(hitPoint + offset);
				Vector3 val = feedbacker.SolveParryForce(hitPoint + offset, ((Component)counterBeam).transform.rotation * Vector3.forward * counterBeam.speed);
				counterBeamGo.transform.position = hitPoint + offset;
				counterBeamGo.transform.rotation = Quaternion.LookRotation(val);
				counterBeamGo.SetActive(true);
				IReadOnlyList<Collider> colliders = enemy.Colliders;
				counterBeamBoostTracker.IgnoreColliders = colliders;
				counterBeamBoostTracker.SafeEid = eid;
				counterBeam.playerBullet = true;
				counterBeam.damage = coinPower * 5f;
				counterBeamBoostTracker.SetTempSafeEnemyType(enemy.Eid.enemyType);
				counterBeam.enemyDamageMultiplier = 0.2f;
			});
			currentCoin.GetDeleted();
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instr in instructions)
			{
				if (CodeInstructionExtensions.Calls(instr, typeof(EnemyIdentifier).GetMethod("DeliverDamage")))
				{
					instr.operand = typeof(CoinPunchflectionPatch).GetMethod("DeliverDamageReplacement", BindingFlags.Static | BindingFlags.NonPublic);
				}
				yield return instr;
			}
		}

		public static void Prefix(Coin __instance)
		{
			_currentCoin = __instance;
		}

		public static void Postfix(Coin __instance)
		{
			_currentCoin = null;
		}
	}

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		CoinEvents.PostCoinAwake += new PostCoinAwakeEventHandler(PostCoinAwake);
	}

	private static void PostCoinAwake(EventMethodCancelInfo cancelInfo, Coin coin)
	{
		ComponentExtensions.GetOrAddComponent<ProjectileBoostTracker>((Component)(object)coin);
	}
}
public static class GrenadePatches
{
	private static FieldInfo grenadeBeamFi = typeof(Grenade).GetField("grenadeBeam", BindingFlags.Instance | BindingFlags.NonPublic);

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		GrenadeEvents.PreGrenadeStart += new PreGrenadeStartEventHandler(PreGrenadeStart);
		GrenadeEvents.PreGrenadeBeam += new PreGrenadeBeamEventHandler(PreGrenadeBeam);
		GrenadeEvents.PostGrenadeBeam += new PostGrenadeBeamEventHandler(PostGrenadeBeam);
		GrenadeEvents.PreGrenadeCollision += new PreGrenadeCollisionEventHandler(PreGrenadeCollision);
	}

	private static void PreGrenadeStart(EventMethodCanceler canceler, Grenade grenade)
	{
		ComponentExtensions.GetOrAddComponent<ProjectileBoostTracker>((Component)(object)grenade);
	}

	private static void PreGrenadeBeam(EventMethodCanceler canceler, Grenade grenade, Vector3 targetPoint, GameObject newSourceWeapon)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		RevolverBeam val = (RevolverBeam)grenadeBeamFi.GetValue(grenade);
		ProjectileBoostTracker projectileBoostTracker = ((Component)val).gameObject.AddComponent<ProjectileBoostTracker>();
		ProjectileBoostTracker component = ((Component)grenade).GetComponent<ProjectileBoostTracker>();
		Assert.IsNotNull((Object)(object)projectileBoostTracker, "");
		Assert.IsNotNull((Object)(object)grenade, "");
		Assert.IsNotNull((Object)(object)((Component)grenade).GetComponent<ProjectileBoostTracker>(), "");
		if (component.NumEnemyBoosts != 0)
		{
			if (grenade.rocket)
			{
				MonoSingleton<StyleHUD>.Instance.AddPoints(10, "<color=#ae57ff>MODERN <color=#ff0000>T<color=#ffaa00>E<color=#0dff00>C<color=#ffd500>H<color=#7bff00>N<color=#00ff59>O<color=#00c3ff>L<color=#0080ff>O<color=#7300ff>G<color=#ff00ee>Y", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
			}
			else
			{
				MonoSingleton<StyleHUD>.Instance.AddPoints(10, "<color=#00fff7>CONVERSION</color>", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
			}
		}
		projectileBoostTracker.CopyFrom(component);
		projectileBoostTracker.IncrementPlayerBoosts();
	}

	private static void PostGrenadeBeam(EventMethodCancelInfo cancelInfo, Grenade grenade, Vector3 targetPoint, GameObject newSourceWeapon)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		RevolverBeam val = (RevolverBeam)grenadeBeamFi.GetValue(grenade);
	}

	private static void PreGrenadeCollision(EventMethodCanceler canceler, Grenade grenade, Collider other, Vector3 velocity)
	{
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		if (!Cheats.Enabled || !Options.GrenadesParryable.Value)
		{
			return;
		}
		ProjectileBoostTracker boostTracker = ((Component)grenade).GetComponent<ProjectileBoostTracker>();
		double parryability = boostTracker.NotifyContact();
		PortalAwarePlayerColliderClone val = default(PortalAwarePlayerColliderClone);
		EnemyIdentifierIdentifier val2 = default(EnemyIdentifierIdentifier);
		if (((Component)other).TryGetComponent<PortalAwarePlayerColliderClone>(ref val) || GrenadeExtensions.IsExploded(grenade) || (!grenade.enemy && ((Component)other).CompareTag("Player")) || ((Component)other).gameObject.layer == 14 || ((Component)other).gameObject.layer == 20 || (((Component)other).gameObject.layer != 11 && ((Component)other).gameObject.layer != 10) || !(Object.op_Implicit((Object)(object)other.attachedRigidbody) ? ((Component)other.attachedRigidbody).TryGetComponent<EnemyIdentifierIdentifier>(ref val2) : ((Component)other).TryGetComponent<EnemyIdentifierIdentifier>(ref val2)) || !Object.op_Implicit((Object)(object)val2.eid))
		{
			return;
		}
		EnemyComponents enemy = ((Component)val2.eid).GetComponent<EnemyComponents>();
		Assert.IsNotNull((Object)(object)enemy, "");
		if (enemy.Eid.Dead || (grenade.ignoreEnemyType.Count > 0 && grenade.ignoreEnemyType.Contains(enemy.Eid.enemyType)))
		{
			return;
		}
		EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
		if (!feedbacker.Enabled || !feedbacker.ReadyToParry || !feedbacker.CanParry(boostTracker, parryability))
		{
			return;
		}
		feedbacker.ParryEffect(((Component)grenade).transform.position);
		boostTracker.IncrementEnemyBoost();
		((Component)grenade).gameObject.SetActive(false);
		feedbacker.QueueParry(delegate(Vector3 offset)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00d8: 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)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			((Component)grenade).gameObject.SetActive(true);
			feedbacker.ParryFinishEffect(((Component)grenade).transform.position + offset);
			Vector3 velocity2;
			if (grenade.rocket)
			{
				Vector3 val3 = feedbacker.SolveParryForce(((Component)grenade).transform.position + offset, ((Component)grenade).transform.rotation * Vector3.forward * grenade.rocketSpeed);
				Rigidbody rb = grenade.rb;
				Vector3 val4 = val3;
				velocity2 = grenade.rb.velocity;
				rb.velocity = val4 * ((Vector3)(ref velocity2)).magnitude;
				grenade.rb.rotation = Quaternion.LookRotation(val3);
			}
			else
			{
				Vector3 val3 = feedbacker.SolveParryForce(((Component)grenade).transform.position + offset, grenade.rb.velocity * 5f);
				Vector3 val5 = val3;
				velocity2 = grenade.rb.velocity;
				Vector3 velocity3 = val5 * ((Vector3)(ref velocity2)).magnitude * 5f;
				if (((Vector3)(ref velocity3)).magnitude > 80f)
				{
					velocity3 = ((Vector3)(ref velocity3)).normalized * 80f;
				}
				grenade.rb.velocity = velocity3;
			}
			grenade.enemy = true;
			boostTracker.IgnoreColliders = enemy.Colliders;
			boostTracker.SafeEid = enemy.Eid;
			Transform transform = ((Component)grenade).transform;
			transform.position += offset;
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			Physics.IgnoreCollision(((Component)grenade).GetComponent<Collider>(), (Collider)(object)instance.playerCollider, false);
		});
		((EventMethodCanceler)(ref canceler)).CancelMethod();
	}
}
public static class NailPatches
{
	[HarmonyPatch(typeof(Nail), "FixedUpdate")]
	private static class NailFixedUpdatePatch
	{
		public static void Prefix(Nail __instance)
		{
			if (__instance.sawblade || __instance.chainsaw)
			{
				ProjectileBoostTracker component = ((Component)__instance).GetComponent<ProjectileBoostTracker>();
				component.PreNailFixedUpdate();
			}
		}

		public static void Postfix(Nail __instance)
		{
		}
	}

	private static FieldInfo sameEnemyHitCooldownFi = AccessTools.Field(typeof(Nail), "sameEnemyHitCooldown");

	private static FieldInfo currentHitEnemyFi = AccessTools.Field(typeof(Nail), "currentHitEnemy");

	private static FieldInfo hitLimbsFi = AccessTools.Field(typeof(Nail), "hitLimbs");

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		NailEvents.PreNailStart += new PreNailStartEventHandler(PreNailStart);
		NailEvents.PreNailHitEnemy += new PreNailHitEnemyEventHandler(PreNailHitEnemy);
	}

	private static void PreNailStart(EventMethodCanceler canceler, Nail nail)
	{
		ComponentExtensions.GetOrAddComponent<ProjectileBoostTracker>((Component)(object)nail);
	}

	private static void PreNailHitEnemy(EventMethodCanceler canceler, Nail nail, Transform other, EnemyIdentifierIdentifier eidid)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: 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_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: 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_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		if ((!nail.chainsaw && !nail.sawblade) || nail.magnets.Count > 0)
		{
			return;
		}
		float num = (float)sameEnemyHitCooldownFi.GetValue(nail);
		EnemyIdentifier val = (EnemyIdentifier)currentHitEnemyFi.GetValue(nail);
		List<Transform> list = (List<Transform>)hitLimbsFi.GetValue(nail);
		if (((Object)(object)eidid == (Object)null && !((Component)other).TryGetComponent<EnemyIdentifierIdentifier>(ref eidid)) || !Object.op_Implicit((Object)(object)eidid.eid) || (nail.enemy && (Object)(object)eidid != (Object)null && (Object)(object)eidid.eid != (Object)null && eidid.eid.enemyType == nail.safeEnemyType) || (nail.sawblade && ((num > 0f && (Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)eidid.eid) || list.Contains(other))))
		{
			return;
		}
		Assert.IsNotNull((Object)(object)eidid, "");
		Assert.IsNotNull((Object)(object)eidid.eid, "");
		EnemyComponents component = ((Component)eidid.eid).GetComponent<EnemyComponents>();
		Assert.IsNotNull((Object)(object)component, "");
		if (!Options.SawsParryable.Value || component.Eid.Dead)
		{
			return;
		}
		EnemyFeedbacker feedbacker = component.GetFeedbacker();
		if (!feedbacker.Enabled)
		{
			return;
		}
		ProjectileBoostTracker component2 = ((Component)nail).GetComponent<ProjectileBoostTracker>();
		if ((Object)(object)component2 == (Object)null)
		{
			return;
		}
		if ((Object)(object)component2.SafeEid == (Object)(object)component.Eid)
		{
			((EventMethodCanceler)(ref canceler)).CancelMethod();
			return;
		}
		double parryability = component2.NotifyContact();
		component2.MarkCannotBeEnemyParried();
		if (!feedbacker.ReadyToParry || !feedbacker.CanParry(component2, parryability))
		{
			return;
		}
		Vector3 val2 = feedbacker.SolveParryForce(((Component)nail).transform.position, nail.rb.velocity);
		Rigidbody rb = nail.rb;
		Vector3 velocity = nail.rb.velocity;
		rb.velocity = val2 * ((Vector3)(ref velocity)).magnitude;
		((Component)nail.rb).transform.rotation = Quaternion.LookRotation(val2);
		component2.IncrementEnemyBoost();
		feedbacker.ParryEffect(((Component)nail).transform.position);
		component2.IgnoreColliders = component.Colliders;
		component2.SafeEid = component.Eid;
		nail.enemy = true;
		((Component)nail).gameObject.layer = 2;
		NewMovement instance = MonoSingleton<NewMovement>.Instance;
		foreach (Collider collider in component2.Colliders)
		{
			Physics.IgnoreCollision(collider, (Collider)(object)instance.playerCollider, false);
		}
		((EventMethodCanceler)(ref canceler)).CancelMethod();
	}
}
public static class ProjectilePatches
{
	private static FieldInfo _activeFi = typeof(Projectile).GetField("active", BindingFlags.Instance | BindingFlags.NonPublic);

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		ProjectileEvents.PostProjectileAwake += new PostProjectileAwakeEventHandler(PostProjectileAwake);
		ProjectileEvents.PreProjectileCollided += new PreProjectileCollidedEventHandler(PreProjectileCollided);
	}

	private static void PostProjectileAwake(EventMethodCancelInfo cancelInfo, Projectile projectile)
	{
		ComponentExtensions.GetOrAddComponent<ProjectileBoostTracker>((Component)(object)projectile);
	}

	private static void PreProjectileCollided(EventMethodCanceler canceler, Projectile projectile, Collider other)
	{
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Invalid comparison between Unknown and I4
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
		if (!(bool)_activeFi.GetValue(projectile) || !Cheats.Enabled)
		{
			return;
		}
		ProjectileBoostTracker boostTracker = ((Component)projectile).GetComponent<ProjectileBoostTracker>();
		if (boostTracker.IsPlayerSourced && !Options.PlayerProjectilesParryable.Value)
		{
			return;
		}
		if (boostTracker.IgnoreColliders.Contains(other))
		{
			((EventMethodCanceler)(ref canceler)).CancelMethod();
		}
		else
		{
			if (!projectile.friendly)
			{
				return;
			}
			double parryability = boostTracker.NotifyContact();
			Action action = delegate
			{
				if (boostTracker.ProjectileType == ProjectileBoostTracker.ProjectileCategory.Coin && boostTracker.NumPlayerBoosts != 0 && boostTracker.NumEnemyBoosts != 0)
				{
					MonoSingleton<StyleHUD>.Instance.AddPoints(10, "<color=#ffd000>KEEP THE CHANGE</color>", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
				}
			};
			EnemyIdentifierIdentifier val = null;
			if ((!projectile.friendly && !projectile.hittingPlayer && ((Component)other).gameObject.CompareTag("Player")) || (projectile.canHitCoin && ((Component)other).gameObject.CompareTag("Coin")))
			{
				return;
			}
			if ((((Component)other).gameObject.CompareTag("Armor") && (projectile.friendly || !((Component)other).TryGetComponent<EnemyIdentifierIdentifier>(ref val) || !Object.op_Implicit((Object)(object)val.eid) || val.eid.enemyType != projectile.safeEnemyType)) || (projectile.boosted && ((Component)other).gameObject.layer == 11 && ((Component)other).gameObject.CompareTag("Body") && ((Component)other).TryGetComponent<EnemyIdentifierIdentifier>(ref val) && Object.op_Implicit((Object)(object)val.eid) && (int)val.eid.enemyType == 4 && !val.eid.isGasolined))
			{
				EnemyIdentifier val2 = null;
				if ((Object)(object)val != (Object)null && (Object)(object)val.eid != (Object)null)
				{
					val2 = val.eid;
				}
				EnemyComponents component = ((Component)val2).GetComponent<EnemyComponents>();
				Assert.IsNotNull((Object)(object)component, "");
				EnemyFeedbacker feedbacker2 = component.GetFeedbacker();
				if (feedbacker2.Enabled && (Object)(object)boostTracker.SafeEid == (Object)(object)val2)
				{
					((EventMethodCanceler)(ref canceler)).CancelMethod();
				}
			}
			else
			{
				if ((!((Component)other).gameObject.CompareTag("Head") && !((Component)other).gameObject.CompareTag("Body") && !((Component)other).gameObject.CompareTag("Limb") && !((Component)other).gameObject.CompareTag("EndLimb")) || ((Component)other).gameObject.CompareTag("Armor"))
				{
					return;
				}
				val = ((Component)other).gameObject.GetComponentInParent<EnemyIdentifierIdentifier>();
				EnemyIdentifier val3 = null;
				if ((Object)(object)val != (Object)null && (Object)(object)val.eid != (Object)null)
				{
					val3 = val.eid;
				}
				if ((Object)(object)val3 == (Object)null || (projectile.alreadyHitEnemies.Count != 0 && projectile.alreadyHitEnemies.Contains(val3)) || ((val3.enemyType == projectile.safeEnemyType || EnemyIdentifier.CheckHurtException(projectile.safeEnemyType, val3.enemyType, projectile.targetHandle)) && (!projectile.friendly || val3.immuneToFriendlyFire) && !projectile.playerBullet && !projectile.parried) || val3.Dead)
				{
					return;
				}
				Log.Debug($"Deciding parry capability for enemy {val3}, for projectile {projectile} with a hit that hit collider {other}");
				Log.Debug($"boostTracker.IgnoreEid = {boostTracker.SafeEid}");
				EnemyComponents enemy = ((Component)val3).GetComponent<EnemyComponents>();
				Assert.IsNotNull((Object)(object)enemy, "");
				EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
				if (!feedbacker.Enabled)
				{
					action();
					return;
				}
				if ((Object)(object)boostTracker.SafeEid == (Object)(object)val3)
				{
					((EventMethodCanceler)(ref canceler)).CancelMethod();
					return;
				}
				if (!feedbacker.ReadyToParry)
				{
					action();
					return;
				}
				if (projectile.unparryable || projectile.undeflectable)
				{
					action();
					return;
				}
				if (!feedbacker.CanParry(boostTracker, parryability))
				{
					action();
					return;
				}
				boostTracker.IncrementEnemyBoost();
				feedbacker.ParryEffect(((Component)projectile).transform.position);
				((Component)projectile).gameObject.SetActive(false);
				feedbacker.QueueParry(delegate(Vector3 offset)
				{
					//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_001d: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: 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_0044: Unknown result type (might be due to invalid IL or missing references)
					//IL_0059: 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_0070: 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_0086: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
					feedbacker.ParryFinishEffect(((Component)projectile).transform.position + offset);
					Vector3 val4 = feedbacker.SolveParryForce(((Component)projectile).transform.position + offset, ((Component)projectile).GetComponent<Rigidbody>().velocity);
					projectile.homingType = (HomingType)0;
					((Component)projectile).transform.rotation = Quaternion.LookRotation(val4);
					boostTracker.IgnoreColliders = enemy.Colliders;
					boostTracker.SetTempSafeEnemyType(enemy.Eid.enemyType);
					boostTracker.SafeEid = enemy.Eid;
					projectile.friendly = false;
					((Component)projectile).gameObject.SetActive(true);
				});
				((EventMethodCanceler)(ref canceler)).CancelMethod();
			}
		}
	}
}
public static class PunchPatches
{
	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		PlayerPunchEvents.PreParryProjectile += new PreParryProjectileEventHandler(PreParryProjectile);
	}

	private static void PreParryProjectile(EventMethodCanceler canceler, Punch punch, Projectile proj)
	{
		if (!Cheats.Enabled)
		{
			return;
		}
		ProjectileBoostTracker component = ((Component)proj).GetComponent<ProjectileBoostTracker>();
		if ((Object)(object)component != (Object)null)
		{
			component.IncrementPlayerBoosts();
			if (component.NumPlayerBoosts > 1)
			{
				proj.speed *= 0.55f;
			}
			if (component.NumEnemyBoosts != 0 && (component.ProjectileType == ProjectileBoostTracker.ProjectileCategory.RevolverBeam || component.ProjectileType == ProjectileBoostTracker.ProjectileCategory.PlayerProjectile))
			{
				MonoSingleton<StyleHUD>.Instance.AddPoints(10, "<color=#26ff00>PARRY PONG</color>", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
			}
		}
	}
}
public static class RevolverBeamPatches
{
	private static FieldInfo _enemiesPiercedFi = typeof(RevolverBeam).GetField("enemiesPierced", BindingFlags.Instance | BindingFlags.NonPublic);

	internal static void Initialize()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		RevolverBeamEvents.PreRevolverBeamStart += new PreRevolverBeamStartEventHandler(PreRevolverBeamStart);
		RevolverBeamEvents.PreRevolverBeamHitSomething += new PreRevolverBeamHitSomethingEventHandler(PreRevolverBeamHitSomething);
		RevolverBeamEvents.PreRevolverBeamPiercingShotCheck += new PreRevolverBeamPiercingShotCheckEventHandler(PreRevolverBeamPiercingShotCheck);
	}

	private static void PreRevolverBeamStart(EventMethodCanceler canceler, RevolverBeam revolverBeam)
	{
		if ((Object)(object)((Component)revolverBeam).GetComponent<ProjectileBoostTracker>() == (Object)null)
		{
			((Component)revolverBeam).gameObject.AddComponent<ProjectileBoostTracker>();
		}
	}

	private static void PreRevolverBeamHitSomething(EventMethodCanceler canceler, RevolverBeam revolverBeam, PhysicsCastResult hit)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Invalid comparison between Unknown and I4
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		if (!Cheats.Enabled || !Options.BeamsParryable.Value || (int)revolverBeam.beamType == 3 || (int)revolverBeam.beamType == 2)
		{
			return;
		}
		ProjectileBoostTracker component = ((Component)revolverBeam).GetComponent<ProjectileBoostTracker>();
		if ((component.ProjectileType == ProjectileBoostTracker.ProjectileCategory.Coin && !Options.ShotCoinsParryable.Value) || (component.ProjectileType == ProjectileBoostTracker.ProjectileCategory.Grenade && !Options.GrenadesParryable.Value))
		{
			return;
		}
		double parryability = component.NotifyContact();
		EnemyIdentifierIdentifier val = default(EnemyIdentifierIdentifier);
		if (!(Object.op_Implicit((Object)(object)hit.collider.attachedRigidbody) ? ((Component)hit.collider.attachedRigidbody).TryGetComponent<EnemyIdentifierIdentifier>(ref val) : ((Component)hit.collider).TryGetComponent<EnemyIdentifierIdentifier>(ref val)) || !Object.op_Implicit((Object)(object)val.eid))
		{
			return;
		}
		EnemyComponents enemy = ((Component)val.eid).GetComponent<EnemyComponents>();
		Assert.IsNotNull((Object)(object)enemy, "");
		if (enemy.Eid.Dead)
		{
			return;
		}
		EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
		if (feedbacker.CanParry(component, parryability) && feedbacker.Enabled && feedbacker.ReadyToParry)
		{
			feedbacker.ParryEffect(hit.point);
			float revBeamDmg = revolverBeam.damage;
			GameObject counterBeamGo = Object.Instantiate<GameObject>(Assets.EnemyRevolverBullet);
			Projectile counterBeam = counterBeamGo.GetComponent<Projectile>();
			ProjectileBoostTracker counterBeamBoostTracker = GameObjectExtensions.GetOrAddComponent<ProjectileBoostTracker>(counterBeamGo);
			counterBeamBoostTracker.CopyFrom(component);
			feedbacker.QueueParry(delegate(Vector3 offset)
			{
				//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_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: 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)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				counterBeamBoostTracker.IncrementEnemyBoost();
				feedbacker.ParryFinishEffect(hit.point + offset);
				Vector3 val2 = feedbacker.SolveParryForce(hit.point + offset, counterBeamGo.transform.rotation * Vector3.forward * counterBeam.speed);
				counterBeamGo.transform.position = hit.point + offset;
				counterBeamGo.transform.rotation = Quaternion.LookRotation(val2);
				counterBeamGo.SetActive(true);
				IReadOnlyList<Collider> colliders = enemy.Colliders;
				counterBeamBoostTracker.IgnoreColliders = colliders;
				counterBeam.playerBullet = true;
				counterBeam.damage = revBeamDmg * 25f;
				counterBeam.enemyDamageMultiplier = 0.12f;
			});
			revolverBeam.fake = true;
			((EventMethodCanceler)(ref canceler)).CancelMethod();
		}
	}

	private static void PreRevolverBeamPiercingShotCheck(EventMethodCanceler canceler, RevolverBeam revolverBeam)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between Unknown and I4
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Invalid comparison between Unknown and I4
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		if (!Cheats.Enabled || !Options.BeamsParryable.Value || (int)revolverBeam.beamType == 3 || (int)revolverBeam.beamType == 2)
		{
			return;
		}
		int num = (int)_enemiesPiercedFi.GetValue(revolverBeam);
		if (num != 0)
		{
			return;
		}
		ProjectileBoostTracker component = ((Component)revolverBeam).GetComponent<ProjectileBoostTracker>();
		if (component.ProjectileType == ProjectileBoostTracker.ProjectileCategory.Coin && !Options.ShotCoinsParryable.Value)
		{
			return;
		}
		double parryability = component.NotifyContact();
		if (revolverBeam.hitList.Count <= num)
		{
			return;
		}
		PhysicsCastResult hit = revolverBeam.hitList[num];
		EnemyIdentifierIdentifier val = default(EnemyIdentifierIdentifier);
		if ((Object)(object)hit.collider == (Object)null || !(Object.op_Implicit((Object)(object)hit.collider.attachedRigidbody) ? ((Component)hit.collider.attachedRigidbody).TryGetComponent<EnemyIdentifierIdentifier>(ref val) : ((Component)hit.collider).TryGetComponent<EnemyIdentifierIdentifier>(ref val)) || !Object.op_Implicit((Object)(object)val.eid))
		{
			return;
		}
		EnemyComponents enemy = ((Component)val.eid).GetComponent<EnemyComponents>();
		Assert.IsNotNull((Object)(object)enemy, "");
		if (enemy.Eid.Dead)
		{
			return;
		}
		EnemyFeedbacker feedbacker = enemy.GetFeedbacker();
		if (feedbacker.CanParry(component, parryability) && feedbacker.Enabled && feedbacker.ReadyToParry)
		{
			feedbacker.ParryEffect(hit.point);
			float revBeamDmg = revolverBeam.damage * 3f;
			GameObject counterBeamGo = Object.Instantiate<GameObject>(Assets.EnemyRevolverBullet);
			Projectile counterBeam = counterBeamGo.GetComponent<Projectile>();
			ProjectileBoostTracker counterBeamBoostTracker = GameObjectExtensions.GetOrAddComponent<ProjectileBoostTracker>(counterBeamGo);
			counterBeamBoostTracker.CopyFrom(component);
			feedbacker.QueueParry(delegate(Vector3 offset)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: 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_006c: 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_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: 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_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				counterBeamBoostTracker.IncrementEnemyBoost();
				counterBeamGo.transform.position = hit.point + offset;
				feedbacker.ParryFinishEffect(hit.point + offset);
				Vector3 val2 = feedbacker.SolveParryForce(hit.point + offset, ((Component)counterBeam).transform.rotation * Vector3.forward * counterBeam.speed);
				counterBeamGo.transform.rotation = Quaternion.LookRotation(val2);
				counterBeamGo.SetActive(true);
				IReadOnlyList<Collider> colliders = enemy.Colliders;
				counterBeamBoostTracker.IgnoreColliders = colliders;
				counterBeamBoostTracker.SafeEid = enemy.Eid;
				counterBeam.playerBullet = true;
				counterBeam.damage = revBeamDmg * 5f;
				counterBeam.enemyDamageMultiplier = 0.2f;
			});
			revolverBeam.fake = true;
			_enemiesPiercedFi.SetValue(revolverBeam, int.MaxValue);
		}
	}
}
public class ProjectileBoostTracker : MonoBehaviour
{
	public enum ProjectileCategory : byte
	{
		Null,
		RevolverBeam,
		EnemyRevolverBeam,
		PlayerProjectile,
		Projectile,
		HomingProjectile,
		Rocket,
		Grenade,
		EnemyRocket,
		EnemyGrenade,
		Coin,
		Nail,
		Saw
	}

	public bool LastBoostedByPlayer = false;

	private Cannonball _cannonball;

	public EnemyIdentifier SafeEid = null;

	public bool Electric = false;

	public bool CoinPunched = false;

	[SerializeField]
	private uint _numPlayerBoosts = 0u;

	[SerializeField]
	private uint _numEnemyBoosts = 0u;

	[SerializeField]
	private ProjectileCategory _projectileType = ProjectileCategory.Null;

	private static FieldInfo _cballInterruptionExplosionFi = AccessTools.Field(typeof(Cannonball), "interruptionExplosion");

	[SerializeField]
	private double _startParryabilityDist = double.PositiveInfinity;

	[SerializeField]
	private double _creationProgressParryabilityDist = double.PositiveInfinity;

	private FixedTimeStamp _creationStartTime = default(FixedTimeStamp);

	private FixedTimeStamp _creationProgressTime = default(FixedTimeStamp);

	private Collider[] _ignoreColliders = (Collider[])(object)new Collider[0];

	private Collider[] _colliders = null;

	private Projectile _proj;

	private double _safeEnemyTypeCountDown = -1.0;

	private bool _explosiveAndExplosionUnique = false;

	private ExplosionAdditions _explosion = null;

	private GameObject _prefabHolder = null;

	[SerializeField]
	private bool _canBeEnemyParried = true;

	private Nail _nail;

	public bool HasBeenBoosted => NumPlayerBoosts != 0 || NumEnemyBoosts != 0;

	public bool IsPlayerSourced => ProjectileType == ProjectileCategory.RevolverBeam || ProjectileType == ProjectileCategory.PlayerProjectile || ProjectileType == ProjectileCategory.Rocket || ProjectileType == ProjectileCategory.Grenade;

	public uint NumPlayerBoosts
	{
		get
		{
			return _numPlayerBoosts;
		}
		private set
		{
			_numPlayerBoosts = value;
		}
	}

	public uint NumEnemyBoosts
	{
		get
		{
			return _numEnemyBoosts;
		}
		private set
		{
			_numEnemyBoosts = value;
		}
	}

	public uint NumBoosts => NumPlayerBoosts + NumEnemyBoosts;

	public ProjectileCategory ProjectileType
	{
		get
		{
			return _projectileType;
		}
		private set
		{
			_projectileType = value;
		}
	}

	public IReadOnlyList<Collider> Colliders => _colliders;

	public IReadOnlyList<Collider> IgnoreColliders
	{
		get
		{
			return _ignoreColliders;
		}
		set
		{
			Collider[] ignoreColliders = _ignoreColliders;
			foreach (Collider val in ignoreColliders)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Collider[] colliders = _colliders;
					foreach (Collider val2 in colliders)
					{
						Physics.IgnoreCollision(val, val2, false);
					}
				}
			}
			if (value == null)
			{
				_ignoreColliders = (Collider[])(object)new Collider[0];
				return;
			}
			_ignoreColliders = value.ToArray();
			Collider[] ignoreColliders2 = _ignoreColliders;
			foreach (Collider val3 in ignoreColliders2)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Collider[] colliders2 = _colliders;
					foreach (Collider val4 in colliders2)
					{
						Physics.IgnoreCollision(val3, val4, true);
					}
				}
			}
		}
	}

	public void IncrementPlayerBoosts()
	{
		if (LastBoostedByPlayer && NumPlayerBoosts != 0)
		{
			return;
		}
		NumPlayerBoosts++;
		LastBoostedByPlayer = true;
		_canBeEnemyParried = true;
		_creationProgressParryabilityDist = ParryabilityTracker.NotifyCreationProgress(((object)this).GetHashCode());
		((FixedTimeStamp)(ref _creationProgressTime)).UpdateToNow();
		SafeEid = null;
		if (NumEnemyBoosts != 0)
		{
			_safeEnemyTypeCountDown = 0.0;
			if ((Object)(object)_proj != (Object)null && NumBoosts == 1 && !_proj.friendly)
			{
				((FixedTimeStamp)(ref _creationStartTime)).UpdateToNow();
				_startParryabilityDist = ParryabilityTracker.NotifyCreationStart(((object)this).GetHashCode());
			}
			IgnoreColliders = (IReadOnlyList<Collider>)(object)new Collider[0];
			if (NumPlayerBoosts > 1 || NumEnemyBoosts >= 1)
			{
				BoostOomph(bigOomph: true);
			}
			Log.Debug($"IncrementPlayerBoosts called for ProjectileBoostTracker {this}");
		}
	}

	public void IncrementEnemyBoost()
	{
		if (!LastBoostedByPlayer && NumEnemyBoosts != 0)
		{
			return;
		}
		if (NumEnemyBoosts == 0)
		{
			for (int i = 1; i < NumPlayerBoosts; i++)
			{
				BoostOomph(bigOomph: true);
			}
		}
		NumEnemyBoosts++;
		LastBoostedByPlayer = false;
		_creationProgressParryabilityDist = ParryabilityTracker.NotifyCreationProgress(((object)this).GetHashCode());
		((FixedTimeStamp)(ref _creationProgressTime)).UpdateToNow();
		_canBeEnemyParried = true;
		BoostOomph(bigOomph: false);
		Log.Debug($"IncrementEnemyBoosts called for ProjectileBoostTracker {this}");
	}

	private void BoostOomph(bool bigOomph)
	{
		if (!Cheats.Enabled || NumEnemyBoosts == 0)
		{
			return;
		}
		if ((Object)(object)_proj != (Object)null)
		{
			if (bigOomph)
			{
				Log.Debug("Oomph boosting for projectile bigly");
				MakeExplosiveAndExplosionUnique();
				Projectile proj = _proj;
				proj.enemyDamageMultiplier *= 2f;
				Projectile proj2 = _proj;
				proj2.damage *= 1.2f;
				ExplosionAdditions explosion = _explosion;
				explosion.ExplosionScale += 0.5f;
				ExplosionAdditions explosion2 = _explosion;
				explosion2.ExplosionSpeedScale += 0.5f;
				ExplosionAdditions explosion3 = _explosion;
				explosion3.ExplosionDamageScale += 0.25f;
				ExplosionAdditions explosion4 = _explosion;
				explosion4.ExplosionEnemyDamageMultiplierScale += 0.75f;
			}
			else
			{
				Log.Debug("Oomph boosting for projectile not so bigly");
				MakeExplosiveAndExplosionUnique();
				Projectile proj3 = _proj;
				proj3.enemyDamageMultiplier *= 1.2f;
				Projectile proj4 = _proj;
				proj4.damage *= 1.1f;
			}
		}
		else if ((Object)(object)_cannonball != (Object)null)
		{
			if (bigOomph)
			{
				Log.Debug("Oomph boosting for cannonball bigly");
				MakeExplosiveAndExplosionUnique();
				Cannonball cannonball = _cannonball;
				cannonball.damage *= 2f;
				ExplosionAdditions explosion5 = _explosion;
				explosion5.ExplosionScale *= 1.5f;
				ExplosionAdditions explosion6 = _explosion;
				explosion6.ExplosionSpeedScale *= 1.5f;
				ExplosionAdditions explosion7 = _explosion;
				explosion7.ExplosionDamageScale += 0.1f;
			}
			else
			{
				Log.Debug("Oomph boosting for not so bigly");
				MakeExplosiveAndExplosionUnique();
				Cannonball cannonball2 = _cannonball;
				cannonball2.damage *= 1.1f;
			}
		}
	}

	protected void Awake()
	{
		_colliders = ((Component)this).GetComponentsInChildren<Collider>();
		if (ProjectileType == ProjectileCategory.Null)
		{
			((FixedTimeStamp)(ref _creationStartTime)).UpdateToNow();
			((FixedTimeStamp)(ref _creationProgressTime)).UpdateToNow();
		}
	}

	protected void Start()
	{
		TrySolveType();
		((FixedTimeStamp)(ref _creationProgressTime)).UpdateToNow();
		MaybeEnforceOurExplosionPrefab();
	}

	private void TrySolveType()
	{
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Invalid comparison between Unknown and I4
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Invalid comparison between Unknown and I4
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Invalid comparison between Unknown and I4
		Cannonball cannonball2 = default(Cannonball);
		Projectile proj = default(Projectile);
		if (ProjectileType == ProjectileCategory.Null)
		{
			Grenade val = default(Grenade);
			Projectile val2 = default(Projectile);
			RevolverBeam val3 = default(RevolverBeam);
			Coin val4 = default(Coin);
			Cannonball cannonball = default(Cannonball);
			Nail val5 = default(Nail);
			if (((Component)this).TryGetComponent<Grenade>(ref val))
			{
				if (val.enemy)
				{
					if (val.rocket)
					{
						ProjectileType = ProjectileCategory.EnemyRocket;
					}
					else
					{
						ProjectileType = ProjectileCategory.EnemyGrenade;
					}
				}
				else if (val.rocket)
				{
					ProjectileType = ProjectileCategory.Rocket;
				}
				else
				{
					ProjectileType = ProjectileCategory.Grenade;
				}
			}
			else if (((Component)this).TryGetComponent<Projectile>(ref val2))
			{
				_proj = val2;
				if (val2.playerBullet)
				{
					ProjectileType = ProjectileCategory.PlayerProjectile;
				}
				else if ((int)val2.homingType == 0)
				{
					ProjectileType = ProjectileCategory.Projectile;
				}
				else
				{
					ProjectileType = ProjectileCategory.HomingProjectile;
				}
			}
			else if (((Component)this).TryGetComponent<RevolverBeam>(ref val3))
			{
				if ((Object)(object)val3.previouslyHitTransform != (Object)null && val3.noMuzzleflash)
				{
					ProjectileType = ProjectileCategory.Coin;
				}
				else if ((int)val3.beamType == 3 || (int)val3.beamType == 2)
				{
					ProjectileType = ProjectileCategory.EnemyRevolverBeam;
				}
				else
				{
					ProjectileType = ProjectileCategory.RevolverBeam;
				}
				if (val3.attributes.Contains((HitterAttribute)2))
				{
					Electric = true;
				}
			}
			else if (((Component)this).TryGetComponent<Coin>(ref val4))
			{
				ProjectileType = ProjectileCategory.Coin;
			}
			else if (((Component)this).TryGetComponent<Cannonball>(ref cannonball))
			{
				ProjectileType = ProjectileCategory.Rocket;
				_cannonball = cannonball;
			}
			else if (((Component)this).TryGetComponent<Nail>(ref val5))
			{
				if (val5.chainsaw)
				{
					ProjectileType = ProjectileCategory.Saw;
				}
				else if (val5.sawblade)
				{
					ProjectileType = ProjectileCategory.Saw;
				}
				else
				{
					ProjectileType = ProjectileCategory.Nail;
				}
				_nail = val5;
			}
			_startParryabilityDist = ParryabilityTracker.NotifyCreationStart(((object)this).GetHashCode());
			((FixedTimeStamp)(ref _creationStartTime)).UpdateToNow();
		}
		else if (((Component)this).TryGetComponent<Cannonball>(ref cannonball2))
		{
			_cannonball = cannonball2;
		}
		else if (((Component)this).TryGetComponent<Projectile>(ref proj))
		{
			_proj = proj;
		}
	}

	internal void PreNailFixedUpdate()
	{
		if ((Object)(object)_nail == (Object)null)
		{
			_nail = ((Component)this).GetComponent<Nail>();
		}
		if (_nail.punched)
		{
			IncrementPlayerBoosts();
		}
	}

	protected void FixedUpdate()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		if (_safeEnemyTypeCountDown >= 0.0)
		{
			_safeEnemyTypeCountDown -= Time.fixedDeltaTime;
			if (_safeEnemyTypeCountDown <= 0.0)
			{
				_safeEnemyTypeCountDown = -1.0;
				if ((Object)(object)_proj != (Object)null)
				{
					_proj.safeEnemyType = (EnemyType)21;
				}
			}
		}
		MaybeEnforceOurExplosionPrefab();
	}

	private void MaybeEnforceOurExplosionPrefab()
	{
		if (_explosiveAndExplosionUnique)
		{
			if ((Object)(object)_proj != (Object)null)
			{
				_proj.explosionEffect = ((Component)_explosion).gameObject;
			}
			else if ((Object)(object)_cannonball != (Object)null)
			{
				_cballInterruptionExplosionFi.SetValue(_cannonball, ((Component)_explosion).gameObject);
			}
		}
	}

	public double NotifyContact()
	{
		if (!_canBeEnemyParried)
		{
			return 0.0;
		}
		TrySolveType();
		double num = ParryabilityTracker.NotifyContact(((object)this).GetHashCode());
		double num2 = Math.Max(Math.Max(0.4 + ((FixedTimeStamp)(ref _creationStartTime)).TimeSince * 0.25, 0.3 + ((FixedTimeStamp)(ref _creationProgressTime)).TimeSince * 0.5), 0.75);
		double val = _creationProgressParryabilityDist;
		if (_startParryabilityDist < _creationProgressParryabilityDist)
		{
			double num3 = 1f / (float)(NumBoosts + 1);
			val = (_startParryabilityDist * num3 + _creationProgressParryabilityDist) / (1.0 + 1.0 * num3);
		}
		doubl