Decompiled source of BetterGrapplingHook v1.0.6

BetterGrapplingHook.dll

Decompiled 4 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BetterGrapplingHook.Config;
using BetterGrapplingHook.Features;
using BetterGrapplingHook.Infrastructure;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("BetterGrapplingHook")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6+7601a6a030dfa45a2aef00146af5760d65e2f7bf")]
[assembly: AssemblyProduct("BetterGrapplingHook")]
[assembly: AssemblyTitle("BetterGrapplingHook")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BetterGrapplingHook
{
	[BepInPlugin("JevMods.BetterGrapplingHook", "BetterGrapplingHook", "1.0.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "JevMods.BetterGrapplingHook";

		public const string PluginName = "BetterGrapplingHook";

		private AssistedGrappleFeature _feature;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			GameEvents events = (GameEvents.Instance = new GameEvents());
			_feature = new AssistedGrappleFeature(events, new ModSettings(((BaseUnityPlugin)this).Config));
			_feature.Enable();
			_harmony = new Harmony("JevMods.BetterGrapplingHook");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_feature?.Disable();
			GameEvents.Instance = null;
		}
	}
	internal static class BuildInfo
	{
		public const string Version = "1.0.6";
	}
}
namespace BetterGrapplingHook.Patches
{
	internal static class GrapplingPointPatches
	{
		[HarmonyPatch(typeof(GrapplingPoint), "Activate")]
		private static class Activate
		{
			private static void Postfix(GrapplingPoint __instance)
			{
				if (IsLocalPulling(__instance))
				{
					GameEvents.Instance?.RaiseGrappleLaunched(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(GrapplingPoint), "Update")]
		private static class Update
		{
			private static void Prefix(GrapplingPoint __instance)
			{
				if (IsLocalPulling(__instance))
				{
					GameEvents.Instance?.RaiseGrappleTickStarting(__instance);
				}
			}

			private static void Postfix(GrapplingPoint __instance)
			{
				if (IsLocalPulling(__instance))
				{
					GameEvents.Instance?.RaiseGrappleTick(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(GrapplingPoint), "Deactivate")]
		private static class Deactivate
		{
			private static void Postfix(GrapplingPoint __instance)
			{
				if (IsLocalHook(__instance))
				{
					GameEvents.Instance?.RaiseGrapplePullEnded(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Character), "CustomFixedUpdate")]
		private static class CharacterFixedUpdate
		{
			private static void Prefix(Character __instance)
			{
				if (IsLocalPlayer(__instance))
				{
					GameEvents.Instance?.RaiseLocalPlayerFixedUpdating(Player.m_localPlayer);
				}
			}

			private static void Postfix(Character __instance)
			{
				if (IsLocalPlayer(__instance))
				{
					GameEvents.Instance?.RaiseLocalPlayerFixedUpdate(Player.m_localPlayer);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		private static class PlayerUpdateStats
		{
			private static void Prefix(Player __instance, out float __state)
			{
				__state = __instance.m_stamina;
			}

			private static void Postfix(Player __instance, float __state)
			{
				if (IsLocalPlayer((Character)(object)__instance))
				{
					GameEvents.Instance?.RaiseLocalPlayerStatsUpdated(__instance, __state);
				}
			}
		}

		private static bool IsLocalPlayer(Character character)
		{
			if ((Object)(object)character != (Object)null)
			{
				return (Object)(object)character == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}

		private static bool IsLocalHook(GrapplingPoint point)
		{
			if ((Object)(object)point == (Object)null || !IsLocalPlayer(point.m_character))
			{
				return false;
			}
			ZNetView nview = point.m_nview;
			bool num = (Object)(object)nview != (Object)null && nview.IsValid() && nview.IsOwner();
			bool flag = (Object)(object)point.m_lineRenderer != (Object)null && ((Renderer)point.m_lineRenderer).enabled;
			return num && flag;
		}

		private static bool IsLocalPulling(GrapplingPoint point)
		{
			if (IsLocalHook(point))
			{
				return !point.m_secondary;
			}
			return false;
		}
	}
}
namespace BetterGrapplingHook.Infrastructure
{
	public sealed class GameEvents : IGameEvents
	{
		internal static GameEvents Instance { get; set; }

		public event Action<GrapplingPoint> GrappleLaunched;

		public event Action<GrapplingPoint> GrappleTickStarting;

		public event Action<GrapplingPoint> GrappleTick;

		public event Action<GrapplingPoint> GrapplePullEnded;

		public event Action<Player> LocalPlayerFixedUpdating;

		public event Action<Player> LocalPlayerFixedUpdate;

		public event Action<Player, float> LocalPlayerStatsUpdated;

		internal void RaiseGrappleLaunched(GrapplingPoint point)
		{
			this.GrappleLaunched?.Invoke(point);
		}

		internal void RaiseGrappleTickStarting(GrapplingPoint point)
		{
			this.GrappleTickStarting?.Invoke(point);
		}

		internal void RaiseGrappleTick(GrapplingPoint point)
		{
			this.GrappleTick?.Invoke(point);
		}

		internal void RaiseGrapplePullEnded(GrapplingPoint point)
		{
			this.GrapplePullEnded?.Invoke(point);
		}

		internal void RaiseLocalPlayerFixedUpdating(Player player)
		{
			this.LocalPlayerFixedUpdating?.Invoke(player);
		}

		internal void RaiseLocalPlayerFixedUpdate(Player player)
		{
			this.LocalPlayerFixedUpdate?.Invoke(player);
		}

		internal void RaiseLocalPlayerStatsUpdated(Player player, float staminaBefore)
		{
			this.LocalPlayerStatsUpdated?.Invoke(player, staminaBefore);
		}
	}
	public interface IGameEvents
	{
		event Action<GrapplingPoint> GrappleLaunched;

		event Action<GrapplingPoint> GrappleTickStarting;

		event Action<GrapplingPoint> GrappleTick;

		event Action<GrapplingPoint> GrapplePullEnded;

		event Action<Player> LocalPlayerFixedUpdating;

		event Action<Player> LocalPlayerFixedUpdate;

		event Action<Player, float> LocalPlayerStatsUpdated;
	}
}
namespace BetterGrapplingHook.Features
{
	public sealed class AssistedGrappleFeature
	{
		private const float HangDepth = 3f;

		private const float GroundSettleDistance = 0.6f;

		private const float MaxProbeError = 2f;

		private static readonly RaycastHit[] ProbeHits = (RaycastHit[])(object)new RaycastHit[32];

		private readonly IGameEvents _events;

		private readonly IModSettings _settings;

		private GrapplingPoint _attached;

		private GrapplingPoint _hanging;

		private float _depth;

		private bool _gravityOff;

		public AssistedGrappleFeature(IGameEvents events, IModSettings settings)
		{
			_events = events;
			_settings = settings;
		}

		public void Enable()
		{
			_events.GrappleLaunched += OnLaunched;
			_events.GrappleTickStarting += OnTickStarting;
			_events.GrappleTick += OnTick;
			_events.GrapplePullEnded += OnPullEnded;
			_events.LocalPlayerFixedUpdating += OnPhysicsStepStarting;
			_events.LocalPlayerFixedUpdate += OnPhysicsStep;
			_events.LocalPlayerStatsUpdated += OnStatsUpdated;
		}

		public void Disable()
		{
			_events.GrappleLaunched -= OnLaunched;
			_events.GrappleTickStarting -= OnTickStarting;
			_events.GrappleTick -= OnTick;
			_events.GrapplePullEnded -= OnPullEnded;
			_events.LocalPlayerFixedUpdating -= OnPhysicsStepStarting;
			_events.LocalPlayerFixedUpdate -= OnPhysicsStep;
			_events.LocalPlayerStatsUpdated -= OnStatsUpdated;
		}

		private void OnLaunched(GrapplingPoint point)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (IsConstantVelocity(point))
			{
				_attached = point;
				_depth = ChooseDepth(point);
				point.m_closeBreakDist = Mathf.Max(point.m_closeBreakDist, _depth + 0.5f);
				Character character = point.m_character;
				Vector3 val = Target(point) - ((Component)character).transform.position;
				Vector3 val2 = ((Vector3)(ref val)).normalized * point.m_pullForce + Vector3.up * _settings.LaunchLift;
				character.ForceJump(val2, false);
			}
		}

		private void OnTickStarting(GrapplingPoint point)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (IsConstantVelocity(point))
			{
				Vector3 val = ((Component)point.m_character).transform.position - ((Component)point).transform.position;
				if (((Vector3)(ref val)).magnitude < point.m_lastDist)
				{
					point.m_breakingTime = 0f;
				}
			}
		}

		private void OnTick(GrapplingPoint point)
		{
			//IL_0012: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (IsConstantVelocity(point))
			{
				Character character = point.m_character;
				Vector3 val = Target(point) - ((Component)character).transform.position;
				Vector3 val2 = Vector3.zero;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					val2 = ((Vector3)(ref val)).normalized * point.m_pullForce;
				}
				float num = GrappleMath.LiftSpeed(_settings.LaunchLift, _settings.LiftDuration, point.m_time);
				character.SetVelocity(val2 + Vector3.up * num);
			}
		}

		private void OnPullEnded(GrapplingPoint point)
		{
			if (IsConstantVelocity(point))
			{
				if (_settings.OnArrival == ArrivalBehavior.AutoRetract)
				{
					point.Break(true);
					return;
				}
				_hanging = point;
				point.StandUp();
			}
		}

		private void OnPhysicsStepStarting(Player player)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (IsHolding())
			{
				((Character)player).SetMoveDir(Vector3.zero);
			}
		}

		private void OnPhysicsStep(Player player)
		{
			if (IsHolding())
			{
				HoldInPlace(player);
				return;
			}
			_hanging = null;
			if (_gravityOff)
			{
				((Character)player).m_body.useGravity = true;
				_gravityOff = false;
			}
		}

		private void OnStatsUpdated(Player player, float staminaBefore)
		{
			if (!IsAttached())
			{
				_attached = null;
				return;
			}
			if (player.m_stamina > staminaBefore)
			{
				player.m_stamina = staminaBefore;
			}
			if (player.m_stamina <= 0f)
			{
				_attached.Break(true);
			}
		}

		private void HoldInPlace(Player player)
		{
			//IL_0001: 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)
			((Character)player).SetVelocity(Vector3.zero);
			bool flag = IsGroundWithin(((Component)player).transform.position, 0.6f);
			((Character)player).m_body.useGravity = flag;
			_gravityOff = !flag;
		}

		private float ChooseDepth(GrapplingPoint point)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)point.m_character).transform.position;
			Vector3 position2 = ((Component)point).transform.position;
			float? num = SurfaceNormalY(position, position2);
			float num2 = GrappleMath.HangDepth(position2.y - position.y, 3f, num ?? 1f);
			Vector3 val = position2 - position;
			float? num3 = GroundHeightBelow(position2, ((Vector3)(ref val)).normalized);
			if (num3.HasValue)
			{
				num2 = Mathf.Min(num2, Mathf.Max(0f, position2.y - num3.Value));
			}
			return num2;
		}

		private Vector3 Target(GrapplingPoint point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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)
			return ((Component)point).transform.position + Vector3.down * _depth;
		}

		private bool IsAttached()
		{
			if ((Object)(object)_attached != (Object)null)
			{
				return IsLineVisible(_attached);
			}
			return false;
		}

		private bool IsHolding()
		{
			if ((Object)(object)_hanging != (Object)null && _hanging.m_secondary)
			{
				return IsLineVisible(_hanging);
			}
			return false;
		}

		private static bool IsLineVisible(GrapplingPoint point)
		{
			if ((Object)(object)point.m_lineRenderer != (Object)null)
			{
				return ((Renderer)point.m_lineRenderer).enabled;
			}
			return false;
		}

		private static bool IsConstantVelocity(GrapplingPoint point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			return (int)point.Method == 1;
		}

		private static bool IsEnvironment(RaycastHit hit)
		{
			bool num = (Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Character>() != (Object)null;
			bool flag = (Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<GrapplingPoint>() != (Object)null;
			if (!num)
			{
				return !flag;
			}
			return false;
		}

		private static float? GroundHeightBelow(Vector3 anchor, Vector3 toAnchor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.RaycastNonAlloc(anchor - toAnchor * 0.3f, Vector3.down, ProbeHits, 100f, -5, (QueryTriggerInteraction)1);
			float? result = null;
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit hit = ProbeHits[i];
				if (IsEnvironment(hit) && ((RaycastHit)(ref hit)).distance < num2)
				{
					num2 = ((RaycastHit)(ref hit)).distance;
					result = ((RaycastHit)(ref hit)).point.y;
				}
			}
			return result;
		}

		private static bool IsGroundWithin(Vector3 feet, float distance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.RaycastNonAlloc(feet + Vector3.up * 0.5f, Vector3.down, ProbeHits, 0.5f + distance, -5, (QueryTriggerInteraction)1);
			for (int i = 0; i < num; i++)
			{
				if (IsEnvironment(ProbeHits[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static float? SurfaceNormalY(Vector3 feet, Vector3 anchor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0030: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = feet + Vector3.up;
			Vector3 val2 = anchor - val;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (magnitude < 1f)
			{
				return null;
			}
			int num = Physics.RaycastNonAlloc(val, val2 / magnitude, ProbeHits, magnitude + 1f, -5, (QueryTriggerInteraction)1);
			float? result = null;
			float num2 = 2f;
			for (int i = 0; i < num; i++)
			{
				RaycastHit hit = ProbeHits[i];
				Vector3 val3 = ((RaycastHit)(ref hit)).point - anchor;
				float magnitude2 = ((Vector3)(ref val3)).magnitude;
				if (IsEnvironment(hit) && magnitude2 < num2)
				{
					num2 = magnitude2;
					result = ((RaycastHit)(ref hit)).normal.y;
				}
			}
			return result;
		}
	}
	public static class GrappleMath
	{
		private const float FloorNormalY = 0.5f;

		public static float HangDepth(float anchorAbovePlayer, float maxDepth, float surfaceNormalY)
		{
			if (surfaceNormalY >= 0.5f)
			{
				return 0f;
			}
			return Mathf.Clamp(anchorAbovePlayer, 0f, maxDepth);
		}

		public static float LiftSpeed(float lift, float duration, float elapsed)
		{
			if (duration <= 0f)
			{
				return 0f;
			}
			return lift * Mathf.Clamp01(1f - elapsed / duration);
		}
	}
}
namespace BetterGrapplingHook.Config
{
	public enum ArrivalBehavior
	{
		Hang,
		AutoRetract
	}
	public interface IModSettings
	{
		float LaunchLift { get; }

		float LiftDuration { get; }

		ArrivalBehavior OnArrival { get; }
	}
	public sealed class ModSettings : IModSettings
	{
		private readonly ConfigEntry<float> _launchLift;

		private readonly ConfigEntry<float> _liftDuration;

		private readonly ConfigEntry<ArrivalBehavior> _onArrival;

		public float LaunchLift => _launchLift.Value;

		public float LiftDuration => _liftDuration.Value;

		public ArrivalBehavior OnArrival => _onArrival.Value;

		public ModSettings(ConfigFile file)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			_launchLift = file.Bind<float>("Flight", "LaunchLift", 6f, new ConfigDescription("Extra upward speed at launch, in m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			_liftDuration = file.Bind<float>("Flight", "LiftDuration", 0.75f, new ConfigDescription("How long the extra upward speed lasts, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			_onArrival = file.Bind<ArrivalBehavior>("Flight", "OnArrival", ArrivalBehavior.Hang, "What happens when you reach the hook. Hang = stay attached and hold in place. AutoRetract = release the hook.");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}