Decompiled source of Rebound v1.1.1

plugins/Rebound/Rebound.dll

Decompiled a year ago
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Reptile;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("Rebound")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Rebound")]
[assembly: AssemblyTitle("Rebound")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Rebound;

[BepInPlugin("goatgirl.Rebound", "Rebound", "1.0.0")]
[BepInProcess("Bomb Rush Cyberfunk.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class ReboundPlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	public static Player player;

	internal static Harmony Harmony = new Harmony("goatgirl.Rebound");

	public static float landTime = float.PositiveInfinity;

	public static Vector2 landingVelocity = new Vector2(0f, 0f);

	public static float distanceFallenFromPeakOfJump = 0f;

	public static float landingComboMeter = 1f;

	public static bool MPlusActive = false;

	public static float reboundVelocityMultiplier = 0.8f;

	public static float launcherBonusMultiplier = 0.5f;

	public static float maxLandingTimeToRebound = 0.15f;

	public static float minimumVelocityToRebound = 8f;

	public static float minimumReboundYVelocity = 8f;

	public static float maximumReboundYVelocity = 0f;

	public static float comboCost = 0.15f;

	public static float boostCost = 0f;

	public static bool capBasedOnHeight = true;

	public static float heightCapGenerosity = 1.5f;

	public static bool alwaysCalculateBasedOnHeight = false;

	public static bool canCancelCombo = false;

	public static bool refreshCombo = true;

	public static bool allowBoostedRebounds = true;

	public static bool tempDisableBoost = true;

	public static bool allowReduceComboOnGround = true;

	public static List<string> cancelReboundActions = new List<string>();

	public static List<string> doReboundActions = new List<string>();

	public static Dictionary<string, bool> playerActionsDictionary = new Dictionary<string, bool>
	{
		{ "jumpRequested", false },
		{ "trick1ButtonHeld", false },
		{ "trick2ButtonHeld", false },
		{ "trick3ButtonHeld", false },
		{ "slideButtonHeld", false },
		{ "boostButtonHeld", false },
		{ "sprayButtonHeld", false },
		{ "danceButtonHeld", false },
		{ "switchStyleButtonHeld", false },
		{ "walkButtonHeld", false }
	};

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		Harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Rebound is loaded!");
		foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
		{
			if (pluginInfo.Value.Metadata.GUID.Equals("com.yuril.MovementPlus"))
			{
				MPlusActive = true;
				Log.LogInfo((object)"Rebound: MovementPlus found!");
			}
		}
		RBSettings.UpdateSettings(((BaseUnityPlugin)this).Config);
	}

	private void FixedUpdate()
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: 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)
		if (!((Object)(object)player != (Object)null) || player.isDisabled || Core.Instance.BaseModule.IsInGamePaused || !isPlayer(player))
		{
			return;
		}
		if (landTime < maxLandingTimeToRebound)
		{
			landTime += Core.dt;
		}
		if (!player.IsGrounded())
		{
			landingVelocity = new Vector2(player.GetForwardSpeed(), player.GetVelocity().y);
			landingComboMeter = player.comboTimeOutTimer;
			if (player.GetVelocity().y < 0f)
			{
				distanceFallenFromPeakOfJump += Mathf.Abs(player.GetVelocity().y);
				landTime = 0f;
			}
			else
			{
				distanceFallenFromPeakOfJump = 0f;
			}
		}
		playerActionsDictionary = new Dictionary<string, bool>
		{
			{ "jumpRequested", player.jumpRequested },
			{ "trick1ButtonHeld", player.trick1ButtonHeld },
			{ "trick2ButtonHeld", player.trick2ButtonHeld },
			{ "trick3ButtonHeld", player.trick3ButtonHeld },
			{ "slideButtonHeld", player.slideButtonHeld },
			{ "boostButtonHeld", player.boostButtonHeld },
			{ "sprayButtonHeld", player.sprayButtonHeld },
			{ "danceButtonHeld", player.danceButtonHeld },
			{ "switchStyleButtonHeld", player.switchStyleButtonHeld },
			{ "walkButtonHeld", player.walkButtonHeld }
		};
	}

	public static bool CanRebound(Player _p)
	{
		return landTime < maxLandingTimeToRebound && _p.IsGrounded();
	}

	public static bool PlayerIsCancellingRebound(Player _p)
	{
		return actionsAreBeingPressed(cancelReboundActions, RBSettings.config_requireAllCRA.Value, player);
	}

	public static void ReboundTrick(Player _p)
	{
		//IL_0018: 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_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: 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_0185: Invalid comparison between Unknown and I4
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Invalid comparison between Unknown and I4
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: 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_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: Unknown result type (might be due to invalid IL or missing references)
		//IL_0398: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
		bool flag = allowBoostedRebounds && _p.boosting;
		Vector3 val = Vector3.ProjectOnPlane(_p.motor.groundNormalVisual, Vector3.up);
		float num = Vector3.Dot(((Vector3)(ref val)).normalized, _p.dir);
		_p.animInfosSets[_p.moveStyle][Animator.StringToHash("jumpTrick1")].fadeTo[_p.fallHash] = 1f;
		_p.animInfosSets[_p.moveStyle][Animator.StringToHash("jumpTrick1")].fadeTo[Animator.StringToHash("fallIdle")] = 1f;
		OnStartRebound(_p);
		if (refreshCombo)
		{
			_p.comboTimeOutTimer = landingComboMeter;
		}
		Vector2 val2 = landingVelocity;
		val2.y = (0f - val2.y) * reboundVelocityMultiplier;
		if (_p.CheckBoostTrick() && allowBoostedRebounds)
		{
			_p.DoTrick((TrickType)6, "Boosted Rebound", 0);
			_p.ActivateAbility((Ability)(object)_p.airTrickAbility);
			val2.x = Mathf.Max(val2.x, _p.GetForwardSpeed());
		}
		else
		{
			if (tempDisableBoost)
			{
				_p.ActivateAbility((Ability)(object)_p.airTrickAbility);
				AirTrickAbility airTrickAbility = _p.airTrickAbility;
				airTrickAbility.duration /= 3f;
				_p.PlayAnim(Animator.StringToHash("jumpTrick1"), true, true, -1f);
			}
			string text = "Corkscrew";
			if ((int)_p.moveStyle == 1)
			{
				text = "360 Backflip";
			}
			if ((int)_p.moveStyle == 2)
			{
				text = "McTwist";
			}
			_p.DoTrick((TrickType)6, "Rebound " + text, 0);
		}
		float num2 = distanceFallenFromPeakOfJump * reboundVelocityMultiplier;
		float num3 = Mathf.Sqrt(2f * num2 * _p.motor.gravity);
		float num4 = num3 / 9f + heightCapGenerosity;
		if (!alwaysCalculateBasedOnHeight && capBasedOnHeight)
		{
			val2.y = Mathf.Min(val2.y, num4);
		}
		else if (alwaysCalculateBasedOnHeight)
		{
			val2.y = num4 - heightCapGenerosity;
		}
		if (Object.op_Implicit((Object)(object)_p.onLauncher))
		{
			if (!RBSettings.config_slopeOnLauncher.Value)
			{
				num = 0f;
			}
			float num5 = (((Object)((Component)_p.onLauncher.parent).gameObject).name.Contains("Super") ? (_p.jumpSpeedLauncher * 1.4f) : _p.jumpSpeedLauncher);
			val2.y = Mathf.Max(val2.y + num5 * launcherBonusMultiplier, num5);
		}
		val2.y = Mathf.Max(val2.y, minimumReboundYVelocity);
		if (val2.y > maximumReboundYVelocity && maximumReboundYVelocity != 0f)
		{
			val2.x = maximumReboundYVelocity * (val2.x / val2.y);
			val2.y = maximumReboundYVelocity;
		}
		Vector2 val3 = default(Vector2);
		((Vector2)(ref val3))..ctor(Mathf.Sin(num) * RBSettings.config_slopeMultiplierX.Value, Mathf.Cos(num) * RBSettings.config_slopeMultiplierY.Value);
		if (val3.x < 0f)
		{
			val3.y += 1f;
		}
		_p.motor.SetVelocityYOneTime(val2.y * val3.y);
		float num6 = val2.x + val2.y * val3.x;
		_p.SetForwardSpeed(num6);
		if (num6 < 0f)
		{
			_p.SetRotation(-_p.dir);
		}
		float comboTimeOutTimer = _p.comboTimeOutTimer;
		if (comboCost != 0f)
		{
			if (_p.comboTimeOutTimer - comboCost > 1f)
			{
				_p.ResetComboTimeOut();
			}
			else
			{
				_p.DoComboTimeOut(comboCost);
				_p.comboTimeOutTimer = Mathf.Clamp(_p.comboTimeOutTimer, 0f, 1f);
			}
		}
		if (_p.comboTimeOutTimer == 0f && comboTimeOutTimer == _p.comboTimeOutTimer)
		{
			_p.LandCombo();
		}
		if (boostCost != 0f)
		{
			_p.AddBoostCharge(0f - boostCost);
		}
	}

	public static void OnStartRebound(Player _p)
	{
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		bool flag = allowBoostedRebounds && _p.boosting;
		if (!flag)
		{
			_p.StopCurrentAbility();
		}
		_p.jumpedThisFrame = true;
		_p.isJumping = true;
		_p.maintainSpeedJump = true;
		_p.jumpConsumed = true;
		_p.jumpRequested = false;
		_p.jumpedThisFrame = true;
		_p.timeSinceLastJump = 0f;
		_p.ForceUnground(true);
		_p.radialHitbox.SetActive(true);
		_p.AudioManager.PlaySfxGameplay((SfxCollectionID)20, (AudioClipID)130, _p.playerOneShotAudioSource, 0f);
		_p.PlayVoice((AudioClipID)489, (VoicePriority)0, true);
		if (!flag)
		{
			_p.PlayAnim(Animator.StringToHash("jumpTrick1"), true, false, -1f);
		}
		else
		{
			_p.PlayAnim(Animator.StringToHash("jump"), true, false, -1f);
		}
		_p.DoHighJumpEffects(_p.motor.groundNormalVisual * -1f);
	}

	public static void CancelRebound()
	{
		if (ComboUpForGrabs())
		{
			landTime = maxLandingTimeToRebound + 1f;
			player.LandCombo();
		}
	}

	public static bool ComboUpForGrabs()
	{
		return (!MPlusActive || player.comboTimeOutTimer <= 0f) && player.ability != player.slideAbility && canCancelCombo && !player.IsPerformingManualTrick && !((Ability)player.slideAbility).locked && player.ability != player.ledgeClimbAbility && player.switchMoveStyleAbility != player.ability;
	}

	private void OnDestroy()
	{
		Harmony.UnpatchSelf();
	}

	public static bool actionsAreBeingPressed(List<string> actions, bool checkIfAllPressed, Player _p)
	{
		if (actions == null || !actions.Any())
		{
			return false;
		}
		bool result = checkIfAllPressed;
		foreach (string action in actions)
		{
			if (playerActionsDictionary[action] == !checkIfAllPressed)
			{
				result = !checkIfAllPressed;
			}
		}
		return result;
	}

	public static bool isPlayer(Player _p)
	{
		WorldHandler instance = WorldHandler.instance;
		return (Object)(object)_p == (Object)(object)((instance != null) ? instance.GetCurrentPlayer() : null) && !_p.isAI;
	}
}
[HarmonyPatch(typeof(Player))]
internal class PlayerPatches
{
	[HarmonyPrefix]
	[HarmonyPatch("Init")]
	public static bool InitPrefix_SetPluginPlayerReference(Player __instance)
	{
		if ((Object)(object)ReboundPlugin.player == (Object)null && ReboundPlugin.isPlayer(__instance))
		{
			ReboundPlugin.player = __instance;
			ReboundPlugin.Log.LogDebug((object)"Set ReboundPlugin player instance");
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch("HandleJump")]
	public static bool HandleJumpPrefix_HandleRebound(Player __instance)
	{
		if (!ReboundPlugin.isPlayer(__instance))
		{
			return true;
		}
		InitPrefix_SetPluginPlayerReference(__instance);
		RBSettings.SetSettingsInPlugin();
		__instance.jumpedThisFrame = false;
		__instance.timeSinceJumpRequested += Core.dt;
		if (__instance.jumpRequested && !__instance.jumpConsumed && (__instance.IsGrounded() || __instance.timeSinceLastAbleToJump <= __instance.JumpPostGroundingGraceTime))
		{
			bool flag = !ReboundPlugin.doReboundActions.Any() || ReboundPlugin.actionsAreBeingPressed(ReboundPlugin.doReboundActions, RBSettings.config_requireAllDRA.Value, __instance);
			if (ReboundPlugin.landingVelocity.y < 0f - ReboundPlugin.minimumVelocityToRebound && ReboundPlugin.CanRebound(__instance) && !ReboundPlugin.PlayerIsCancellingRebound(__instance) && flag)
			{
				ReboundPlugin.ReboundTrick(__instance);
			}
			else if (__instance.JumpIsAllowed())
			{
				if (ReboundPlugin.CanRebound(__instance))
				{
					ReboundPlugin.CancelRebound();
				}
				__instance.Jump();
			}
			ReboundPlugin.distanceFallenFromPeakOfJump = 0f;
		}
		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch("OnLanded")]
	public static bool OnLandedPrefix_ReboundVel(Player __instance)
	{
		if (!ReboundPlugin.isPlayer(__instance))
		{
			return true;
		}
		ReboundPlugin.landTime = 0f;
		ReboundPlugin.distanceFallenFromPeakOfJump += __instance.reallyMovedVelocity.y;
		if (__instance.comboTimeOutTimer <= 0f)
		{
			ReboundPlugin.CancelRebound();
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch("DoTrick")]
	public static bool DoTrickPrefix_FailIfNotRebound(TrickType type, string trickName, int trickNum, Player __instance)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Invalid comparison between Unknown and I4
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Invalid comparison between Unknown and I4
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Invalid comparison between Unknown and I4
		if (!ReboundPlugin.isPlayer(__instance))
		{
			return true;
		}
		if (ReboundPlugin.CanRebound(__instance) && (!trickName.Contains("Rebound") || trickNum != 0 || (int)type != 6) && ReboundPlugin.landTime > Core.dt && ((int)__instance.currentTrickType != 12 || (int)type != 12))
		{
			ReboundPlugin.CancelRebound();
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch("LandCombo")]
	public static bool LandComboPrefix_ExtendForRebound(Player __instance)
	{
		if (!ReboundPlugin.isPlayer(__instance))
		{
			return true;
		}
		return !ReboundPlugin.CanRebound(__instance) || __instance.slideAbility.stopDecided;
	}

	[HarmonyPrefix]
	[HarmonyPatch("ActivateAbility")]
	public static bool AbilityPrefix_CancelRBIfSlide(Ability a, Player __instance)
	{
		if (!ReboundPlugin.isPlayer(__instance))
		{
			return true;
		}
		if (__instance.ability == null && a == __instance.slideAbility && ReboundPlugin.CanRebound(__instance) && ReboundPlugin.landTime > Core.dt * 3f)
		{
			ReboundPlugin.CancelRebound();
		}
		return true;
	}
}
internal class RBSettings
{
	public static List<string> PlayerActionTypes = new List<string> { "slide", "boost", "spray", "dance", "trick1", "trick2", "trick3", "trickany", "switchstyle", "walk" };

	private static ConfigEntry<float> config_reboundVelocityMultiplier;

	private static ConfigEntry<float> config_maxLandingTimeToRebound;

	private static ConfigEntry<float> config_minimumVelocityToRebound;

	private static ConfigEntry<float> config_minimumReboundYVelocity;

	private static ConfigEntry<float> config_maximumReboundYVelocity;

	private static ConfigEntry<float> config_launcherBonusMultiplier;

	private static ConfigEntry<float> config_comboCost;

	private static ConfigEntry<float> config_boostCost;

	public static ConfigEntry<float> config_slopeMultiplierX;

	public static ConfigEntry<float> config_slopeMultiplierY;

	private static ConfigEntry<bool> config_capBasedOnHeight;

	private static ConfigEntry<float> config_heightCapGenerosity;

	private static ConfigEntry<bool> config_refreshCombo;

	private static ConfigEntry<bool> config_allowBoostedRebounds;

	private static ConfigEntry<bool> config_tempDisableBoost;

	private static ConfigEntry<bool> config_alwaysCalculateBasedOnHeight;

	public static ConfigEntry<bool> config_slopeOnLauncher;

	private static ConfigEntry<string> config_cancelReboundActions;

	private static ConfigEntry<string> config_doReboundActions;

	public static ConfigEntry<bool> config_requireAllDRA;

	public static ConfigEntry<bool> config_requireAllCRA;

	public static void UpdateSettings(ConfigFile Config)
	{
		BindSettings(Config);
		SetSettingsInPlugin();
	}

	public static void SetSettingsInPlugin()
	{
		ReboundPlugin.reboundVelocityMultiplier = config_reboundVelocityMultiplier.Value;
		ReboundPlugin.maxLandingTimeToRebound = config_maxLandingTimeToRebound.Value;
		ReboundPlugin.minimumVelocityToRebound = config_minimumVelocityToRebound.Value;
		ReboundPlugin.minimumReboundYVelocity = config_minimumReboundYVelocity.Value;
		ReboundPlugin.maximumReboundYVelocity = config_maximumReboundYVelocity.Value;
		ReboundPlugin.launcherBonusMultiplier = config_launcherBonusMultiplier.Value;
		ReboundPlugin.comboCost = config_comboCost.Value;
		ReboundPlugin.boostCost = config_boostCost.Value;
		ReboundPlugin.capBasedOnHeight = config_capBasedOnHeight.Value;
		ReboundPlugin.heightCapGenerosity = config_heightCapGenerosity.Value;
		ReboundPlugin.refreshCombo = config_refreshCombo.Value;
		ReboundPlugin.alwaysCalculateBasedOnHeight = config_alwaysCalculateBasedOnHeight.Value;
		ReboundPlugin.allowBoostedRebounds = config_allowBoostedRebounds.Value;
		ReboundPlugin.tempDisableBoost = config_tempDisableBoost.Value;
		ReboundPlugin.cancelReboundActions = ConvertString(config_cancelReboundActions.Value, PlayerActionTypes);
		ReboundPlugin.doReboundActions = ConvertString(config_doReboundActions.Value, PlayerActionTypes);
	}

	public static List<string> ConvertString(string _string, List<string> _list)
	{
		string text = _string.Replace(" ", "").ToLower();
		List<string> list = text.Split(new char[1] { ',' }).ToList();
		List<string> list2 = new List<string>();
		foreach (string item in list)
		{
			string text2 = item;
			if (_list.Contains(text2))
			{
				if (!text2.Equals("trickany"))
				{
					text2 = ((!text2.Equals("switchstyle")) ? (text2 + "ButtonHeld") : "switchStyleButtonHeld");
				}
				else
				{
					text2 = "trick1ButtonHeld";
					list2.Add(text2);
					text2 = "trick2ButtonHeld";
					list2.Add(text2);
					text2 = "trick3ButtonHeld";
				}
				list2.Add(text2);
			}
		}
		return list2;
	}

	private static void BindSettings(ConfigFile Config)
	{
		config_reboundVelocityMultiplier = Config.Bind<float>("1. Variables", "Rebound Velocity Multiplier", 0.8f, "How much vertical speed is preserved when rebounding.");
		config_maxLandingTimeToRebound = Config.Bind<float>("1. Variables", "Rebound Grace Period", 0.15f, "How much time you have after landing to do a rebound.");
		config_minimumVelocityToRebound = Config.Bind<float>("1. Variables", "Minimum Falling Velocity to Rebound", 0f, "How fast you have to be falling to be able to do a rebound. (For reference, 8 is the player's jump height)");
		config_minimumReboundYVelocity = Config.Bind<float>("1. Variables", "Minimum Rebound Velocity", 8f, "The minimum upward speed a rebound can send you. (For reference, 8 is the player's jump height)");
		config_maximumReboundYVelocity = Config.Bind<float>("1. Variables", "Maximum Rebound Velocity", 0f, "The maximum upward speed a rebound can send you. If zero or below, there's no upper limit (except the maximum fall speed). Note that reaching this limit will slow down your forward speed as well as your upward speed.");
		config_launcherBonusMultiplier = Config.Bind<float>("1. Variables", "Launcher Bonus Multiplier", 0.5f, "How much extra momentum you get from rebounding off a launcher. A rebound off a launcher will never send you lower than the height a launcher sends you by default.");
		config_comboCost = Config.Bind<float>("1. Variables", "Combo Meter Cost", 0.15f, "How much combo meter it costs to do a rebound (ranging from 0 to 1). 0.15 is equivalent to jumping out of a manual. Set to a negative number to gain meter after a rebound.");
		config_boostCost = Config.Bind<float>("1. Variables", "Boost Meter Cost", 0f, "How much boost meter it costs to do a rebound. Set to a negative number to gain boost after every rebound.");
		config_slopeMultiplierX = Config.Bind<float>("1. Variables", "Ground Angle Multiplier on Forward Speed", 1f, "How much the angle of the ground you rebound off affects your forward speed. Speeds up on downward slopes, slows down on upward slopes. Note that you will automatically be flipped over if the slope sends you backwards.");
		config_slopeMultiplierY = Config.Bind<float>("1. Variables", "Ground Angle Multiplier on Upward Speed", 1f, "How much the angle of the ground you rebound off affects your rebound height. Higher on upward slopes, lower on downward slopes. Not restricted by minimum/maximum rebound height.");
		config_capBasedOnHeight = Config.Bind<bool>("2. Options", "Cap Rebound Velocity Based on Height", true, "Limit your rebound speed based on the peak of your jump, preventing you from going really high really fast by abusing Movement Plus fast falls. Shouldn't ever have an effect on vanilla gameplay, but when playing with Movement Plus, you may be sent lower than you might expect.");
		config_heightCapGenerosity = Config.Bind<float>("2. Options", "Height Cap Generosity", 1.5f, "How much extra speed is added to the height-based velocity cap. Note that this is not a multiplier, but an offset added to the height cap.");
		config_refreshCombo = Config.Bind<bool>("2. Options", "Refresh Combo Meter", true, "Toggle whether your combo meter is set to the value it was at before you landed before every rebound. Keeps your combo losses consistent, regardless of when within the grace period you rebounded.");
		config_allowBoostedRebounds = Config.Bind<bool>("2. Options", "Allow Boosted Rebounds", true, "Allow the player to do a Boosted Rebound (boost trick + rebound) when the boost button is held.");
		config_tempDisableBoost = Config.Bind<bool>("2. Options", "Can Temporarily Disable Boost", true, "Toggle whether doing a rebound stops you from boosting until the trick is done. Does not affect Boosted Rebounds.");
		config_alwaysCalculateBasedOnHeight = Config.Bind<bool>("2. Options", "Always Calculate Rebound Velocity Based On Height", false, "Always set the rebound velocity to the height-based velocity cap, regardless of the player's falling velocity. Note that this method tends to send you slightly higher, and also may be less accurate with mid-jump velocity changes (ex. wall plants or air boosts). However, this does allow you to bypass the fall speed limitations. Highly recommended to leave on false.");
		config_slopeOnLauncher = Config.Bind<bool>("2. Options", "Apply Slope Physics when Rebounding off Launcher", false, "If false, rebounding off a launcher will act like you have rebounded off of flat ground. If true, rebounding off a launcher will send you at an angle. Note that this can and will send you flying in directions you may not want - but it also could be used to your advantage to get insane height/speed.");
		config_doReboundActions = Config.Bind<string>("3. Input", "Rebound Modifier Actions", "", "A list of what additional player actions need to be pressed/held to do a rebound, separated by commas. Note that jumping is always required. Acceptable values: slide, boost, spray, dance, trick1, trick2, trick3, trickAny, switchStyle, walk");
		config_requireAllDRA = Config.Bind<bool>("3. Input", "Require ALL Rebound Modifiers to Rebound", false, "If true, the player must press/hold ALL the rebound modifier actions (as well as jump) to successfully rebound. If false, the player can hold ANY of them (along with jump) to rebound.");
		config_cancelReboundActions = Config.Bind<string>("3. Input", "Cancel Rebound Modifier Actions", "slide", "A list of what player actions can be pressed/held to cancel a rebound and do a regular jump instead, separated by commas. Acceptable values: slide, boost, spray, dance, trick1, trick2, trick3, trickAny, switchStyle, walk");
		config_requireAllCRA = Config.Bind<bool>("3. Input", "Require ALL Cancel Rebound Modifiers to Cancel", false, "If true, the player must press/hold ALL the cancel modifier actions to cancel a rebound. If false, the player can hold ANY of them to cancel a rebound.");
	}
}
public static class PluginInfo
{
	public const string PLUGIN_GUID = "Rebound";

	public const string PLUGIN_NAME = "Rebound";

	public const string PLUGIN_VERSION = "1.0.0";
}