Decompiled source of Titanfall2 Movement v1.0.1

NotGodlike.TitanfallMovement.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("NotGodlike")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Titanfall 2 inspired momentum, slides, double jumps, crouching and wall running for H3VR.")]
[assembly: AssemblyFileVersion("1.8.7.0")]
[assembly: AssemblyInformationalVersion("1.8.7")]
[assembly: AssemblyProduct("NotGodlike.TitanfallMovement")]
[assembly: AssemblyTitle("Titanfall Movement")]
[assembly: AssemblyVersion("1.8.7.0")]
namespace NotGodlike.TitanfallMovement;

internal sealed class MovementAudio : MonoBehaviour
{
	private readonly List<AudioClip> _jumpClips = new List<AudioClip>();

	private readonly List<AudioClip> _doubleJumpClips = new List<AudioClip>();

	private readonly List<AudioClip> _wallRunClips = new List<AudioClip>();

	private readonly List<AudioClip> _slideClips = new List<AudioClip>();

	private TitanfallMovementPlugin _plugin;

	private AudioSource _jumpSource;

	private AudioSource _doubleJumpSource;

	private AudioSource _wallRunSource;

	private AudioSource _slideSource;

	private int _lastJumpIndex = -1;

	private int _lastDoubleJumpIndex = -1;

	private int _lastWallRunIndex = -1;

	private int _lastSlideIndex = -1;

	private bool _slideFading;

	private float _slideFadeStartVolume;

	private float _slideFadeElapsed;

	private bool _doubleJumpFading;

	private float _doubleJumpFadeStartVolume;

	private float _doubleJumpFadeElapsed;

	private const float SlideFadeDuration = 0.24f;

	private const float DoubleJumpFadeDuration = 0.2f;

	internal void Initialize(TitanfallMovementPlugin plugin)
	{
		_plugin = plugin;
		_jumpSource = CreateNonSpatialSource(loop: false);
		_doubleJumpSource = CreateNonSpatialSource(loop: false);
		_wallRunSource = CreateNonSpatialSource(loop: true);
		_slideSource = CreateNonSpatialSource(loop: true);
		((MonoBehaviour)this).StartCoroutine(LoadAllClips());
	}

	internal void PlayJump()
	{
		PlayRandom(_jumpSource, _jumpClips, ref _lastJumpIndex);
	}

	internal void PlayDoubleJump()
	{
		StopDoubleJumpImmediate();
		PlayRandom(_doubleJumpSource, _doubleJumpClips, ref _lastDoubleJumpIndex);
	}

	internal void FadeOutDoubleJump()
	{
		if (!((Object)(object)_doubleJumpSource == (Object)null) && _doubleJumpSource.isPlaying && !_doubleJumpFading)
		{
			_doubleJumpFading = true;
			_doubleJumpFadeStartVolume = _doubleJumpSource.volume;
			_doubleJumpFadeElapsed = 0f;
		}
	}

	internal void StartWallRun()
	{
		if (_wallRunClips.Count != 0 && !_wallRunSource.isPlaying)
		{
			int index = PickRandomIndex(_wallRunClips.Count, ref _lastWallRunIndex);
			_wallRunSource.clip = _wallRunClips[index];
			_wallRunSource.volume = Mathf.Clamp01(_plugin.SoundVolume.Value);
			_wallRunSource.Play();
		}
	}

	internal void StopWallRun()
	{
		if ((Object)(object)_wallRunSource != (Object)null && _wallRunSource.isPlaying)
		{
			_wallRunSource.Stop();
		}
	}

	internal void StartSlide()
	{
		if (_slideClips.Count != 0)
		{
			StopSlideImmediate();
			int index = PickRandomIndex(_slideClips.Count, ref _lastSlideIndex);
			_slideSource.clip = _slideClips[index];
			_slideSource.volume = Mathf.Clamp01(_plugin.SoundVolume.Value);
			_slideSource.Play();
		}
	}

	internal void StopSlide()
	{
		if (!((Object)(object)_slideSource == (Object)null) && _slideSource.isPlaying && !_slideFading)
		{
			_slideFading = true;
			_slideFadeStartVolume = _slideSource.volume;
			_slideFadeElapsed = 0f;
		}
	}

	internal void StopAllMovementSounds()
	{
		if ((Object)(object)_jumpSource != (Object)null)
		{
			_jumpSource.Stop();
		}
		StopDoubleJumpImmediate();
		if ((Object)(object)_wallRunSource != (Object)null)
		{
			_wallRunSource.Stop();
			_wallRunSource.clip = null;
		}
		StopSlideImmediate();
	}

	private void Update()
	{
		if (_slideFading && (Object)(object)_slideSource != (Object)null)
		{
			_slideFadeElapsed += Time.deltaTime;
			float num = 1f - Mathf.Clamp01(_slideFadeElapsed / 0.24f);
			_slideSource.volume = _slideFadeStartVolume * num;
			if (num <= 0f)
			{
				StopSlideImmediate();
			}
		}
		if (_doubleJumpFading && (Object)(object)_doubleJumpSource != (Object)null)
		{
			_doubleJumpFadeElapsed += Time.deltaTime;
			float num2 = 1f - Mathf.Clamp01(_doubleJumpFadeElapsed / 0.2f);
			_doubleJumpSource.volume = _doubleJumpFadeStartVolume * num2;
			if (num2 <= 0f)
			{
				StopDoubleJumpImmediate();
			}
		}
	}

	private void StopSlideImmediate()
	{
		_slideFading = false;
		_slideFadeElapsed = 0f;
		if ((Object)(object)_slideSource != (Object)null)
		{
			_slideSource.Stop();
			_slideSource.clip = null;
		}
	}

	private void StopDoubleJumpImmediate()
	{
		_doubleJumpFading = false;
		_doubleJumpFadeElapsed = 0f;
		if ((Object)(object)_doubleJumpSource != (Object)null)
		{
			_doubleJumpSource.Stop();
			_doubleJumpSource.clip = null;
		}
	}

	private AudioSource CreateNonSpatialSource(bool loop)
	{
		AudioSource obj = ((Component)this).gameObject.AddComponent<AudioSource>();
		obj.playOnAwake = false;
		obj.loop = loop;
		obj.spatialBlend = 0f;
		return obj;
	}

	private void PlayRandom(AudioSource source, List<AudioClip> clips, ref int lastIndex)
	{
		if (!((Object)(object)source == (Object)null) && clips.Count != 0)
		{
			int index = PickRandomIndex(clips.Count, ref lastIndex);
			source.clip = clips[index];
			source.volume = Mathf.Clamp01(_plugin.SoundVolume.Value);
			source.Play();
		}
	}

	private static int PickRandomIndex(int count, ref int lastIndex)
	{
		if (count <= 1)
		{
			lastIndex = 0;
			return 0;
		}
		if (lastIndex < 0 || lastIndex >= count)
		{
			lastIndex = Random.Range(0, count);
			return lastIndex;
		}
		int num = Random.Range(0, count - 1);
		if (num >= lastIndex)
		{
			num++;
		}
		lastIndex = num;
		return num;
	}

	private IEnumerator LoadAllClips()
	{
		string directoryName = Path.GetDirectoryName(typeof(TitanfallMovementPlugin).Assembly.Location);
		string soundDirectory = Path.Combine(directoryName, "jump sounds");
		if (!Directory.Exists(soundDirectory))
		{
			soundDirectory = directoryName;
		}
		string[] fileNames = new string[3] { "jump1.wav", "jump2.wav", "jump3.wav" };
		string[] doubleJumpFiles = new string[3] { "doublejump1.wav", "doublejump2.wav", "doublejump3.wav" };
		string[] wallRunFiles = new string[3] { "wallrun1.wav", "wallrun2.wav", "wallrun3.wav" };
		string[] slideFiles = new string[3] { "slide.wav", "slide2.wav", "slide3.wav" };
		yield return ((MonoBehaviour)this).StartCoroutine(LoadGroup(soundDirectory, fileNames, (AudioType)20, _jumpClips));
		yield return ((MonoBehaviour)this).StartCoroutine(LoadGroup(soundDirectory, doubleJumpFiles, (AudioType)20, _doubleJumpClips));
		yield return ((MonoBehaviour)this).StartCoroutine(LoadGroup(soundDirectory, wallRunFiles, (AudioType)20, _wallRunClips));
		yield return ((MonoBehaviour)this).StartCoroutine(LoadGroup(soundDirectory, slideFiles, (AudioType)20, _slideClips));
		TitanfallMovementPlugin.Logger.LogInfo((object)$"Movement audio loaded: {_jumpClips.Count} jump, {_doubleJumpClips.Count} double-jump, {_wallRunClips.Count} wall-run, {_slideClips.Count} slide clips.");
	}

	private IEnumerator LoadGroup(string directory, string[] fileNames, AudioType audioType, List<AudioClip> destination)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < fileNames.Length; i++)
		{
			string text = Path.Combine(directory, fileNames[i]);
			if (!File.Exists(text))
			{
				TitanfallMovementPlugin.Logger.LogWarning((object)("Missing movement sound: " + text));
				continue;
			}
			string absoluteUri = new Uri(text).AbsoluteUri;
			WWW request = new WWW(absoluteUri);
			try
			{
				yield return request;
				if (!string.IsNullOrEmpty(request.error))
				{
					TitanfallMovementPlugin.Logger.LogWarning((object)("Could not load " + fileNames[i] + ": " + request.error));
					continue;
				}
				AudioClip audioClip = WWWAudioExtensions.GetAudioClip(request, false, false, audioType);
				if ((Object)(object)audioClip != (Object)null)
				{
					((Object)audioClip).name = Path.GetFileNameWithoutExtension(fileNames[i]);
					destination.Add(audioClip);
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}
	}
}
internal sealed class PlayerFootstepsBridge
{
	private const string PluginGuid = "h3vr.kodeman.playerfootsteps";

	private readonly object[] _playArguments = new object[2];

	private object _instance;

	private MethodInfo _playFootstepMethod;

	private FieldInfo _initializedField;

	private bool _resolutionAttempted;

	private bool _disabledAfterFailure;

	internal bool PlayWallRunStep(BulletImpactSoundType surface, bool useGenericFallback)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		if (_disabledAfterFailure || (!Resolve() && _instance == null))
		{
			return false;
		}
		if ((object)_initializedField != null && !(bool)_initializedField.GetValue(_instance))
		{
			return false;
		}
		try
		{
			_playArguments[0] = surface;
			_playArguments[1] = useGenericFallback;
			_playFootstepMethod.Invoke(_instance, _playArguments);
			return true;
		}
		catch (Exception ex)
		{
			_disabledAfterFailure = true;
			TitanfallMovementPlugin.Logger.LogWarning((object)("Player Footsteps wall-run integration disabled after an invocation failure: " + ex));
			return false;
		}
	}

	private bool Resolve()
	{
		if (_instance != null && (object)_playFootstepMethod != null)
		{
			return true;
		}
		if (_resolutionAttempted)
		{
			return false;
		}
		_resolutionAttempted = true;
		if (!Chainloader.PluginInfos.TryGetValue("h3vr.kodeman.playerfootsteps", out var value) || (Object)(object)value.Instance == (Object)null)
		{
			TitanfallMovementPlugin.Logger.LogInfo((object)"Player Footsteps is not installed; wall-run footstep integration will remain inactive.");
			return false;
		}
		Type type = ((object)value.Instance).GetType();
		_playFootstepMethod = type.GetMethod("PlayFootstepSound", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2]
		{
			typeof(BulletImpactSoundType),
			typeof(bool)
		}, null);
		_initializedField = type.GetField("_initialized", BindingFlags.Instance | BindingFlags.NonPublic);
		if ((object)_playFootstepMethod == null)
		{
			TitanfallMovementPlugin.Logger.LogWarning((object)"Player Footsteps was found, but its compatible PlayFootstepSound method was not available.");
			return false;
		}
		_instance = value.Instance;
		TitanfallMovementPlugin.Logger.LogInfo((object)"Player Footsteps wall-run integration enabled; installed sound-pack replacements will be used.");
		return true;
	}
}
internal sealed class TitanfallMovementController : IDisposable
{
	private readonly TitanfallMovementPlugin _plugin;

	private readonly MovementAudio _audio;

	private readonly PlayerFootstepsBridge _playerFootsteps;

	private readonly TransformVelocity _velocityFilter;

	private FVRMovementManager _manager;

	private Vector3 _horizontalMomentum;

	private float _verticalVelocity;

	private bool _lastGrounded = true;

	private bool _jumpQueued;

	private bool _crouchQueued;

	private bool _crouched;

	private bool _sliding;

	private float _slideTime;

	private float _slideDuration;

	private Vector3 _slideDirection;

	private float _slideCooldownRemaining;

	private float _lastSlideEndTime = -10f;

	private int _airJumpsRemaining = 1;

	private bool _jumpedSinceGrounded;

	private bool _sprinting;

	private Vector3 _rawMoveDirection;

	private float _rawMoveAmount;

	private bool _landingSlideHeld;

	private bool _wallRunning;

	private Vector3 _wallNormal;

	private Vector3 _wallDirection;

	private Collider _currentWallCollider;

	private Collider _blockedWallCollider;

	private float _wallRunCameraSide;

	private float _wallRunTime;

	private float _wallRunDuration;

	private float _wallRunDistance;

	private float _wallRunDistanceLimit;

	private float _wallRunCooldown;

	private float _wallRunFootstepDistance;

	private bool _crouchPressedLastFrame;

	private float _crouchOffset;

	private float _appliedCrouchOffset;

	private float _lastVelocityTickTime = -10f;

	internal bool IsWallRunning
	{
		get
		{
			if (_wallRunning)
			{
				return _plugin.Enabled.Value;
			}
			return false;
		}
	}

	internal float WallRunCameraSide
	{
		get
		{
			//IL_003a: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!_wallRunning || (Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
			{
				return 0f;
			}
			Vector3 forward = _manager.Head.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				return _wallRunCameraSide;
			}
			Vector3 val = Vector3.Cross(Vector3.up, ((Vector3)(ref forward)).normalized);
			Vector3 val2 = -_wallNormal;
			val2.y = 0f;
			float num = Vector3.Dot(((Vector3)(ref val2)).normalized, val);
			if (num > 0.08f)
			{
				return -1f;
			}
			if (num < -0.08f)
			{
				return 1f;
			}
			return _wallRunCameraSide;
		}
	}

	internal TitanfallMovementController(TitanfallMovementPlugin plugin, MovementAudio audio, PlayerFootstepsBridge playerFootsteps)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		_plugin = plugin;
		_audio = audio;
		_playerFootsteps = playerFootsteps;
		_velocityFilter = new TransformVelocity(ModifyVelocity);
	}

	internal bool IsBoundTo(FVRMovementManager manager)
	{
		if ((Object)(object)manager != (Object)null && (Object)(object)manager == (Object)(object)_manager)
		{
			return IsSupportedMode(manager);
		}
		return false;
	}

	internal void Update()
	{
		BindCurrentManager();
		if (!_plugin.Enabled.Value || !((Object)(object)_manager != (Object)null) || !IsSupportedMode(_manager))
		{
			StopTransientState();
			UpdateCrouchOffset(lowered: false);
			return;
		}
		FVRViveHand hand = FindActionHand(_manager);
		FVRViveHand hand2 = FindRightHand(_manager);
		FVRViveHand hand3 = FindLeftHand(_manager);
		FVRViveHand hand4 = FindMovementHand(_manager);
		bool flag = ReadStickClickDown(hand2);
		bool flag2 = ReadStickClickDown(hand3);
		bool flag3 = ReadSouthPressed(hand);
		bool flag4 = ReadSouthPressed(hand2);
		ReadRawMovement(hand4, out _rawMoveDirection, out _rawMoveAmount);
		_landingSlideHeld = !_lastGrounded && flag4;
		if (flag)
		{
			_jumpQueued = true;
		}
		if (flag2)
		{
			_sprinting = !_sprinting;
		}
		if (flag3 && !_crouchPressedLastFrame)
		{
			_crouchQueued = true;
		}
		_crouchPressedLastFrame = flag3;
		UpdateCrouchOffset(_crouched || _sliding);
	}

	internal void BeforeMovementTick(FVRMovementManager manager)
	{
		//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_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)
		if (!((Object)(object)manager != (Object)(object)_manager) && !(_appliedCrouchOffset <= 0f))
		{
			Transform transform = ((Component)manager).transform;
			transform.position += Vector3.up * _appliedCrouchOffset;
			_appliedCrouchOffset = 0f;
		}
	}

	internal void AfterMovementTick(FVRMovementManager manager)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)manager != (Object)(object)_manager) && _plugin.Enabled.Value && IsSupportedMode(manager) && !(_crouchOffset <= 0f))
		{
			Transform transform = ((Component)manager).transform;
			transform.position -= Vector3.up * _crouchOffset;
			_appliedCrouchOffset = _crouchOffset;
			if ((Object)(object)manager.Body != (Object)null)
			{
				manager.Body.UpdatePlayerBodyPositions();
			}
		}
	}

	public void Dispose()
	{
		UnbindManager();
		_audio.StopAllMovementSounds();
	}

	private void BindCurrentManager()
	{
		if ((Object)(object)ManagerSingleton<GM>.Instance == (Object)null)
		{
			return;
		}
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if (!((Object)(object)currentMovementManager == (Object)(object)_manager))
		{
			UnbindManager();
			_manager = currentMovementManager;
			if ((Object)(object)_manager != (Object)null)
			{
				_manager.RegisterSmoothLocoRestrictor(_velocityFilter);
				ResetState();
				TitanfallMovementPlugin.Logger.LogInfo((object)("Attached to movement manager in mode " + ((object)Unsafe.As<MovementMode, MovementMode>(ref _manager.Mode)/*cast due to .constrained prefix*/).ToString() + "."));
			}
		}
	}

	private void UnbindManager()
	{
		RestoreCrouchOffset();
		if ((Object)(object)_manager != (Object)null)
		{
			_manager.DeregisterSmoothLocoRestrictor(_velocityFilter);
		}
		_manager = null;
		ResetState();
	}

	private void ModifyVelocity(ref Vector3 velocity, ref bool isGrounded, ref bool didChange)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: 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_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: 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_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		if (!_plugin.Enabled.Value || (Object)(object)_manager == (Object)null || !IsSupportedMode(_manager))
		{
			return;
		}
		float time = Time.time;
		float num = Mathf.Clamp(Time.deltaTime, 0.001f, 0.05f);
		Vector3 horizontalMomentum = default(Vector3);
		((Vector3)(ref horizontalMomentum))..ctor(velocity.x, 0f, velocity.z);
		if (time - _lastVelocityTickTime > 0.25f)
		{
			_horizontalMomentum = horizontalMomentum;
			_verticalVelocity = velocity.y;
		}
		_lastVelocityTickTime = time;
		if (_wallRunCooldown > 0f)
		{
			_wallRunCooldown -= num;
		}
		if (_slideCooldownRemaining > 0f)
		{
			_slideCooldownRemaining -= num;
		}
		bool flag = isGrounded && !_lastGrounded;
		if (isGrounded)
		{
			if (flag)
			{
				_airJumpsRemaining = 1;
				_jumpedSinceGrounded = false;
				StopWallRun();
				_blockedWallCollider = null;
				_audio.FadeOutDoubleJump();
			}
			_verticalVelocity = 0f;
		}
		else if (_crouched || _sliding)
		{
			_crouched = false;
			StopSlide(standUp: true);
		}
		if (flag && _landingSlideHeld && TryStartBufferedLandingSlide())
		{
			_crouchQueued = false;
			_landingSlideHeld = false;
		}
		ProcessCrouchOrSlide(isGrounded);
		ProcessJump(ref isGrounded);
		float inputAmount = Mathf.Clamp01(((Vector3)(ref horizontalMomentum)).magnitude / 1.5f);
		Vector3 inputDirection = ((((Vector3)(ref horizontalMomentum)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref horizontalMomentum)).normalized : Vector3.zero);
		if (!isGrounded)
		{
			inputAmount = _rawMoveAmount;
			inputDirection = _rawMoveDirection;
		}
		if (!isGrounded && _jumpedSinceGrounded && !_wallRunning && _wallRunCooldown <= 0f)
		{
			TryStartWallRun(inputDirection);
		}
		if (_wallRunning)
		{
			UpdateWallRun(num, inputDirection, ref isGrounded);
		}
		else if (_sliding & isGrounded)
		{
			UpdateSlide(num);
		}
		else
		{
			UpdateRunning(num, inputDirection, inputAmount, isGrounded);
		}
		if (!isGrounded && !_wallRunning)
		{
			_verticalVelocity -= Mathf.Max(0.01f, _plugin.Gravity.Value) * num;
		}
		else if (isGrounded)
		{
			_verticalVelocity = Mathf.Max(0f, _verticalVelocity);
		}
		_horizontalMomentum = Vector3.ClampMagnitude(_horizontalMomentum, Mathf.Max(1f, _plugin.MaxMomentumSpeed.Value));
		velocity = _horizontalMomentum + Vector3.up * _verticalVelocity;
		didChange = true;
		_lastGrounded = isGrounded;
	}

	private void ProcessCrouchOrSlide(bool isGrounded)
	{
		if (!_crouchQueued)
		{
			return;
		}
		_crouchQueued = false;
		if (!isGrounded)
		{
			_crouched = false;
			return;
		}
		if (_sliding)
		{
			StopSlide(standUp: false);
			_crouched = false;
			return;
		}
		if (_crouched)
		{
			_crouched = false;
			return;
		}
		float magnitude = ((Vector3)(ref _horizontalMomentum)).magnitude;
		bool flag = magnitude >= _plugin.SlideMinimumSpeed.Value;
		bool flag2 = IsSlideDirectionAllowed();
		if (flag && flag2 && _slideCooldownRemaining <= 0f)
		{
			StartSlide(magnitude);
		}
		else if (!(flag && flag2))
		{
			_crouched = true;
		}
	}

	private void ProcessJump(ref bool isGrounded)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: 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_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		if (!_jumpQueued)
		{
			return;
		}
		_jumpQueued = false;
		if (_wallRunning)
		{
			float num = Mathf.Max(((Vector3)(ref _horizontalMomentum)).magnitude, _plugin.WallRunMinimumSpeed.Value);
			Vector3 val = HorizontalHeadForward();
			float num2 = Vector3.Dot(val, -_wallNormal);
			if (num2 > 0f)
			{
				Vector3 val2 = val + _wallNormal * (num2 + 0.15f);
				val = ((Vector3)(ref val2)).normalized;
			}
			float num3 = Mathf.Min(_plugin.MaxMomentumSpeed.Value, num + _plugin.WallJumpPushSpeed.Value * 0.5f);
			_horizontalMomentum = val * num3;
			_verticalVelocity = _plugin.WallJumpUpSpeed.Value;
			_manager.DelayGround(0.25f);
			isGrounded = false;
			_jumpedSinceGrounded = true;
			_crouched = false;
			StopSlide(standUp: true);
			StopWallRun();
			_wallRunCooldown = 0.22f;
			_audio.PlayDoubleJump();
		}
		else if (isGrounded)
		{
			_verticalVelocity = _plugin.JumpSpeed.Value;
			_manager.DelayGround(0.25f);
			isGrounded = false;
			_jumpedSinceGrounded = true;
			_crouched = false;
			StopSlide(standUp: true);
			_audio.PlayJump();
		}
		else if (_airJumpsRemaining > 0)
		{
			_airJumpsRemaining--;
			_verticalVelocity = _plugin.DoubleJumpSpeed.Value;
			Vector3 val3 = ((((Vector3)(ref _rawMoveDirection)).sqrMagnitude > 0.001f) ? ((Vector3)(ref _rawMoveDirection)).normalized : ((((Vector3)(ref _horizontalMomentum)).sqrMagnitude > 0.001f) ? ((Vector3)(ref _horizontalMomentum)).normalized : HorizontalHeadForward()));
			float num4 = Mathf.Min(_plugin.MaxMomentumSpeed.Value, ((Vector3)(ref _horizontalMomentum)).magnitude + Mathf.Max(0f, _plugin.DoubleJumpMomentumBoost.Value));
			_horizontalMomentum = val3 * num4;
			_manager.DelayGround(0.2f);
			_jumpedSinceGrounded = true;
			_crouched = false;
			StopSlide(standUp: true);
			_audio.PlayDoubleJump();
		}
	}

	private bool TryStartBufferedLandingSlide()
	{
		if (_sliding || _slideCooldownRemaining > 0f || !IsSlideDirectionAllowed())
		{
			return false;
		}
		float entrySpeed = Mathf.Max(((Vector3)(ref _horizontalMomentum)).magnitude, _plugin.SlideMinimumSpeed.Value);
		StartSlide(entrySpeed);
		return true;
	}

	private void UpdateRunning(float deltaTime, Vector3 inputDirection, float inputAmount, bool grounded)
	{
		//IL_001a: 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_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_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: 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_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		float magnitude = ((Vector3)(ref _horizontalMomentum)).magnitude;
		if (inputAmount <= 0.01f)
		{
			if (grounded)
			{
				_horizontalMomentum = Vector3.MoveTowards(_horizontalMomentum, Vector3.zero, _plugin.GroundFriction.Value * deltaTime);
			}
			return;
		}
		float num = (_sprinting ? _plugin.RunSpeed.Value : _plugin.WalkSpeed.Value) * inputAmount;
		if (_crouched)
		{
			num *= Mathf.Clamp01(_plugin.CrouchSpeedMultiplier.Value);
		}
		if (grounded)
		{
			if (_sprinting && !_crouched && inputAmount >= 0.75f)
			{
				float num2 = magnitude + _plugin.SprintMomentumAcceleration.Value * inputAmount * deltaTime;
				num = Mathf.Max(num, Mathf.Min(_plugin.MaxMomentumSpeed.Value, num2));
			}
			float num3 = ((magnitude > num) ? _plugin.OverspeedDrag.Value : _plugin.GroundAcceleration.Value);
			float num4 = Mathf.MoveTowards(magnitude, num, num3 * deltaTime);
			Vector3 val = inputDirection * num4;
			float num5 = ((((magnitude > 0.01f) ? Vector3.Dot(_horizontalMomentum / magnitude, inputDirection) : 1f) < 0.7f) ? Mathf.Max(_plugin.GroundFriction.Value, _plugin.GroundAcceleration.Value) : Mathf.Max(_plugin.GroundAcceleration.Value, num4 * 4f));
			_horizontalMomentum = Vector3.MoveTowards(_horizontalMomentum, val, num5 * deltaTime);
		}
		else
		{
			float num6 = Mathf.Max(magnitude, num);
			float num7 = Mathf.MoveTowards(magnitude, num6, _plugin.AirAcceleration.Value * deltaTime);
			_horizontalMomentum = inputDirection * num7;
		}
	}

	private void StartSlide(float entrySpeed)
	{
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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)
		float num = Mathf.InverseLerp(_plugin.SlideMinimumSpeed.Value, _plugin.MaxMomentumSpeed.Value, entrySpeed);
		float num2 = Mathf.Sqrt(num);
		float num3 = ((Time.time - _lastSlideEndTime <= _plugin.SlideRepeatPenaltyWindow.Value) ? _plugin.SlideRepeatSpeedMultiplier.Value : 1f);
		float num4 = Mathf.Min(_plugin.MaxMomentumSpeed.Value, entrySpeed + _plugin.SlideBoost.Value * num * num3);
		_slideDirection = ((((Vector3)(ref _horizontalMomentum)).sqrMagnitude > 0.001f) ? ((Vector3)(ref _horizontalMomentum)).normalized : HorizontalHeadForward());
		_horizontalMomentum = _slideDirection * num4;
		_slideDuration = Mathf.Lerp(_plugin.SlideMinimumDuration.Value, _plugin.SlideMaximumDuration.Value, num2);
		_slideTime = 0f;
		_sliding = true;
		_crouched = true;
		_audio.StartSlide();
	}

	private bool IsSlideDirectionAllowed()
	{
		//IL_001a: 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)
		if (((Vector3)(ref _horizontalMomentum)).sqrMagnitude < 0.001f)
		{
			return true;
		}
		return Vector3.Dot(((Vector3)(ref _horizontalMomentum)).normalized, HorizontalHeadForward()) >= -0.05f;
	}

	private void UpdateSlide(float deltaTime)
	{
		//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)
		_slideTime += deltaTime;
		float num = Mathf.MoveTowards(((Vector3)(ref _horizontalMomentum)).magnitude, 0f, _plugin.SlideFriction.Value * deltaTime);
		_horizontalMomentum = _slideDirection * num;
		if (_slideTime >= _slideDuration || num < 0.8f)
		{
			StopSlide(standUp: false);
		}
	}

	private void StopSlide(bool standUp)
	{
		bool sliding = _sliding;
		_sliding = false;
		_slideTime = 0f;
		_slideDuration = 0f;
		if (sliding)
		{
			_lastSlideEndTime = Time.time;
			_slideCooldownRemaining = Mathf.Max(_slideCooldownRemaining, _plugin.SlideCooldown.Value);
			_audio.StopSlide();
		}
		if (standUp)
		{
			_crouched = false;
		}
	}

	private void TryStartWallRun(Vector3 inputDirection)
	{
		//IL_005c: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: 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_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: 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_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		float magnitude = ((Vector3)(ref _horizontalMomentum)).magnitude;
		if (!(magnitude < _plugin.WallRunMinimumSpeed.Value) && !(((Vector3)(ref inputDirection)).sqrMagnitude < 0.01f) && FindRunnableWall(out var bestHit) && (!((Object)(object)_blockedWallCollider != (Object)null) || !((Object)(object)((RaycastHit)(ref bestHit)).collider == (Object)(object)_blockedWallCollider)))
		{
			Vector3 val = Vector3.Cross(Vector3.up, ((RaycastHit)(ref bestHit)).normal);
			Vector3 val2 = ((Vector3)(ref val)).normalized;
			Vector3 val3 = ((((Vector3)(ref _horizontalMomentum)).sqrMagnitude > 0.001f) ? ((Vector3)(ref _horizontalMomentum)).normalized : inputDirection);
			if (Vector3.Dot(val2, val3) < 0f)
			{
				val2 = -val2;
			}
			float num = Mathf.InverseLerp(_plugin.WallRunMinimumSpeed.Value, _plugin.MaxMomentumSpeed.Value, magnitude);
			_wallNormal = ((RaycastHit)(ref bestHit)).normal;
			_wallDirection = val2;
			_currentWallCollider = ((RaycastHit)(ref bestHit)).collider;
			Vector3 val4 = _manager.Head.right;
			val4.y = 0f;
			val4 = ((((Vector3)(ref val4)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val4)).normalized : Vector3.right);
			float num2 = Vector3.Dot(((RaycastHit)(ref bestHit)).point - _manager.Head.position, val4);
			if (Mathf.Abs(num2) < 0.01f)
			{
				num2 = 0f - Vector3.Dot(((RaycastHit)(ref bestHit)).normal, val4);
			}
			_wallRunCameraSide = ((num2 < 0f) ? 1f : (-1f));
			_wallRunDuration = Mathf.Lerp(_plugin.WallRunMinimumDuration.Value, _plugin.WallRunMaximumDuration.Value, num);
			float num3 = Mathf.Max(_plugin.WallRunMinimumSpeed.Value + 0.01f, _plugin.RunSpeed.Value);
			if (magnitude <= num3)
			{
				float num4 = Mathf.InverseLerp(_plugin.WallRunMinimumSpeed.Value, num3, magnitude);
				_wallRunDistanceLimit = Mathf.Lerp(_plugin.WallRunRunSpeedDistance.Value * 0.7f, _plugin.WallRunRunSpeedDistance.Value, num4);
			}
			else
			{
				float num5 = Mathf.InverseLerp(num3, _plugin.MaxMomentumSpeed.Value, magnitude);
				_wallRunDistanceLimit = Mathf.Lerp(_plugin.WallRunRunSpeedDistance.Value, _plugin.WallRunMaximumDistance.Value, num5);
			}
			_wallRunTime = 0f;
			_wallRunDistance = 0f;
			_wallRunFootstepDistance = 0f;
			_wallRunning = true;
			_sliding = false;
			_crouched = false;
			_airJumpsRemaining = 1;
			_verticalVelocity = Mathf.Max(_verticalVelocity, _plugin.WallRunVerticalSpeed.Value);
			_audio.FadeOutDoubleJump();
			_audio.StartWallRun();
			PlayWallRunFootstep(bestHit);
		}
	}

	private void UpdateWallRun(float deltaTime, Vector3 inputDirection, ref bool isGrounded)
	{
		//IL_0026: 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_0086: 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_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: 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_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		_wallRunTime += deltaTime;
		RaycastHit hit;
		bool num = FindCurrentWall(out hit);
		bool flag = ((Vector3)(ref inputDirection)).sqrMagnitude > 0.01f && Vector3.Dot(((Vector3)(ref inputDirection)).normalized, _wallDirection) > 0.2f;
		bool flag2 = IsWallRunPathBlocked();
		if (!num || !flag || flag2 || _wallRunDistance >= _wallRunDistanceLimit || _wallRunTime >= _wallRunDuration)
		{
			StopWallRun();
			_wallRunCooldown = 0.15f;
			return;
		}
		_wallNormal = ((RaycastHit)(ref hit)).normal;
		_currentWallCollider = ((RaycastHit)(ref hit)).collider;
		float num2 = Mathf.InverseLerp(_plugin.WallRunMinimumDuration.Value, _plugin.WallRunMaximumDuration.Value, _wallRunDuration);
		float num3 = Mathf.Lerp(_plugin.WallRunMinimumSpeed.Value, _plugin.MaxMomentumSpeed.Value, num2);
		float num4 = Mathf.Max(((Vector3)(ref _horizontalMomentum)).magnitude, num3);
		num4 = Mathf.Min(_plugin.MaxMomentumSpeed.Value, num4 + _plugin.WallRunAcceleration.Value * deltaTime);
		_wallRunDistance += num4 * deltaTime;
		Vector3 val = Vector3.ProjectOnPlane(_wallDirection, _wallNormal);
		val.y = 0f;
		_horizontalMomentum = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? (((Vector3)(ref val)).normalized * num4) : (_wallDirection * num4));
		_verticalVelocity = Mathf.MoveTowards(_verticalVelocity, _plugin.WallRunVerticalSpeed.Value, _plugin.Gravity.Value * 0.8f * deltaTime);
		UpdateWallRunFootsteps(hit, num4, deltaTime);
		isGrounded = false;
	}

	private void UpdateWallRunFootsteps(RaycastHit wallHit, float speed, float deltaTime)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (_plugin.PlayerFootstepsWallRun.Value && _playerFootsteps != null)
		{
			_wallRunFootstepDistance += Mathf.Max(0f, speed) * deltaTime;
			float num = Mathf.Max(0.25f, _plugin.WallRunFootstepDistance.Value);
			if (!(_wallRunFootstepDistance < num))
			{
				_wallRunFootstepDistance %= num;
				PlayWallRunFootstep(wallHit);
			}
		}
	}

	private void PlayWallRunFootstep(RaycastHit wallHit)
	{
		//IL_001c: 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_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if (!_plugin.PlayerFootstepsWallRun.Value || _playerFootsteps == null)
		{
			return;
		}
		BulletImpactSoundType surface = (BulletImpactSoundType)5;
		bool useGenericFallback = true;
		Collider collider = ((RaycastHit)(ref wallHit)).collider;
		if ((Object)(object)collider != (Object)null)
		{
			PMat component = ((Component)collider).GetComponent<PMat>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.MatDef != (Object)null)
			{
				surface = component.MatDef.BulletImpactSound;
				useGenericFallback = false;
			}
		}
		_playerFootsteps.PlayWallRunStep(surface, useGenericFallback);
	}

	private bool FindCurrentWall(out RaycastHit hit)
	{
		//IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
		hit = default(RaycastHit);
		if ((Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
		{
			return false;
		}
		Vector3 val = -_wallNormal;
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
		{
			return false;
		}
		float num = _plugin.WallRunProbeDistance.Value + 0.15f;
		if (!Physics.Raycast(_manager.Head.position, ((Vector3)(ref val)).normalized, ref hit, num, LayerMask.op_Implicit(_manager.LM_TeleCast)) || !IsRunnableWall(((RaycastHit)(ref hit)).normal))
		{
			return false;
		}
		Vector3 val2 = Vector3.ProjectOnPlane(_wallDirection, ((RaycastHit)(ref hit)).normal);
		val2.y = 0f;
		if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
		{
			return Vector3.Dot(((Vector3)(ref val2)).normalized, _wallDirection) > 0.35f;
		}
		return false;
	}

	private bool IsWallRunPathBlocked()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
		{
			return true;
		}
		RaycastHit val = default(RaycastHit);
		return Physics.Raycast(_manager.Head.position, _wallDirection, ref val, 0.55f, LayerMask.op_Implicit(_manager.LM_TeleCast));
	}

	private bool FindRunnableWall(out RaycastHit bestHit)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: 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)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: 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_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: 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)
		bestHit = default(RaycastHit);
		if ((Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
		{
			return false;
		}
		Vector3 position = _manager.Head.position;
		Vector3 right = _manager.Head.right;
		right.y = 0f;
		if (((Vector3)(ref right)).sqrMagnitude < 0.001f)
		{
			return false;
		}
		((Vector3)(ref right)).Normalize();
		RaycastHit val = default(RaycastHit);
		bool flag = Physics.Raycast(position, right, ref val, _plugin.WallRunProbeDistance.Value, LayerMask.op_Implicit(_manager.LM_TeleCast)) && IsRunnableWall(((RaycastHit)(ref val)).normal) && (Object)(object)((RaycastHit)(ref val)).collider != (Object)(object)_blockedWallCollider;
		RaycastHit val2 = default(RaycastHit);
		bool flag2 = Physics.Raycast(position, -right, ref val2, _plugin.WallRunProbeDistance.Value, LayerMask.op_Implicit(_manager.LM_TeleCast)) && IsRunnableWall(((RaycastHit)(ref val2)).normal) && (Object)(object)((RaycastHit)(ref val2)).collider != (Object)(object)_blockedWallCollider;
		if (flag && flag2)
		{
			bestHit = ((((RaycastHit)(ref val)).distance <= ((RaycastHit)(ref val2)).distance) ? val : val2);
			return true;
		}
		if (flag)
		{
			bestHit = val;
			return true;
		}
		if (flag2)
		{
			bestHit = val2;
			return true;
		}
		return false;
	}

	private static bool IsRunnableWall(Vector3 normal)
	{
		//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)
		return Mathf.Abs(Vector3.Dot(((Vector3)(ref normal)).normalized, Vector3.up)) < 0.3f;
	}

	private void StopWallRun()
	{
		if (_wallRunning && (Object)(object)_currentWallCollider != (Object)null)
		{
			_blockedWallCollider = _currentWallCollider;
		}
		_wallRunning = false;
		_currentWallCollider = null;
		_wallRunCameraSide = 0f;
		_wallRunTime = 0f;
		_wallRunDuration = 0f;
		_wallRunDistance = 0f;
		_wallRunDistanceLimit = 0f;
		_wallRunFootstepDistance = 0f;
		_audio.StopWallRun();
	}

	private void UpdateCrouchOffset(bool lowered)
	{
		float num = (lowered ? Mathf.Max(0f, _plugin.CrouchHeight.Value) : 0f);
		_crouchOffset = Mathf.MoveTowards(_crouchOffset, num, Mathf.Max(0.01f, _plugin.CrouchTransitionSpeed.Value) * Time.deltaTime);
	}

	private void RestoreCrouchOffset()
	{
		//IL_0027: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_manager != (Object)null && _appliedCrouchOffset > 0f)
		{
			Transform transform = ((Component)_manager).transform;
			transform.position += Vector3.up * _appliedCrouchOffset;
			if ((Object)(object)_manager.Body != (Object)null)
			{
				_manager.Body.UpdatePlayerBodyPositions();
			}
		}
		_appliedCrouchOffset = 0f;
		_crouchOffset = 0f;
	}

	private void StopTransientState()
	{
		_jumpQueued = false;
		_crouchQueued = false;
		_crouched = false;
		StopSlide(standUp: true);
		StopWallRun();
		_audio.StopAllMovementSounds();
	}

	private void ResetState()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		_horizontalMomentum = Vector3.zero;
		_verticalVelocity = 0f;
		_lastGrounded = true;
		_sprinting = false;
		_rawMoveDirection = Vector3.zero;
		_rawMoveAmount = 0f;
		_landingSlideHeld = false;
		_airJumpsRemaining = 1;
		_jumpedSinceGrounded = false;
		_wallRunCooldown = 0f;
		_crouchPressedLastFrame = false;
		_lastVelocityTickTime = -10f;
		StopTransientState();
		_currentWallCollider = null;
		_blockedWallCollider = null;
		_slideCooldownRemaining = 0f;
		_lastSlideEndTime = -10f;
	}

	private Vector3 HorizontalHeadForward()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
		{
			return Vector3.forward;
		}
		Vector3 forward = _manager.Head.forward;
		forward.y = 0f;
		if (!(((Vector3)(ref forward)).sqrMagnitude > 0.001f))
		{
			return Vector3.forward;
		}
		return ((Vector3)(ref forward)).normalized;
	}

	private static bool IsSupportedMode(FVRMovementManager manager)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Invalid comparison between Unknown and I4
		if ((int)manager.Mode != 6 && (int)manager.Mode != 2)
		{
			return (int)manager.Mode == 4;
		}
		return true;
	}

	private FVRViveHand FindActionHand(FVRMovementManager manager)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Invalid comparison between Unknown and I4
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Invalid comparison between Unknown and I4
		if (manager.Hands == null || manager.Hands.Length == 0)
		{
			return null;
		}
		string a = (_plugin.ActionHand.Value ?? "TurnHand").Trim();
		bool flag;
		if (string.Equals(a, "Left", StringComparison.OrdinalIgnoreCase))
		{
			flag = false;
		}
		else if (string.Equals(a, "Right", StringComparison.OrdinalIgnoreCase))
		{
			flag = true;
		}
		else
		{
			flag = true;
			if ((int)manager.Mode == 6)
			{
				flag = (int)GM.Options.MovementOptions.TwinStickLeftRightState != 1;
			}
		}
		for (int i = 0; i < manager.Hands.Length; i++)
		{
			FVRViveHand val = manager.Hands[i];
			if ((Object)(object)val != (Object)null && val.IsThisTheRightHand == flag)
			{
				return val;
			}
		}
		return manager.Hands[0];
	}

	private static FVRViveHand FindRightHand(FVRMovementManager manager)
	{
		if ((Object)(object)manager == (Object)null || manager.Hands == null)
		{
			return null;
		}
		for (int i = 0; i < manager.Hands.Length; i++)
		{
			FVRViveHand val = manager.Hands[i];
			if ((Object)(object)val != (Object)null && val.IsThisTheRightHand)
			{
				return val;
			}
		}
		return null;
	}

	private static FVRViveHand FindLeftHand(FVRMovementManager manager)
	{
		if ((Object)(object)manager == (Object)null || manager.Hands == null)
		{
			return null;
		}
		for (int i = 0; i < manager.Hands.Length; i++)
		{
			FVRViveHand val = manager.Hands[i];
			if ((Object)(object)val != (Object)null && !val.IsThisTheRightHand)
			{
				return val;
			}
		}
		return null;
	}

	private static FVRViveHand FindMovementHand(FVRMovementManager manager)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Invalid comparison between Unknown and I4
		if ((Object)(object)manager == (Object)null || manager.Hands == null)
		{
			return null;
		}
		bool flag = (int)manager.Mode == 6 && (int)GM.Options.MovementOptions.TwinStickLeftRightState == 1;
		for (int i = 0; i < manager.Hands.Length; i++)
		{
			FVRViveHand val = manager.Hands[i];
			if ((Object)(object)val != (Object)null && val.IsThisTheRightHand == flag)
			{
				return val;
			}
		}
		if (manager.Hands.Length == 0)
		{
			return null;
		}
		return manager.Hands[0];
	}

	private void ReadRawMovement(FVRViveHand hand, out Vector3 direction, out float amount)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Invalid comparison between Unknown and I4
		//IL_0066: 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_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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		direction = Vector3.zero;
		amount = 0f;
		if ((Object)(object)hand == (Object)null || (Object)(object)_manager == (Object)null || (Object)(object)_manager.Head == (Object)null)
		{
			return;
		}
		Vector2 val = (((int)hand.CMode == 0 || (int)hand.CMode == 1) ? hand.Input.TouchpadAxes : hand.Input.Secondary2AxisInputAxes);
		float num = Mathf.Clamp01(((Vector2)(ref val)).magnitude);
		if (!(num <= 0.12f))
		{
			amount = Mathf.InverseLerp(0.12f, 1f, num);
			Vector3 val2 = HorizontalHeadForward();
			Vector3 val3 = _manager.Head.right;
			val3.y = 0f;
			val3 = ((((Vector3)(ref val3)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val3)).normalized : Vector3.right);
			Vector3 val4 = val3 * val.x + val2 * val.y;
			if (((Vector3)(ref val4)).sqrMagnitude > 0.001f)
			{
				direction = ((Vector3)(ref val4)).normalized;
			}
		}
	}

	private static bool ReadStickClickDown(FVRViveHand hand)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		if ((Object)(object)hand == (Object)null)
		{
			return false;
		}
		if ((int)hand.CMode == 0 || (int)hand.CMode == 1)
		{
			return hand.Input.TouchpadDown;
		}
		return hand.Input.Secondary2AxisInputDown;
	}

	private static bool ReadSouthPressed(FVRViveHand hand)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		if ((Object)(object)hand == (Object)null)
		{
			return false;
		}
		if ((int)hand.CMode == 0 || (int)hand.CMode == 1)
		{
			return hand.Input.TouchpadSouthPressed;
		}
		return hand.Input.Secondary2AxisSouthPressed;
	}
}
[BepInPlugin("com.notgodlike.h3vr.titanfallmovement", "Titanfall Movement", "1.8.7")]
[BepInProcess("h3vr.exe")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class TitanfallMovementPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.notgodlike.h3vr.titanfallmovement";

	public const string PluginName = "Titanfall Movement";

	public const string PluginVersion = "1.8.7";

	private Harmony _harmony;

	private TitanfallMovementController _controller;

	private MovementAudio _audio;

	private PlayerFootstepsBridge _playerFootsteps;

	private WallRunCameraTilt _cameraTilt;

	private bool _markedRunningModded;

	internal static TitanfallMovementPlugin Instance { get; private set; }

	internal static ManualLogSource Logger { get; private set; }

	internal ConfigEntry<bool> Enabled { get; private set; }

	internal ConfigEntry<float> WalkSpeed { get; private set; }

	internal ConfigEntry<float> RunSpeed { get; private set; }

	internal ConfigEntry<float> GroundAcceleration { get; private set; }

	internal ConfigEntry<float> GroundFriction { get; private set; }

	internal ConfigEntry<float> OverspeedDrag { get; private set; }

	internal ConfigEntry<float> SprintMomentumAcceleration { get; private set; }

	internal ConfigEntry<float> AirAcceleration { get; private set; }

	internal ConfigEntry<float> MaxMomentumSpeed { get; private set; }

	internal ConfigEntry<float> JumpSpeed { get; private set; }

	internal ConfigEntry<float> DoubleJumpSpeed { get; private set; }

	internal ConfigEntry<float> DoubleJumpMomentumBoost { get; private set; }

	internal ConfigEntry<float> Gravity { get; private set; }

	internal ConfigEntry<float> SlideMinimumSpeed { get; private set; }

	internal ConfigEntry<float> SlideBoost { get; private set; }

	internal ConfigEntry<float> SlideFriction { get; private set; }

	internal ConfigEntry<float> SlideMinimumDuration { get; private set; }

	internal ConfigEntry<float> SlideMaximumDuration { get; private set; }

	internal ConfigEntry<float> SlideCooldown { get; private set; }

	internal ConfigEntry<float> SlideRepeatPenaltyWindow { get; private set; }

	internal ConfigEntry<float> SlideRepeatSpeedMultiplier { get; private set; }

	internal ConfigEntry<float> CrouchSpeedMultiplier { get; private set; }

	internal ConfigEntry<float> CrouchHeight { get; private set; }

	internal ConfigEntry<float> CrouchTransitionSpeed { get; private set; }

	internal ConfigEntry<float> WallRunProbeDistance { get; private set; }

	internal ConfigEntry<float> WallRunMinimumSpeed { get; private set; }

	internal ConfigEntry<float> WallRunMinimumDuration { get; private set; }

	internal ConfigEntry<float> WallRunMaximumDuration { get; private set; }

	internal ConfigEntry<float> WallRunRunSpeedDistance { get; private set; }

	internal ConfigEntry<float> WallRunMaximumDistance { get; private set; }

	internal ConfigEntry<float> WallRunVerticalSpeed { get; private set; }

	internal ConfigEntry<float> WallRunAcceleration { get; private set; }

	internal ConfigEntry<float> WallJumpUpSpeed { get; private set; }

	internal ConfigEntry<float> WallJumpPushSpeed { get; private set; }

	internal ConfigEntry<string> ActionHand { get; private set; }

	internal ConfigEntry<float> SoundVolume { get; private set; }

	internal ConfigEntry<bool> WallRunHeadTilt { get; private set; }

	internal ConfigEntry<float> WallRunCameraTiltAngle { get; private set; }

	internal ConfigEntry<float> WallRunCameraTiltSpeed { get; private set; }

	internal ConfigEntry<bool> PlayerFootstepsWallRun { get; private set; }

	internal ConfigEntry<float> WallRunFootstepDistance { get; private set; }

	private void Awake()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		BindConfiguration();
		_audio = ((Component)this).gameObject.AddComponent<MovementAudio>();
		_audio.Initialize(this);
		_playerFootsteps = new PlayerFootstepsBridge();
		_controller = new TitanfallMovementController(this, _audio, _playerFootsteps);
		_cameraTilt = ((Component)this).gameObject.AddComponent<WallRunCameraTilt>();
		_cameraTilt.Initialize(this, _controller);
		_harmony = new Harmony("com.notgodlike.h3vr.titanfallmovement");
		_harmony.PatchAll(typeof(TitanfallMovementPlugin).Assembly);
		Logger.LogMessage((object)"Titanfall Movement 1.8.7 initialized; waiting for the H3VR movement manager.");
	}

	private void Update()
	{
		if (!((Object)(object)ManagerSingleton<GM>.Instance == (Object)null))
		{
			if (!_markedRunningModded)
			{
				GM.SetRunningModded();
				_markedRunningModded = true;
			}
			if (_controller != null)
			{
				_controller.Update();
			}
		}
	}

	private void OnDestroy()
	{
		if (_controller != null)
		{
			_controller.Dispose();
		}
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		Instance = null;
	}

	private void BindConfiguration()
	{
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Titanfall movement while using an H3VR smooth locomotion mode.");
		ActionHand = ((BaseUnityPlugin)this).Config.Bind<string>("Input", "CrouchActionHand", "TurnHand", "Stick used for crouch/slide: TurnHand, Left, or Right. Jump is the right-stick click; left-stick click toggles sprint.");
		WalkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "WalkSpeed", 3.2f, "Maximum walking speed before sprint is toggled.");
		RunSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "RunSpeed", 5.2f, "Maximum sprint speed after clicking the left stick.");
		GroundAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "GroundAcceleration", 22f, "Ground acceleration in metres per second squared.");
		GroundFriction = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "GroundFriction", 32f, "Braking and sharp-turn response when the movement stick is released or reversed.");
		OverspeedDrag = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "OverspeedDrag", 1.6f, "How quickly accumulated speed decays when walking instead of sprinting.");
		SprintMomentumAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "SprintMomentumAcceleration", 0.35f, "Speed gained per second while sprinting at strong stick input, up to MaxMomentumSpeed.");
		AirAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "AirAcceleration", 5f, "Air-control acceleration.");
		MaxMomentumSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Running", "MaxMomentumSpeed", 12f, "Safety cap for horizontal momentum.");
		JumpSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Jumping", "JumpSpeed", 5.35f, "Vertical speed of the first jump.");
		DoubleJumpSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Jumping", "DoubleJumpSpeed", 5f, "Vertical speed of the double jump.");
		DoubleJumpMomentumBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Jumping", "DoubleJumpMomentumBoost", 1.4f, "Horizontal speed added by a double jump and carried into the next slide.");
		Gravity = ((BaseUnityPlugin)this).Config.Bind<float>("Jumping", "Gravity", 12.5f, "Custom downward acceleration while airborne.");
		SlideMinimumSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "MinimumSpeed", 3f, "Minimum horizontal speed required to start a slide.");
		SlideBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "Boost", 1.8f, "Maximum speed added when a fast slide starts.");
		SlideFriction = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "Friction", 2.4f, "Slide deceleration.");
		SlideMinimumDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "MinimumDuration", 0.65f, "Slide duration at minimum entry speed. Mid-speed slides use a generous nonlinear duration curve.");
		SlideMaximumDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "MaximumDuration", 1.55f, "Slide duration at maximum momentum.");
		SlideCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "Cooldown", 0.65f, "Delay after a slide ends before another slide can start.");
		SlideRepeatPenaltyWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "RepeatPenaltyWindow", 1.5f, "Time after a slide ends during which the next slide receives less boost.");
		SlideRepeatSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Sliding", "RepeatSpeedMultiplier", 0.55f, "Multiplier applied only to the next slide's added speed when used inside RepeatPenaltyWindow. Duration is never reduced.");
		CrouchSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Crouching", "SpeedMultiplier", 0.48f, "Maximum running speed while crouched.");
		CrouchHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Crouching", "VirtualHeight", 0.52f, "Virtual camera/body lowering in metres. Set to zero to disable forced lowering.");
		CrouchTransitionSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Crouching", "TransitionSpeed", 3.5f, "Crouch lowering/raising speed in metres per second.");
		WallRunProbeDistance = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "ProbeDistance", 0.72f, "Maximum distance from the head to a runnable wall.");
		WallRunMinimumSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "MinimumSpeed", 3.5f, "Minimum horizontal speed required to attach to a wall.");
		WallRunMinimumDuration = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "MinimumDuration", 0.65f, "Wall-run duration at minimum entry speed.");
		WallRunMaximumDuration = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "MaximumDuration", 2.4f, "Wall-run duration at maximum momentum.");
		WallRunRunSpeedDistance = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "RunSpeedDistance", 4.75f, "Wall-run distance in metres at ordinary sprint speed.");
		WallRunMaximumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "MaximumDistance", 18f, "Wall-run distance in metres at maximum accumulated momentum.");
		WallRunVerticalSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "VerticalSpeed", -0.25f, "Vertical speed maintained during a wall run.");
		WallRunAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "Acceleration", 0.9f, "Horizontal speed gained per second during wall running, up to MaxMomentumSpeed.");
		WallJumpUpSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "JumpUpSpeed", 5.1f, "Vertical wall-jump speed.");
		WallJumpPushSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "JumpPushSpeed", 4f, "Horizontal speed away from the wall during a wall jump.");
		WallRunHeadTilt = ((BaseUnityPlugin)this).Config.Bind<bool>("WallRunning", "Head Tilt Enabled", true, "Tilt the player tracking space and HD spectator camera toward the wall during wall running.");
		WallRunCameraTiltAngle = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "Head Tilt Angle", 25f, "Wall-run head tilt in degrees (clamped to 25 degrees for comfort and to prevent accidental double roll).");
		WallRunCameraTiltSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("WallRunning", "Head Tilt Transition Speed", 180f, "Head tilt transition speed in degrees per second.");
		PlayerFootstepsWallRun = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "PlayerFootstepsWallRun", true, "Use the installed Player Footsteps mod and its sound-pack addons for wall-run steps.");
		WallRunFootstepDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Compatibility", "WallRunFootstepDistance", 0.9f, "Distance travelled along a wall between Player Footsteps sounds, in metres.");
		SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.85f, "Volume for jump, double-jump, looping wall-run and looping slide sounds.");
		if (Mathf.Abs(GroundAcceleration.Value - 16f) < 0.001f)
		{
			GroundAcceleration.Value = 22f;
		}
		if (Mathf.Abs(GroundFriction.Value - 9f) < 0.001f)
		{
			GroundFriction.Value = 32f;
		}
		if (Mathf.Abs(RunSpeed.Value - 6.5f) < 0.001f)
		{
			RunSpeed.Value = 5.2f;
		}
		if (Mathf.Abs(WallRunCameraTiltAngle.Value - 45f) < 0.001f)
		{
			WallRunCameraTiltAngle.Value = 25f;
		}
		if (Mathf.Abs(SlideMinimumDuration.Value - 0.45f) < 0.001f)
		{
			SlideMinimumDuration.Value = 0.65f;
		}
		ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Sliding", "Omnimovement Slide", false, "Removed in 1.8.6; slides now always support forward and lateral movement.");
		((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
		((BaseUnityPlugin)this).Config.Save();
	}

	internal bool BlockVanillaJump(FVRMovementManager manager)
	{
		if (Enabled.Value && _controller != null)
		{
			return _controller.IsBoundTo(manager);
		}
		return false;
	}

	internal void BeforeMovementTick(FVRMovementManager manager)
	{
		if (_controller != null)
		{
			_controller.BeforeMovementTick(manager);
		}
	}

	internal void AfterMovementTick(FVRMovementManager manager)
	{
		if (_controller != null)
		{
			_controller.AfterMovementTick(manager);
		}
	}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "get_m_handPos")]
internal static class HeldObjectPositionTiltPatch
{
	private static void Postfix(ref Vector3 __result)
	{
		WallRunCameraTilt.CompensatePoint(ref __result);
	}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "get_m_handRot")]
internal static class HeldObjectRotationTiltPatch
{
	private static void Postfix(ref Quaternion __result)
	{
		WallRunCameraTilt.CompensateRotation(ref __result);
	}
}
[HarmonyPatch(typeof(FVRPhysicalObject), "GetPosTarget")]
internal static class QuickbeltObjectPositionTiltPatch
{
	private static void Postfix(FVRPhysicalObject __instance, ref Vector3 __result)
	{
		if (!((FVRInteractiveObject)__instance).IsHeld && (Object)(object)__instance.QuickbeltSlot != (Object)null)
		{
			WallRunCameraTilt.CompensatePoint(ref __result);
		}
	}
}
[HarmonyPatch(typeof(FVRPhysicalObject), "GetRotTarget")]
internal static class QuickbeltObjectRotationTiltPatch
{
	private static void Postfix(FVRPhysicalObject __instance, ref Quaternion __result)
	{
		if (!((FVRInteractiveObject)__instance).IsHeld && (Object)(object)__instance.QuickbeltSlot != (Object)null)
		{
			WallRunCameraTilt.CompensateRotation(ref __result);
		}
	}
}
[HarmonyPatch(typeof(FVRMovementManager), "Jump")]
internal static class VanillaJumpPatch
{
	private static bool Prefix(FVRMovementManager __instance)
	{
		TitanfallMovementPlugin instance = TitanfallMovementPlugin.Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			return !instance.BlockVanillaJump(__instance);
		}
		return true;
	}
}
[HarmonyPatch(typeof(FVRMovementManager), "FU")]
internal static class MovementTickPatch
{
	private static void Prefix(FVRMovementManager __instance)
	{
		TitanfallMovementPlugin instance = TitanfallMovementPlugin.Instance;
		if ((Object)(object)instance != (Object)null)
		{
			instance.BeforeMovementTick(__instance);
		}
	}

	private static void Postfix(FVRMovementManager __instance)
	{
		TitanfallMovementPlugin instance = TitanfallMovementPlugin.Instance;
		if ((Object)(object)instance != (Object)null)
		{
			instance.AfterMovementTick(__instance);
		}
	}
}
internal sealed class WallRunCameraTilt : MonoBehaviour
{
	private sealed class ExternalPose
	{
		internal Transform Transform;

		internal Vector3 BasePosition;

		internal Quaternion BaseRotation;

		internal Vector3 AppliedPosition;

		internal Quaternion AppliedRotation;
	}

	private TitanfallMovementPlugin _plugin;

	private TitanfallMovementController _controller;

	private Transform _trackingRoot;

	private Transform _rollPivot;

	private float _currentRoll;

	private float _targetRoll;

	private bool _rigRollApplied;

	private Camera _appliedSpectatorCamera;

	private Vector3 _spectatorBasePosition;

	private Quaternion _spectatorBaseRotation;

	private bool _spectatorRollApplied;

	private bool _loggedRig;

	private bool _loggedSpectatorCamera;

	private bool _loggedMeasuredRoll;

	private readonly List<ExternalPose> _externalPoses = new List<ExternalPose>();

	private const float MaximumTiltAngle = 25f;

	private const float HmdTrackingRollScale = 0.5f;

	internal static WallRunCameraTilt Instance { get; private set; }

	internal void Initialize(TitanfallMovementPlugin plugin, TitanfallMovementController controller)
	{
		_plugin = plugin;
		_controller = controller;
		Instance = this;
	}

	private void OnEnable()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(ApplySpectatorRoll));
		Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(ApplySpectatorRoll));
		Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(RestoreSpectatorRoll));
	}

	private void OnDisable()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(ApplySpectatorRoll));
		Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(ApplySpectatorRoll));
		Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(RestoreSpectatorRoll));
		CleanupRigPivot();
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private void Update()
	{
		float num = (((Object)(object)_plugin != (Object)null && _controller != null && _plugin.Enabled.Value && _plugin.WallRunHeadTilt.Value && _controller.IsWallRunning) ? (_controller.WallRunCameraSide * Mathf.Clamp(Mathf.Abs(_plugin.WallRunCameraTiltAngle.Value), 0f, 25f)) : 0f);
		_targetRoll = num * 0.5f;
		float num2 = Mathf.Max(1f, _plugin.WallRunCameraTiltSpeed.Value);
		_currentRoll = Mathf.MoveTowards(_currentRoll, _targetRoll, num2 * 0.5f * Time.deltaTime);
	}

	private void LateUpdate()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: 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_00cd: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: 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)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		RestoreExternalCompensation();
		RestoreRigRoll();
		if (Mathf.Abs(_currentRoll) < 0.01f || !EnsureRigPivot())
		{
			return;
		}
		AdoptNewTrackingChildren();
		Camera val = (((Object)(object)GM.CurrentPlayerBody != (Object)null) ? GM.CurrentPlayerBody.EyeCam : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Vector3 position = ((Component)val).transform.position;
		Vector3 forward = ((Component)val).transform.forward;
		Vector3 up = ((Component)val).transform.up;
		_rollPivot.rotation = Quaternion.AngleAxis(_currentRoll, forward) * _trackingRoot.rotation;
		Transform rollPivot = _rollPivot;
		rollPivot.position += position - ((Component)val).transform.position;
		_rigRollApplied = true;
		ApplyQuickbeltCompensation(position, forward);
		if (!_loggedMeasuredRoll && Mathf.Abs(_currentRoll - _targetRoll) < 0.05f)
		{
			Vector3 val2 = Vector3.ProjectOnPlane(up, forward);
			Vector3 val3 = Vector3.ProjectOnPlane(((Component)val).transform.up, forward);
			float num = _currentRoll;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.001f && ((Vector3)(ref val3)).sqrMagnitude > 0.001f)
			{
				num = Vector3.Angle(val2, val3) * Mathf.Sign(Vector3.Dot(forward, Vector3.Cross(val2, val3)));
			}
			TitanfallMovementPlugin.Logger.LogInfo((object)("Wall-run configured visual roll=" + (_targetRoll / 0.5f).ToString("F1") + " degrees, tracking-space delta=" + num.ToString("F1") + " degrees."));
			_loggedMeasuredRoll = true;
		}
		if (!_loggedRig)
		{
			TitanfallMovementPlugin.Logger.LogInfo((object)("Wall-run physical tracking roll attached inside player root " + ((Object)_trackingRoot).name + "."));
			_loggedRig = true;
		}
	}

	private bool EnsureRigPivot()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ManagerSingleton<GM>.Instance == (Object)null || (Object)(object)GM.CurrentPlayerRoot == (Object)null)
		{
			return false;
		}
		Transform currentPlayerRoot = GM.CurrentPlayerRoot;
		if ((Object)(object)_rollPivot != (Object)null && (Object)(object)_trackingRoot == (Object)(object)currentPlayerRoot && (Object)(object)_rollPivot.parent == (Object)(object)currentPlayerRoot)
		{
			return true;
		}
		CleanupRigPivot();
		_trackingRoot = currentPlayerRoot;
		GameObject val = new GameObject("Titanfall Player Tracking Roll Pivot");
		_rollPivot = val.transform;
		_rollPivot.SetParent(currentPlayerRoot, false);
		_rollPivot.localPosition = Vector3.zero;
		_rollPivot.localRotation = Quaternion.identity;
		_rollPivot.localScale = Vector3.one;
		AdoptNewTrackingChildren();
		return true;
	}

	private void AdoptNewTrackingChildren()
	{
		if ((Object)(object)_trackingRoot == (Object)null || (Object)(object)_rollPivot == (Object)null)
		{
			return;
		}
		for (int num = _trackingRoot.childCount - 1; num >= 0; num--)
		{
			Transform child = _trackingRoot.GetChild(num);
			if ((Object)(object)child != (Object)(object)_rollPivot)
			{
				child.SetParent(_rollPivot, false);
			}
		}
	}

	private void RestoreRigRoll()
	{
		//IL_001c: 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)
		if (_rigRollApplied && (Object)(object)_rollPivot != (Object)null)
		{
			_rollPivot.localPosition = Vector3.zero;
			_rollPivot.localRotation = Quaternion.identity;
		}
		_rigRollApplied = false;
	}

	private void ApplyQuickbeltCompensation(Vector3 eyePosition, Vector3 viewForward)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
		if ((Object)(object)currentPlayerBody == (Object)null || currentPlayerBody.QuickbeltSlots == null)
		{
			return;
		}
		Quaternion roll = Quaternion.AngleAxis(_currentRoll, viewForward);
		for (int i = 0; i < currentPlayerBody.QuickbeltSlots.Count; i++)
		{
			FVRQuickBeltSlot val = currentPlayerBody.QuickbeltSlots[i];
			if (!((Object)(object)val == (Object)null))
			{
				CompensateExternalTransform(((Component)val).transform, eyePosition, roll);
				FVRPhysicalObject curObject = val.CurObject;
				if ((Object)(object)curObject != (Object)null && !((FVRInteractiveObject)curObject).IsHeld)
				{
					CompensateExternalTransform(((Component)curObject).transform, eyePosition, roll);
				}
			}
		}
	}

	private void CompensateExternalTransform(Transform target, Vector3 eyePosition, Quaternion roll)
	{
		//IL_0065: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || (Object)(object)target == (Object)(object)_rollPivot || target.IsChildOf(_rollPivot))
		{
			return;
		}
		for (int i = 0; i < _externalPoses.Count; i++)
		{
			if ((Object)(object)_externalPoses[i].Transform == (Object)(object)target)
			{
				return;
			}
		}
		ExternalPose externalPose = new ExternalPose();
		externalPose.Transform = target;
		externalPose.BasePosition = target.position;
		externalPose.BaseRotation = target.rotation;
		externalPose.AppliedPosition = eyePosition + roll * (externalPose.BasePosition - eyePosition);
		externalPose.AppliedRotation = roll * externalPose.BaseRotation;
		target.position = externalPose.AppliedPosition;
		target.rotation = externalPose.AppliedRotation;
		_externalPoses.Add(externalPose);
	}

	private void RestoreExternalCompensation()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < _externalPoses.Count; i++)
		{
			ExternalPose externalPose = _externalPoses[i];
			if (!((Object)(object)externalPose.Transform == (Object)null))
			{
				Vector3 val = externalPose.Transform.position - externalPose.AppliedPosition;
				if (((Vector3)(ref val)).sqrMagnitude < 1E-06f && Quaternion.Angle(externalPose.Transform.rotation, externalPose.AppliedRotation) < 0.05f)
				{
					externalPose.Transform.position = externalPose.BasePosition;
					externalPose.Transform.rotation = externalPose.BaseRotation;
				}
			}
		}
		_externalPoses.Clear();
	}

	private void CleanupRigPivot()
	{
		RestoreSpectatorRollInternal();
		RestoreExternalCompensation();
		RestoreRigRoll();
		if ((Object)(object)_trackingRoot != (Object)null && (Object)(object)_rollPivot != (Object)null && (Object)(object)_rollPivot.parent == (Object)(object)_trackingRoot)
		{
			while (_rollPivot.childCount > 0)
			{
				_rollPivot.GetChild(0).SetParent(_trackingRoot, false);
			}
		}
		if ((Object)(object)_rollPivot != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_rollPivot).gameObject);
		}
		_trackingRoot = null;
		_rollPivot = null;
		_loggedMeasuredRoll = false;
	}

	internal bool TryGetPhysicalCompensation(out Vector3 eyePosition, out Quaternion roll)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		eyePosition = Vector3.zero;
		roll = Quaternion.identity;
		if ((Object)(object)_plugin == (Object)null || !_plugin.Enabled.Value || !_plugin.WallRunHeadTilt.Value || Mathf.Abs(_currentRoll) < 0.01f || (Object)(object)GM.CurrentPlayerBody == (Object)null || (Object)(object)GM.CurrentPlayerBody.EyeCam == (Object)null)
		{
			return false;
		}
		Camera eyeCam = GM.CurrentPlayerBody.EyeCam;
		eyePosition = ((Component)eyeCam).transform.position;
		roll = Quaternion.AngleAxis(_currentRoll, ((Component)eyeCam).transform.forward);
		return true;
	}

	internal static void CompensatePoint(ref Vector3 point)
	{
		//IL_001e: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Instance != (Object)null && Instance.TryGetPhysicalCompensation(out var eyePosition, out var roll))
		{
			point = eyePosition + roll * (point - eyePosition);
		}
	}

	internal static void CompensateRotation(ref Quaternion rotation)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Instance != (Object)null && Instance.TryGetPhysicalCompensation(out var _, out var roll))
		{
			rotation = roll * rotation;
		}
	}

	private void ApplySpectatorRoll(Camera camera)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		if (IsHdSpectatorCamera(camera) && !(Mathf.Abs(_currentRoll) < 0.01f))
		{
			RestoreSpectatorRollInternal();
			_appliedSpectatorCamera = camera;
			_spectatorBasePosition = ((Component)camera).transform.position;
			_spectatorBaseRotation = ((Component)camera).transform.rotation;
			Vector3 forward = ((Component)camera).transform.forward;
			Vector3 val = Vector3.ProjectOnPlane(Vector3.up, forward);
			Quaternion val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(forward, ((Vector3)(ref val)).normalized) : ((Component)camera).transform.rotation);
			float num = _currentRoll / 0.5f;
			((Component)camera).transform.rotation = Quaternion.AngleAxis(num, forward) * val2;
			_spectatorRollApplied = true;
			if (!_loggedSpectatorCamera)
			{
				TitanfallMovementPlugin.Logger.LogInfo((object)("Wall-run roll attached to H3VR HD spectator camera " + ((Object)camera).name + "."));
				_loggedSpectatorCamera = true;
			}
		}
	}

	private void RestoreSpectatorRoll(Camera camera)
	{
		if ((Object)(object)camera == (Object)(object)_appliedSpectatorCamera)
		{
			RestoreSpectatorRollInternal();
		}
	}

	private void RestoreSpectatorRollInternal()
	{
		//IL_0022: 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)
		if (_spectatorRollApplied && (Object)(object)_appliedSpectatorCamera != (Object)null)
		{
			((Component)_appliedSpectatorCamera).transform.position = _spectatorBasePosition;
			((Component)_appliedSpectatorCamera).transform.rotation = _spectatorBaseRotation;
		}
		_appliedSpectatorCamera = null;
		_spectatorRollApplied = false;
	}

	private static bool IsHdSpectatorCamera(Camera camera)
	{
		if ((Object)(object)camera != (Object)null && (Object)(object)ManagerSingleton<GM>.Instance != (Object)null && (Object)(object)GM.CurrentSceneSettings != (Object)null)
		{
			return (Object)(object)camera == (Object)(object)GM.CurrentSceneSettings.SpectatorCamera;
		}
		return false;
	}
}