Decompiled source of GrappleMomentum v0.3.2

BepInEx/plugins/GrappleMomentum/GrappleMomentum.dll

Decompiled 3 weeks 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 BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GrappleMomentum")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.2.0")]
[assembly: AssemblyInformationalVersion("0.3.2+256d7e1c98fca9edf890f043ba84dc9f23ebe80e")]
[assembly: AssemblyProduct("GrappleMomentum")]
[assembly: AssemblyTitle("GrappleMomentum")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 GrappleMomentum
{
	[BepInPlugin("dugi.GrappleMomentum", "GrappleMomentum", "0.3.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal struct Settings
		{
			internal bool Enabled;

			internal bool Debug;

			internal float MaxSpeed;

			internal float InitialImpulse;

			internal float GroundLift;

			internal float PullDelay;

			internal float RampSeconds;

			internal float PullAcceleration;

			internal float PullSpeed;

			internal float SwingPull;

			internal float AirAcceleration;

			internal float Stamina;

			internal float FallGrace;

			internal float Cooldown;

			internal float JumpWindow;

			internal float JumpMultiplier;

			internal KeyCode OffhandKey;
		}

		internal const string Id = "dugi.GrappleMomentum";

		internal const string Name = "GrappleMomentum";

		internal static Settings Cached;

		private static ManualLogSource? _log;

		private Harmony? _harmony;

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<float> _maxSpeed;

		private ConfigEntry<bool> _debug;

		private ConfigEntry<float> _initialImpulse;

		private ConfigEntry<float> _groundLift;

		private ConfigEntry<float> _pullDelay;

		private ConfigEntry<float> _rampSeconds;

		private ConfigEntry<float> _pullAcceleration;

		private ConfigEntry<float> _pullSpeed;

		private ConfigEntry<float> _swingPull;

		private ConfigEntry<float> _airAcceleration;

		private ConfigEntry<float> _stamina;

		private ConfigEntry<float> _fallGrace;

		private ConfigEntry<float> _cooldown;

		private ConfigEntry<float> _jumpWindow;

		private ConfigEntry<float> _jumpMultiplier;

		private ConfigEntry<KeyCode> _offhandKey;

		internal static bool Operational { get; private set; }

		private void Awake()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			try
			{
				_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle. Off restores vanilla behaviour.");
				_maxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Inertia", "MaxSpeed", 50f, new ConfigDescription("Maximum commanded speed (m/s) while attached or preserving inertia.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 150f), Array.Empty<object>()));
				_initialImpulse = BindFloat("Pull", "InitialImpulse", 8f, 0f, 30f, "Added speed toward anchor on attachment (m/s).");
				_groundLift = BindFloat("Pull", "GroundLift", 1.5f, 0f, 5f, "Minimum upward takeoff speed on ground attachment (m/s).");
				_pullDelay = BindFloat("Pull", "DelaySeconds", 0.2f, 0f, 1f, "Delay between initial impulse and continuous acceleration. Not a bonus-jump window.");
				_rampSeconds = BindFloat("Pull", "RampSeconds", 1.5f, 0.05f, 5f, "Time to ramp from initial pull speed to TargetSpeed.");
				_pullAcceleration = BindFloat("Pull", "Acceleration", 25f, 1f, 100f, "Acceleration toward anchor (m/s squared), added to current velocity.");
				_pullSpeed = BindFloat("Pull", "TargetSpeed", 24f, 1f, 80f, "Final target inward speed; higher existing momentum is not overwritten.");
				_swingPull = BindFloat("Pull", "SwingPullFactor", 0.15f, 0f, 1f, "Fraction of inward pull target when looking away from the anchor to swing.");
				_jumpWindow = BindFloat("Pull", "JumpWindowSeconds", 0.5f, 0.05f, 0.5f, "After a ground attachment, time during which jump is still accepted (tip glows gold meanwhile).");
				_jumpMultiplier = BindFloat("Pull", "JumpMultiplier", 1.5f, 1f, 3f, "Jump velocity multiplier for the grapple jump (Apex grapple_jumpFrac). 1 = vanilla jump.");
				_airAcceleration = BindFloat("Control", "AirAcceleration", 6f, 0f, 25f, "Directional air acceleration (m/s squared), tangent to rope while attached.");
				_stamina = BindFloat("General", "StaminaPerShot", 5f, 0f, 30f, "Exact cost per grappling-hook shot. Normal jump costs remain vanilla.");
				_fallGrace = BindFloat("Inertia", "FallGraceSeconds", 0f, 0f, 10f, "Optional fall-damage immunity after release, until landing/reset. Zero preserves vanilla protection only.");
				_cooldown = BindFloat("General", "CooldownSeconds", 0.2f, 0f, 5f, "Seconds from a hook shot until the next one is ready. Replaces the vanilla reload, also while attached.");
				_offhandKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Offhand", "Key", (KeyCode)327, "Fires the grappling hook carried in the inventory without equipping it. Mouse4 = back side button, Mouse3 = forward side button, None = off.");
				_debug = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DebugTransitions", false, "Log state changes (at most 4 per second).");
				((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
				RefreshSettings();
				_harmony = new Harmony("dugi.GrappleMomentum");
				Patches.Install(_harmony, ((BaseUnityPlugin)this).Logger);
				SceneManager.sceneUnloaded += OnSceneUnloaded;
				Operational = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[GrappleMomentum] 0.3.2 loaded. Fixed-step pull, swing and grapple jump; reference assembly Valheim 1.0.16.");
			}
			catch (Exception ex)
			{
				Operational = false;
				Harmony? harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("[GrappleMomentum] Disabled: target validation or patch installation failed; all own patches removed. " + ex));
			}
		}

		private void OnSettingChanged(object sender, SettingChangedEventArgs args)
		{
			RefreshSettings();
		}

		private ConfigEntry<float> BindFloat(string section, string key, float value, float min, float max, string description)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}

		private void RefreshSettings()
		{
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			Cached = new Settings
			{
				Enabled = _enabled.Value,
				Debug = _debug.Value,
				MaxSpeed = ValidRange(_maxSpeed.Value, 1f, 150f, 50f),
				InitialImpulse = ValidRange(_initialImpulse.Value, 0f, 30f, 8f),
				GroundLift = ValidRange(_groundLift.Value, 0f, 5f, 1.5f),
				PullDelay = ValidRange(_pullDelay.Value, 0f, 1f, 0.2f),
				RampSeconds = ValidRange(_rampSeconds.Value, 0.05f, 5f, 1.5f),
				PullAcceleration = ValidRange(_pullAcceleration.Value, 1f, 100f, 25f),
				PullSpeed = ValidRange(_pullSpeed.Value, 1f, 80f, 24f),
				SwingPull = ValidRange(_swingPull.Value, 0f, 1f, 0.15f),
				AirAcceleration = ValidRange(_airAcceleration.Value, 0f, 25f, 6f),
				Stamina = ValidRange(_stamina.Value, 0f, 30f, 5f),
				FallGrace = ValidRange(_fallGrace.Value, 0f, 10f, 0f),
				Cooldown = ValidRange(_cooldown.Value, 0f, 5f, 0.2f),
				JumpWindow = ValidRange(_jumpWindow.Value, 0.05f, 0.5f, 0.5f),
				JumpMultiplier = ValidRange(_jumpMultiplier.Value, 1f, 3f, 1.5f),
				OffhandKey = _offhandKey.Value
			};
		}

		private static float ValidRange(float value, float min, float max, float fallback)
		{
			if (GrappleController.IsFinite(value))
			{
				return Math.Max(min, Math.Min(max, value));
			}
			return fallback;
		}

		private static void OnSceneUnloaded(Scene scene)
		{
			GrappleController.Reset(GrappleController.Reason.Scene);
		}

		private void OnDestroy()
		{
			Operational = false;
			((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
			SceneManager.sceneUnloaded -= OnSceneUnloaded;
			GrappleController.Reset(GrappleController.Reason.Disabled);
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			GrappleController.DestroyDot();
		}

		internal static void Fault(Exception error)
		{
			if (Operational)
			{
				Operational = false;
				GrappleController.Reset(GrappleController.Reason.Fault);
				ManualLogSource? log = _log;
				if (log != null)
				{
					log.LogError((object)("[GrappleMomentum] Disabled after a runtime failure; vanilla callbacks remain enabled. " + error));
				}
			}
		}

		internal static void NumericFault()
		{
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogError((object)"[GrappleMomentum] Non-finite velocity detected: no velocity written; state reset.");
			}
		}

		internal static void TransitionLog(string message)
		{
			ManualLogSource? log = _log;
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}
	}
	internal static class GrappleController
	{
		private enum State
		{
			Idle,
			Attached,
			Inertia
		}

		internal enum Reason
		{
			Hook,
			Release,
			Arrival,
			Ground,
			Stopped,
			Unsafe,
			AnchorLost,
			HookLost,
			Ownership,
			Disabled,
			Scene,
			Death,
			Teleport,
			Destroyed,
			Ship,
			Rescue,
			Impact,
			Fault
		}

		internal struct AirControlScope
		{
			internal bool Changed;

			internal float Original;
		}

		internal struct ImpactScope
		{
			internal bool Local;

			internal int PreviousId;
		}

		private const float Epsilon = 0.0001f;

		private const float MinRopeLength = 1f;

		private const float MaxCorrection = 0.05f;

		private const string HookItemName = "$item_graplinghook";

		private const string SparkPrefab = "vfx_HitSparks";

		private const float PullLift = 0.6f;

		private const float PassSpeed = 0.5f;

		private static State _state;

		private static Player? _player;

		private static Player? _tickPlayer;

		private static GrapplingPoint? _hook;

		private static GameObject? _anchor;

		private static Collider? _anchorCollider;

		private static bool _hadAnchor;

		private static bool _hadCollider;

		private static int _hookId;

		private static int _ignoredHookId;

		private static bool _inTick;

		private static bool _walkingReplaced;

		private static bool _breaking;

		private static bool _abortQueued;

		private static Reason _abortReason;

		private static bool _initialPending;

		private static bool _releaseRequested;

		private static bool _jumpRequested;

		private static bool _jumpUsed;

		private static bool _groundedOnAttach;

		private static float _attachedAt;

		private static float _pullAt;

		private static float _jumpUntil;

		private static float _jumpPressedAt;

		private static float _rampSeconds;

		private static float _ropeLength;

		private static float _fallUntil;

		private static float _nextLogTime;

		private static bool _numericErrorLogged;

		private static bool _ownsFallCap;

		private static SE_Stats? _ownedEffect;

		private static float _savedFallCap;

		private static float _effectReleaseTtl;

		private static Color _savedTipColor;

		private static Vector3 _approach;

		private static float _lateJumpUntil;

		private static float _attachY;

		private static float _traceUntil;

		private static float _traceNext;

		private static int _lastJumpTraceFrame;

		private static bool _colorSaved;

		private static bool _colorRestored;

		private static Vector3 _steer;

		private static Vector3 _look;

		private static Plugin.Settings _tickSettings;

		private static float _lastShotAt = float.NegativeInfinity;

		private static bool _reloadPending;

		private static EffectList? _spark;

		private static bool _sparkMissingLogged;

		private static readonly RaycastHit[] DotHits = (RaycastHit[])(object)new RaycastHit[16];

		private static readonly Color DotInRange = new Color(0.25f, 0.6f, 1f, 1f);

		private static readonly Color DotOutOfRange = new Color(0.55f, 0.55f, 0.55f, 0.9f);

		private static int _dotMask;

		private static Image? _dot;

		private static Sprite? _dotSprite;

		private static bool Tracing
		{
			get
			{
				if (Plugin.Cached.Debug && _traceUntil > 0f)
				{
					return Time.fixedTime <= _traceUntil;
				}
				return false;
			}
		}

		internal static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static bool Finite(Vector3 value)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (IsFinite(value.x) && IsFinite(value.y))
			{
				return IsFinite(value.z);
			}
			return false;
		}

		private static float Length(Vector3 value)
		{
			//IL_0000: 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_000f: 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_001f: 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)
			return (float)Math.Sqrt((double)value.x * (double)value.x + (double)value.y * (double)value.y + (double)value.z * (double)value.z);
		}

		private static float HorizontalSpeed(Vector3 v)
		{
			//IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			return Length(new Vector3(v.x, 0f, v.z));
		}

		private static float Clamp01(float value)
		{
			return Math.Max(0f, Math.Min(1f, value));
		}

		internal static bool TryLimitVelocity(Vector3 velocity, float limit, out Vector3 result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0021: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			result = velocity;
			if (!Finite(velocity) || !IsFinite(limit) || limit <= 0f)
			{
				return false;
			}
			double num = (double)velocity.x * (double)velocity.x + (double)velocity.y * (double)velocity.y + (double)velocity.z * (double)velocity.z;
			if (num > (double)limit * (double)limit)
			{
				double num2 = (double)limit / Math.Sqrt(num);
				result = new Vector3((float)((double)velocity.x * num2), (float)((double)velocity.y * num2), (float)((double)velocity.z * num2));
			}
			return Finite(result);
		}

		internal static float RampSpeed(float elapsed, float duration, float start, float end)
		{
			return start + (end - start) * Clamp01(elapsed / Math.Max(0.0001f, duration));
		}

		internal static Vector3 StepPull(Vector3 velocity, Vector3 offset, Vector3 steer, Vector3 look, float target, float acceleration, float airAcceleration, float swingFactor, float dt)
		{
			//IL_0000: 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_0019: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			float num = Length(offset);
			if (!IsFinite(num) || num <= 0.0001f)
			{
				return velocity;
			}
			Vector3 val = offset / num;
			float num2 = Length(look);
			float num3 = ((num2 > 0.0001f) ? Clamp01(Vector3.Dot(look / num2, -val)) : 1f);
			float num4 = target * (swingFactor + (1f - swingFactor) * num3);
			float num5 = Vector3.Dot(velocity, -val);
			float num6 = Math.Max(0f, Math.Min(acceleration * dt, num4 - num5));
			Vector3 val2 = steer - val * Vector3.Dot(steer, val);
			return velocity - val * num6 + val2 * (airAcceleration * dt);
		}

		internal static Vector3 ConstrainRope(Vector3 velocity, Vector3 offset, float length)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			float num = Length(offset);
			if (!IsFinite(num) || num <= 0.0001f || num < length - 0.01f)
			{
				return velocity;
			}
			Vector3 val = offset / num;
			float num2 = Vector3.Dot(velocity, val);
			if (!(num2 > 0f))
			{
				return velocity;
			}
			return velocity - val * num2;
		}

		internal static Vector3 RopeCorrection(Vector3 offset, float length, float maxStep)
		{
			//IL_0000: 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_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			float num = Length(offset);
			if (!IsFinite(num) || num <= 0.0001f || num <= length)
			{
				return Vector3.zero;
			}
			return -offset / num * Math.Min(Math.Max(0f, maxStep), num - length);
		}

		internal static bool RopeActive(Vector3 offset)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return offset.y < 0f;
		}

		internal static bool PassedAnchor(Vector3 offset, Vector3 velocity, Vector3 approach, float minOutwardSpeed)
		{
			//IL_0000: 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_0026: 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_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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			float num = Length(offset);
			if (!IsFinite(num) || num <= 0.0001f)
			{
				return false;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(offset.x, 0f, offset.z);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(approach.x, 0f, approach.z);
			if (Length(val2) <= 0.0001f || Vector3.Dot(val2, val) > 0f)
			{
				return Vector3.Dot(velocity, offset / num) > minOutwardSpeed;
			}
			return false;
		}

		internal static Vector3 AddJump(Vector3 velocity, Vector3 jump)
		{
			//IL_0000: 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_000d: 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_001e: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(velocity.x + jump.x, Math.Max(velocity.y, jump.y), velocity.z + jump.z);
		}

		internal static bool JumpEligible(bool used, bool grounded, bool groundedAtAttach, float pressedAt, float deadline)
		{
			if (!used)
			{
				if (!grounded)
				{
					if (groundedAtAttach)
					{
						return pressedAt <= deadline;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static bool Owns(Player player)
		{
			if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)((Character)player).m_nview) && ((Character)player).m_nview.IsValid() && ((Character)player).m_nview.IsOwner())
			{
				return Object.op_Implicit((Object)(object)((Character)player).m_body);
			}
			return false;
		}

		private static bool Supported(GrapplingPoint? hook, Player player)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			if (Object.op_Implicit((Object)(object)hook) && (Object)(object)hook.m_character == (Object)(object)player && Object.op_Implicit((Object)(object)hook.m_nview) && hook.m_nview.IsValid() && hook.m_nview.IsOwner() && Object.op_Implicit((Object)(object)hook.m_lineRenderer) && ((Renderer)hook.m_lineRenderer).enabled && (int)hook.Method == 1 && !hook.m_secondary && Object.op_Implicit((Object)(object)hook.m_equipCheck))
			{
				return hook.m_equipCheck.m_itemData.m_shared.m_name == "$item_graplinghook";
			}
			return false;
		}

		private static bool Unsafe(Player player)
		{
			if (!((Character)player).IsDead() && !(((Character)player).GetHealth() <= 0f) && !((Character)player).IsTeleporting() && !((Character)player).InIntro() && !((Character)player).InCutscene() && !((Character)player).InWater() && !((Character)player).IsSwimming() && !((Character)player).IsAttached() && !((Character)player).IsAttachedToShip() && !((Character)player).IsSitting() && !((Character)player).IsRiding())
			{
				return ((Character)player).IsDebugFlying();
			}
			return true;
		}

		private static bool AnchorLost()
		{
			if (!_hadAnchor || Object.op_Implicit((Object)(object)_anchor))
			{
				if (_hadCollider)
				{
					return !Object.op_Implicit((Object)(object)_anchorCollider);
				}
				return false;
			}
			return true;
		}

		private static bool ActiveTick(Character character)
		{
			if (_inTick)
			{
				return (Object)(object)character == (Object)(object)_tickPlayer;
			}
			return false;
		}

		private static void RestoreHookPresentation()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_hook) && Object.op_Implicit((Object)(object)_hook.m_lineRenderer) && _colorSaved)
			{
				_hook.m_lineRenderer.startColor = _savedTipColor;
			}
			GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
			bool flag = Object.op_Implicit((Object)(object)localGrappler) && (Object)(object)localGrappler != (Object)(object)_hook && (Object)(object)localGrappler.m_se == (Object)(object)_ownedEffect;
			if (_ownsFallCap && Object.op_Implicit((Object)(object)_ownedEffect) && !flag)
			{
				if (Object.op_Implicit((Object)(object)_hook))
				{
					_ownedEffect.m_maxMaxFallSpeed = _savedFallCap;
				}
				else
				{
					_ownedEffect.m_maxMaxFallSpeed = 0f;
					((StatusEffect)_ownedEffect).ResetTime();
					((StatusEffect)_ownedEffect).m_ttl = _effectReleaseTtl;
				}
			}
			_ownedEffect = null;
			_ownsFallCap = false;
			_colorSaved = false;
		}

		private static void Transition(State next, Reason reason)
		{
			//IL_00ee: 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_00f4: 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)
			State state = _state;
			if (next == State.Inertia && state != State.Attached)
			{
				next = State.Idle;
			}
			_lateJumpUntil = 0f;
			if (state != next)
			{
				Trace(state.ToString() + " -> " + next.ToString() + " (" + reason.ToString() + ")");
			}
			if (next != State.Attached)
			{
				RestoreHookPresentation();
				_hook = null;
				_anchor = null;
				_anchorCollider = null;
				_hadAnchor = (_hadCollider = false);
				_releaseRequested = (_jumpRequested = (_initialPending = false));
				_abortQueued = false;
			}
			_state = next;
			if (next == State.Inertia)
			{
				_fallUntil = Time.fixedTime + _tickSettings.FallGrace;
			}
			if (next == State.Idle)
			{
				_player = null;
				_hookId = 0;
				_fallUntil = 0f;
				_steer = (_look = Vector3.zero);
			}
			if (state != next && Plugin.Cached.Debug && !Tracing && Time.unscaledTime >= _nextLogTime)
			{
				_nextLogTime = Time.unscaledTime + 0.25f;
				Plugin.TransitionLog("[GrappleMomentum] " + state.ToString() + " -> " + next.ToString() + " (" + reason.ToString() + ")");
			}
		}

		internal static void Reset(Reason reason)
		{
			if (_hookId != 0)
			{
				_ignoredHookId = _hookId;
			}
			if (reason == Reason.Scene || reason == Reason.Destroyed)
			{
				_ignoredHookId = 0;
			}
			if ((reason == Reason.Death || reason == Reason.Destroyed || reason == Reason.Teleport || reason == Reason.Scene || reason == Reason.Ownership) && Object.op_Implicit((Object)(object)_hook) && Object.op_Implicit((Object)(object)_hook.m_nview) && _hook.m_nview.IsValid() && _hook.m_nview.IsOwner())
			{
				GrapplingPoint hook = _hook;
				RestoreHookPresentation();
				GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
				if (!Object.op_Implicit((Object)(object)localGrappler) || !((Object)(object)localGrappler != (Object)(object)hook))
				{
					int num;
					if (Object.op_Implicit((Object)(object)_player))
					{
						num = (Owns(_player) ? 1 : 0);
						if (num != 0)
						{
							_player.m_grappling = 0f;
						}
					}
					else
					{
						num = 0;
					}
					if (num != 0 && Object.op_Implicit((Object)(object)hook.m_anim))
					{
						hook.m_anim.SetBool("grappling", false);
						hook.m_anim.SetBool("repell", false);
					}
					if (num != 0 && Object.op_Implicit((Object)(object)hook.m_se))
					{
						((StatusEffect)hook.m_se).ResetTime();
						((StatusEffect)hook.m_se).m_ttl = _effectReleaseTtl;
						hook.m_se.m_maxMaxFallSpeed = 0f;
					}
					if (Object.op_Implicit((Object)(object)GameCamera.instance))
					{
						GameCamera.instance.ResetTempFOV();
					}
				}
				if (Object.op_Implicit((Object)(object)hook.m_lineRenderer))
				{
					((Renderer)hook.m_lineRenderer).enabled = false;
				}
				if (Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					ZNetScene.instance.Destroy(((Component)hook).gameObject);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)hook).gameObject);
				}
			}
			Transition(State.Idle, reason);
		}

		internal static void ResetLocal(Character character, Reason reason)
		{
			if (!((Object)(object)character != (Object)(object)Player.m_localPlayer) || !((Object)(object)character != (Object)(object)_player))
			{
				if (reason != Reason.Death && reason != Reason.Destroyed && reason != Reason.Teleport && reason != Reason.Scene && reason != Reason.Ownership && reason != Reason.Disabled && ActiveTick(character) && _state == State.Attached)
				{
					_abortQueued = true;
					_abortReason = reason;
				}
				else
				{
					Reset(reason);
				}
			}
		}

		private static void Track(GrapplingPoint hook, Player player)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)hook).GetInstanceID();
			if (instanceID != _ignoredHookId && (_state != State.Attached || instanceID != _hookId))
			{
				Transition(State.Idle, Reason.Hook);
				_player = player;
				_hook = hook;
				_hookId = instanceID;
				_ignoredHookId = 0;
				Plugin.Settings cached = Plugin.Cached;
				_attachedAt = Time.fixedTime;
				_pullAt = _attachedAt + cached.PullDelay;
				_jumpUntil = _attachedAt + cached.JumpWindow;
				_rampSeconds = cached.RampSeconds;
				_ropeLength = Math.Max(1f, Length(((Character)player).m_body.position - ((Component)hook).transform.position));
				_approach = ((Component)hook).transform.position - ((Character)player).m_body.position;
				_approach.y = 0f;
				_groundedOnAttach = ((Character)player).IsOnGround();
				_attachY = ((Character)player).m_body.position.y;
				_traceUntil = _attachedAt + 2f;
				_traceNext = 0f;
				Trace("attached: distance " + Length(((Character)player).m_body.position - ((Component)hook).transform.position).ToString("0.0") + " m, anchor height " + (((Component)hook).transform.position.y - _attachY).ToString("0.00") + " m, grounded " + _groundedOnAttach);
				_jumpUsed = false;
				_initialPending = true;
				_savedTipColor = hook.m_lineRenderer.startColor;
				_colorSaved = true;
				_colorRestored = false;
				_effectReleaseTtl = (IsFinite(hook.m_ttlSE) ? Math.Max(0.01f, hook.m_ttlSE) : 2f);
				Transition(State.Attached, Reason.Hook);
				AttachSpark(((Component)hook).transform.position);
			}
		}

		private static void AttachSpark(Vector3 position)
		{
			//IL_0079: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_004c: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (_spark == null)
			{
				GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab("vfx_HitSparks") : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					if (!_sparkMissingLogged)
					{
						Plugin.TransitionLog("[GrappleMomentum] vfx_HitSparks not found; tip colour only.");
					}
					_sparkMissingLogged = true;
					return;
				}
				EffectList val2 = new EffectList();
				val2.m_effectPrefabs = (EffectData[])(object)new EffectData[1]
				{
					new EffectData
					{
						m_prefab = val,
						m_enabled = true
					}
				};
				_spark = val2;
			}
			_spark.Create(position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}

		internal static void BeginTick(Character character)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			if ((Object)(object)character != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)character;
			_tickSettings = Plugin.Cached;
			if (!Plugin.Operational || !_tickSettings.Enabled)
			{
				Reset(Reason.Disabled);
				return;
			}
			if (!Owns(val))
			{
				Reset(Reason.Ownership);
				return;
			}
			if (Object.op_Implicit((Object)(object)_player) && (Object)(object)_player != (Object)(object)val)
			{
				Reset(Reason.Destroyed);
			}
			_tickPlayer = val;
			_inTick = true;
			_walkingReplaced = false;
		}

		internal static Exception? EndTick(Character character, Exception? error)
		{
			if ((Object)(object)character == (Object)(object)_tickPlayer)
			{
				_inTick = false;
				_tickPlayer = null;
				if (error != null)
				{
					Plugin.Fault(error);
				}
			}
			return error;
		}

		internal static void PrepareMotion(Character character)
		{
			//IL_017c: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			if (!ActiveTick(character))
			{
				return;
			}
			Player tickPlayer = _tickPlayer;
			if (!Owns(tickPlayer))
			{
				Reset(Reason.Ownership);
				return;
			}
			GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
			if (Supported(localGrappler, tickPlayer))
			{
				Track(localGrappler, tickPlayer);
			}
			if (Unsafe(tickPlayer))
			{
				ResetLocal((Character)(object)tickPlayer, Reason.Unsafe);
				return;
			}
			if (((Character)tickPlayer).IsKnockedBack() || ((Character)tickPlayer).IsStaggering())
			{
				ResetLocal((Character)(object)tickPlayer, Reason.Impact);
				return;
			}
			if (_state == State.Attached)
			{
				if (!Supported(_hook, tickPlayer) || (Object)(object)_hook != (Object)(object)localGrappler || !Object.op_Implicit((Object)(object)_hook.m_attachPoint))
				{
					ResetLocal((Character)(object)tickPlayer, Reason.HookLost);
					return;
				}
				if (AnchorLost())
				{
					ResetLocal((Character)(object)tickPlayer, Reason.AnchorLost);
					return;
				}
				if (!_ownsFallCap && Object.op_Implicit((Object)(object)_hook.m_se))
				{
					_ownedEffect = _hook.m_se;
					_savedFallCap = _ownedEffect.m_maxMaxFallSpeed;
					_ownedEffect.m_maxMaxFallSpeed = 0f;
					_ownsFallCap = true;
				}
				if (CarriedHook(tickPlayer) == null)
				{
					ResetLocal((Character)(object)tickPlayer, Reason.Unsafe);
					return;
				}
			}
			if (_state == State.Inertia)
			{
				if (((Character)tickPlayer).IsOnGround() && !LateJumpOpen())
				{
					Reset(Reason.Ground);
					return;
				}
				if (Time.fixedTime >= _fallUntil && !LateJumpOpen() && HorizontalSpeed(((Character)tickPlayer).m_body.linearVelocity) <= ((Character)tickPlayer).m_runSpeed)
				{
					Reset(Reason.Stopped);
					return;
				}
				if (((Character)tickPlayer).m_rootMotion != Vector3.zero)
				{
					Reset(Reason.Impact);
					return;
				}
			}
			if (_state != State.Idle && !TryLimitVelocity(((Character)tickPlayer).m_body.linearVelocity, _tickSettings.MaxSpeed, out var _))
			{
				NumericReset();
			}
		}

		internal static bool BeforeWalking(Character character, out AirControlScope scope)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			scope = default(AirControlScope);
			if (!ActiveTick(character) || _abortQueued)
			{
				return true;
			}
			if (_state == State.Attached)
			{
				_walkingReplaced = true;
				character.m_body.useGravity = true;
				character.m_rootMotion = Vector3.zero;
				character.m_currentVel = Vector3.zero;
				character.m_lastPos = ((Component)character).transform.position;
				character.m_lazyPos = ((Component)character).transform.position;
				return false;
			}
			if (_state == State.Inertia)
			{
				scope = new AirControlScope
				{
					Changed = true,
					Original = character.m_airControl
				};
				character.m_airControl = 0f;
			}
			return true;
		}

		internal static void RestoreAirControl(Character character, AirControlScope scope)
		{
			if (scope.Changed && Object.op_Implicit((Object)(object)character))
			{
				character.m_airControl = scope.Original;
			}
		}

		private static void Detach(bool retainMomentum, Reason reason)
		{
			GrapplingPoint hook = _hook;
			RestoreHookPresentation();
			_breaking = true;
			try
			{
				if (Object.op_Implicit((Object)(object)hook) && Object.op_Implicit((Object)(object)hook.m_nview) && hook.m_nview.IsValid() && hook.m_nview.IsOwner() && Object.op_Implicit((Object)(object)hook.m_character))
				{
					hook.Break(true);
				}
			}
			finally
			{
				_breaking = false;
			}
			if (retainMomentum)
			{
				Transition(State.Inertia, reason);
				if (reason == Reason.Arrival && _groundedOnAttach && !_jumpUsed && Time.fixedTime <= _jumpUntil)
				{
					_lateJumpUntil = _jumpUntil;
				}
			}
			else
			{
				Reset(reason);
			}
		}

		internal static void ObserveBreak(GrapplingPoint hook)
		{
			if (!_breaking && (Object)(object)hook == (Object)(object)_hook)
			{
				Reset(Reason.HookLost);
			}
		}

		internal static void BeforeSync(Character character)
		{
			//IL_0050: 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)
			//IL_0073: 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_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_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_04f2: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: 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_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: 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_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: 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_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			if (!ActiveTick(character) || _state == State.Idle)
			{
				return;
			}
			Player tickPlayer = _tickPlayer;
			if (!Owns(tickPlayer))
			{
				Reset(Reason.Ownership);
				return;
			}
			if (_abortQueued || Unsafe(tickPlayer))
			{
				Detach(retainMomentum: false, _abortQueued ? _abortReason : Reason.Unsafe);
				return;
			}
			if (!TryLimitVelocity(((Character)tickPlayer).m_body.linearVelocity, _tickSettings.MaxSpeed, out var result))
			{
				NumericReset();
				return;
			}
			Vector3 val = Vector3.zero;
			bool flag = false;
			bool flag2 = false;
			bool trainJump = false;
			if (!((Character)tickPlayer).TakeInput())
			{
				_jumpRequested = false;
				_releaseRequested = false;
				_steer = Vector3.zero;
			}
			if (_state == State.Attached)
			{
				if (!Supported(_hook, tickPlayer) || AnchorLost())
				{
					Detach(retainMomentum: false, Reason.HookLost);
					return;
				}
				Vector3 val2 = ((Character)tickPlayer).m_body.position - ((Component)_hook).transform.position;
				float num = Length(val2);
				if (!Finite(val2) || !IsFinite(num))
				{
					NumericReset();
					return;
				}
				if (num > _hook.m_maxLength)
				{
					Detach(retainMomentum: false, Reason.HookLost);
					return;
				}
				_hook.m_time = Time.fixedTime - _attachedAt;
				_hook.m_lastDist = num;
				_hook.m_breakingTime = 0f;
				bool flag3 = ((Character)tickPlayer).IsOnGround();
				if (_initialPending)
				{
					if (Object.op_Implicit((Object)(object)_hook.m_anim))
					{
						_hook.m_anim.SetBool("repell", false);
						_hook.m_anim.SetBool("grappling", true);
					}
					Vector3 val3 = ((num > 0.0001f) ? (-val2 / num) : Vector3.zero);
					if (flag3 && val3.y < 0f)
					{
						val3.y = 0f;
						float num2 = Length(val3);
						if (num2 > 0.0001f)
						{
							val3 /= num2;
						}
					}
					result += val3 * _tickSettings.InitialImpulse;
					if (flag3 && !((Character)tickPlayer).IsEncumbered() && _tickSettings.GroundLift > 0f)
					{
						result.y = Math.Max(result.y, _tickSettings.GroundLift);
						flag = true;
					}
					_initialPending = false;
				}
				bool jumpRequested = _jumpRequested;
				_jumpRequested = false;
				if (jumpRequested && TryJump(tickPlayer, flag3, late: false, ref result, out trainJump))
				{
					flag = (flag2 = true);
				}
				bool flag4 = RopeActive(val2);
				if (_releaseRequested || num <= _hook.m_closeBreakDist)
				{
					Detach(retainMomentum: true, _releaseRequested ? Reason.Release : Reason.Arrival);
				}
				else if (!flag4 && PassedAnchor(val2, result, _approach, 0.5f))
				{
					Detach(retainMomentum: true, Reason.Arrival);
				}
				else
				{
					if (Time.fixedTime >= _pullAt)
					{
						float target = RampSpeed(Time.fixedTime - _pullAt, _rampSeconds, _tickSettings.InitialImpulse, _tickSettings.PullSpeed);
						float y = result.y;
						result = StepPull(result, val2 - Vector3.up * 0.6f, _steer, _look, target, _tickSettings.PullAcceleration, _tickSettings.AirAcceleration, _tickSettings.SwingPull, Time.fixedDeltaTime);
						if (!flag4 && y > 0f && result.y < y)
						{
							result.y = y;
						}
					}
					_ropeLength = Math.Min(_ropeLength, Math.Max(1f, num));
					if (flag4)
					{
						result = ConstrainRope(result, val2, _ropeLength);
						val = RopeCorrection(val2, _ropeLength, 0.05f);
					}
				}
			}
			if (_state == State.Inertia && _lateJumpUntil > 0f)
			{
				bool jumpRequested2 = _jumpRequested;
				_jumpRequested = false;
				if (jumpRequested2 && TryJump(tickPlayer, ((Character)tickPlayer).IsOnGround(), late: true, ref result, out trainJump))
				{
					flag = (flag2 = true);
				}
			}
			if (_state == State.Inertia)
			{
				result += _steer * (_tickSettings.AirAcceleration * Time.fixedDeltaTime);
			}
			if (_walkingReplaced)
			{
				((Character)tickPlayer).m_seman.ModifyWalkVelocity(ref result);
			}
			if (!TryLimitVelocity(result, _tickSettings.MaxSpeed, out result) || !Finite(val))
			{
				NumericReset();
				return;
			}
			if (flag)
			{
				((Character)tickPlayer).m_body.WakeUp();
				((Character)tickPlayer).ResetGroundContact();
				((Character)tickPlayer).m_lastGroundTouch = 1f;
				((Character)tickPlayer).m_jumpTimer = 0f;
				((Character)tickPlayer).UpdateBodyFriction();
			}
			((Character)tickPlayer).m_body.linearVelocity = result;
			float num3 = Length(val);
			if (num3 > 0.0001f)
			{
				Vector3 val4 = val / num3;
				RaycastHit val5 = default(RaycastHit);
				if (((Character)tickPlayer).m_body.SweepTest(val4, ref val5, num3 + 0.01f, (QueryTriggerInteraction)1))
				{
					num3 = Math.Max(0f, Math.Min(num3, ((RaycastHit)(ref val5)).distance - 0.01f));
				}
				if (num3 > 0.0001f)
				{
					Rigidbody body = ((Character)tickPlayer).m_body;
					body.position += val4 * num3;
				}
			}
			TraceSample(tickPlayer, result);
			if (flag2)
			{
				((Character)tickPlayer).m_zanim.SetTrigger("jump");
				((Character)tickPlayer).OnJump();
				if (trainJump)
				{
					((Character)tickPlayer).RaiseSkill((SkillType)100, 1f);
				}
			}
			if (_walkingReplaced)
			{
				float num4 = ((Character)tickPlayer).UpdateRotation(((Character)tickPlayer).m_turnSpeed, Time.fixedDeltaTime, false);
				((Character)tickPlayer).UpdateEyeRotation();
				((Character)tickPlayer).m_zanim.SetFloat(Character.s_forwardSpeed, 0f);
				((Character)tickPlayer).m_zanim.SetFloat(Character.s_sidewaySpeed, 0f);
				((Character)tickPlayer).m_zanim.SetFloat(Character.s_turnSpeed, num4);
				((Character)tickPlayer).m_zanim.SetBool(Character.s_onGround, ((Character)tickPlayer).IsOnGround());
				((Character)tickPlayer).m_zanim.SetBool(Character.s_inWater, false);
				((Character)tickPlayer).m_zanim.SetBool(Character.s_flying, false);
				((Character)tickPlayer).m_zanim.SetBool(Character.s_encumbered, ((Character)tickPlayer).IsEncumbered());
				((Character)tickPlayer).m_zanim.SetBool(Character.s_slipping, false);
				((Character)tickPlayer).m_zanim.SetBool(Character.s_skating, false);
				((Character)tickPlayer).m_zanim.SetBool(Character.s_skatgliding, false);
			}
		}

		private static bool LateJumpOpen()
		{
			if (_state == State.Inertia && _lateJumpUntil > 0f && !_jumpUsed)
			{
				if (!(Time.fixedTime <= _lateJumpUntil))
				{
					return _jumpRequested;
				}
				return true;
			}
			return false;
		}

		private static bool TryJump(Player player, bool grounded, bool late, ref Vector3 velocity, out bool trainJump)
		{
			//IL_0180: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			trainJump = false;
			bool flag = (late ? JumpEligible(used: false, grounded: false, groundedAtAttach: true, _jumpPressedAt, _lateJumpUntil) : JumpEligible(used: false, grounded, _groundedOnAttach, _jumpPressedAt, _jumpUntil));
			string text = (_jumpUsed ? "already used" : (((Character)player).IsEncumbered() ? "encumbered" : (((Character)player).InDodge() ? "dodging" : (flag ? null : (_groundedOnAttach ? "margin closed" : "air attachment")))));
			if (text != null)
			{
				Trace("jump rejected: " + text + " (pressed +" + (_jumpPressedAt - _attachedAt).ToString("0.00") + " s)");
				return false;
			}
			float skillFactor = ((Character)player).GetSkillFactor((SkillType)100);
			float num = (1f + skillFactor * 0.4f) * _tickSettings.JumpMultiplier;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(_steer.x * ((Character)player).m_jumpForceForward * num, ((Character)player).m_jumpForce * num, _steer.z * ((Character)player).m_jumpForceForward * num);
			float num2 = ((Character)player).m_jumpStaminaUsage * (1f - ((Character)player).GetEquipmentMovementModifier() + ((Character)player).GetEquipmentJumpStaminaModifier());
			((Character)player).m_seman.ModifyJumpStaminaUsage(num2, ref num2, true);
			num2 *= Game.m_moveStaminaRate;
			trainJump = ((Character)player).HaveStamina(num2);
			if (!trainJump)
			{
				val *= ((Character)player).m_jumpForceTiredFactor;
			}
			((Character)player).m_seman.ApplyStatusEffectJumpMods(ref val);
			velocity = AddJump(velocity, val);
			_jumpUsed = true;
			Trace("jump accepted" + (late ? " after arrival" : "") + ": pressed +" + (_jumpPressedAt - _attachedAt).ToString("0.00") + " s, jump.y " + val.y.ToString("0.0") + " m/s, vel " + Fmt(velocity) + (trainJump ? "" : " (tired)"));
			return true;
		}

		private static string Fmt(Vector3 v)
		{
			//IL_0010: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			return "(h " + Length(new Vector3(v.x, 0f, v.z)).ToString("0.0") + ", y " + v.y.ToString("0.0") + ")";
		}

		private static void Trace(string message)
		{
			if (Tracing)
			{
				Plugin.TransitionLog("[GrappleMomentum] trace +" + (Time.fixedTime - _attachedAt).ToString("0.00") + " s " + message);
			}
		}

		private static void TraceSample(Player player, Vector3 velocity)
		{
			//IL_0053: 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)
			if (Tracing && !(Time.fixedTime < _traceNext))
			{
				_traceNext = Time.fixedTime + 0.1f - 0.001f;
				Trace(_state.ToString() + " height " + (((Character)player).m_body.position.y - _attachY).ToString("0.00") + " m, vel " + Fmt(velocity) + ", ground " + ((Character)player).IsOnGround());
			}
		}

		private static void NumericReset()
		{
			if (_inTick && _state == State.Attached)
			{
				Detach(retainMomentum: false, Reason.Fault);
			}
			else
			{
				Reset(Reason.Fault);
			}
			if (!_numericErrorLogged)
			{
				_numericErrorLogged = true;
				Plugin.NumericFault();
			}
		}

		internal static void CaptureInput()
		{
			if (!Plugin.Operational || !Plugin.Cached.Enabled)
			{
				Reset(Reason.Disabled);
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Owns(localPlayer))
			{
				Reset(Reason.Ownership);
				return;
			}
			CaptureButtons(localPlayer, GrapplingPoint.m_localGrappler);
			TryOffhandFire(localPlayer);
		}

		private static void CaptureButtons(Player player, GrapplingPoint? hook)
		{
			//IL_0019: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_013d: 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_0113: 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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if (Time.inFixedTimeStep)
			{
				return;
			}
			if (Supported(hook, player))
			{
				Track(hook, player);
			}
			_look = ((Character)player).GetLookDir();
			_steer = Vector3.zero;
			if (!((Character)player).TakeInput())
			{
				return;
			}
			Vector2 joyLeftStick = ZInput.GetJoyLeftStick();
			float num = joyLeftStick.x + (ZInput.GetButton("Right") ? 1f : 0f) - (ZInput.GetButton("Left") ? 1f : 0f);
			float num2 = joyLeftStick.y + (ZInput.GetButton("Forward") ? 1f : 0f) - (ZInput.GetButton("Backward") ? 1f : 0f);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(_look.x, 0f, _look.z);
			float num3 = Length(val);
			if (num3 <= 0.0001f)
			{
				Vector3 forward = ((Component)player).transform.forward;
				((Vector3)(ref val))..ctor(forward.x, 0f, forward.z);
				num3 = Length(val);
			}
			if (num3 > 0.0001f)
			{
				val /= num3;
			}
			if (!TryLimitVelocity(val * num2 + new Vector3(val.z, 0f, 0f - val.x) * num, 1f, out _steer))
			{
				_steer = Vector3.zero;
			}
			bool flag = ZInput.GetButtonDown("Jump") || ZInput.GetButtonDown("JoyJump");
			bool flag2 = LateJumpOpen();
			if (!flag2 && (_state != State.Attached || (Object)(object)hook != (Object)(object)_hook))
			{
				if (flag && _lastJumpTraceFrame != Time.frameCount)
				{
					_lastJumpTraceFrame = Time.frameCount;
					if (Plugin.Cached.Debug)
					{
						Plugin.TransitionLog("[GrappleMomentum] trace jump pressed with no hook to jump from (" + _state.ToString() + ", last attach " + (Time.fixedTime - _attachedAt).ToString("0.00") + " s ago)");
					}
				}
			}
			else
			{
				if (!flag2 && (ZInput.GetButton("Block") || ZInput.GetButton("JoyBlock")))
				{
					_releaseRequested = true;
				}
				if (!_jumpRequested && flag)
				{
					_jumpRequested = true;
					_jumpPressedAt = Time.fixedTime;
				}
			}
		}

		internal static bool GrappleFrame(GrapplingPoint hook)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Operational || !Plugin.Cached.Enabled)
			{
				if ((Object)(object)hook == (Object)(object)_hook)
				{
					Reset(Reason.Disabled);
				}
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)hook.m_character != (Object)(object)localPlayer || (Object)(object)hook != (Object)(object)GrapplingPoint.m_localGrappler || !Owns(localPlayer) || !Supported(hook, localPlayer))
			{
				return true;
			}
			if (((Object)hook).GetInstanceID() == _ignoredHookId)
			{
				return true;
			}
			Track(hook, localPlayer);
			CaptureButtons(localPlayer, hook);
			if (Object.op_Implicit((Object)(object)hook.m_attachPoint))
			{
				hook.UpdateLinePosition();
			}
			localPlayer.m_grappling = 0.2f;
			if (!_colorRestored)
			{
				if (Time.fixedTime < _jumpUntil)
				{
					hook.m_lineRenderer.startColor = new Color(1f, 0.75f, 0.2f, 1f);
				}
				else
				{
					hook.m_lineRenderer.startColor = _savedTipColor;
					_colorRestored = true;
				}
			}
			return false;
		}

		internal static bool AllowVanillaJump(Character character)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (!Plugin.Operational || !Plugin.Cached.Enabled || (Object)(object)character != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			Player player = (Player)character;
			if (!Owns(player))
			{
				return true;
			}
			GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
			if (_state == State.Inertia && Object.op_Implicit((Object)(object)localGrappler) && ((Object)localGrappler).GetInstanceID() == _hookId)
			{
				return false;
			}
			if (LateJumpOpen())
			{
				return false;
			}
			if (Supported(localGrappler, player))
			{
				return ((Object)localGrappler).GetInstanceID() == _ignoredHookId;
			}
			return true;
		}

		internal static ImpactScope BeforeImpact(Projectile projectile)
		{
			if (!Plugin.Operational || !Plugin.Cached.Enabled || (Object)(object)projectile.m_owner != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return default(ImpactScope);
			}
			GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
			return new ImpactScope
			{
				Local = true,
				PreviousId = (Object.op_Implicit((Object)(object)localGrappler) ? ((Object)localGrappler).GetInstanceID() : 0)
			};
		}

		internal static void AfterImpact(Projectile projectile, GameObject? target, Collider? collider, ImpactScope impact)
		{
			if (impact.Local && Plugin.Operational && Plugin.Cached.Enabled)
			{
				Player localPlayer = Player.m_localPlayer;
				GrapplingPoint localGrappler = GrapplingPoint.m_localGrappler;
				if (Object.op_Implicit((Object)(object)localPlayer) && Owns(localPlayer) && !((Object)(object)projectile.m_owner != (Object)(object)localPlayer) && Supported(localGrappler, localPlayer) && ((Object)localGrappler).GetInstanceID() != impact.PreviousId)
				{
					Track(localGrappler, localPlayer);
					_anchor = target;
					_anchorCollider = collider;
					_hadAnchor = Object.op_Implicit((Object)(object)target);
					_hadCollider = Object.op_Implicit((Object)(object)collider);
				}
			}
		}

		internal static void AttackCost(Attack attack, ref float cost)
		{
			Plugin.Settings cached = Plugin.Cached;
			Player localPlayer = Player.m_localPlayer;
			if (Plugin.Operational && cached.Enabled && Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)attack.m_character == (Object)(object)localPlayer && Owns(localPlayer) && attack.m_weapon?.m_shared.m_name == "$item_graplinghook")
			{
				cost = cached.Stamina;
			}
		}

		internal static void FallDamage(SEMan effects, ref float damage)
		{
			if (_inTick && Object.op_Implicit((Object)(object)_tickPlayer) && (Object)(object)effects.m_character == (Object)(object)_tickPlayer && _tickSettings.FallGrace > 0f && _state == State.Inertia && Time.fixedTime < _fallUntil && Owns(_tickPlayer) && !Unsafe(_tickPlayer))
			{
				damage = 0f;
			}
		}

		private static ItemData? CarriedHook(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return null;
			}
			foreach (ItemData item in inventory.m_inventory)
			{
				if (IsHook(item))
				{
					return item;
				}
			}
			return null;
		}

		private static bool IsHook(ItemData? item)
		{
			if (item != null)
			{
				return item.m_shared.m_name == "$item_graplinghook";
			}
			return false;
		}

		internal static bool HookLoading(Player player, ItemData? weapon)
		{
			if (!Plugin.Operational || !Plugin.Cached.Enabled || (Object)(object)player != (Object)(object)Player.m_localPlayer || !IsHook(weapon) || !weapon.m_shared.m_attack.m_requiresReload || !Owns(player))
			{
				return true;
			}
			if (player.m_weaponLoaded == weapon)
			{
				_reloadPending = false;
				return false;
			}
			player.CancelReloadAction();
			if (!_reloadPending)
			{
				_reloadPending = true;
				_lastShotAt = Math.Max(_lastShotAt, Time.time);
			}
			if (Time.time >= _lastShotAt + Plugin.Cached.Cooldown)
			{
				player.SetWeaponLoaded(weapon);
				_reloadPending = false;
			}
			return false;
		}

		private static void TryOffhandFire(Player player)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_006d: Invalid comparison between Unknown and I4
			KeyCode offhandKey = Plugin.Cached.OffhandKey;
			if (Time.inFixedTimeStep || (int)offhandKey == 0 || !ZInput.GetKeyDown(offhandKey, false) || !((Character)player).TakeInput() || ((Character)player).InPlaceMode() || Unsafe(player) || Time.time < _lastShotAt + Plugin.Cached.Cooldown)
			{
				return;
			}
			ItemData val = CarriedHook(player);
			if (val == null)
			{
				return;
			}
			Attack attack = val.m_shared.m_attack;
			if ((int)attack.m_attackType != 2 || !Object.op_Implicit((Object)(object)attack.m_attackProjectile))
			{
				return;
			}
			Attack val2 = attack.Clone();
			val2.m_character = (Humanoid)(object)player;
			val2.m_baseAI = null;
			val2.m_body = ((Character)player).m_body;
			val2.m_zanim = ((Character)player).m_zanim;
			val2.m_animEvent = ((Character)player).m_animEvent;
			val2.m_visEquipment = ((Humanoid)player).m_visEquipment;
			val2.m_weapon = val;
			val2.m_attackDrawPercentage = 0f;
			if (!attack.m_perBurstResourceUsage)
			{
				float attackStamina = val2.GetAttackStamina();
				if (attackStamina > 0f && !((Character)player).HaveStamina(attackStamina + 0.1f))
				{
					if (Object.op_Implicit((Object)(object)Hud.instance))
					{
						Hud.instance.StaminaBarEmptyFlash();
					}
					return;
				}
				if (attackStamina > 0f)
				{
					((Character)player).UseStamina(attackStamina);
				}
			}
			_lastShotAt = Time.time;
			val2.FireProjectileBurst();
			if (((Humanoid)player).GetCurrentWeapon() == val)
			{
				((Humanoid)player).ResetLoadedWeapon();
			}
		}

		internal static void UpdateDot(Hud hud, Player player)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = null;
			if (Plugin.Operational && Plugin.Cached.Enabled && Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer && Object.op_Implicit((Object)(object)hud.m_crosshair))
			{
				val = CarriedHook(player);
			}
			if (val == null)
			{
				if (Object.op_Implicit((Object)(object)_dot))
				{
					((Component)_dot).gameObject.SetActive(false);
				}
				return;
			}
			Image val2 = EnsureDot(hud.m_crosshair);
			if (!((Component)val2).gameObject.activeSelf)
			{
				((Component)val2).gameObject.SetActive(true);
			}
			((Graphic)val2).color = (HookInRange(player, val) ? DotInRange : DotOutOfRange);
		}

		internal static void DestroyDot()
		{
			if (Object.op_Implicit((Object)(object)_dot))
			{
				Object.Destroy((Object)(object)((Component)_dot).gameObject);
			}
			_dot = null;
		}

		private static Image EnsureDot(Image crosshair)
		{
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_015b: 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_0163: 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_016b: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_00eb: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_dot) && (Object)(object)((Component)_dot).transform.parent == (Object)(object)((Component)crosshair).transform)
			{
				return _dot;
			}
			DestroyDot();
			if (!Object.op_Implicit((Object)(object)_dotSprite))
			{
				Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false)
				{
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1
				};
				for (int i = 0; i < 16; i++)
				{
					for (int j = 0; j < 16; j++)
					{
						float num = (float)j + 0.5f - 8f;
						float num2 = (float)i + 0.5f - 8f;
						float num3 = Clamp01(8f - (float)Math.Sqrt(num * num + num2 * num2));
						val.SetPixel(j, i, new Color(1f, 1f, 1f, num3));
					}
				}
				val.Apply();
				_dotSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f));
			}
			GameObject val2 = new GameObject("GrappleMomentumDot", new Type[1] { typeof(RectTransform) });
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent(((Component)crosshair).transform, false);
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0.5f, 0.5f);
			val3.pivot = val4;
			Vector2 anchorMin = (val3.anchorMax = val4);
			val3.anchorMin = anchorMin;
			val3.anchoredPosition = Vector2.zero;
			val3.sizeDelta = new Vector2(4f, 4f);
			_dot = val2.AddComponent<Image>();
			_dot.sprite = _dotSprite;
			((Graphic)_dot).raycastTarget = false;
			return _dot;
		}

		private static bool HookInRange(Player player, ItemData item)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: 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_026b: 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_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			Attack attack = item.m_shared.m_attack;
			GameObject attackProjectile = attack.m_attackProjectile;
			Projectile val = (Object.op_Implicit((Object)(object)attackProjectile) ? attackProjectile.GetComponent<Projectile>() : null);
			GrapplingPoint val2 = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.m_spawnOnHit)) ? val.m_spawnOnHit.GetComponent<GrapplingPoint>() : null);
			if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)((Character)player).m_body))
			{
				return false;
			}
			if (_dotMask == 0)
			{
				_dotMask = LayerMask.GetMask(new string[12]
				{
					"Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox",
					"character_noenv", "vehicle"
				});
			}
			Transform transform = ((Component)player).transform;
			Transform val3 = ((attack.m_attackOriginJoint.Length > 0 && Object.op_Implicit((Object)(object)((Character)player).GetVisual())) ? Utils.FindChild(((Character)player).GetVisual().transform, attack.m_attackOriginJoint, (IterativeSearchType)0) : null);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				val3 = transform;
			}
			Vector3 val4 = val3.position + transform.up * attack.m_attackHeight + transform.forward * attack.m_attackRange + transform.right * attack.m_attackOffset;
			Vector3 val5 = ((Humanoid)player).GetAimDir(val4);
			if (attack.m_launchAngle != 0f)
			{
				val5 = Quaternion.AngleAxis(attack.m_launchAngle, Vector3.Cross(Vector3.up, val5)) * val5;
			}
			Vector3 val6 = val5 * attack.m_projectileVel;
			Vector3 position = ((Character)player).m_body.position;
			float maxLength = val2.m_maxLength;
			float num = Math.Max(0.005f, Time.fixedDeltaTime);
			for (float num2 = 0f; num2 < val.m_ttl; num2 += num)
			{
				val6 += Vector3.down * (val.m_gravity * num);
				float num3 = Length(val6);
				if (num3 > 0.0001f)
				{
					val6 -= val6 / num3 * (num3 * num3 * val.m_drag * num);
				}
				Vector3 val7 = val6 * num;
				float num4 = Length(val7);
				if (!Finite(val7) || num4 <= 0.0001f)
				{
					return false;
				}
				int num5 = Physics.RaycastNonAlloc(val4, val7 / num4, DotHits, num4, _dotMask);
				RaycastHit? val8 = null;
				RaycastHit value;
				for (int i = 0; i < num5; i++)
				{
					Collider collider = ((RaycastHit)(ref DotHits[i])).collider;
					if (!Object.op_Implicit((Object)(object)collider) || (Object)(object)((Component)collider).GetComponentInParent<Character>() == (Object)(object)player)
					{
						continue;
					}
					if (val8.HasValue)
					{
						float distance = ((RaycastHit)(ref DotHits[i])).distance;
						value = val8.Value;
						if (!(distance < ((RaycastHit)(ref value)).distance))
						{
							continue;
						}
					}
					val8 = DotHits[i];
				}
				if (val8.HasValue)
				{
					value = val8.Value;
					GameObject val9 = Projectile.FindHitObject(((RaycastHit)(ref value)).collider);
					if (val2.CanAttach(val9))
					{
						value = val8.Value;
						return Length(((RaycastHit)(ref value)).point - position) <= maxLength;
					}
					return false;
				}
				val4 += val7;
				if (Length(val4 - position) > maxLength)
				{
					return false;
				}
			}
			return false;
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(Character), "CustomFixedUpdate", new Type[] { typeof(float) })]
		private static class Tick
		{
			private static void Prefix(Character __instance)
			{
				GrappleController.BeginTick(__instance);
			}

			private static Exception? Finalizer(Character __instance, Exception? __exception)
			{
				return GrappleController.EndTick(__instance, __exception);
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateMotion", new Type[] { typeof(float) })]
		private static class Motion
		{
			private static void Prefix(Character __instance)
			{
				GrappleController.PrepareMotion(__instance);
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateWalking", new Type[] { typeof(float) })]
		private static class Walking
		{
			private static bool Prefix(Character __instance, out GrappleController.AirControlScope __state)
			{
				return GrappleController.BeforeWalking(__instance, out __state);
			}

			private static Exception? Finalizer(Character __instance, GrappleController.AirControlScope __state, Exception? __exception)
			{
				GrappleController.RestoreAirControl(__instance, __state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(Character), "SyncVelocity", new Type[] { })]
		private static class Sync
		{
			private static void Prefix(Character __instance)
			{
				GrappleController.BeforeSync(__instance);
			}
		}

		[HarmonyPatch(typeof(ZInput), "Update", new Type[] { typeof(float) })]
		private static class Input
		{
			private static void Postfix()
			{
				GrappleController.CaptureInput();
			}
		}

		[HarmonyPatch(typeof(GrapplingPoint), "Update", new Type[] { })]
		private static class GrappleInput
		{
			private static bool Prefix(GrapplingPoint __instance)
			{
				return GrappleController.GrappleFrame(__instance);
			}
		}

		[HarmonyPatch(typeof(GrapplingPoint), "Break", new Type[] { typeof(bool) })]
		private static class Break
		{
			private static void Prefix(GrapplingPoint __instance)
			{
				GrappleController.ObserveBreak(__instance);
			}
		}

		[HarmonyPatch(typeof(Projectile), "SpawnOnHit", new Type[]
		{
			typeof(GameObject),
			typeof(Collider),
			typeof(Vector3)
		})]
		private static class Impact
		{
			private static void Prefix(Projectile __instance, out GrappleController.ImpactScope __state)
			{
				__state = GrappleController.BeforeImpact(__instance);
			}

			private static void Postfix(Projectile __instance, GameObject go, Collider collider, GrappleController.ImpactScope __state)
			{
				GrappleController.AfterImpact(__instance, go, collider, __state);
			}
		}

		[HarmonyPatch(typeof(Player), "OnDeath", new Type[] { })]
		private static class Death
		{
			private static void Prefix(Player __instance)
			{
				GrappleController.ResetLocal((Character)(object)__instance, GrappleController.Reason.Death);
			}
		}

		[HarmonyPatch(typeof(Player), "TeleportTo", new Type[]
		{
			typeof(Vector3),
			typeof(Quaternion),
			typeof(bool)
		})]
		private static class Teleport
		{
			private static void Postfix(Player __instance, bool __result)
			{
				if (__result)
				{
					GrappleController.ResetLocal((Character)(object)__instance, GrappleController.Reason.Teleport);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "OnDestroy", new Type[] { })]
		private static class Destroy
		{
			private static void Prefix(Player __instance)
			{
				GrappleController.ResetLocal((Character)(object)__instance, GrappleController.Reason.Destroyed);
			}
		}

		[HarmonyPatch(typeof(Game), "Logout", new Type[]
		{
			typeof(bool),
			typeof(bool)
		})]
		private static class Logout
		{
			private static void Prefix()
			{
				GrappleController.Reset(GrappleController.Reason.Scene);
			}
		}

		[HarmonyPatch(typeof(Character), "GetStandingOnShip", new Type[] { })]
		private static class Ship
		{
			private static void Postfix(Character __instance, Ship __result)
			{
				if (Object.op_Implicit((Object)(object)__result))
				{
					GrappleController.ResetLocal(__instance, GrappleController.Reason.Ship);
				}
			}
		}

		[HarmonyPatch(typeof(Character), "UnderWorldCheck", new Type[] { typeof(float) })]
		private static class Rescue
		{
			private static void Prefix(Character __instance, out Vector3 __state)
			{
				//IL_001f: 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_0016: 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)
				__state = (Vector3)(((Object)(object)__instance == (Object)(object)Player.m_localPlayer) ? ((Component)__instance).transform.position : default(Vector3));
			}

			private static void Postfix(Character __instance, Vector3 __state)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ((Component)__instance).transform.position != __state)
				{
					GrappleController.ResetLocal(__instance, GrappleController.Reason.Rescue);
				}
			}
		}

		[HarmonyPatch(typeof(Character), "Jump", new Type[] { typeof(bool) })]
		private static class Jump
		{
			private static bool Prefix(Character __instance)
			{
				return GrappleController.AllowVanillaJump(__instance);
			}
		}

		[HarmonyPatch(typeof(Attack), "GetAttackStamina", new Type[] { })]
		private static class Stamina
		{
			private static void Postfix(Attack __instance, ref float __result)
			{
				GrappleController.AttackCost(__instance, ref __result);
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static class FallDamage
		{
			private static void Postfix(SEMan __instance, ref float damage)
			{
				GrappleController.FallDamage(__instance, ref damage);
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateWeaponLoading", new Type[]
		{
			typeof(ItemData),
			typeof(float)
		})]
		private static class WeaponLoading
		{
			private static bool Prefix(Player __instance, ItemData weapon)
			{
				return GrappleController.HookLoading(__instance, weapon);
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateCrosshair", new Type[]
		{
			typeof(Player),
			typeof(float)
		})]
		private static class Crosshair
		{
			private static void Postfix(Hud __instance, Player player)
			{
				GrappleController.UpdateDot(__instance, player);
			}
		}

		internal static void Install(Harmony harmony, ManualLogSource log)
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			Type[] array = new Type[19]
			{
				typeof(Tick),
				typeof(Motion),
				typeof(Walking),
				typeof(Sync),
				typeof(Input),
				typeof(GrappleInput),
				typeof(Break),
				typeof(Impact),
				typeof(Death),
				typeof(Teleport),
				typeof(Destroy),
				typeof(Logout),
				typeof(Ship),
				typeof(Rescue),
				typeof(Jump),
				typeof(Stamina),
				typeof(FallDamage),
				typeof(WeaponLoading),
				typeof(Crosshair)
			};
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				HarmonyMethod info = ((HarmonyAttribute)(HarmonyPatch)Attribute.GetCustomAttribute(type, typeof(HarmonyPatch))).info;
				MethodInfo methodInfo = AccessTools.DeclaredMethod(info.declaringType, info.methodName, info.argumentTypes, (Type[])null) ?? throw new MissingMethodException(info.declaringType.FullName, info.methodName);
				Type type2 = ((type == typeof(Teleport)) ? typeof(bool) : ((type == typeof(Ship)) ? typeof(Ship) : ((type == typeof(Stamina)) ? typeof(float) : typeof(void))));
				if (methodInfo.ReturnType != type2)
				{
					throw new MissingMethodException("Unexpected return type: " + methodInfo);
				}
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
				if (patchInfo == null)
				{
					continue;
				}
				foreach (string owner in patchInfo.Owners)
				{
					if (owner != "dugi.GrappleMomentum")
					{
						log.LogWarning((object)("[GrappleMomentum] Shared target " + methodInfo.DeclaringType.Name + "." + methodInfo.Name + ": " + owner));
					}
				}
			}
			RequireField(typeof(Character), "m_body", typeof(Rigidbody));
			RequireField(typeof(Character), "m_nview", typeof(ZNetView));
			RequireField(typeof(Character), "m_airControl", typeof(float));
			RequireField(typeof(Character), "m_rootMotion", typeof(Vector3));
			RequireField(typeof(GrapplingPoint), "m_character", typeof(Character));
			RequireField(typeof(GrapplingPoint), "m_nview", typeof(ZNetView));
			RequireField(typeof(GrapplingPoint), "m_lineRenderer", typeof(LineRenderer));
			RequireField(typeof(GrapplingPoint), "Method", typeof(GrapplingMethod));
			RequireField(typeof(GrapplingPoint), "m_localGrappler", typeof(GrapplingPoint));
			RequireField(typeof(Projectile), "m_owner", typeof(Character));
			RequireField(typeof(Attack), "m_character", typeof(Humanoid));
			RequireField(typeof(Attack), "m_weapon", typeof(ItemData));
			RequireField(typeof(SEMan), "m_character", typeof(Character));
			RequireField(typeof(GrapplingPoint), "m_se", typeof(SE_Stats));
			RequireField(typeof(GrapplingPoint), "m_equipCheck", typeof(ItemDrop));
			RequireField(typeof(GrapplingPoint), "m_secondary", typeof(bool));
			RequireField(typeof(Character), "m_lastGroundTouch", typeof(float));
			RequireField(typeof(Character), "m_jumpTimer", typeof(float));
			RequireField(typeof(Player), "m_weaponLoaded", typeof(ItemData));
			RequireField(typeof(Hud), "m_crosshair", typeof(Image));
			array2 = array;
			foreach (Type type3 in array2)
			{
				harmony.CreateClassProcessor(type3).Patch();
			}
		}

		private static void RequireField(Type type, string name, Type fieldType)
		{
			if ((AccessTools.Field(type, name) ?? throw new MissingFieldException(type.FullName, name)).FieldType != fieldType)
			{
				throw new MissingFieldException("Unexpected field type: " + type.Name + "." + name);
			}
		}
	}
	internal static class PluginVersion
	{
		internal const string Value = "0.3.2";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}