Decompiled source of MovementPlus v2.0.0

plugins/MovementPlus/MovementPlus.dll

Decompiled a year ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MovementPlus.NewAbility;
using Reptile;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MovementPlus")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MovementPlus")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("aa66f97d-0b0a-40a8-a961-64081a320b66")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MovementPlus
{
	public class MyConfig
	{
		public class ConfigRailGoon
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Rail Goon Enabled", true, "Trigered by landing on a rail corner.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Rail Goon Amount", 15f, "Amount of speed added when triggering a rail goon.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Rail Goon Cap", -1f, "Maximum amount of speed that can be added when triggering a rail goon.");

			public ConfigRailGoon(ConfigFile config, string category)
			{
			}
		}

		public class ConfigRailFrameboost
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Rail Frameboost Enabled", true, "Trigered by jumping shortly after landing on a rail.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Rail Frameboost Amount", 5f, "Amount of speed added when triggering a rail frameboost.");

			public ConfigEntry<float> Grace = config.Bind<float>(category, "Rail Frameboost Grace", 0.1f, "Amount of time for a rail frameboost.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Rail Frameboost Cap", -1f, "Maximum speed that can be obtained from rail frameboosts.");

			public ConfigRailFrameboost(ConfigFile config, string category)
			{
			}
		}

		public class ConfigWallFrameboost
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Wall Frameboost Enabled", true, "Trigered by jumping after landing on a wallride.");

			public ConfigEntry<bool> RunoffEnabled = config.Bind<bool>(category, "Wall Frameboost Runoff Enabled", false, "Trigered by running off a wallride");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Wall Frameboost Amount", 5f, "Amount of speed added when triggering a wallride frameboost.");

			public ConfigEntry<float> Grace = config.Bind<float>(category, "Wall Frameboost Grace", 0.1f, "Amount of time for a wallride frameboost.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Wall Frameboost Cap", -1f, "Maximum speed that can be obtained from wallride frameboosts.");

			public ConfigWallFrameboost(ConfigFile config, string category)
			{
			}
		}

		public class ConfigWallGeneral
		{
			public ConfigEntry<float> wallTotalSpeedCap = config.Bind<float>(category, "Wall Total Speed Cap", -1f, "Maximum amount of speed that can be added when landing on a wallride.");

			public ConfigWallGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigSuperTrickJump
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Super Trick Jump Enabled", true, "On foot trick jump height increases with forward speed.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Super Trick Jump Amount", 0.2f, "Amount of height gained with forward speed.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Super Trick Jump Cap", 30f, "Maximum height gained from a super trick jump.");

			public ConfigEntry<float> Threshold = config.Bind<float>(category, "Super Trick Jump Threshold", 21f, "Minimum Speed required to add any jump height.");

			public ConfigSuperTrickJump(ConfigFile config, string category)
			{
			}
		}

		public class ConfigPerfectManual
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Perfect Manual Enabled", true, "Pressing manual just before landing.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Perfect Manual Amount", 5f, "Amount of speed added when performing a perfect manual.");

			public ConfigEntry<float> Grace = config.Bind<float>(category, "Perfect Manual Grace", 0.1f, "Amount of time for a perfect manual.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Perfect Manual Cap", 45f, "Maximum speed that can be obtained from perfect manuals.");

			public ConfigPerfectManual(ConfigFile config, string category)
			{
			}
		}

		public class ConfigSuperSlide
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Super Slide Enabled", true, "Carpet sliding changes.");

			public ConfigEntry<float> Speed = config.Bind<float>(category, "Super Slide Base Speed", 35f, "Base speed of the super slide, this speed is reached very quickly.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Super Slide Amount", 0.1f, "Amount of speed added while super sliding.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Super Slide Cap", 55f, "Maximum speed that can be obtained from super sliding.");

			public ConfigSuperSlide(ConfigFile config, string category)
			{
			}
		}

		public class ConfigFastFall
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Fast Fall Enabled", true, "Pressing manual while falling.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Fast Fall Amount", -13f, "Amount of speed added when triggering a fast fall.");

			public ConfigFastFall(ConfigFile config, string category)
			{
			}
		}

		public class ConfigVertGeneral
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Vert Change Enabled", true, "Vert ramp speed is adjusted to your total speed.");

			public ConfigEntry<bool> JumpEnabled = config.Bind<bool>(category, "Vert Jump Change Enabled", true, "Jump height from vert ramps scales with your speed.");

			public ConfigEntry<float> JumpStrength = config.Bind<float>(category, "Vert Jump Strength", 0.4f, "Multiplier applied to your total speed to calculate vert jump height.");

			public ConfigEntry<float> JumpCap = config.Bind<float>(category, "Vert Jump Cap", 75f, "Maximum jump height from vert ramps.");

			public ConfigEntry<float> ExitSpeed = config.Bind<float>(category, "Vert Bonus Bottom Exit Speed", 7f, "Bonus speed added when exiting a vert ramp.");

			public ConfigEntry<float> ExitSpeedCap = config.Bind<float>(category, "Vert Bonus Bottom Exit Speed Cap", 75f, "Maximum speed that can be obtained from exiting a vert ramp.");

			public ConfigVertGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigBoostGeneral
		{
			public ConfigEntry<bool> StartEnabled = config.Bind<bool>(category, "Boost Start Change Enabled", true, "Bonus speed when using a boost outside of a grind or wallride.");

			public ConfigEntry<float> StartAmount = config.Bind<float>(category, "Boost Start Amount", 2f, "Amount of speed added when starting a boost.");

			public ConfigEntry<float> StartCap = config.Bind<float>(category, "Boost Start Cap", 60f, "Maximum speed that can be obtained from starting a boost.");

			public ConfigEntry<float> RailAmount = config.Bind<float>(category, "Boost On Rail Speed Over Time", 4f, "Amount of speed added over time while boosting on a rail.");

			public ConfigEntry<float> WallAmount = config.Bind<float>(category, "Boost On Wallride Speed Over Time", 15f, "Amount of speed added over time while boosting on a wallride.");

			public ConfigEntry<float> RailCap = config.Bind<float>(category, "Boost Rail Cap", 55f, "Maximum amount of speed that can be obtained from boosting while on a rail.");

			public ConfigEntry<float> WallCap = config.Bind<float>(category, "Boost Wallride Cap", 70f, "Maximum amount of speed that can be obtained from boosting while on a wallride.");

			public ConfigEntry<bool> TotalSpeedEnabled = config.Bind<bool>(category, "Total Speed Change Enabled", true, "Boost speed scales with total speed.");

			public ConfigEntry<float> TotalSpeedCap = config.Bind<float>(category, "Total Speed Change Cap", -1f, "Maximum amount of speed obtainable from the total speed boost change.");

			public ConfigBoostGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigRailGeneral
		{
			public ConfigEntry<float> HardAmount = config.Bind<float>(category, "Rail Hard Corner Amount", 3f, "Amount of speed per hard corner.");

			public ConfigEntry<float> HardCap = config.Bind<float>(category, "Rail Hard Corner Cap", 45f, "Maximum amount of speed that can be obtained from rail hard corners.");

			public ConfigEntry<float> Decc = config.Bind<float>(category, "Rail Deceleration", 1f, "Deceleration while grinding.");

			public ConfigRailGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigRailSlope
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Rail Slope Change Enabled", true, "Jumping while on an upwards sloped rail gives a larger jump and a downwards slope gives bonus speed.");

			public ConfigEntry<float> SlopeJumpAmount = config.Bind<float>(category, "Rail Slope Jump Height Amount", 4f, "Bonus height amount for sloped rail jump. This is affected by your speed and the slope of the rail.");

			public ConfigEntry<float> SlopeSpeedAmount = config.Bind<float>(category, "Rail Slope Jump Speed Amount", 6f, "Bonus speed amount for sloped rail jump. This is affected by your speed and the slope of the rail.");

			public ConfigEntry<float> SlopeJumpMax = config.Bind<float>(category, "Rail Slope Jump Height Max", 20f, "Maximum jump height you can gain from a sloped rail jump.");

			public ConfigEntry<float> SlopeSpeedCap = config.Bind<float>(category, "Rail Slope Jump Speed Cap", -1f, "Maximum Speed you can gain from a sloped rail jump.");

			public ConfigEntry<float> SlopeJumpMin = config.Bind<float>(category, "Rail Slope Jump Height Minimum", -7f, "Minimum jump height from a sloped rail jump.");

			public ConfigEntry<float> SlopeSpeedMin = config.Bind<float>(category, "Rail Slope Jump Speed Minimum", -10f, "Minimum speed from a sloped rail jump.");

			public ConfigEntry<float> SlopeSpeedMax = config.Bind<float>(category, "Rail Slope Jump Speed Max", 7f, "Maximum speed gained from a single sloped rail jump.");

			public ConfigRailSlope(ConfigFile config, string category)
			{
			}
		}

		public class ConfigComboGeneral
		{
			public ConfigEntry<bool> BoostEnabled = config.Bind<bool>(category, "Combo During Boost Enabled", true, "Allows you to maintain combo while boosting.");

			public ConfigEntry<bool> NoAbilityEnabled = config.Bind<bool>(category, "Combo No Ability Enabled", true, "Forces combo meter when touching the ground even without a manual.");

			public ConfigEntry<float> BoostTimeout = config.Bind<float>(category, "Combo Boost Timer", 0.5f, "How fast the combo timer ticks while boosting.");

			public ConfigEntry<float> BoostJumpAmount = config.Bind<float>(category, "Combo Boost Jump", 0.1f, "Amount of the combo timer is removed when jumping while boosting.");

			public ConfigEntry<float> NoAbilityTimeout = config.Bind<float>(category, "Combo No Ability Timer", 5f, "How fast the combo timer ticks down while not manualing.");

			public ConfigComboGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigLedgeClimbGeneral
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Ledge Climb Cancel Enabled", true, "Allows you to cancel the ledge climb animation with a jump.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Ledge Climb Cancel Amount", 15f, "Amount of speed added when you cancel a ledge climb.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Ledge Climb Cancel Cap", -1f, "Maximum amount of speed that can be added when canceling a ledge climb.");

			public ConfigLedgeClimbGeneral(ConfigFile config, string category)
			{
			}
		}

		public class ConfigButtslap
		{
			public ConfigEntry<bool> Enabled = config.Bind<bool>(category, "Buttslap Enabled", true, "Allows a jump during a ground trick animation while in the air.");

			public ConfigEntry<bool> MultiEnabled = config.Bind<bool>(category, "Buttslap Multi Enabled", true, "Allows multiple jumps during a buttslap.");

			public ConfigEntry<float> Amount = config.Bind<float>(category, "Buttslap Amount", 2f, "Forward speed added when performing a buttslap.");

			public ConfigEntry<float> ComboAmount = config.Bind<float>(category, "Buttslap Combo Amount", -0.1f, "Amount of combo meter added when performing a buttslap.");

			public ConfigEntry<float> Cap = config.Bind<float>(category, "Buttslap Cap", -1f, "Maximum amount of speed that can be added when performing a buttslap.");

			public ConfigEntry<float> JumpAmount = config.Bind<float>(category, "Buttslap Jump Amount", 5f, "Jump height per buttslap.");

			public ConfigEntry<float> Timer = config.Bind<float>(category, "Buttslap Multi Time", 0.3f, "Amount of time after the initial buttslap to perform multiple.");

			public ConfigButtslap(ConfigFile config, string category)
			{
			}
		}

		public class ConfigMisc
		{
			public ConfigEntry<float> groundTrickDecc = config.Bind<float>(category, "Ground Trick Deceleration", 1f, "Deceleration while performing a ground trick.");

			public ConfigEntry<bool> collisionChangeEnabled = config.Bind<bool>(category, "Collision Change Enabled", true, "Changes the collision fixing almost all instances of clipping through objects.");

			public ConfigEntry<float> speedLimit = config.Bind<float>(category, "Speed Limit", -1f, "Soft speed limit, if moving faster than this speed your speed will be reduced over time.");

			public ConfigEntry<float> speedLimitAmount = config.Bind<float>(category, "Speed Limit Penalty Amount", 5f, "Amount of speed to remove over time while above the speed limit.");

			public ConfigEntry<float> maxFallSpeed = config.Bind<float>(category, "Max Fall Speed", 40f, "Maximum speed you're allowed to fall.");

			public ConfigEntry<float> airDashStrength = config.Bind<float>(category, "Air Dash Strength", 0.3f, "How much speed you lose when changing direction with the air dash.");

			public ConfigEntry<float> averageSpeedTimer = config.Bind<float>(category, "Average Speed Timer", 0.4f, "Many mechanics use your average speed over a period of time this is that period of time, a lower time will be more responsive but less forgiving and might feel less smooth.");

			public ConfigMisc(ConfigFile config, string category)
			{
			}
		}

		public ConfigRailGoon RailGoon = new ConfigRailGoon(config, "Rail Goon");

		public ConfigRailFrameboost RailFrameboost = new ConfigRailFrameboost(config, "Rail Frameboost");

		public ConfigWallFrameboost WallFrameboost = new ConfigWallFrameboost(config, "Wall Frameboost");

		public ConfigWallGeneral WallGeneral = new ConfigWallGeneral(config, "Wall General");

		public ConfigSuperTrickJump SuperTrickJump = new ConfigSuperTrickJump(config, "Super Trick Jump");

		public ConfigPerfectManual PerfectManual = new ConfigPerfectManual(config, "Perfect Manual");

		public ConfigSuperSlide SuperSlide = new ConfigSuperSlide(config, "Super Slide");

		public ConfigFastFall FastFall = new ConfigFastFall(config, "Fast Fall");

		public ConfigVertGeneral VertGeneral = new ConfigVertGeneral(config, "Vert General");

		public ConfigBoostGeneral BoostGeneral = new ConfigBoostGeneral(config, "Boost General");

		public ConfigRailGeneral RailGeneral = new ConfigRailGeneral(config, "Rail General");

		public ConfigRailSlope RailSlope = new ConfigRailSlope(config, "Rail Slope");

		public ConfigComboGeneral ComboGeneral = new ConfigComboGeneral(config, "Combo General");

		public ConfigLedgeClimbGeneral LedgeClimbGeneral = new ConfigLedgeClimbGeneral(config, "Ledge Climb General");

		public ConfigButtslap Buttslap = new ConfigButtslap(config, "Buttslap");

		public ConfigMisc Misc = new ConfigMisc(config, "Misc");

		public MyConfig(ConfigFile config)
		{
		}
	}
	[BepInPlugin("com.yuril.MovementPlus", "MovementPlus", "2.0.0")]
	public class MovementPlusPlugin : BaseUnityPlugin
	{
		private const string MyGUID = "com.yuril.MovementPlus";

		private const string PluginName = "MovementPlus";

		private const string VersionString = "2.0.0";

		private Harmony harmony;

		public static Player player;

		public static MyConfig ConfigSettings;

		public static bool canFastFall;

		public static float defaultBoostSpeed;

		public static float defaultVertMaxSpeed;

		public static float defaultVertTopJumpSpeed;

		public static float defaultJumpSpeed;

		public static float savedLastSpeed;

		public static float noAbilitySpeed;

		public static float timeInAir;

		public static Queue<float> forwardSpeeds;

		public static Queue<float> totalSpeeds;

		public static Queue<Vector3> forwardDirs;

		public static float averageSpeedTimer;

		public static float averageForwardTimer;

		public static bool hasGooned;

		public static bool railGoonAppllied;

		public static bool jumpedFromRail;

		public static float jumpedFromRailTimer;

		private bool slideBoost;

		private float slideTimer;

		private bool slideTimerStarted;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("com.yuril.MovementPlus");
			PatchAllInNamespace(harmony, "MovementPlus.Patches");
			ConfigSettings = new MyConfig(((BaseUnityPlugin)this).Config);
			forwardSpeeds = new Queue<float>();
			totalSpeeds = new Queue<float>();
			forwardDirs = new Queue<Vector3>();
			averageSpeedTimer = 0f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MovementPlus has been loaded!");
		}

		private void FixedUpdate()
		{
			if ((Object)(object)player != (Object)null)
			{
				FastFall();
				VertChanges();
				BoostChanges();
				SaveSpeed();
				TimeInAir();
				LogSpeed(ConfigSettings.Misc.averageSpeedTimer.Value);
				LogForward(0.032f);
				JustJumpedFromRail();
				SpeedLimit();
				if (ConfigSettings.PerfectManual.Enabled.Value)
				{
					PerfectManual();
				}
			}
		}

		public static void PatchAllInNamespace(Harmony harmony, string namespaceName)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			IEnumerable<Type> enumerable = from t in executingAssembly.GetTypes()
				where t.Namespace == namespaceName
				select t;
			foreach (Type item in enumerable)
			{
				harmony.PatchAll(item);
			}
		}

		private void PerfectManual()
		{
			if (!player.IsGrounded())
			{
				slideBoost = false;
			}
			if (player.slideButtonNew)
			{
				slideTimer = 0f;
				slideTimerStarted = true;
			}
			if (slideTimerStarted)
			{
				slideTimer += Time.deltaTime;
				if (player.IsGrounded() && player.timeGrounded <= ConfigSettings.PerfectManual.Grace.Value && !slideBoost)
				{
					DoPerfectManual();
				}
				if (slideTimer >= ConfigSettings.PerfectManual.Grace.Value)
				{
					slideTimerStarted = false;
				}
			}
		}

		private void DoPerfectManual()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			player.SetForwardSpeed(LosslessClamp(AverageForwardSpeed(), ConfigSettings.PerfectManual.Amount.Value, ConfigSettings.PerfectManual.Cap.Value));
			slideBoost = true;
			player.CreateHighJumpDustEffect(player.tf.up);
			player.DoTrick((TrickType)4, "Perfect Manual", 1);
		}

		private void FastFall()
		{
			//IL_0028: 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)
			if (player.slideButtonNew && !player.TreatPlayerAsSortaGrounded() && player.motor.velocity.y <= 0f && canFastFall && ConfigSettings.FastFall.Enabled.Value)
			{
				player.motor.SetVelocityYOneTime(Mathf.Min(player.motor.velocity.y + ConfigSettings.FastFall.Amount.Value, ConfigSettings.FastFall.Amount.Value));
				player.ringParticles.Emit(1);
				player.AudioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)19, player.playerOneShotAudioSource, 0f);
				canFastFall = false;
			}
			if (player.TreatPlayerAsSortaGrounded())
			{
				canFastFall = true;
			}
		}

		private void BoostChanges()
		{
			if (hasGooned)
			{
				ApplyRailGoon();
			}
			else if (player.ability != player.wallrunAbility && player.ability != player.grindAbility && player.ability != player.boostAbility)
			{
				player.normalBoostSpeed = Mathf.Max(defaultBoostSpeed, AverageForwardSpeed());
			}
		}

		private void ApplyRailGoon()
		{
			if (!railGoonAppllied && ConfigSettings.RailGoon.Enabled.Value)
			{
				player.grindAbility.speed = LosslessClamp(Mathf.Max(AverageForwardSpeed(), defaultBoostSpeed), ConfigSettings.RailGoon.Amount.Value, ConfigSettings.RailGoon.Cap.Value);
				railGoonAppllied = true;
			}
		}

		private void HandleGrindAbility()
		{
			player.normalBoostSpeed = LosslessClamp(player.normalBoostSpeed, ConfigSettings.BoostGeneral.RailAmount.Value * Core.dt, ConfigSettings.BoostGeneral.RailCap.Value);
		}

		private void VertChanges()
		{
			if (player.ability != player.vertAbility)
			{
				HandleVertAbility();
			}
		}

		private void HandleVertAbility()
		{
			if (ConfigSettings.VertGeneral.Enabled.Value)
			{
				UpdateVertBottomExitSpeed();
			}
			if (ConfigSettings.VertGeneral.JumpEnabled.Value)
			{
				UpdateVertTopJumpSpeed();
			}
		}

		private void UpdateVertBottomExitSpeed()
		{
			float num = Mathf.Max(player.GetTotalSpeed(), AverageTotalSpeed());
			float num2 = num + ConfigSettings.VertGeneral.ExitSpeed.Value;
			num2 = Mathf.Min(num2, ConfigSettings.VertGeneral.ExitSpeedCap.Value);
			player.vertMaxSpeed = Mathf.Max(defaultVertMaxSpeed, player.GetTotalSpeed());
			player.vertBottomExitSpeed = num2;
		}

		private void UpdateVertTopJumpSpeed()
		{
			float num = Mathf.Max(player.GetTotalSpeed(), AverageTotalSpeed());
			float num2 = Mathf.Max(defaultVertTopJumpSpeed, num * ConfigSettings.VertGeneral.JumpStrength.Value);
			num2 = Mathf.Min(ConfigSettings.VertGeneral.JumpCap.Value, num2);
			player.vertTopJumpSpeed = num2;
		}

		private void JustJumpedFromRail()
		{
			if (jumpedFromRail)
			{
				player.SetForwardSpeed(Mathf.Max(AverageForwardSpeed(), player.GetForwardSpeed()));
				jumpedFromRailTimer -= Core.dt;
			}
			if (jumpedFromRailTimer <= 0f)
			{
				jumpedFromRail = false;
			}
		}

		private void SpeedLimit()
		{
			if (player.GetForwardSpeed() >= ConfigSettings.Misc.speedLimit.Value && player.ability != player.grindAbility && player.ability != player.wallrunAbility && ConfigSettings.Misc.speedLimit.Value > 0f)
			{
				float forwardSpeed = player.GetForwardSpeed() - ConfigSettings.Misc.speedLimitAmount.Value * Core.dt;
				player.SetForwardSpeed(forwardSpeed);
			}
		}

		private void LogSpeed(float time)
		{
			forwardSpeeds.Enqueue(player.GetForwardSpeed());
			totalSpeeds.Enqueue(player.GetTotalSpeed());
			if (averageSpeedTimer >= time)
			{
				forwardSpeeds.Dequeue();
				totalSpeeds.Dequeue();
			}
			else
			{
				averageSpeedTimer += Core.dt;
			}
		}

		public static float AverageForwardSpeed()
		{
			float num = 0f;
			foreach (float forwardSpeed in forwardSpeeds)
			{
				num += forwardSpeed;
			}
			return num / (float)forwardSpeeds.Count;
		}

		public static float AverageTotalSpeed()
		{
			float num = 0f;
			foreach (float totalSpeed in totalSpeeds)
			{
				num += totalSpeed;
			}
			return num / (float)totalSpeeds.Count;
		}

		private void LogForward(float time)
		{
			//IL_000f: 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)
			forwardDirs.Enqueue(player.tf.forward);
			if (averageForwardTimer >= time)
			{
				forwardDirs.Dequeue();
			}
			else
			{
				averageForwardTimer += Core.dt;
			}
		}

		public static Vector3 AverageForwardDir()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0022: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.zero;
			foreach (Vector3 forwardDir in forwardDirs)
			{
				val += forwardDir;
			}
			return val / (float)forwardDirs.Count;
		}

		private void SaveSpeed()
		{
			noAbilitySpeed = ((player.ability == player.grindAbility || player.ability == player.handplantAbility) ? Mathf.Max(noAbilitySpeed, player.grindAbility.speed) : player.GetForwardSpeed());
		}

		private void TimeInAir()
		{
			timeInAir = (player.TreatPlayerAsSortaGrounded() ? 0f : (timeInAir + Core.dt));
		}

		public static float Remap(float val, float in1, float in2, float out1, float out2)
		{
			return out1 + (val - in1) * (out2 - out1) / (in2 - in1);
		}

		public static float TableCurve(float a, float b, float c, float x)
		{
			return (a + b) * x / (b + x) + c;
		}

		public static float LosslessClamp(float input, float toAdd, float cap)
		{
			float num = input;
			float num2 = num + toAdd;
			if (cap < 0f)
			{
				return num2;
			}
			num = Mathf.Min(num2, cap);
			return Mathf.Max(num, input);
		}
	}
}
namespace MovementPlus.Patches
{
	internal static class BoostAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		private static float defaultBoostSpeed;

		[HarmonyPatch(typeof(BoostAbility), "Init")]
		[HarmonyPostfix]
		private static void BoostAbility_Init_Postfix(BoostAbility __instance)
		{
			if (!((Ability)__instance).p.isAI)
			{
				((Ability)__instance).decc = 0f;
				defaultBoostSpeed = ((Ability)__instance).p.normalBoostSpeed;
			}
		}

		[HarmonyPatch(typeof(BoostAbility), "FixedUpdateAbility")]
		[HarmonyPostfix]
		private static void BoostAbility_FixedUpdateAbility_Postfix(BoostAbility __instance)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (((Ability)__instance).p.IsGrounded() && ((Ability)__instance).p.IsComboing() && ConfigSettings.ComboGeneral.BoostEnabled.Value)
			{
				((Ability)__instance).p.DoComboTimeOut(Core.dt / 2f * ConfigSettings.ComboGeneral.BoostTimeout.Value);
			}
			if (ConfigSettings.BoostGeneral.StartEnabled.Value && (int)__instance.state == 0)
			{
				float num = ((((Ability)__instance).p.ability == ((Ability)__instance).p.grindAbility) ? MovementPlusPlugin.AverageForwardSpeed() : MovementPlusPlugin.AverageTotalSpeed());
				float input = Mathf.Max(defaultBoostSpeed, num);
				float normalBoostSpeed = MovementPlusPlugin.LosslessClamp(input, ConfigSettings.BoostGeneral.StartAmount.Value, ConfigSettings.BoostGeneral.StartCap.Value);
				((Ability)__instance).p.normalBoostSpeed = normalBoostSpeed;
			}
			else if (ConfigSettings.BoostGeneral.TotalSpeedEnabled.Value)
			{
				float normalBoostSpeed2 = MovementPlusPlugin.LosslessClamp(MovementPlusPlugin.AverageForwardSpeed(), MovementPlusPlugin.AverageTotalSpeed() - MovementPlusPlugin.AverageForwardSpeed(), ConfigSettings.BoostGeneral.TotalSpeedCap.Value);
				((Ability)__instance).p.normalBoostSpeed = normalBoostSpeed2;
			}
		}

		[HarmonyPatch(typeof(BoostAbility), "OnJump")]
		[HarmonyPrefix]
		private static void BoostAbility_OnJump_PreFix(BoostAbility __instance)
		{
			if (((Ability)__instance).p.IsComboing())
			{
				((Ability)__instance).p.DoComboTimeOut(ConfigSettings.ComboGeneral.BoostJumpAmount.Value);
			}
		}
	}
	internal static class GrindAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(GrindAbility), "Init")]
		[HarmonyPrefix]
		private static void GrindAbility_Init_Prefix(GrindAbility __instance)
		{
			__instance.grindDeccAboveNormal = ConfigSettings.RailGeneral.Decc.Value;
		}

		[HarmonyPatch(typeof(GrindAbility), "OnStartAbility")]
		[HarmonyPrefix]
		private static void GrindAbility_OnStartAbility_Prefix(GrindAbility __instance)
		{
			__instance.trickTimer = 0f;
		}

		[HarmonyPatch(typeof(GrindAbility), "UpdateSpeed")]
		[HarmonyPrefix]
		private static bool GrindAbility_UpdateSpeed_Prefix(GrindAbility __instance)
		{
			if (((Ability)__instance).p.abilityTimer <= 0.025f && !((Ability)__instance).p.isJumping)
			{
				float num = MovementPlusPlugin.AverageForwardSpeed();
				num = Mathf.Max(num, __instance.speedTarget);
				((Ability)__instance).p.normalBoostSpeed = num;
				__instance.speed = Mathf.Max(num, __instance.speedTarget);
			}
			if (__instance.speed < __instance.speedTarget)
			{
				__instance.speed = Mathf.Min(__instance.speedTarget, __instance.speed + __instance.grindAcc * Core.dt);
			}
			else if (__instance.speed > __instance.speedTarget)
			{
				__instance.speed = Mathf.Max(__instance.speedTarget, __instance.speed - ((__instance.speed >= ((Ability)__instance).p.stats.grindSpeed) ? __instance.grindDeccAboveNormal : __instance.grindDeccBelowNormal) * Core.dt);
			}
			if (((Ability)__instance).p.boosting)
			{
				float input = Mathf.Max(MovementPlusPlugin.AverageForwardSpeed(), __instance.speed);
				__instance.speed = MovementPlusPlugin.LosslessClamp(input, ConfigSettings.BoostGeneral.RailAmount.Value * Core.dt, ConfigSettings.BoostGeneral.RailCap.Value);
			}
			if (__instance.softCornerBoost)
			{
				__instance.speedTarget = Mathf.Max(MovementPlusPlugin.AverageForwardSpeed(), ((Ability)__instance).p.GetForwardSpeed());
				if (__instance.timeSinceLastNode > 1f)
				{
					__instance.softCornerBoost = false;
				}
			}
			else
			{
				if (((Ability)__instance).p.AirBraking() && !((Ability)__instance).p.isAI)
				{
					__instance.braking = true;
					__instance.speedTarget = ((Ability)__instance).p.stats.grindSpeed * 0.35f;
				}
				__instance.braking = false;
				__instance.speedTarget = ((Ability)__instance).p.stats.grindSpeed;
			}
			return false;
		}

		[HarmonyPatch(typeof(GrindAbility), "FixedUpdateAbility")]
		[HarmonyPrefix]
		private static bool GrindAbility_FixedUpdateAbility_Prefix(GrindAbility __instance)
		{
			//IL_0011: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: 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)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_0588: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0675: Unknown result type (might be due to invalid IL or missing references)
			//IL_067a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0730: Unknown result type (might be due to invalid IL or missing references)
			//IL_0732: Unknown result type (might be due to invalid IL or missing references)
			//IL_0737: Unknown result type (might be due to invalid IL or missing references)
			//IL_073b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0741: Unknown result type (might be due to invalid IL or missing references)
			//IL_0746: Unknown result type (might be due to invalid IL or missing references)
			//IL_0711: Unknown result type (might be due to invalid IL or missing references)
			//IL_0713: Unknown result type (might be due to invalid IL or missing references)
			//IL_0718: Unknown result type (might be due to invalid IL or missing references)
			//IL_071b: Unknown result type (might be due to invalid IL or missing references)
			//IL_071d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0692: Unknown result type (might be due to invalid IL or missing references)
			//IL_0694: Unknown result type (might be due to invalid IL or missing references)
			//IL_0699: Unknown result type (might be due to invalid IL or missing references)
			//IL_069d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Invalid comparison between Unknown and I4
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_0608: Unknown result type (might be due to invalid IL or missing references)
			//IL_060a: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0613: Unknown result type (might be due to invalid IL or missing references)
			//IL_0618: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_077a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0787: Unknown result type (might be due to invalid IL or missing references)
			//IL_078c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0796: Unknown result type (might be due to invalid IL or missing references)
			//IL_079b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_075d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0760: Unknown result type (might be due to invalid IL or missing references)
			//IL_0765: Unknown result type (might be due to invalid IL or missing references)
			//IL_076a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0772: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Unknown result type (might be due to invalid IL or missing references)
			//IL_063d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0640: Unknown result type (might be due to invalid IL or missing references)
			//IL_0642: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0665: Unknown result type (might be due to invalid IL or missing references)
			//IL_0501: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			float absoluteLinePos = __instance.grindLine.GetAbsoluteLinePos(((Ability)__instance).p.tf.position, ((Ability)__instance).p.dir);
			if (((Ability)__instance).p.abilityTimer >= 0.1f)
			{
				MovementPlusPlugin.hasGooned = false;
			}
			if (absoluteLinePos <= 1.5f && ((Ability)__instance).p.boosting && ((Ability)__instance).p.abilityTimer <= 0.1f && !MovementPlusPlugin.hasGooned)
			{
				MovementPlusPlugin.hasGooned = true;
			}
			if (__instance.inRetour)
			{
				if (((Ability)__instance).p.GetAnimTime() < 1f)
				{
					return false;
				}
				__instance.EndRetour();
			}
			int curAnim = ((Ability)__instance).p.curAnim;
			bool flag = false;
			int num = 3;
			for (int i = 0; i < num; i++)
			{
				flag |= curAnim == __instance.grindTrickHoldHashes[i] || curAnim == __instance.grindBoostTrickHoldHashes[i];
			}
			__instance.timeSinceLastNode += Core.dt;
			((Ability)__instance).p.SetDustEmission(0);
			__instance.UpdateSpeed();
			__instance.UpdateTricks();
			Vector3 position = ((Ability)__instance).p.tf.position;
			Vector3 val = ((Ability)__instance).p.tf.forward;
			Vector3 right = ((Ability)__instance).p.tf.right;
			if (!__instance.justFollowNodes)
			{
				__instance.nextNode = __instance.grindLine.GetNextNode(val);
			}
			position = __instance.grindLine.SnapPosToLine(position);
			Vector3 val2 = position;
			Vector3 val3 = __instance.nextNode - position;
			position = val2 + ((Vector3)(ref val3)).normalized * __instance.speed * Core.dt;
			__instance.posOnLine = (__instance.justFollowNodes ? __instance.grindLine.GetRelativePosOnLine(position, __instance.nextNode) : __instance.grindLine.GetRelativePosOnLine(position, val));
			float num2 = (__instance.justFollowNodes ? __instance.grindLine.GetAbsoluteLinePos(position, __instance.nextNode) : __instance.grindLine.GetAbsoluteLinePos(position, val));
			if (__instance.posOnLine >= 1f)
			{
				__instance.timeSinceLastNode = 0f;
				float num3 = __instance.posOnLine * __instance.grindLine.Length() - __instance.grindLine.Length();
				if (__instance.nextNode.IsEndpoint)
				{
					if (__instance.nextNode.retour)
					{
						__instance.StartRetour();
						return false;
					}
					if (__instance.grindLine.isPole)
					{
						if (Mathf.Abs(Vector3.Dot(val, Vector3.up)) > 0f)
						{
							((Ability)__instance).p.handplantAbility.SetToPole(__instance.nextNode.position);
							return false;
						}
						__instance.JumpOut(true);
						return false;
					}
					if (Mathf.Abs(Vector3.Dot(((Ability)__instance).p.tf.up, Vector3.up)) < 0.35f || __instance.grindLine.alwaysFlipBack)
					{
						__instance.JumpOut(true);
						return false;
					}
					((Ability)__instance).p.motor.SetPositionTeleport(position + Vector3.up * ((Ability)__instance).p.motor.GetCapsule().height * Mathf.Clamp(((Ability)__instance).p.tf.up.y, -1f, 0f));
					__instance.normal = Vector3.up;
					Vector3 val4 = ((Ability)__instance).p.FlattenRotationHard();
					((Ability)__instance).p.SetVelocity(val4 * __instance.speed);
					if (((Ability)__instance).p.boosting)
					{
						((Ability)__instance).p.ActivateAbility((Ability)(object)((Ability)__instance).p.boostAbility);
						((Ability)__instance).p.boostAbility.StartFromRunOffGrindOrWallrun();
						return false;
					}
					((Ability)__instance).p.StopCurrentAbility();
					((Ability)__instance).p.FlattenRotationHard();
					return false;
				}
				GrindLine val5 = (__instance.justFollowNodes ? __instance.grindLine.GetNextLine(val, __instance.nextNode) : __instance.grindLine.GetNextLine(val, (GrindNode)null));
				val3 = val5.GetOtherNode(__instance.nextNode) - __instance.nextNode;
				Vector3 normalized = ((Vector3)(ref val3)).normalized;
				__instance.RewardTilting(right, normalized);
				val = normalized;
				position = __instance.nextNode.position + num3 * normalized;
				if (__instance.grindLine.sfxCollection != val5.sfxCollection && (int)val5.sfxCollection != -1)
				{
					((Ability)__instance).p.AudioManager.PlaySfxGameplayLooping(val5.sfxCollection, (AudioClipID)11, ((Ability)__instance).p.playerGrindLoopAudioSource, 0f, 0f);
				}
				__instance.grindLine = val5;
				__instance.nextNode = (__instance.justFollowNodes ? __instance.grindLine.GetOtherNode(__instance.nextNode) : __instance.grindLine.GetNextNode(normalized));
				__instance.posOnLine = (__instance.justFollowNodes ? __instance.grindLine.GetRelativePosOnLine(position, __instance.nextNode) : __instance.grindLine.GetRelativePosOnLine(position, normalized));
				num2 = (__instance.justFollowNodes ? __instance.grindLine.GetAbsoluteLinePos(position, __instance.nextNode) : __instance.grindLine.GetAbsoluteLinePos(position, val));
				__instance.normal = __instance.grindLine.GetNormalAtPos(position);
				((Ability)__instance).p.SetRotation(normalized, __instance.normal);
			}
			__instance.UpdateBoostpack();
			__instance.UpdateTilting();
			if (!__instance.grindLine.isPole)
			{
				__instance.normal = __instance.grindLine.GetNormalAtPos(position);
			}
			float num4 = __instance.grindLine.Length();
			float num5 = Mathf.Min(num4 * 0.5f, 1.5f);
			Vector3 val6 = Vector3.forward;
			if (!__instance.nextNode.IsEndpoint && num2 >= num4 - num5)
			{
				val3 = (__instance.justFollowNodes ? __instance.grindLine.GetNextLine(val, __instance.nextNode) : __instance.grindLine.GetNextLine(val, (GrindNode)null)).GetOtherNode(__instance.nextNode) - __instance.nextNode;
				Vector3 normalized2 = ((Vector3)(ref val3)).normalized;
				val3 = __instance.nextNode - position;
				Vector3 normalized3 = ((Vector3)(ref val3)).normalized;
				Vector3 val7 = Vector3.Slerp(normalized3, normalized2, 0.5f);
				val6 = ((!(num2 >= num4)) ? Vector3.Slerp(normalized3, val7, 1f - (num4 - num2) / num5) : val7);
				__instance.preGrindDir = normalized3;
				if (!((Ability)__instance).p.smoothRotation)
				{
					((Ability)__instance).p.SetRotation(((Vector3)(ref val6)).normalized, __instance.normal);
				}
			}
			else if (__instance.preGrindDir != Vector3.zero && num2 <= num5)
			{
				val3 = __instance.nextNode - position;
				Vector3 normalized4 = ((Vector3)(ref val3)).normalized;
				Vector3 val8 = Vector3.Slerp(normalized4, __instance.preGrindDir, 0.5f);
				val6 = ((!(num2 <= 0f)) ? Vector3.Slerp(val8, normalized4, num2 / num5) : val8);
				if (!((Ability)__instance).p.smoothRotation)
				{
					((Ability)__instance).p.SetRotation(((Vector3)(ref val6)).normalized, __instance.normal);
				}
			}
			else if (((Ability)__instance).p.smoothRotation)
			{
				val6 = (__instance.preGrindDir = __instance.nextNode - position);
			}
			else
			{
				Player p = ((Ability)__instance).p;
				val3 = __instance.nextNode - position;
				p.SetRotHard(Quaternion.LookRotation(((Vector3)(ref val3)).normalized, __instance.normal));
			}
			if (((Ability)__instance).p.smoothRotation)
			{
				Quaternion rotation = Quaternion.LookRotation(val6, __instance.normal);
				((Ability)__instance).p.SetRotation(rotation);
			}
			((Ability)__instance).customVelocity = (position - ((Ability)__instance).p.tf.position) * 60f;
			((Ability)__instance).p.lastElevationForSlideBoost = position.y;
			if (((Ability)__instance).p.jumpButtonNew || ((Ability)__instance).p.isAI)
			{
				float num6 = Vector3.Dot(((Ability)__instance).p.tf.up, Vector3.up);
				__instance.JumpOut(__instance.grindLine.isPole || (num6 > -0.25f && num6 < 0.35f));
				return false;
			}
			((Ability)__instance).p.SetVisualRotLocalZ(__instance.grindTilt.x * -30f);
			return false;
		}

		[HarmonyPatch(typeof(GrindAbility), "JumpOut")]
		[HarmonyPrefix]
		private static bool GrindAbility_JumpOut_Prefix(bool flipOut, GrindAbility __instance)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0171: 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_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: 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_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			float num = ((Ability)__instance).customVelocity.y / ((Vector3)(ref ((Ability)__instance).customVelocity)).magnitude;
			num = (float)Math.Round(num, 2);
			float num2 = Vector3.Dot(((Ability)__instance).p.tf.up, Vector3.up);
			((Ability)__instance).p.AudioManager.PlayVoice(ref ((Ability)__instance).p.currentVoicePriority, ((Ability)__instance).p.character, (AudioClipID)489, ((Ability)__instance).p.playerGameplayVoicesAudioSource, (VoicePriority)0);
			((Ability)__instance).p.timeSinceLastJump = 0f;
			((Ability)__instance).p.isJumping = true;
			((Ability)__instance).p.jumpConsumed = true;
			((Ability)__instance).p.jumpRequested = false;
			((Ability)__instance).p.jumpedThisFrame = true;
			((Ability)__instance).p.maintainSpeedJump = false;
			((Ability)__instance).p.lastElevationForSlideBoost = float.PositiveInfinity;
			Vector3 up = ((Ability)__instance).p.tf.up;
			((Ability)__instance).p.DoJumpEffects(up);
			Transform tf = ((Ability)__instance).p.tf;
			tf.position += Vector3.up * ((Ability)__instance).p.motor.GetCapsule().height * Mathf.Clamp(((Ability)__instance).p.tf.up.y, -1f, 0f);
			if (flipOut)
			{
				Vector3 val = Vector3.ProjectOnPlane(up, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				((Ability)__instance).p.SetRotHard(Quaternion.LookRotation(normalized));
				float num3 = ((Ability)__instance).p.jumpSpeed * 0.35f;
				float num4 = ((((Ability)__instance).p.abilityTimer <= ConfigSettings.RailFrameboost.Grace.Value) ? MovementPlusPlugin.noAbilitySpeed : ((Ability)__instance).p.maxMoveSpeed);
				((Ability)__instance).p.SetVelocity(num3 * Vector3.up + normalized * num4);
				((Ability)__instance).p.ActivateAbility((Ability)(object)((Ability)__instance).p.flipOutJumpAbility);
			}
			else
			{
				((Ability)__instance).p.PlayAnim(__instance.jumpHash, false, false, -1f);
				Vector3 val2 = ((Ability)__instance).p.FlattenRotationHard();
				float num5 = 1f + Mathf.Clamp01(0f) * 0.5f;
				if (!__instance.lastPath.upwardsGrindJumpAllowed || !__instance.grindLine.upwardsGrindJump)
				{
					num5 = 1f;
				}
				float num6 = ((Ability)__instance).p.jumpSpeed + ((Ability)__instance).p.bonusJumpSpeedGrind;
				float num7 = ((Vector3.Dot(up, Vector3.up) > -0.1f) ? (num6 * num5) : ((0f - ((Ability)__instance).p.jumpSpeed) * 0.5f));
				float num8 = Mathf.Min(__instance.speed, ((Ability)__instance).p.boostSpeed);
				if (num2 >= 0.35f && !flipOut && ConfigSettings.RailSlope.Enabled.Value)
				{
					float num9 = num * ConfigSettings.RailSlope.SlopeJumpAmount.Value;
					float num10 = num * (0f - ConfigSettings.RailSlope.SlopeSpeedAmount.Value);
					num9 *= MovementPlusPlugin.AverageTotalSpeed() / 10f;
					num10 *= MovementPlusPlugin.AverageTotalSpeed() / 10f;
					num10 = Mathf.Clamp(num10, ConfigSettings.RailSlope.SlopeSpeedMin.Value, ConfigSettings.RailSlope.SlopeSpeedMax.Value);
					num9 = Mathf.Clamp(num9, ConfigSettings.RailSlope.SlopeJumpMin.Value, num9);
					num7 = Mathf.Clamp(num7 + num9, ConfigSettings.RailSlope.SlopeJumpMin.Value, ConfigSettings.RailSlope.SlopeJumpMax.Value);
					num8 = ((num10 > 0f) ? MovementPlusPlugin.LosslessClamp(num8, num10, ConfigSettings.RailSlope.SlopeSpeedCap.Value) : (num8 + num10));
				}
				if (((Ability)__instance).p.boosting)
				{
					((Ability)__instance).p.ActivateAbility((Ability)(object)((Ability)__instance).p.boostAbility);
					((Ability)__instance).p.boostAbility.StartFromJumpGrindOrWallrun();
				}
				else if (((Ability)__instance).p.slideButtonHeld)
				{
					num7 *= ((Ability)__instance).p.abilityShorthopFactor;
					((Ability)__instance).p.StopCurrentAbility();
					((Ability)__instance).p.maintainSpeedJump = true;
				}
				else
				{
					((Ability)__instance).p.StopCurrentAbility();
				}
				if (((Ability)__instance).p.abilityTimer <= ConfigSettings.RailFrameboost.Grace.Value && ConfigSettings.RailFrameboost.Enabled.Value)
				{
					float num11 = MovementPlusPlugin.LosslessClamp(num8, ConfigSettings.RailFrameboost.Amount.Value, ConfigSettings.RailFrameboost.Cap.Value);
					num8 = num11;
					((Ability)__instance).p.DoTrick((TrickType)2, "Frameboost", 0);
				}
				((Ability)__instance).p.SetVelocity(num7 * Vector3.up + val2 * num8);
			}
			((Ability)__instance).p.ForceUnground(true);
			MovementPlusPlugin.jumpedFromRail = true;
			MovementPlusPlugin.jumpedFromRailTimer = 0.025f;
			return false;
		}

		[HarmonyPatch(typeof(GrindAbility), "RewardTilting")]
		[HarmonyPrefix]
		private static bool GrindAbility_RewardTilting_Prefix(Vector3 rightDir, Vector3 nextLineDir, GrindAbility __instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_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_0038: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Invalid comparison between Unknown and I4
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Invalid comparison between Unknown and I4
			//IL_00ab: 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)
			rightDir = Vector3.Cross(((Component)__instance.nextNode).transform.up, __instance.preGrindDir);
			if (!__instance.grindLine.cornerBoost)
			{
				return false;
			}
			Vector3 val = rightDir;
			Vector3 val2 = Vector3.ProjectOnPlane(nextLineDir, Vector3.up);
			float num = Vector3.Dot(val, ((Vector3)(ref val2)).normalized);
			Side val3 = (Side)(-1);
			if (__instance.grindTiltBuffer.x < -0.25f)
			{
				val3 = (Side)6;
			}
			else if (__instance.grindTiltBuffer.x > 0.25f)
			{
				val3 = (Side)2;
			}
			Side val4 = (Side)(-1);
			if (num < -0.02f)
			{
				val4 = (Side)6;
			}
			else if (num > 0.02f)
			{
				val4 = (Side)2;
			}
			if ((int)val4 != -1)
			{
				__instance.softCornerBoost = false;
			}
			bool flag = Mathf.Abs(num) > 0.1f;
			if ((int)val3 != -1 && val3 == val4)
			{
				if (flag && __instance.lastPath.hardCornerBoostsAllowed)
				{
					((Ability)__instance).p.StartScreenShake((ScreenShakeType)0, 0.2f, false);
					((Ability)__instance).p.AudioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)19, ((Ability)__instance).p.playerOneShotAudioSource, 0f);
					((Ability)__instance).p.ringParticles.Emit(1);
					float speed = MovementPlusPlugin.LosslessClamp(__instance.speed, ConfigSettings.RailGeneral.HardAmount.Value, ConfigSettings.RailGeneral.HardCap.Value);
					__instance.speed = speed;
					((Ability)__instance).p.HardCornerGrindLine(__instance.nextNode);
					return false;
				}
				if (__instance.lastPath.softCornerBoostsAllowed)
				{
					__instance.softCornerBoost = true;
					((Ability)__instance).p.DoTrick((TrickType)22, "Corner", 0);
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(GrindAbility), "OnStopAbility")]
		[HarmonyPostfix]
		private static void GrindAbility_OnStopAbility_Postfix()
		{
			MovementPlusPlugin.hasGooned = false;
			MovementPlusPlugin.railGoonAppllied = false;
		}
	}
	internal static class GroundTrickAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(GroundTrickAbility), "OnStartAbility")]
		[HarmonyPostfix]
		private static void GroundTrickAbility_OnStartAbility_Postfix(GroundTrickAbility __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			((Ability)__instance).decc = ConfigSettings.Misc.groundTrickDecc.Value;
			if ((int)((Ability)__instance).p.moveStyle == 0)
			{
				((Ability)__instance).allowNormalJump = false;
			}
			else
			{
				((Ability)__instance).allowNormalJump = true;
			}
		}

		[HarmonyPatch(typeof(GroundTrickAbility), "FixedUpdateAbility")]
		[HarmonyPrefix]
		private static void GroundTrickAbility_FixedUpdateAbility_Prefix(GroundTrickAbility __instance)
		{
			if (!((Ability)__instance).p.TreatPlayerAsSortaGrounded() && ((Ability)__instance).p.jumpButtonNew)
			{
				_ = ConfigSettings.Buttslap.Enabled.Value;
			}
		}
	}
	internal static class AirDashAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(AirDashAbility), "OnStartAbility")]
		[HarmonyPrefix]
		private static bool AirDashAbility_onStartAbility_Prefix(AirDashAbility __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_00a8: 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_00b2: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00a1: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((Ability)__instance).p.moveStyle == 4)
			{
				((Ability)__instance).p.ActivateAbility((Ability)(object)((Ability)__instance).p.airTrickAbility);
				Vector3 velocity = ((Ability)__instance).p.GetVelocity();
				velocity.y = 5f;
				((Ability)__instance).p.SetVelocity(velocity);
				return false;
			}
			((Ability)__instance).p.ringParticles.Emit(1);
			__instance.airDashSpeed = __instance.airDashStartSpeed;
			Vector3 val = ((Ability)__instance).p.moveInput;
			if (((Vector3)(ref val)).sqrMagnitude == 0f)
			{
				val = (__instance.dirIfNoSteer.HasValue ? __instance.dirIfNoSteer.Value : ((Ability)__instance).p.dir);
			}
			Vector3 val2 = Vector3.ProjectOnPlane(val, Vector3.up);
			val = ((Vector3)(ref val2)).normalized;
			if (((Ability)__instance).p.smoothRotation)
			{
				((Ability)__instance).p.SetRotHard(val);
			}
			else
			{
				((Ability)__instance).p.SetRotation(val);
			}
			((Ability)__instance).p.OrientVisualInstantReset();
			val2 = ((Ability)__instance).p.GetFlatVelocity();
			if (((Vector3)(ref val2)).magnitude > __instance.airDashStartSpeed)
			{
				Vector3 val3 = val;
				val2 = ((Ability)__instance).p.GetFlatVelocity();
				float val4 = Vector3.Dot(val3, ((Vector3)(ref val2)).normalized);
				val4 = MovementPlusPlugin.Remap(val4, -1f, 1f, ConfigSettings.Misc.airDashStrength.Value, 1f);
				if (val4 < 0f)
				{
					val4 = 0f;
				}
				float airDashStartSpeed = __instance.airDashStartSpeed;
				val2 = ((Ability)__instance).p.GetFlatVelocity();
				__instance.airDashSpeed = airDashStartSpeed + (((Vector3)(ref val2)).magnitude - __instance.airDashStartSpeed) * val4;
			}
			((Ability)__instance).p.SetVelocity(new Vector3(val.x * __instance.airDashSpeed, Mathf.Max(__instance.airDashInitialUpSpeed, ((Ability)__instance).p.GetVelocity().y), val.z * __instance.airDashSpeed));
			((Ability)__instance).targetSpeed = __instance.airDashSpeed;
			__instance.haveAirDash = false;
			((Ability)__instance).p.PlayAnim(__instance.airDashHash, true, false, -1f);
			Core.Instance.AudioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)4, ((Ability)__instance).p.playerOneShotAudioSource, 0f);
			((Ability)__instance).p.wallrunAbility.cooldownTimer = 0f;
			((Ability)__instance).p.wallrunAbility.wallrunLine = null;
			return false;
		}
	}
	internal static class HandplantAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(HandplantAbility), "FixedUpdateAbility")]
		[HarmonyPrefix]
		private static bool HandplantAbility_FixedUpdateAbility_Prefix(HandplantAbility __instance)
		{
			//IL_0052: 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_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			if (((Ability)__instance).p.abilityTimer < 0.35f)
			{
				((Ability)__instance).p.hitbox.SetActive(true);
			}
			else
			{
				((Ability)__instance).p.hitbox.SetActive(false);
			}
			if (__instance.screwPoleMode)
			{
				float num = 0f;
				if (((Component)((Ability)__instance).p).transform.position.y + Mathf.Epsilon < __instance.screwPole.maxPoint.position.y)
				{
					int num2 = 6;
					float num3 = 1f;
					if (((Ability)__instance).p.AnyTrickInput())
					{
						if ((double)__instance.screwSpinTimer < 0.25)
						{
							__instance.screwSpinTimer = 0.5f;
						}
						if (__instance.screwFastSpinTimer > 0f)
						{
							__instance.screwFastPressCount++;
							num = ((__instance.screwFastPressCount > num2) ? num3 : 0f);
						}
						else
						{
							__instance.screwFastPressCount = 0;
						}
						__instance.screwFastSpinTimer = 0.25f;
					}
					else if (__instance.screwFastSpinTimer > 0f)
					{
						__instance.screwFastSpinTimer -= Core.dt;
						num = Mathf.Lerp(0f, num3, (float)Convert.ToInt32(__instance.screwFastPressCount > num2) * __instance.screwFastSpinTimer * 4f);
					}
				}
				float num4;
				if (__instance.screwSpinTimer > 0f)
				{
					__instance.screwSpinTimer -= Core.dt;
					num4 = Mathf.Min(((Ability)__instance).customVelocity.y + __instance.screwAcc * Core.dt, __instance.maxScrewSpeed + num);
				}
				else
				{
					num4 = Mathf.Max(((Ability)__instance).customVelocity.y - __instance.screwDecc * Core.dt, 0f);
				}
				if (((Component)((Ability)__instance).p).transform.position.y + Mathf.Epsilon < __instance.screwPole.maxPoint.position.y)
				{
					((Ability)__instance).customVelocity.y = num4;
					__instance.screwPole.Move(num4);
					((Ability)__instance).p.rotLean = Mathf.Min(num4, __instance.screwSpinTimer * 2f);
				}
				else
				{
					if (((Ability)__instance).customVelocity.y != 0f)
					{
						__instance.screwPole.StopPlayingSound();
						((Ability)__instance).p.AudioManager.PlaySfxGameplay(((Ability)__instance).p.moveStyle, (AudioClipID)490, ((Ability)__instance).p.playerOneShotAudioSource, 0f);
					}
					((Ability)__instance).customVelocity.y = 0f;
					((Ability)__instance).p.rotLean = __instance.screwSpinTimer * 2f;
				}
			}
			if (((Ability)__instance).p.jumpButtonNew || ((Ability)__instance).p.isAI)
			{
				float num5 = ((Ability)__instance).p.maxMoveSpeed;
				if (__instance.screwPoleMode)
				{
					num5 = ((Ability)__instance).p.maxMoveSpeed / 2f;
				}
				Vector3 val;
				if (((Ability)__instance).p.isAI)
				{
					((Ability)__instance).p.AI.HandplantJump();
					if ((Object)(object)((Ability)__instance).p.AI.nextWaypoint != (Object)null)
					{
						val = ((Ability)__instance).p.AI.dirToWaypoint;
						val.y = 0f;
						val = ((Vector3)(ref val)).normalized;
						((Ability)__instance).p.SetRotHard(Vector3.ProjectOnPlane(val, Vector3.up));
						val *= num5;
					}
					else
					{
						val = ((Ability)__instance).p.dir * num5;
					}
				}
				else
				{
					val = ((Ability)__instance).p.cam.realTf.forward;
					val.y = 0f;
					val = ((Vector3)(ref val)).normalized;
					((Ability)__instance).p.SetRotHard(Vector3.ProjectOnPlane(val, Vector3.up));
					val *= num5;
				}
				((Ability)__instance).p.AudioManager.PlayVoice(ref ((Ability)__instance).p.currentVoicePriority, ((Ability)__instance).p.character, (AudioClipID)489, ((Ability)__instance).p.playerGameplayVoicesAudioSource, (VoicePriority)0);
				val.y = ((Ability)__instance).p.jumpSpeed + ((Ability)__instance).p.bonusJumpSpeedHandplantJump;
				((Ability)__instance).p.SetVelocity(val);
				((Ability)__instance).p.CreateHighJumpDustEffect(Vector3.up);
				((Ability)__instance).p.PlayAnim(Animator.StringToHash("jump"), false, false, -1f);
				if (((Ability)__instance).p.abilityTimer <= 0.12f + ConfigSettings.RailFrameboost.Grace.Value)
				{
					((Ability)__instance).p.SetForwardSpeed(Mathf.Max(MovementPlusPlugin.noAbilitySpeed, ((Ability)__instance).p.GetForwardSpeed()));
				}
				((Ability)__instance).p.StopCurrentAbility();
			}
			return false;
		}
	}
	internal static class SlideAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(SlideAbility), "FixedUpdateAbility")]
		[HarmonyPostfix]
		private static void SlideAbility_FixedUpdateAbility_Postfix(SlideAbility __instance)
		{
			float num = Mathf.Max(ConfigSettings.SuperSlide.Speed.Value, ((Ability)__instance).p.GetForwardSpeed());
			if (ConfigSettings.SuperSlide.Enabled.Value)
			{
				num = MovementPlusPlugin.LosslessClamp(num, ConfigSettings.SuperSlide.Amount.Value, ConfigSettings.SuperSlide.Cap.Value);
			}
			__instance.superSpeed = num;
			__instance.slopeSlideSpeed = num;
		}
	}
	internal static class LedgeClimbAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		private static float savedSpeed;

		[HarmonyPatch(typeof(LedgeClimbAbility), "OnStartAbility")]
		[HarmonyPrefix]
		private static void LedgeClimbAbility_OnStartAbility_Prefix()
		{
			savedSpeed = MovementPlusPlugin.AverageTotalSpeed();
		}

		[HarmonyPatch(typeof(LedgeClimbAbility), "FixedUpdateAbility")]
		[HarmonyPrefix]
		private static void LedgeClimbAbility_FixedUpdateAbility_Prefix(LedgeClimbAbility __instance)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (((Ability)__instance).p.jumpButtonNew && ConfigSettings.LedgeClimbGeneral.Enabled.Value)
			{
				float num = MovementPlusPlugin.LosslessClamp(savedSpeed, ConfigSettings.LedgeClimbGeneral.Amount.Value, ConfigSettings.LedgeClimbGeneral.Cap.Value);
				((Ability)__instance).p.SetVelocity(((Ability)__instance).p.dir * num);
				((Ability)__instance).p.ringParticles.Emit(1);
				((Ability)__instance).p.AudioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)19, ((Ability)__instance).p.playerOneShotAudioSource, 0f);
				((Ability)__instance).p.Jump();
				((Ability)__instance).p.StopCurrentAbility();
			}
		}
	}
	internal static class SpecialAirAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		[HarmonyPatch(typeof(SpecialAirAbility), "OnStartAbility")]
		[HarmonyPrefix]
		private static void SpecialAirAbility_OnStartAbility_Prefix(SpecialAirAbility __instance)
		{
			if (ConfigSettings.SuperTrickJump.Enabled.Value)
			{
				float num = Mathf.Max(((Ability)__instance).p.GetForwardSpeed() - ConfigSettings.SuperTrickJump.Threshold.Value, 0f);
				__instance.jumpSpeed = MovementPlusPlugin.LosslessClamp(__instance.jumpSpeed, num * ConfigSettings.SuperTrickJump.Amount.Value, ConfigSettings.SuperTrickJump.Cap.Value);
				__instance.duration = 0.3f;
			}
		}

		[HarmonyPatch(typeof(SpecialAirAbility), "OnStopAbility")]
		[HarmonyPostfix]
		private static void SpecialAirAbility_OnStopAbility_Prefix(SpecialAirAbility __instance)
		{
			__instance.jumpSpeed = MovementPlusPlugin.defaultJumpSpeed;
		}
	}
	internal static class PlayerPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		public static ButtslapAbility buttslapAbility;

		private static bool tooFast;

		[HarmonyPatch(typeof(Player), "Init")]
		[HarmonyPostfix]
		private static void Player_Init_Postfix(Player __instance)
		{
			if (!((Object)(object)MovementPlusPlugin.player == (Object)null) || __instance.isAI)
			{
				return;
			}
			MovementPlusPlugin.player = __instance;
			MovementPlusPlugin.defaultBoostSpeed = __instance.normalBoostSpeed;
			MovementPlusPlugin.defaultVertMaxSpeed = __instance.vertMaxSpeed;
			MovementPlusPlugin.defaultVertTopJumpSpeed = __instance.vertTopJumpSpeed;
			MovementPlusPlugin.defaultJumpSpeed = __instance.specialAirAbility.jumpSpeed;
			__instance.motor.maxFallSpeed = ConfigSettings.Misc.maxFallSpeed.Value;
			__instance.wallrunAbility.lastSpeed = MovementPlusPlugin.savedLastSpeed;
			__instance.vertBottomExitSpeedThreshold = 0f;
			buttslapAbility = new ButtslapAbility(__instance);
			if (ConfigSettings.Misc.collisionChangeEnabled.Value)
			{
				Rigidbody[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Rigidbody>();
				Rigidbody[] array = componentsInChildren;
				foreach (Rigidbody val in array)
				{
					val.collisionDetectionMode = (CollisionDetectionMode)2;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "FixedUpdatePlayer")]
		[HarmonyPostfix]
		private static void Player_FixedUpdatePlayer_Postfix(Player __instance)
		{
			if (MovementPlusPlugin.timeInAir >= 1.5f)
			{
				tooFast = true;
			}
			else
			{
				tooFast = false;
			}
			buttslapAbility.Activation();
		}

		[HarmonyPatch(typeof(Player), "Jump")]
		[HarmonyPrefix]
		private static bool Player_Jump_Prefix(Player __instance)
		{
			//IL_000d: 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_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_007a: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			__instance.audioManager.PlayVoice(ref __instance.currentVoicePriority, __instance.character, (AudioClipID)489, __instance.playerGameplayVoicesAudioSource, (VoicePriority)0);
			__instance.PlayAnim(__instance.jumpHash, false, false, -1f);
			float num = 1f;
			if ((int)__instance.targetMovement == 0 && __instance.IsGrounded() && ((Component)__instance.motor.groundCollider).gameObject.layer != 23)
			{
				Vector3 val = Vector3.ProjectOnPlane(__instance.motor.groundNormal, Vector3.up);
				if (Vector3.Dot(((Vector3)(ref val)).normalized, __instance.dir) < -0.5f)
				{
					num = 1f + Mathf.Min(__instance.motor.groundAngle / 90f, 0.3f);
				}
			}
			__instance.ForceUnground(true);
			float num2 = 0f;
			if (__instance.timeSinceGrinding <= __instance.JumpPostGroundingGraceTime)
			{
				num2 = __instance.bonusJumpSpeedGrind;
			}
			else if (__instance.timeSinceWallrunning <= __instance.JumpPostGroundingGraceTime)
			{
				num2 = __instance.bonusJumpSpeedWallrun;
			}
			float num3 = __instance.jumpSpeed * num + num2;
			if (num2 != 0f && __instance.slideButtonHeld)
			{
				num3 *= __instance.abilityShorthopFactor;
				__instance.maintainSpeedJump = true;
			}
			else
			{
				__instance.maintainSpeedJump = false;
			}
			if (Object.op_Implicit((Object)(object)__instance.onLauncher))
			{
				if (!((Object)((Component)__instance.onLauncher.parent).gameObject).name.Contains("Super"))
				{
					__instance.motor.SetVelocityYOneTime(__instance.jumpSpeedLauncher);
				}
				else
				{
					__instance.motor.SetVelocityYOneTime(__instance.jumpSpeedLauncher * 1.4f);
				}
				if ((int)__instance.targetMovement == 0 && Vector3.Dot(__instance.dir, TransformExtentions.back(__instance.onLauncher)) > 0.7f && !((Object)((Component)__instance.onLauncher.parent).gameObject).name.Contains("flat"))
				{
					__instance.SetForwardSpeed(__instance.GetForwardSpeed() + 5f);
				}
				__instance.audioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)114, __instance.playerOneShotAudioSource, 0f);
				__instance.DoHighJumpEffects(__instance.motor.groundNormalVisual * -1f);
			}
			else
			{
				__instance.DoJumpEffects(__instance.motor.groundNormalVisual * -1f);
				__instance.motor.SetVelocityYOneTime(num3);
				__instance.isJumping = true;
			}
			__instance.jumpRequested = false;
			__instance.jumpConsumed = true;
			__instance.jumpedThisFrame = true;
			__instance.timeSinceLastJump = 0f;
			if (__instance.ability != null)
			{
				__instance.ability.OnJump();
				if (__instance.ability != null && Object.op_Implicit((Object)(object)__instance.onLauncher) && __instance.ability.autoAirTrickFromLauncher)
				{
					__instance.ActivateAbility((Ability)(object)__instance.airTrickAbility);
					return false;
				}
			}
			else if (Object.op_Implicit((Object)(object)__instance.onLauncher))
			{
				__instance.ActivateAbility((Ability)(object)__instance.airTrickAbility);
			}
			return false;
		}

		[HarmonyPatch(typeof(Player), "OnLanded")]
		[HarmonyPrefix]
		private static bool Player_OnLanded_Prefix(Player __instance)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			__instance.OrientVisualInstant();
			if ((Object)(object)__instance.motor.groundRigidbody != (Object)null)
			{
				Car component = ((Component)__instance.motor.groundRigidbody).GetComponent<Car>();
				if ((Object)(object)component != (Object)null)
				{
					component.PlayerLandsOn();
				}
			}
			if (__instance.ability == null)
			{
				if (__instance.GetForwardSpeed() <= __instance.minMoveSpeed + 1f)
				{
					__instance.PlayAnim(__instance.landHash, false, false, -1f);
				}
				else
				{
					__instance.PlayAnim(__instance.landRunHash, false, false, -1f);
				}
				if (tooFast && (int)__instance.moveStyle == 0)
				{
					__instance.SetSpeedFlat(__instance.maxMoveSpeed);
				}
				if (__instance.slideButtonHeld && !((Ability)__instance.slideAbility).locked)
				{
					__instance.ActivateAbility((Ability)(object)__instance.slideAbility);
				}
				else if (!ConfigSettings.ComboGeneral.NoAbilityEnabled.Value)
				{
					__instance.LandCombo();
				}
			}
			else if (__instance.ability == __instance.boostAbility && !ConfigSettings.ComboGeneral.BoostEnabled.Value)
			{
				__instance.LandCombo();
			}
			__instance.audioManager.PlaySfxGameplay(__instance.moveStyle, (AudioClipID)255, __instance.playerOneShotAudioSource, 0f);
			__instance.CreateCircleDustEffect(__instance.motor.groundNormalVisual * -1f);
			return false;
		}

		[HarmonyPatch(typeof(Player), "FixedUpdateAbilities")]
		[HarmonyPrefix]
		private static bool Player_FixedUpdateAbilities_Prefix(Player __instance)
		{
			if (__instance.hitpause > 0f)
			{
				__instance.hitpause -= Core.dt;
				if (__instance.hitpause <= 0f)
				{
					__instance.StopHitpause();
					return false;
				}
			}
			else
			{
				bool flag = __instance.IsGrounded();
				__instance.abilityTimer += Core.dt;
				if (flag)
				{
					__instance.RegainAirMobility();
				}
				__instance.grindAbility.PassiveUpdate();
				if (__instance.isAI)
				{
					__instance.pseudoGraffitiAbility.PassiveUpdate();
				}
				__instance.wallrunAbility.PassiveUpdate();
				__instance.handplantAbility.PassiveUpdate();
				if (__instance.ability == null)
				{
					if (!__instance.IsBusyWithSequence())
					{
						for (int i = 0; i < __instance.abilities.Count; i++)
						{
							if (__instance.abilities[i].CheckActivation())
							{
								return false;
							}
						}
					}
					if (flag && __instance.inWalkZone)
					{
						if (__instance.usingEquippedMovestyle)
						{
							__instance.ActivateAbility((Ability)(object)__instance.switchMoveStyleAbility);
						}
					}
					else if (__instance.switchStyleButtonNew && !__instance.switchToEquippedMovestyleLocked && !flag)
					{
						__instance.SwitchToEquippedMovestyle(!__instance.usingEquippedMovestyle, true, true, true);
					}
				}
				else
				{
					__instance.ability.FixedUpdateAbility();
				}
				if (__instance.ability == null && flag)
				{
					if (!__instance.IsBusyWithSequence() && !__instance.motor.wasGrounded && __instance.slideButtonHeld && !((Ability)__instance.slideAbility).locked)
					{
						__instance.ActivateAbility((Ability)(object)__instance.slideAbility);
						return false;
					}
					if (__instance.IsComboing() && ConfigSettings.ComboGeneral.NoAbilityEnabled.Value && !__instance.boosting)
					{
						float num = Mathf.Min(__instance.GetForwardSpeed() / __instance.boostSpeed, 0.95f);
						__instance.DoComboTimeOut(Mathf.Max(Core.dt * (1f - num), Core.dt / 2f) * ConfigSettings.ComboGeneral.NoAbilityTimeout.Value);
					}
					else
					{
						__instance.LandCombo();
					}
				}
			}
			return false;
		}
	}
	internal static class WallrunLineAbilityPatch
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		private static float defaultMoveSpeed;

		private static float savedSpeed;

		[HarmonyPatch(typeof(WallrunLineAbility), "Init")]
		[HarmonyPostfix]
		private static void WallrunLineAbility_Init_Postfix(WallrunLineAbility __instance)
		{
			__instance.minDurationBeforeJump = 0f;
			__instance.wallrunDecc = 0f;
			defaultMoveSpeed = __instance.wallRunMoveSpeed;
		}

		[HarmonyPatch(typeof(WallrunLineAbility), "RunOff")]
		[HarmonyPrefix]
		private static bool WallrunLineAbility_RunOff_Prefix(WallrunLineAbility __instance, Vector3 direction)
		{
			//IL_011e: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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)
			//IL_0198: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 velocity;
			if (((Ability)__instance).p.abilityTimer <= ConfigSettings.WallFrameboost.Grace.Value)
			{
				if (ConfigSettings.WallFrameboost.Enabled.Value && ConfigSettings.WallFrameboost.RunoffEnabled.Value)
				{
					float num = MovementPlusPlugin.LosslessClamp(Mathf.Max(__instance.lastSpeed, ((Vector3)(ref ((Ability)__instance).customVelocity)).magnitude), ConfigSettings.WallFrameboost.Amount.Value, ConfigSettings.WallFrameboost.Cap.Value);
					velocity = direction * num + __instance.wallrunFaceNormal * 1f;
					((Ability)__instance).p.DoTrick((TrickType)10, "Frameboost", 0);
				}
				else
				{
					velocity = direction * Mathf.Max(__instance.lastSpeed, ((Vector3)(ref ((Ability)__instance).customVelocity)).magnitude) + __instance.wallrunFaceNormal * 1f;
				}
				__instance.lastSpeed = Mathf.Max(savedSpeed, __instance.lastSpeed);
				savedSpeed = __instance.lastSpeed;
			}
			else
			{
				velocity = direction * Mathf.Max(new float[3]
				{
					__instance.lastSpeed,
					((Vector3)(ref ((Ability)__instance).customVelocity)).magnitude,
					13f
				}) + __instance.wallrunFaceNormal * 1f;
				savedSpeed = __instance.lastSpeed;
			}
			((Ability)__instance).p.SetVelocity(velocity);
			((Ability)__instance).p.SetRotHard(Quaternion.LookRotation(((Vector3)(ref velocity)).normalized));
			((Ability)__instance).p.FlattenRotationHard();
			if (((Ability)__instance).p.boosting)
			{
				((Ability)__instance).p.ActivateAbility((Ability)(object)((Ability)__instance).p.boostAbility);
				((Ability)__instance).p.boostAbility.StartFromRunOffGrindOrWallrun();
				return false;
			}
			((Ability)__instance).p.StopCurrentAbility();
			((Ability)__instance).p.PlayAnim(__instance.fallHash, false, false, -1f);
			return false;
		}

		[HarmonyPatch(typeof(WallrunLineAbility), "FixedUpdateAbility")]
		[HarmonyPrefix]
		private static bool WallrunLineAbility_FixedUpdateAbility_Prefix(WallrunLineAbility __instance)
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			__instance.UpdateBoostpack();
			__instance.scoreTimer += Core.dt;
			if (((Ability)__instance).p.abilityTimer <= 0.025f && !((Ability)__instance).p.isJumping)
			{
				float num = MovementPlusPlugin.LosslessClamp(MovementPlusPlugin.AverageForwardSpeed(), MovementPlusPlugin.AverageTotalSpeed() - MovementPlusPlugin.AverageForwardSpeed(), ConfigSettings.WallGeneral.wallTotalSpeedCap.Value);
				__instance.speed = Mathf.Max(num, __instance.wallRunMoveSpeed);
			}
			if (__instance.scoreTimer > 0.7f)
			{
				__instance.scoreTimer = 0f;
				((Ability)__instance).p.DoTrick((TrickType)10, __instance.trickName, 0);
			}
			if (__instance.speed > __instance.wallRunMoveSpeed)
			{
				__instance.speed = Mathf.Max(__instance.wallRunMoveSpeed, __instance.speed - __instance.wallrunDecc * Core.dt);
			}
			if (((Ability)__instance).p.boosting)
			{
				__instance.speed = MovementPlusPlugin.LosslessClamp(__instance.speed, ConfigSettings.BoostGeneral.WallAmount.Value * Core.dt, ConfigSettings.BoostGeneral.WallCap.Value);
			}
			__instance.journey += __instance.speed / __instance.nodeToNodeLength * Core.dt;
			__instance.wallrunPos = Vector3.LerpUnclamped(__instance.prevNode.position, __instance.nextNode.position, __instance.journey);
			Vector3 val = __instance.nextNode.position - __instance.prevNode.position;
			__instance.dirToNextNode = ((Vector3)(ref val)).normalized;
			__instance.wallrunFaceNormal = ((Component)__instance.wallrunLine).transform.forward;
			float num2 = (0f - ((Ability)__instance).p.motor.GetCapsule().height) * 1f;
			if (__instance.wallrunHeight > num2)
			{
				if (__instance.wallRunUpDownSpeed > 0f)
				{
					__instance.wallRunUpDownSpeed = Mathf.Max(__instance.wallRunUpDownSpeed - __instance.wallRunUpDownDecc * Core.dt, 0f);
				}
				else if (__instance.wallRunUpDownSpeed < 0f)
				{
					__instance.wallRunUpDownSpeed = Mathf.Min(__instance.wallRunUpDownSpeed + __instance.wallRunUpDownDecc * Core.dt, 0f);
				}
			}
			else
			{
				__instance.wallRunUpDownSpeed = __instance.wallRunUpDownMaxSpeed;
			}
			__instance.wallrunHeight += __instance.wallRunUpDownSpeed * Core.dt;
			Vector3 val2 = __instance.wallrunPos + __instance.wallrunHeight * Vector3.up + __instance.wallrunFaceNormal * ((Ability)__instance).p.motor.GetCapsule().radius;
			((Ability)__instance).customVelocity = (val2 - ((Ability)__instance).p.tf.position) / Core.dt;
			__instance.lastSpeed = ((Vector3)(ref ((Ability)__instance).customVelocity)).magnitude;
			((Ability)__instance).p.lastElevationForSlideBoost = val2.y;
			val = Vector3.RotateTowards(((Ability)__instance).p.dir, __instance.dirToNextNode, __instance.rotSpeed * Core.dt, 1000f);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			if (((Ability)__instance).p.smoothRotation)
			{
				((Ability)__instance).p.SetRotation(normalized);
			}
			else
			{
				((Ability)__instance).p.SetRotHard(normalized);
			}
			if (((Ability)__instance).p.jumpButtonNew && (((Ability)__instance).p.abilityTimer > __instance.minDurationBeforeJump || ((Ability)__instance).p.isAI))
			{
				__instance.Jump();
			}
			else if (__instance.journey > 1f)
			{
				__instance.AtEndOfWallrunLine();
			}
			((Ability)__instance).p.SetVisualRotLocal0();
			MovementPlusPlugin.savedLastSpeed = __instance.lastSpeed;
			if (((Ability)__instance).p.abilityTimer > ConfigSettings.WallFrameboost.Grace.Value && ConfigSettings.WallFrameboost.Enabled.Value)
			{
				savedSpeed = __instance.lastSpeed;
			}
			return false;
		}

		[HarmonyPatch(typeof(WallrunLineAbility), "Jump")]
		[HarmonyPostfix]
		private static void WallrunLineAbility_Jump_Postfix(WallrunLineAbility __instance)
		{
			if (((Ability)__instance).p.abilityTimer <= ConfigSettings.WallFrameboost.Grace.Value && ConfigSettings.WallFrameboost.Enabled.Value)
			{
				float forwardSpeed = MovementPlusPlugin.LosslessClamp(Mathf.Max(MovementPlusPlugin.AverageForwardSpeed(), ((Ability)__instance).p.GetForwardSpeed()), ConfigSettings.WallFrameboost.Amount.Value, ConfigSettings.WallFrameboost.Cap.Value);
				__instance.lastSpeed += ConfigSettings.WallFrameboost.Amount.Value;
				((Ability)__instance).p.SetForwardSpeed(forwardSpeed);
				((Ability)__instance).p.DoTrick((TrickType)10, "Frameboost", 0);
				__instance.lastSpeed = Mathf.Max(savedSpeed, __instance.lastSpeed);
				savedSpeed = __instance.lastSpeed;
			}
		}

		[HarmonyPatch(typeof(WallrunLineAbility), "OnStopAbility")]
		[HarmonyPostfix]
		private static void WallrunLineAbility_OnStopAbility_Postfix(WallrunLineAbility __instance)
		{
			__instance.cooldownTimer = 0.2f;
		}
	}
}
namespace MovementPlus.NewAbility
{
	public class ButtslapAbility : Ability
	{
		private static readonly MyConfig ConfigSettings = MovementPlusPlugin.ConfigSettings;

		private float buttslapTimer;

		public ButtslapAbility(Player player)
			: base(player)
		{
		}

		public override void Init()
		{
			base.allowNormalJump = false;
			base.normalRotation = true;
			buttslapTimer = 0f;
		}

		public void Activation()
		{
			if (!base.p.motor.isGrounded && base.p.jumpButtonNew && ConfigSettings.Buttslap.Enabled.Value && base.p.ability == base.p.groundTrickAbility && !base.p.isJumping)
			{
				base.p.ActivateAbility((Ability)(object)this);
			}
		}

		public override void OnStartAbility()
		{
			if (!ConfigSettings.Buttslap.Multi