Decompiled source of ThrowAssist v1.4.6

ThrowAssist.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("ThrowAssist")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f5b29c0c2dbdaa78bd3131f2c4788223d7382902")]
[assembly: AssemblyProduct("ThrowAssist")]
[assembly: AssemblyTitle("ThrowAssist")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ThrowAssist;

public class AimMarker : MonoBehaviour
{
	public enum State
	{
		Resting,
		Placing,
		Selected
	}

	private struct Frame
	{
		public Vector3 Pos;

		public float Time;
	}

	private static readonly List<AimMarker> All = new List<AimMarker>();

	private Vector3 _localPos;

	private bool _hadSosig;

	private bool _hadObject;

	private Renderer _renderer;

	private Material _mat;

	private float _stateTime;

	private const int SampleFrames = 3;

	private readonly List<Frame> _history = new List<Frame>();

	private Vector3 _velocity;

	private static readonly Color RestColor = new Color(0.2f, 0.85f, 1f, 1f);

	private static readonly Color PlaceColor = new Color(0.2f, 1f, 0.3f, 1f);

	private static readonly Color SelectColor = new Color(1f, 0.15f, 0.15f, 1f);

	private static readonly Color HoverColor = new Color(1f, 0.55f, 0.1f, 1f);

	private Vector3 _localNormal;

	public Transform Anchor { get; private set; }

	public Sosig OwnerSosig { get; private set; }

	public SosigLink OwnerLink { get; private set; }

	public FVRPhysicalObject OwnerObject { get; private set; }

	public State Current { get; private set; }

	public Vector3 Position => ((Component)this).transform.position;

	public Vector3 Normal
	{
		get
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Anchor != (Object)null))
			{
				return Vector3.up;
			}
			Vector3 val = Anchor.TransformDirection(_localNormal);
			return ((Vector3)(ref val)).normalized;
		}
	}

	public Vector3 Velocity => _velocity;

	public static List<AimMarker> GetAll()
	{
		for (int num = All.Count - 1; num >= 0; num--)
		{
			if ((Object)(object)All[num] == (Object)null)
			{
				All.RemoveAt(num);
			}
		}
		return All;
	}

	public static AimMarker Create(RaycastHit hit)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
		((Object)obj).name = "ThrowAssist_AimMarker";
		Collider component = obj.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		AimMarker aimMarker = obj.AddComponent<AimMarker>();
		aimMarker.Init(hit);
		return aimMarker;
	}

	private void Init(RaycastHit hit)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Expected O, but got Unknown
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		Anchor = ((Component)((RaycastHit)(ref hit)).collider).transform;
		_localPos = Anchor.InverseTransformPoint(((RaycastHit)(ref hit)).point + ((RaycastHit)(ref hit)).normal * 0.005f);
		_localNormal = Anchor.InverseTransformDirection(((RaycastHit)(ref hit)).normal);
		SosigLink val = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<SosigLink>();
		if ((Object)(object)val == (Object)null)
		{
			SosigWearable componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<SosigWearable>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				val = componentInParent.L;
			}
		}
		OwnerLink = val;
		OwnerSosig = (((Object)(object)val != (Object)null) ? val.S : null);
		OwnerObject = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<FVRPhysicalObject>();
		_hadSosig = (Object)(object)OwnerSosig != (Object)null;
		_hadObject = (Object)(object)OwnerObject != (Object)null;
		_renderer = ((Component)this).GetComponent<Renderer>();
		Shader val2 = Shader.Find("Sprites/Default");
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = Shader.Find("Particles/Additive");
		}
		_mat = new Material(val2);
		_mat.renderQueue = 4000;
		_renderer.sharedMaterial = _mat;
		_renderer.shadowCastingMode = (ShadowCastingMode)0;
		_renderer.receiveShadows = false;
		((Component)this).transform.position = Anchor.TransformPoint(_localPos);
		SetState(State.Placing);
		All.Add(this);
	}

	public void SetState(State s)
	{
		Current = s;
		_stateTime = Time.time;
	}

	public bool IsPartOfHost(Collider c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return false;
		}
		if ((Object)(object)OwnerSosig != (Object)null)
		{
			SosigLink componentInParent = ((Component)c).GetComponentInParent<SosigLink>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.S == OwnerSosig)
			{
				return true;
			}
		}
		if ((Object)(object)OwnerObject != (Object)null && ((Component)c).GetComponentInParent<FVRPhysicalObject>() == OwnerObject)
		{
			return true;
		}
		if ((Object)(object)Anchor != (Object)null && ((Object)(object)((Component)c).transform == (Object)(object)Anchor || ((Component)c).transform.IsChildOf(Anchor)))
		{
			return true;
		}
		return false;
	}

	public Vector3 Predict(float t)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: 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_008b: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: 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_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)OwnerSosig != (Object)null)
		{
			return SosigMotion.PredictPoint(OwnerSosig, OwnerLink, Position, t);
		}
		Rigidbody val = HostBody();
		if ((Object)(object)OwnerSosig == (Object)null && (Object)(object)val != (Object)null && !val.isKinematic && val.useGravity && !val.IsSleeping())
		{
			Vector3 velocity = val.velocity;
			if (((Vector3)(ref velocity)).magnitude >= Plugin.ObjectBallisticMinSpeed.Value)
			{
				Vector3 velocity2 = val.velocity;
				float num = Ballistic.ClearanceBelow(Position, Plugin.GroundProbeDistance.Value, null, ((Component)val).transform);
				float num2 = Mathf.Min(t, Ballistic.TimeToGround(velocity2.y, num));
				Vector3 val2 = (velocity2 * num2 + 0.5f * Physics.gravity * num2 * num2) * Plugin.LeadStrengthValue;
				val2 = Vector3.ClampMagnitude(val2, Plugin.BallisticLeadMaxDistance.Value);
				Vector3 val3 = Position + val2;
				if (num < float.MaxValue)
				{
					val3.y = Mathf.Max(val3.y, Position.y - num);
				}
				return val3;
			}
		}
		float num3 = t;
		float num4 = float.MaxValue;
		if (_velocity.y < -0.01f)
		{
			num4 = Ballistic.ClearanceBelow(Position, Plugin.GroundProbeDistance.Value, null, Anchor);
			num3 = Mathf.Min(t, Ballistic.TimeToGround(_velocity.y, num4));
		}
		Vector3 val4 = Vector3.ClampMagnitude(_velocity * num3 * Plugin.LeadStrengthValue, Plugin.LeadMaxDistance.Value);
		Vector3 val5 = Position + val4;
		if (num4 < float.MaxValue)
		{
			val5.y = Mathf.Max(val5.y, Position.y - num4);
		}
		return val5;
	}

	private Rigidbody HostBody()
	{
		if ((Object)(object)OwnerObject != (Object)null && (Object)(object)OwnerObject.RootRigidbody != (Object)null)
		{
			return OwnerObject.RootRigidbody;
		}
		if ((Object)(object)Anchor != (Object)null)
		{
			return ((Component)Anchor).GetComponentInParent<Rigidbody>();
		}
		return null;
	}

	public bool IsSuppressedFor(FVRPhysicalObject thrown)
	{
		if ((Object)(object)OwnerObject == (Object)null)
		{
			return false;
		}
		if (OwnerObject == thrown)
		{
			return true;
		}
		if ((Object)(object)thrown != (Object)null && ((Component)OwnerObject).transform.IsChildOf(((Component)thrown).transform))
		{
			return true;
		}
		if (((FVRInteractiveObject)OwnerObject).IsHeld)
		{
			return true;
		}
		if ((Object)(object)OwnerObject.QuickbeltSlot != (Object)null)
		{
			return true;
		}
		return false;
	}

	private void LateUpdate()
	{
		//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)
		if ((Object)(object)Anchor == (Object)null || !((Component)Anchor).gameObject.activeInHierarchy)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		if ((_hadSosig && (Object)(object)OwnerSosig == (Object)null) || (_hadObject && (Object)(object)OwnerObject == (Object)null))
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		((Component)this).transform.position = Anchor.TransformPoint(_localPos);
		TrackVelocity();
		Animate();
	}

	private void TrackVelocity()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		float time = Time.time;
		Frame item = default(Frame);
		item.Pos = ((Component)this).transform.position;
		item.Time = time;
		_history.Add(item);
		if (_history.Count > 3)
		{
			_history.RemoveRange(0, _history.Count - 3);
		}
		Frame frame = _history[0];
		Frame frame2 = _history[_history.Count - 1];
		float num = frame2.Time - frame.Time;
		if (_history.Count < 2 || num < 0.0001f)
		{
			_velocity = Vector3.zero;
			return;
		}
		Vector3 val = (frame2.Pos - frame.Pos) / num;
		val.y *= Plugin.LeadVerticalFactor.Value;
		_velocity = Vector3.ClampMagnitude(val, Plugin.LeadMaxSpeed.Value);
	}

	private void Animate()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: 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_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		bool editMode = MarkerEditor.EditMode;
		float num = Time.time - _stateTime;
		float num2 = Plugin.MarkerDotSize.Value;
		Color color = RestColor;
		bool flag = editMode;
		switch (Current)
		{
		case State.Placing:
		{
			float num3 = Mathf.Clamp01(num / 0.15f);
			float num4 = Mathf.Sin(num3 * (float)Math.PI);
			num2 *= 1f + num4 * 1.6f;
			color = Color.Lerp(PlaceColor, RestColor, num3 * num3);
			flag = true;
			if (num3 >= 1f)
			{
				SetState(State.Resting);
			}
			break;
		}
		case State.Selected:
			color = SelectColor;
			flag = editMode && Mathf.Repeat(num, 0.3f) < 0.18f;
			if (num > Plugin.MarkerSelectTimeout.Value)
			{
				SetState(State.Resting);
			}
			break;
		}
		if (MarkerEditor.Hovered == this)
		{
			if (Current == State.Resting)
			{
				color = HoverColor;
			}
			if (Current != State.Placing)
			{
				num2 *= 1.6f;
			}
		}
		_renderer.enabled = flag;
		if (flag)
		{
			_mat.color = color;
			((Component)this).transform.localScale = Vector3.one * ScreenConstant(((Component)this).transform.position, num2);
		}
	}

	public static float ScreenConstant(Vector3 pos, float size)
	{
		//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)
		FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
		if ((Object)(object)currentPlayerBody == (Object)null || (Object)(object)currentPlayerBody.Head == (Object)null)
		{
			return size;
		}
		float num = Vector3.Distance(currentPlayerBody.Head.position, pos);
		return size * Mathf.Max(num, 0.25f);
	}

	private void OnDestroy()
	{
		All.Remove(this);
		if ((Object)(object)_mat != (Object)null)
		{
			Object.Destroy((Object)(object)_mat);
		}
	}
}
public static class Ballistic
{
	private const int Buffer = 16;

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

	public static float ClearanceBelow(Vector3 point, float maxDrop, Sosig selfSosig, Transform selfRoot)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		float num = float.MaxValue;
		int num2 = Physics.RaycastNonAlloc(point + Vector3.up * 0.02f, Vector3.down, Hits, maxDrop + 0.02f, -5, (QueryTriggerInteraction)1);
		for (int i = 0; i < num2; i++)
		{
			Collider collider = ((RaycastHit)(ref Hits[i])).collider;
			if (!((Object)(object)collider == (Object)null) && !IsSelf(collider, selfSosig, selfRoot))
			{
				float num3 = ((RaycastHit)(ref Hits[i])).distance - 0.02f;
				if (num3 < num)
				{
					num = num3;
				}
			}
		}
		if (!(num < 0f))
		{
			return num;
		}
		return 0f;
	}

	private static bool IsSelf(Collider c, Sosig s, Transform root)
	{
		if ((Object)(object)s != (Object)null)
		{
			SosigLink componentInParent = ((Component)c).GetComponentInParent<SosigLink>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.S == s)
			{
				return true;
			}
			SosigWearable componentInParent2 = ((Component)c).GetComponentInParent<SosigWearable>();
			if ((Object)(object)componentInParent2 != (Object)null && componentInParent2.S == s)
			{
				return true;
			}
		}
		if ((Object)(object)root != (Object)null)
		{
			if (!((Object)(object)((Component)c).transform == (Object)(object)root))
			{
				return ((Component)c).transform.IsChildOf(root);
			}
			return true;
		}
		return false;
	}

	public static float TimeToGround(float verticalSpeed, float clearance)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Abs(Physics.gravity.y);
		if (num < 0.01f || clearance >= float.MaxValue)
		{
			return float.MaxValue;
		}
		float num2 = verticalSpeed * verticalSpeed + 2f * num * Mathf.Max(clearance, 0f);
		if (num2 <= 0f)
		{
			return 0f;
		}
		return Mathf.Max(0f, (verticalSpeed + Mathf.Sqrt(num2)) / num);
	}
}
public class CarriedBodies : MonoBehaviour
{
	private const float WatchSeconds = 1f;

	private Rigidbody _root;

	private Rigidbody[] _parts;

	private readonly HashSet<Rigidbody> _done = new HashSet<Rigidbody>();

	private float _until;

	private bool _report;

	private Vector3 _aim;

	private float _flightTime;

	private float _start;

	private bool _reaimed;

	private const float ReaimBy = 0.5f;

	public static void Begin(FVRPhysicalObject obj, Vector3 aim, float flightTime)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)obj == (Object)null) && !((Object)(object)obj.RootRigidbody == (Object)null))
		{
			CarriedBodies carriedBodies = ((Component)obj).gameObject.GetComponent<CarriedBodies>();
			if ((Object)(object)carriedBodies == (Object)null)
			{
				carriedBodies = ((Component)obj).gameObject.AddComponent<CarriedBodies>();
			}
			carriedBodies._root = obj.RootRigidbody;
			carriedBodies._parts = ((Component)obj).GetComponentsInChildren<Rigidbody>(true);
			carriedBodies._done.Clear();
			carriedBodies._start = Time.time;
			carriedBodies._until = Time.time + 1f;
			carriedBodies._aim = aim;
			carriedBodies._flightTime = flightTime;
			carriedBodies._report = Plugin.DebugLog.Value;
			carriedBodies._reaimed = false;
			((Behaviour)carriedBodies).enabled = true;
			carriedBodies.Sync();
		}
	}

	private void FixedUpdate()
	{
		if ((Object)(object)_root == (Object)null || Time.time > _until)
		{
			if (!_report)
			{
				((Behaviour)this).enabled = false;
			}
			return;
		}
		Sync();
		if (!_reaimed && _done.Count > 0 && (!StillAttached() || Time.time - _start > 0.5f))
		{
			Reaim();
		}
	}

	private bool StillAttached()
	{
		foreach (Rigidbody item in _done)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			Joint[] components = ((Component)item).GetComponents<Joint>();
			for (int i = 0; i < components.Length; i++)
			{
				if ((Object)(object)components[i] != (Object)null && (Object)(object)components[i].connectedBody == (Object)(object)_root)
				{
					return true;
				}
			}
		}
		return false;
	}

	private void Reaim()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: 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_007b: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		_reaimed = true;
		float num = Mathf.Abs(Physics.gravity.y);
		Vector3 worldCenterOfMass = _root.worldCenterOfMass;
		Vector3 velocity = _root.velocity;
		if (num < 0.01f || ((Vector3)(ref velocity)).sqrMagnitude < 1f)
		{
			return;
		}
		Vector3 val = _aim - worldCenterOfMass;
		if (((Vector3)(ref val)).magnitude < 1f || !ThrowSolver.TrySolve(worldCenterOfMass, _aim, ((Vector3)(ref velocity)).magnitude, num, out var solved))
		{
			return;
		}
		float num2 = Vector3.Angle(solved, velocity);
		if (!(num2 > 15f) && !(((Vector3)(ref solved)).magnitude > ((Vector3)(ref velocity)).magnitude * 1.15f))
		{
			_root.velocity = solved;
			if (_report)
			{
				Plugin.Log.LogInfo((object)("[TA]   put back on its arc after the spoon: " + num2.ToString("F1") + " deg, " + (((Vector3)(ref solved)).magnitude - ((Vector3)(ref velocity)).magnitude).ToString("+0.00;-0.00") + " m/s"));
			}
		}
	}

	private void Sync()
	{
		//IL_006c: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		if (_parts == null)
		{
			return;
		}
		for (int i = 0; i < _parts.Length; i++)
		{
			Rigidbody val = _parts[i];
			if (!((Object)(object)val == (Object)null) && val != _root && !_done.Contains(val) && ((Component)val).gameObject.activeInHierarchy && !val.isKinematic)
			{
				IgnoreAgainstRoot(val);
				val.velocity = _root.GetPointVelocity(val.worldCenterOfMass);
				val.angularVelocity = _root.angularVelocity;
				val.drag = 0f;
				_done.Add(val);
				if (_report)
				{
					Plugin.Log.LogInfo((object)("[TA]   " + ((Object)val).name + " came loose " + (Time.time - _start).ToString("F2") + "s after release; set moving with the throw"));
				}
			}
		}
	}

	private void IgnoreAgainstRoot(Rigidbody part)
	{
		Collider[] componentsInChildren = ((Component)part).GetComponentsInChildren<Collider>();
		Collider[] componentsInChildren2 = ((Component)_root).GetComponentsInChildren<Collider>();
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] == (Object)null || !componentsInChildren[i].enabled)
			{
				continue;
			}
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if (!((Object)(object)componentsInChildren2[j] == (Object)null) && componentsInChildren2[j].enabled && ((Component)componentsInChildren2[j]).gameObject.activeInHierarchy && componentsInChildren2[j].attachedRigidbody != part)
				{
					Physics.IgnoreCollision(componentsInChildren[i], componentsInChildren2[j], true);
				}
			}
		}
	}

	private void OnCollisionEnter(Collision col)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		if (_report && !((Object)(object)_root == (Object)null) && (!((Object)(object)col.collider != (Object)null) || !((Component)col.collider).transform.IsChildOf(((Component)this).transform)))
		{
			_report = false;
			Vector3 val = _root.worldCenterOfMass - _aim;
			Plugin.Log.LogInfo((object)("[TA]   first touched " + (((Object)(object)col.collider != (Object)null) ? ((Object)col.collider).name : "?") + " " + (Time.time - _start).ToString("F2") + "s into a " + _flightTime.ToString("F2") + "s flight, " + (((Vector3)(ref val)).magnitude * 100f).ToString("F0") + " cm from the aim (" + ((val.y >= 0f) ? "+" : "") + (val.y * 100f).ToString("F0") + " cm up/down)"));
		}
	}
}
internal static class ConfigMigration
{
	private const string AddedSince130 = "Dagger";

	private static Dictionary<string, string> _fromOldFile;

	public static void AdoptOldFile(ConfigFile config, string oldFile, string newFile)
	{
		try
		{
			if (!File.Exists(oldFile))
			{
				return;
			}
			if (!File.Exists(newFile))
			{
				File.Copy(oldFile, newFile);
				config.Reload();
				Plugin.Log.LogInfo((object)("Settings carried over from " + Path.GetFileName(oldFile) + "."));
			}
			else
			{
				_fromOldFile = Parse(File.ReadAllLines(oldFile));
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not read the old settings file, it is left where it is: " + ex.Message));
			return;
		}
		try
		{
			File.Delete(oldFile);
		}
		catch (Exception ex2)
		{
			Plugin.Log.LogWarning((object)("Could not remove " + Path.GetFileName(oldFile) + ": " + ex2.Message));
		}
	}

	public static void Run(ConfigFile config)
	{
		try
		{
			Dictionary<ConfigDefinition, string> dictionary = Orphans(config);
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			if (_fromOldFile != null)
			{
				foreach (KeyValuePair<string, string> item in _fromOldFile)
				{
					dictionary2[item.Key] = item.Value;
				}
			}
			if (dictionary != null)
			{
				foreach (KeyValuePair<ConfigDefinition, string> item2 in dictionary)
				{
					dictionary2[Key(item2.Key.Section, item2.Key.Key)] = item2.Value;
				}
			}
			if (dictionary2.Count == 0)
			{
				return;
			}
			int num = 0;
			if (_fromOldFile != null)
			{
				List<ConfigDefinition> list = new List<ConfigDefinition>(config.Keys);
				for (int i = 0; i < list.Count; i++)
				{
					if (_fromOldFile.TryGetValue(Key(list[i].Section, list[i].Key), out var value))
					{
						num += Take(config[list[i]], value);
					}
				}
			}
			num += Rename(dictionary2, "General", "Enabled", (ConfigEntryBase)(object)Plugin.Enabled);
			num += Rename(dictionary2, "Eligibility", "AssistHandguns", (ConfigEntryBase)(object)Plugin.AssistHandguns);
			num += Rename(dictionary2, "Eligibility", "AssistLongGuns", (ConfigEntryBase)(object)Plugin.AssistLongGuns);
			num += Rename(dictionary2, "Eligibility", "AssistAmmunition", (ConfigEntryBase)(object)Plugin.AssistAmmunition);
			num += Rename(dictionary2, "Eligibility", "AssistMeleeWeapons", (ConfigEntryBase)(object)Plugin.AssistMeleeWeapons);
			num += Rename(dictionary2, "Eligibility", "AssistAttachments", (ConfigEntryBase)(object)Plugin.AssistAttachments);
			num += Rename(dictionary2, "Eligibility", "AssistMisc", (ConfigEntryBase)(object)Plugin.AssistMisc);
			num += Rename(dictionary2, "Eligibility", "BlacklistNames", (ConfigEntryBase)(object)Plugin.BlacklistNames);
			num += Rename(dictionary2, "Eligibility", "BlacklistTypes", (ConfigEntryBase)(object)Plugin.BlacklistTypes);
			num += Rename(dictionary2, "Debug", "DebugLog", (ConfigEntryBase)(object)Plugin.DebugLog);
			num += Rename(dictionary2, "Debug", "DebugDrawTrajectory", (ConfigEntryBase)(object)Plugin.DebugDrawTrajectory);
			num += Rename(dictionary2, "4. Debug", "DebugDrawTrajectory", (ConfigEntryBase)(object)Plugin.DebugDrawTrajectory);
			if (dictionary2.TryGetValue(Key("Targeting", "LeadMovingTargets"), out var value2) && IsFalse(value2))
			{
				num += Take((ConfigEntryBase)(object)Plugin.LeadStrength, "0");
			}
			if (dictionary2.TryGetValue(Key("Spin", "EnableSpin"), out value2) && IsFalse(value2))
			{
				num += Take((ConfigEntryBase)(object)Plugin.KnifeThrowStyle, "Spear");
			}
			if (dictionary2.TryGetValue(Key("Spin", "AlwaysSpinNames"), out value2))
			{
				num += Take((ConfigEntryBase)(object)Plugin.AddSpinWeapons, ListChanges(value2, "Tomahawk,Hatchet,Axe,Cleaver,Kukri,Sickle,Billhook,Pickaxe,Bardiche,Mace,Warhammer,Hammer,Sledge,Mallet,Crowbar,PipeWrench,Wrench,CircleSaw"));
			}
			if (dictionary2.TryGetValue(Key("Spin", "SpearNames"), out value2))
			{
				num += Take((ConfigEntryBase)(object)Plugin.AddSpearWeapons, ListChanges(value2, "Katana,Rapier,Estoc,Claymore,Espadon,Falchion,Flameberg,Grossmesser,Katzbalger,Zweihander,Gladius,Pilum,Cutlass,Machete,Kabartana,LaserSword,LongSword,BastardSword,ArmingSword,Pitchfork,Pencil,Screwdriver,Scraper,Dagger"));
			}
			if (dictionary2.TryGetValue(Key("Spin", "DiscSpinNames"), out value2))
			{
				num += Take((ConfigEntryBase)(object)Plugin.AddDiscWeapons, ListChanges(value2, "Shuriken"));
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)("Carried " + num + " setting(s) over from an older version's config."));
			}
			if (dictionary != null && dictionary.Count > 0)
			{
				dictionary.Clear();
				config.Save();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Could not carry over settings from an older version: " + ex.Message));
		}
		finally
		{
			_fromOldFile = null;
		}
	}

	private static int Rename(Dictionary<string, string> old, string section, string key, ConfigEntryBase target)
	{
		if (!old.TryGetValue(Key(section, key), out var value))
		{
			return 0;
		}
		return Take(target, value);
	}

	private static int Take(ConfigEntryBase target, string value)
	{
		if (target == null || value == null || !AtDefault(target))
		{
			return 0;
		}
		target.SetSerializedValue(value);
		return (!AtDefault(target)) ? 1 : 0;
	}

	private static bool AtDefault(ConfigEntryBase e)
	{
		return object.Equals(e.BoxedValue, e.DefaultValue);
	}

	private static bool IsFalse(string v)
	{
		if (v != null)
		{
			return string.Equals(v.Trim(), "false", StringComparison.OrdinalIgnoreCase);
		}
		return false;
	}

	private static string ListChanges(string oldList, string builtIn)
	{
		List<string> list = Names(oldList);
		List<string> list2 = Names(builtIn);
		List<string> names = Names("Dagger");
		List<string> list3 = new List<string>();
		for (int i = 0; i < list.Count; i++)
		{
			if (!Has(list2, list[i]) && !Has(list3, list[i]))
			{
				list3.Add(list[i]);
			}
		}
		for (int j = 0; j < list2.Count; j++)
		{
			if (!Has(list, list2[j]) && !Has(names, list2[j]))
			{
				list3.Add("!" + list2[j]);
			}
		}
		return string.Join(",", list3.ToArray());
	}

	private static List<string> Names(string list)
	{
		List<string> list2 = new List<string>();
		if (string.IsNullOrEmpty(list))
		{
			return list2;
		}
		string[] array = list.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length > 0)
			{
				list2.Add(text);
			}
		}
		return list2;
	}

	private static bool Has(List<string> names, string name)
	{
		for (int i = 0; i < names.Count; i++)
		{
			if (string.Equals(names[i], name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
		}
		return false;
	}

	private static string Key(string section, string key)
	{
		return section + "\n" + key;
	}

	private static Dictionary<string, string> Parse(string[] lines)
	{
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		string section = "";
		for (int i = 0; i < lines.Length; i++)
		{
			string text = lines[i].Trim();
			if (text.Length == 0 || text[0] == '#')
			{
				continue;
			}
			if (text[0] == '[' && text[text.Length - 1] == ']')
			{
				section = text.Substring(1, text.Length - 2).Trim();
				continue;
			}
			int num = text.IndexOf('=');
			if (num > 0)
			{
				dictionary[Key(section, text.Substring(0, num).Trim())] = text.Substring(num + 1).Trim();
			}
		}
		return dictionary;
	}

	private static Dictionary<ConfigDefinition, string> Orphans(ConfigFile config)
	{
		PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
		if ((object)propertyInfo == null)
		{
			return null;
		}
		return propertyInfo.GetValue(config, null) as Dictionary<ConfigDefinition, string>;
	}
}
public static class DebugDraw
{
	private class SelfDestruct : MonoBehaviour
	{
		public float Seconds = 3f;

		private float _born;

		private void Awake()
		{
			_born = Time.time;
		}

		private void Update()
		{
			if (Time.time - _born >= Seconds)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}

	private const float Width = 0.012f;

	private static Material _mat;

	private static readonly List<GameObject> Live = new List<GameObject>();

	private static readonly Dictionary<int, Material> Tinted = new Dictionary<int, Material>();

	private static Material Mat
	{
		get
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if ((Object)(object)_mat == (Object)null)
			{
				Shader val = Shader.Find("Sprites/Default");
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Particles/Additive");
				}
				_mat = new Material(val);
				_mat.renderQueue = 4000;
			}
			return _mat;
		}
	}

	public static void Line(Vector3 from, Vector3 to, Color color, float seconds)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		Polyline((Vector3[])(object)new Vector3[2] { from, to }, color, seconds);
	}

	public static void Polyline(Vector3[] points, Color color, float seconds)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		if (points != null && points.Length >= 2)
		{
			GameObject val = new GameObject("ThrowAssist_DebugLine");
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			((Renderer)val2).sharedMaterial = Mat;
			val2.useWorldSpace = true;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			val2.SetVertexCount(points.Length);
			for (int i = 0; i < points.Length; i++)
			{
				val2.SetPosition(i, points[i]);
			}
			val2.SetWidth(0.012f, 0.012f);
			val2.SetColors(color, color);
			val.AddComponent<SelfDestruct>().Seconds = seconds;
			Live.Add(val);
			Prune();
		}
	}

	public static void Cone(Vector3 origin, Vector3 dir, float halfAngleDeg, float length, Color color, float seconds, int segments = 24)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0032: 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_003d: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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_00d5: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		if (((Vector3)(ref dir)).sqrMagnitude < 1E-06f)
		{
			return;
		}
		dir = ((Vector3)(ref dir)).normalized;
		Vector3 val = Vector3.Cross(dir, Vector3.up);
		if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
		{
			val = Vector3.Cross(dir, Vector3.forward);
		}
		val = ((Vector3)(ref val)).normalized;
		Vector3 val2 = Vector3.Cross(val, dir);
		Vector3 normalized = ((Vector3)(ref val2)).normalized;
		float num = Mathf.Tan(Mathf.Clamp(halfAngleDeg, 0f, 89f) * ((float)Math.PI / 180f));
		for (int i = 1; i <= 3; i++)
		{
			float num2 = length * (float)i / 3f;
			float num3 = num2 * num;
			Vector3 val3 = origin + dir * num2;
			Vector3[] array = (Vector3[])(object)new Vector3[segments + 1];
			for (int j = 0; j <= segments; j++)
			{
				float num4 = (float)j / (float)segments * (float)Math.PI * 2f;
				array[j] = val3 + (val * Mathf.Cos(num4) + normalized * Mathf.Sin(num4)) * num3;
			}
			Polyline(array, color, seconds);
		}
	}

	public static void Arrow(Vector3 from, Vector3 to, Color color, float seconds)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		Line(from, to, color, seconds);
		Head(from, to, color, seconds);
	}

	public static void ArrowPath(List<Vector3> points, Color color, float seconds)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_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 (points != null && points.Count >= 2)
		{
			Polyline(points.ToArray(), color, seconds);
			Head(points[points.Count - 2], points[points.Count - 1], color, seconds);
		}
	}

	private static void Head(Vector3 from, Vector3 to, Color color, float seconds)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0029: 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_004c: 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_004e: 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)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: 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_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_00ab: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = to - from;
		if (!(((Vector3)(ref val)).sqrMagnitude < 1E-06f))
		{
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = Vector3.Cross(val, Vector3.up);
			if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
			{
				val2 = Vector3.Cross(val, Vector3.forward);
			}
			val2 = ((Vector3)(ref val2)).normalized;
			Line(to, to - val * 0.12f + val2 * 0.12f * 0.5f, color, seconds);
			Line(to, to - val * 0.12f - val2 * 0.12f * 0.5f, color, seconds);
		}
	}

	public static void Arc(Vector3 origin, Vector3 launch, float flightTime, Color color, float seconds, int steps = 16)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		if (!(flightTime <= 0f))
		{
			Vector3[] array = (Vector3[])(object)new Vector3[steps + 1];
			for (int i = 0; i <= steps; i++)
			{
				float num = flightTime * (float)i / (float)steps;
				array[i] = origin + launch * num + 0.5f * Physics.gravity * num * num;
			}
			Polyline(array, color, seconds);
		}
	}

	public static void Quad(Vector3 at, Vector3 normal, float size, Color color, float seconds)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: 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_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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		if (((Vector3)(ref normal)).sqrMagnitude < 1E-06f)
		{
			normal = Vector3.up;
		}
		GameObject val = GameObject.CreatePrimitive((PrimitiveType)5);
		((Object)val).name = "ThrowAssist_DebugQuad";
		Collider component = val.GetComponent<Collider>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
		val.transform.position = at + ((Vector3)(ref normal)).normalized * 0.005f;
		val.transform.rotation = Quaternion.LookRotation(-((Vector3)(ref normal)).normalized);
		val.transform.localScale = new Vector3(size, size, size);
		Renderer component2 = val.GetComponent<Renderer>();
		component2.sharedMaterial = TintedMat(color);
		component2.shadowCastingMode = (ShadowCastingMode)0;
		component2.receiveShadows = false;
		val.AddComponent<SelfDestruct>().Seconds = seconds;
		Live.Add(val);
		Prune();
	}

	private static Material TintedMat(Color color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		int key = (Color32.op_Implicit(color).r << 24) | (Color32.op_Implicit(color).g << 16) | (Color32.op_Implicit(color).b << 8) | Color32.op_Implicit(color).a;
		if (Tinted.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		Shader val = Shader.Find("Sprites/Default");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Particles/Additive");
		}
		value = new Material(val);
		value.renderQueue = 4000;
		value.color = color;
		Tinted[key] = value;
		return value;
	}

	public static void Points(Transform parent, List<Vector3> worldPoints, List<Vector3> normals, List<Color> colors, float size, float seconds)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Expected O, but got Unknown
		//IL_006f: 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_0079: 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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00c8: 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_00d4: 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_00df: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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)
		//IL_010a: 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_00b8: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: 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_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: 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_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		if (worldPoints == null || worldPoints.Count == 0)
		{
			return;
		}
		GameObject val = new GameObject("ThrowAssist_DebugPoints");
		if ((Object)(object)parent != (Object)null)
		{
			val.transform.SetParent(parent, false);
		}
		int count = worldPoints.Count;
		Vector3[] array = (Vector3[])(object)new Vector3[count * 4];
		Color[] array2 = (Color[])(object)new Color[count * 4];
		int[] array3 = new int[count * 6];
		float num = size * 0.5f;
		for (int i = 0; i < count; i++)
		{
			Vector3 val2 = ((normals != null && i < normals.Count) ? normals[i] : Vector3.up);
			if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
			{
				val2 = Vector3.up;
			}
			((Vector3)(ref val2)).Normalize();
			Vector3 val3 = Vector3.Cross(val2, Vector3.up);
			if (((Vector3)(ref val3)).sqrMagnitude < 1E-06f)
			{
				val3 = Vector3.Cross(val2, Vector3.forward);
			}
			val3 = ((Vector3)(ref val3)).normalized * num;
			Vector3 val4 = Vector3.Cross(((Vector3)(ref val3)).normalized, val2);
			Vector3 val5 = ((Vector3)(ref val4)).normalized * num;
			Vector3 val6 = worldPoints[i] + val2 * 0.004f;
			Vector3 val7 = (((Object)(object)parent != (Object)null) ? parent.InverseTransformPoint(val6) : val6);
			Vector3 val8 = (((Object)(object)parent != (Object)null) ? parent.InverseTransformVector(val3) : val3);
			Vector3 val9 = (((Object)(object)parent != (Object)null) ? parent.InverseTransformVector(val5) : val5);
			int num2 = i * 4;
			array[num2] = val7 - val8 - val9;
			array[num2 + 1] = val7 + val8 - val9;
			array[num2 + 2] = val7 + val8 + val9;
			array[num2 + 3] = val7 - val8 + val9;
			array2[num2 + 3] = (array2[num2 + 2] = (array2[num2 + 1] = (array2[num2] = ((colors != null && i < colors.Count) ? colors[i] : Color.white))));
			int num3 = i * 6;
			array3[num3] = num2;
			array3[num3 + 1] = num2 + 2;
			array3[num3 + 2] = num2 + 1;
			array3[num3 + 3] = num2;
			array3[num3 + 4] = num2 + 3;
			array3[num3 + 5] = num2 + 2;
		}
		Mesh val10 = new Mesh();
		val10.vertices = array;
		val10.colors = array2;
		val10.triangles = array3;
		val10.RecalculateBounds();
		val.AddComponent<MeshFilter>().mesh = val10;
		MeshRenderer obj = val.AddComponent<MeshRenderer>();
		((Renderer)obj).sharedMaterial = Mat;
		((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)obj).receiveShadows = false;
		val.AddComponent<SelfDestruct>().Seconds = seconds;
		Live.Add(val);
		Prune();
	}

	public static void Cross(Vector3 at, float size, Color color, float seconds)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_003a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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_0064: 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_006f: 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)
		Line(at - Vector3.right * size, at + Vector3.right * size, color, seconds);
		Line(at - Vector3.up * size, at + Vector3.up * size, color, seconds);
		Line(at - Vector3.forward * size, at + Vector3.forward * size, color, seconds);
	}

	private static void Prune()
	{
		for (int num = Live.Count - 1; num >= 0; num--)
		{
			if ((Object)(object)Live[num] == (Object)null)
			{
				Live.RemoveAt(num);
			}
		}
		while (Live.Count > 240)
		{
			if ((Object)(object)Live[0] != (Object)null)
			{
				Object.Destroy((Object)(object)Live[0]);
			}
			Live.RemoveAt(0);
		}
	}
}
public class HarnessHold : MonoBehaviour
{
	private class Entry
	{
		public float Until;

		public FVRQuickBeltSlot Slot;
	}

	private static readonly Dictionary<FVRPhysicalObject, Entry> Holds = new Dictionary<FVRPhysicalObject, Entry>();

	private static readonly List<FVRPhysicalObject> Due = new List<FVRPhysicalObject>();

	private static bool _releasing;

	public static void Begin(FVRPhysicalObject obj, float flightTime)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			Entry entry = new Entry();
			entry.Until = Time.time + flightTime + Plugin.HarnessHoldAfterArrival.Value;
			Holds[obj] = entry;
		}
	}

	public static void Clear(FVRPhysicalObject obj)
	{
		if ((Object)(object)obj != (Object)null && Holds.Count > 0)
		{
			Holds.Remove(obj);
		}
	}

	public static void ClearAll()
	{
		Holds.Clear();
	}

	public static bool Allow(FVRPhysicalObject obj, FVRQuickBeltSlot slot)
	{
		if (_releasing || (Object)(object)slot == (Object)null || (Object)(object)obj == (Object)null || Holds.Count == 0)
		{
			return true;
		}
		if (!Holds.TryGetValue(obj, out var value))
		{
			return true;
		}
		if (((FVRInteractiveObject)obj).IsHeld || Time.time >= value.Until)
		{
			Holds.Remove(obj);
			return true;
		}
		value.Slot = slot;
		if (Plugin.DebugLog.Value)
		{
			Plugin.Log.LogInfo((object)("[TA]   " + ((Object)obj).name + " called back to its slot mid-flight; holding it off for " + (value.Until - Time.time).ToString("F1") + "s more"));
		}
		return false;
	}

	private void Update()
	{
		if (Holds.Count == 0)
		{
			return;
		}
		Due.Clear();
		foreach (KeyValuePair<FVRPhysicalObject, Entry> hold in Holds)
		{
			if ((Object)(object)hold.Key == (Object)null || Time.time >= hold.Value.Until)
			{
				Due.Add(hold.Key);
			}
		}
		for (int i = 0; i < Due.Count; i++)
		{
			FVRPhysicalObject val = Due[i];
			Entry entry = Holds[val];
			Holds.Remove(val);
			if ((Object)(object)val == (Object)null || (Object)(object)entry.Slot == (Object)null || ((FVRInteractiveObject)val).IsHeld || (Object)(object)val.QuickbeltSlot != (Object)null)
			{
				continue;
			}
			_releasing = true;
			try
			{
				FVRInteractiveObject heldObject = entry.Slot.HeldObject;
				FVRPhysicalObject val2 = (FVRPhysicalObject)(object)((heldObject is FVRPhysicalObject) ? heldObject : null);
				if ((Object)(object)val2 != (Object)null && val2 != val)
				{
					val2.SetQuickBeltSlot((FVRQuickBeltSlot)null);
				}
				val.SetQuickBeltSlot(entry.Slot);
			}
			finally
			{
				_releasing = false;
			}
		}
	}
}
public class MarkerEditor : MonoBehaviour
{
	private const float PointerScale = 0.8f;

	private FVRViveHand _owner;

	private FVRViveHand _lastPullHand;

	private float _lastPullTime = -10f;

	private bool _lastPullWasSingle;

	private bool _pressActive;

	private float _pressStart;

	private GameObject _liveDot;

	private Material _liveMat;

	private bool _aimValid;

	private RaycastHit _aimHit;

	private AimMarker _selected;

	public static bool EditMode { get; private set; }

	public static AimMarker Hovered { get; private set; }

	private void Update()
	{
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if ((Object)(object)currentMovementManager == (Object)null || currentMovementManager.Hands == null || !Plugin.Enabled.Value || !Plugin.MarkersEnabled.Value)
		{
			if (EditMode)
			{
				Exit("unavailable");
			}
			return;
		}
		if (EditMode && ((Object)(object)_owner == (Object)null || !HoldsMarkerTool(_owner)))
		{
			Exit("weapon released");
		}
		if (EditMode)
		{
			ReadEditTrigger();
		}
		else
		{
			ReadPulls(currentMovementManager.Hands);
		}
		if (EditMode)
		{
			Aim();
			return;
		}
		Hovered = null;
		HideLiveDot();
	}

	private void ReadPulls(FVRViveHand[] hands)
	{
		float value = Plugin.MarkerDoublePullWindow.Value;
		foreach (FVRViveHand val in hands)
		{
			if (!((Object)(object)val == (Object)null) && val.Input.TriggerDown && HoldsMarkerTool(val))
			{
				if (_lastPullWasSingle && val == _lastPullHand && Time.time - _lastPullTime <= value)
				{
					_lastPullWasSingle = false;
					Enter(val);
					break;
				}
				_lastPullHand = val;
				_lastPullTime = Time.time;
				_lastPullWasSingle = true;
			}
		}
	}

	private void ReadEditTrigger()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		HandInput input = _owner.Input;
		if (input.TriggerDown)
		{
			_pressActive = true;
			_pressStart = Time.time;
		}
		if (_pressActive)
		{
			if (input.TriggerPressed && Time.time - _pressStart >= Plugin.MarkerExitHoldTime.Value)
			{
				_pressActive = false;
				Exit("trigger held");
			}
			else if (input.TriggerUp || !input.TriggerPressed)
			{
				_pressActive = false;
				SinglePull();
			}
		}
	}

	private static bool HoldsMarkerTool(FVRViveHand h)
	{
		if ((Object)(object)h == (Object)null)
		{
			return false;
		}
		FVRInteractiveObject currentInteractable = h.CurrentInteractable;
		if ((Object)(object)currentInteractable == (Object)null)
		{
			return false;
		}
		if (!(currentInteractable is FVRMeleeWeapon) && !IsOfNamedType(currentInteractable, Plugin.MarkerThrowableTypes.Value))
		{
			return false;
		}
		return !IsOfNamedType(currentInteractable, Plugin.MarkerExcludedTypes.Value);
	}

	private static bool IsOfNamedType(FVRInteractiveObject o, string list)
	{
		if (string.IsNullOrEmpty(list))
		{
			return false;
		}
		string[] array = list.Split(new char[1] { ',' });
		Type type = ((object)o).GetType();
		while ((object)type != null)
		{
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i].Trim(), type.Name, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			type = type.BaseType;
		}
		return false;
	}

	private void Enter(FVRViveHand owner)
	{
		EditMode = true;
		_owner = owner;
		_pressActive = false;
		Buzz(owner);
		Log("edit mode on (" + (owner.IsThisTheRightHand ? "right" : "left") + " hand)");
	}

	private void Exit(string why)
	{
		EditMode = false;
		if ((Object)(object)_selected != (Object)null)
		{
			_selected.SetState(AimMarker.State.Resting);
			_selected = null;
		}
		if ((Object)(object)_owner != (Object)null)
		{
			Buzz(_owner);
		}
		_owner = null;
		_lastPullWasSingle = false;
		_pressActive = false;
		Hovered = null;
		HideLiveDot();
		Log("edit mode off: " + why);
	}

	private void Aim()
	{
		//IL_0065: 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_009a: 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)
		FVRViveHand val = (((Object)(object)_owner != (Object)null) ? _owner.OtherHand : null);
		_aimValid = (Object)(object)val != (Object)null && (Object)(object)val.PointingTransform != (Object)null && CastFromKnuckles(val, out _aimHit);
		if (!_aimValid)
		{
			Hovered = null;
			HideLiveDot();
			return;
		}
		Hovered = Touching(((RaycastHit)(ref _aimHit)).point);
		if ((Object)(object)Hovered != (Object)null)
		{
			HideLiveDot();
		}
		else
		{
			ShowLiveDot(((RaycastHit)(ref _aimHit)).point + ((RaycastHit)(ref _aimHit)).normal * 0.005f);
		}
	}

	private bool CastFromKnuckles(FVRViveHand pointer, out RaycastHit best)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		best = default(RaycastHit);
		Transform pointingTransform = pointer.PointingTransform;
		RaycastHit[] array = Physics.RaycastAll(pointingTransform.position, pointingTransform.forward, Plugin.MarkerMaxDistance.Value, -1, (QueryTriggerInteraction)1);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		Array.Sort(array, CompareDistance);
		for (int i = 0; i < array.Length; i++)
		{
			if (!IsIgnoredForPlacement(((RaycastHit)(ref array[i])).collider))
			{
				best = array[i];
				return true;
			}
		}
		return false;
	}

	private static int CompareDistance(RaycastHit a, RaycastHit b)
	{
		return ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance);
	}

	private bool IsIgnoredForPlacement(Collider c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return true;
		}
		Transform transform = ((Component)c).transform;
		if ((Object)(object)((Component)c).GetComponentInParent<FVRHealthBar>() != (Object)null)
		{
			return true;
		}
		FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
		if ((Object)(object)currentPlayerBody != (Object)null && transform.IsChildOf(((Component)currentPlayerBody).transform))
		{
			return true;
		}
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if ((Object)(object)currentMovementManager != (Object)null && currentMovementManager.Hands != null)
		{
			for (int i = 0; i < currentMovementManager.Hands.Length; i++)
			{
				FVRViveHand val = currentMovementManager.Hands[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (transform.IsChildOf(((Component)val).transform))
					{
						return true;
					}
					FVRInteractiveObject currentInteractable = val.CurrentInteractable;
					if ((Object)(object)currentInteractable != (Object)null && transform.IsChildOf(((Component)currentInteractable).transform))
					{
						return true;
					}
				}
			}
		}
		FVRPhysicalObject componentInParent = ((Component)c).GetComponentInParent<FVRPhysicalObject>();
		if ((Object)(object)componentInParent != (Object)null && (((FVRInteractiveObject)componentInParent).IsHeld || (Object)(object)componentInParent.QuickbeltSlot != (Object)null))
		{
			return true;
		}
		return false;
	}

	private unsafe void SinglePull()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		if (!_aimValid)
		{
			Log("pull ignored: pointer is not on a surface");
			return;
		}
		Vector3 point = ((RaycastHit)(ref _aimHit)).point;
		AimMarker aimMarker = Touching(point);
		if ((Object)(object)aimMarker != (Object)null)
		{
			if (aimMarker == _selected && aimMarker.Current == AimMarker.State.Selected)
			{
				_selected = null;
				Log("deleted marker on " + Describe(aimMarker));
				Object.Destroy((Object)(object)((Component)aimMarker).gameObject);
			}
			else
			{
				if ((Object)(object)_selected != (Object)null)
				{
					_selected.SetState(AimMarker.State.Resting);
				}
				_selected = aimMarker;
				aimMarker.SetState(AimMarker.State.Selected);
				Log("selected marker on " + Describe(aimMarker) + " - pull again to delete");
			}
			Buzz(_owner);
			return;
		}
		if ((Object)(object)_selected != (Object)null)
		{
			_selected.SetState(AimMarker.State.Resting);
			_selected = null;
		}
		if (AimMarker.GetAll().Count >= Plugin.MarkerMaxCount.Value)
		{
			int value = Plugin.MarkerMaxCount.Value;
			Log("not placed: already at MarkerMaxCount (" + value + ")");
			return;
		}
		AimMarker m = AimMarker.Create(_aimHit);
		Buzz(_owner);
		string text = Describe(m);
		Vector3 val = point;
		Log("placed marker on " + text + " at " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString());
	}

	private static AimMarker Touching(Vector3 pointer)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		List<AimMarker> all = AimMarker.GetAll();
		float value = Plugin.MarkerDotSize.Value;
		float num = AimMarker.ScreenConstant(pointer, value * 0.8f) * 0.5f;
		float value2 = Plugin.MarkerSelectTouchScale.Value;
		AimMarker result = null;
		float num2 = 1f;
		for (int i = 0; i < all.Count; i++)
		{
			AimMarker aimMarker = all[i];
			if (!((Component)aimMarker).gameObject.activeSelf)
			{
				continue;
			}
			float num3 = (AimMarker.ScreenConstant(aimMarker.Position, value) * 0.5f + num) * value2;
			if (!(num3 <= 0f))
			{
				float num4 = Vector3.Distance(aimMarker.Position, pointer) / num3;
				if (num4 <= num2)
				{
					num2 = num4;
					result = aimMarker;
				}
			}
		}
		return result;
	}

	private static string Describe(AimMarker m)
	{
		if ((Object)(object)m.OwnerSosig != (Object)null)
		{
			return ((Object)m.OwnerSosig).name + "/" + ((Object)m.Anchor).name;
		}
		if ((Object)(object)m.OwnerObject != (Object)null)
		{
			return ((Object)m.OwnerObject).name;
		}
		if (!((Object)(object)m.Anchor != (Object)null))
		{
			return "?";
		}
		return ((Object)m.Anchor).name;
	}

	private void ShowLiveDot(Vector3 pos)
	{
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: 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_008c: Expected O, but got Unknown
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_liveDot == (Object)null)
		{
			if ((Object)(object)_liveMat != (Object)null)
			{
				Object.Destroy((Object)(object)_liveMat);
			}
			_liveDot = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)_liveDot).name = "ThrowAssist_PointerDot";
			Collider component = _liveDot.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Shader val = Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Particles/Additive");
			}
			_liveMat = new Material(val);
			_liveMat.renderQueue = 4000;
			_liveMat.color = new Color(1f, 1f, 1f, 0.9f);
			Renderer component2 = _liveDot.GetComponent<Renderer>();
			component2.sharedMaterial = _liveMat;
			component2.shadowCastingMode = (ShadowCastingMode)0;
			component2.receiveShadows = false;
		}
		_liveMat.color = new Color(1f, 1f, 1f, 0.9f);
		_liveDot.SetActive(true);
		_liveDot.transform.position = pos;
		_liveDot.transform.localScale = Vector3.one * AimMarker.ScreenConstant(pos, Plugin.MarkerDotSize.Value * 0.8f);
	}

	private void HideLiveDot()
	{
		if ((Object)(object)_liveDot != (Object)null)
		{
			_liveDot.SetActive(false);
		}
	}

	private static void Buzz(FVRViveHand h)
	{
		if (!((Object)(object)h == (Object)null) && !((Object)(object)h.Buzzer == (Object)null))
		{
			h.Buzz(h.Buzzer.Buzz_BeginInteraction);
		}
	}

	private static void Log(string msg)
	{
		if (Plugin.DebugLog.Value)
		{
			Plugin.Log.LogInfo((object)("[Markers] " + msg));
		}
	}
}
public static class MeatFinder
{
	private struct Cell
	{
		public bool Hit;

		public bool Through;

		public Vector3 Point;

		public Vector3 Normal;
	}

	private const int Grid = 10;

	private const float Padding = 0.04f;

	private const int HitBuffer = 16;

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

	public static bool MustStick;

	public static bool SticksByStab;

	public static bool SticksByLodge;

	public static bool TryFindSoftSpot(Sosig s, SosigLink link, Vector3 origin, int minCells, out Vector3 aim, out int cells)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_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_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_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_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0077: 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_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0424: Unknown result type (might be due to invalid IL or missing references)
		//IL_0429: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: 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_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		aim = Vector3.zero;
		cells = 0;
		if ((Object)(object)s == (Object)null || (Object)(object)link == (Object)null)
		{
			return false;
		}
		if (!LimbBounds(link, out var b))
		{
			return false;
		}
		Vector3 center = ((Bounds)(ref b)).center;
		Vector3 val = center - origin;
		if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		((Vector3)(ref val)).Normalize();
		Vector3 val2 = Vector3.Cross(val, Vector3.up);
		if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f)
		{
			val2 = Vector3.Cross(val, Vector3.forward);
		}
		((Vector3)(ref val2)).Normalize();
		Vector3 val3 = Vector3.Cross(val2, val);
		Vector3 normalized = ((Vector3)(ref val3)).normalized;
		val3 = ((Bounds)(ref b)).extents;
		float num = ((Vector3)(ref val3)).magnitude + 0.04f;
		float num2 = num * 2f;
		float num3 = num + 0.25f;
		int num4 = ResolveMask();
		if (num4 == 0)
		{
			return false;
		}
		Cell[,] array = new Cell[10, 10];
		int num5 = 0;
		bool value = Plugin.DebugDrawTargeting.Value;
		List<Vector3> list = (value ? new List<Vector3>() : null);
		List<Vector3> list2 = (value ? new List<Vector3>() : null);
		List<Color> list3 = (value ? new List<Color>() : null);
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < 10; j++)
			{
				float num6 = ((float)i + 0.5f) / 10f - 0.5f;
				float num7 = ((float)j + 0.5f) / 10f - 0.5f;
				Vector3 val4 = center - val * num3 + val2 * (num6 * num2) + normalized * (num7 * num2);
				int num8 = Physics.RaycastNonAlloc(val4, val, Hits, num3 * 2f, num4, (QueryTriggerInteraction)2);
				float num9 = float.MaxValue;
				bool flag = false;
				bool flag2 = false;
				Vector3 val5 = Vector3.zero;
				Vector3 val6 = -val;
				for (int k = 0; k < num8; k++)
				{
					Collider collider = ((RaycastHit)(ref Hits[k])).collider;
					if (!((Object)(object)collider == (Object)null) && BelongsToLimb(collider, s, link) && !(((RaycastHit)(ref Hits[k])).distance >= num9))
					{
						num9 = ((RaycastHit)(ref Hits[k])).distance;
						val5 = ((RaycastHit)(ref Hits[k])).point;
						val6 = ((RaycastHit)(ref Hits[k])).normal;
						flag2 = CanPenetrate(collider, link, val4, val, num3 * 2f);
						flag = true;
					}
				}
				bool flag3 = false;
				if (flag && flag2 && Plugin.RequireLineOfSight.Value && !ThrowSolver.SosigPointInSight(origin, val5, s))
				{
					flag2 = false;
					flag3 = true;
				}
				array[i, j].Hit = flag;
				array[i, j].Through = flag && flag2;
				array[i, j].Point = val5;
				array[i, j].Normal = val6;
				if (array[i, j].Through)
				{
					num5++;
				}
				if (flag && value)
				{
					list.Add(val5);
					list2.Add(val6);
					list3.Add(flag3 ? new Color(0.5f, 0.5f, 0.5f, 0.6f) : (flag2 ? new Color(0.15f, 1f, 0.3f, 0.6f) : new Color(1f, 0.2f, 0.15f, 0.6f)));
				}
			}
		}
		if (value && list.Count > 0)
		{
			DebugDraw.Points(((Component)link).transform, list, list2, list3, num2 / 10f * 0.5f, Plugin.MeatScanDrawSeconds.Value);
		}
		if (num5 == 0)
		{
			return false;
		}
		List<List<int>> list4 = Patches(array);
		int num10 = -1;
		int num11 = 0;
		for (int l = 0; l < list4.Count; l++)
		{
			if (list4[l].Count >= minCells && list4[l].Count > num11)
			{
				num11 = list4[l].Count;
				num10 = l;
			}
		}
		if (num10 < 0)
		{
			return false;
		}
		aim = Centre(array, list4[num10]);
		cells = list4[num10].Count;
		return true;
	}

	private static bool CanPenetrate(Collider c, SosigLink link, Vector3 from, Vector3 dir, float dist)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		SosigWearable componentInParent = ((Component)c).GetComponentInParent<SosigWearable>();
		if ((Object)(object)componentInParent == (Object)null && (Object)(object)link != (Object)null)
		{
			link.HitsWearable(from, dir, dist, ref componentInParent);
		}
		if ((Object)(object)componentInParent == (Object)null)
		{
			return true;
		}
		if (componentInParent.MeleeDamMult_Piercing < Plugin.PenetrateThreshold.Value)
		{
			return false;
		}
		if (!MustStick)
		{
			return true;
		}
		if (!SticksByStab || !componentInParent.IsStabbable)
		{
			if (SticksByLodge)
			{
				return componentInParent.IsLodgeable;
			}
			return false;
		}
		return true;
	}

	private static bool LimbBounds(SosigLink link, out Bounds b)
	{
		//IL_0001: 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_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)
		b = default(Bounds);
		bool flag = false;
		Collider[] componentsInChildren = ((Component)link).GetComponentsInChildren<Collider>();
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if (!((Object)(object)componentsInChildren[i] == (Object)null) && componentsInChildren[i].enabled)
			{
				if (!flag)
				{
					b = componentsInChildren[i].bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref b)).Encapsulate(componentsInChildren[i].bounds);
				}
			}
		}
		return flag;
	}

	private static bool BelongsToLimb(Collider c, Sosig s, SosigLink link)
	{
		SosigWearable componentInParent = ((Component)c).GetComponentInParent<SosigWearable>();
		if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.L != (Object)null)
		{
			return componentInParent.L == link;
		}
		SosigLink componentInParent2 = ((Component)c).GetComponentInParent<SosigLink>();
		if ((Object)(object)componentInParent2 != (Object)null)
		{
			return componentInParent2 == link;
		}
		return false;
	}

	private static List<List<int>> Patches(Cell[,] grid)
	{
		List<List<int>> list = new List<List<int>>();
		bool[,] array = new bool[10, 10];
		List<int> list2 = new List<int>();
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < 10; j++)
			{
				if (!array[i, j] && grid[i, j].Through)
				{
					List<int> list3 = new List<int>();
					list2.Clear();
					list2.Add(i * 10 + j);
					array[i, j] = true;
					while (list2.Count > 0)
					{
						int num = list2[list2.Count - 1];
						list2.RemoveAt(list2.Count - 1);
						list3.Add(num);
						int num2 = num / 10;
						int num3 = num % 10;
						Push(grid, array, list2, num2 + 1, num3);
						Push(grid, array, list2, num2 - 1, num3);
						Push(grid, array, list2, num2, num3 + 1);
						Push(grid, array, list2, num2, num3 - 1);
					}
					list.Add(list3);
				}
			}
		}
		return list;
	}

	private static void Push(Cell[,] grid, bool[,] seen, List<int> stack, int x, int y)
	{
		if (x >= 0 && y >= 0 && x < 10 && y < 10 && !seen[x, y] && grid[x, y].Through)
		{
			seen[x, y] = true;
			stack.Add(x * 10 + y);
		}
	}

	private static Vector3 Centre(Cell[,] grid, List<int> patch)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Vector3.zero;
		for (int i = 0; i < patch.Count; i++)
		{
			val += grid[patch[i] / 10, patch[i] % 10].Point;
		}
		return val / (float)patch.Count;
	}

	private static int ResolveMask()
	{
		int num = 0;
		string[] array = Plugin.TargetLayers.Value.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length != 0)
			{
				int num2 = LayerMask.NameToLayer(text);
				if (num2 >= 0)
				{
					num |= 1 << num2;
				}
			}
		}
		return num;
	}
}
public static class Patches
{
	public static void Apply(Harmony harmony)
	{
		MethodInfo target = AccessTools.Method(typeof(FVRPhysicalObject), "EndInteraction", new Type[1] { typeof(FVRViveHand) }, (Type[])null);
		MethodInfo target2 = AccessTools.Method(typeof(MeleeParams), "MeleeEndInteraction", new Type[1] { typeof(FVRViveHand) }, (Type[])null);
		MethodInfo target3 = AccessTools.Method(typeof(FVRPhysicalObject), "SetQuickBeltSlot", new Type[1] { typeof(FVRQuickBeltSlot) }, (Type[])null);
		MethodInfo target4 = AccessTools.Method(typeof(FVRPhysicalObject), "BeginInteraction", new Type[1] { typeof(FVRViveHand) }, (Type[])null);
		MethodInfo target5 = AccessTools.Method(typeof(Sosig), "Start", (Type[])null, (Type[])null);
		MethodInfo target6 = AccessTools.Method(typeof(Sosig), "SosigDies", (Type[])null, (Type[])null);
		Patch(harmony, target, "FVRPhysicalObject.EndInteraction", null, "EndInteraction_Postfix");
		Patch(harmony, target2, "FVRPhysicalObject.MeleeParams.MeleeEndInteraction", "MeleeEndInteraction_Prefix", null);
		Patch(harmony, target3, "FVRPhysicalObject.SetQuickBeltSlot", "SetQuickBeltSlot_Prefix", null);
		Patch(harmony, target4, "FVRPhysicalObject.BeginInteraction", null, "BeginInteraction_Postfix");
		Patch(harmony, target5, "Sosig.Start", null, "SosigStart_Postfix");
		Patch(harmony, target6, "Sosig.SosigDies", null, "SosigDies_Postfix");
	}

	private static void Patch(Harmony harmony, MethodInfo target, string label, string prefixName, string postfixName)
	{
		//IL_0034: 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)
		if ((object)target == null)
		{
			Plugin.Log.LogError((object)("[ThrowAssist] could not resolve " + label + " - that part of the mod is inactive on this game build."));
			return;
		}
		try
		{
			HarmonyMethod val = ((prefixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(Patches), prefixName, (Type[])null, (Type[])null)));
			HarmonyMethod val2 = ((postfixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(AccessTools.Method(typeof(Patches), postfixName, (Type[])null, (Type[])null)));
			harmony.Patch((MethodBase)target, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[ThrowAssist] patching " + label + " threw: " + ex));
			return;
		}
		Patches patchInfo = Harmony.GetPatchInfo((MethodBase)target);
		int num = patchInfo?.Prefixes.Count ?? 0;
		int num2 = patchInfo?.Postfixes.Count ?? 0;
		if (patchInfo != null && (prefixName == null || num > 0) && (postfixName == null || num2 > 0))
		{
			Plugin.Log.LogInfo((object)("[ThrowAssist] patched " + label + " (prefixes=" + num + ", postfixes=" + num2 + ")"));
		}
		else
		{
			Plugin.Log.LogError((object)("[ThrowAssist] patch did NOT attach to " + label + " - throw assist will not work correctly."));
		}
	}

	private static void EndInteraction_Postfix(FVRPhysicalObject __instance, FVRViveHand hand)
	{
		try
		{
			ThrowSolver.OnRelease(__instance, hand);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[ThrowAssist] throw solve failed: " + ex));
		}
	}

	private static bool MeleeEndInteraction_Prefix(MeleeParams __instance)
	{
		if (!Plugin.Enabled.Value)
		{
			return true;
		}
		if (!Plugin.SuppressVanillaAutoAim.Value)
		{
			return true;
		}
		try
		{
			if (__instance != null && __instance.GetReadyToAim())
			{
				__instance.SetReadyToAim(false);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[ThrowAssist] clearing ready-to-aim failed: " + ex));
		}
		return false;
	}

	private static bool SetQuickBeltSlot_Prefix(FVRPhysicalObject __instance, FVRQuickBeltSlot slot)
	{
		if (!Plugin.Enabled.Value)
		{
			return true;
		}
		if ((Object)(object)__instance == (Object)null || (Object)(object)slot == (Object)null)
		{
			return true;
		}
		if (!HarnessHold.Allow(__instance, slot))
		{
			return false;
		}
		if (!Plugin.DetachOnHolster.Value)
		{
			return true;
		}
		MeleeParams mP = __instance.MP;
		if (mP == null)
		{
			return true;
		}
		if (!mP.IsJointedToObject && !mP.IsLodgedToObject)
		{
			return true;
		}
		mP.DeJoint();
		if (Plugin.DebugLog.Value)
		{
			Plugin.Log.LogInfo((object)("[ThrowAssist] detached " + ((Object)__instance).name + " before holstering."));
		}
		return true;
	}

	private static void BeginInteraction_Postfix(FVRPhysicalObject __instance)
	{
		HarnessHold.Clear(__instance);
	}

	private static void SosigStart_Postfix(Sosig __instance)
	{
		SosigRegistry.Add(__instance);
	}

	private static void SosigDies_Postfix(Sosig __instance)
	{
		SosigRegistry.Remove(__instance);
	}
}
public sealed class Tuned<T>
{
	public readonly T Value;

	public Tuned(T value)
	{
		Value = value;
	}
}
[BepInPlugin("invent60.h3vr.throwassist", "Throw Assist", "1.4.6")]
[BepInProcess("h3vr.exe")]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "invent60.h3vr.throwassist";

	public const string Version = "1.4.6";

	private const string OldGuid = "ken.h3vr.throwassist";

	public static ManualLogSource Log;

	public static ConfigEntry<bool> Enabled;

	public static ConfigEntry<bool> AssistHandguns;

	public static ConfigEntry<bool> AssistLongGuns;

	public static ConfigEntry<bool> AssistAmmunition;

	public static ConfigEntry<bool> AssistMeleeWeapons;

	public static ConfigEntry<bool> AssistAttachments;

	public static ConfigEntry<bool> AssistMisc;

	public static ConfigEntry<string> BlacklistTypes;

	public static ConfigEntry<string> BlacklistNames;

	public static ConfigEntry<float> LeadStrength;

	public static ConfigEntry<string> KnifeThrowStyle;

	public static ConfigEntry<string> AddSpinWeapons;

	public static ConfigEntry<string> AddSpearWeapons;

	public static ConfigEntry<string> AddDiscWeapons;

	public static ConfigEntry<bool> AimForFlesh;

	public static ConfigEntry<bool> DebugLog;

	public static ConfigEntry<bool> DebugDrawHand;

	public static ConfigEntry<bool> DebugDrawTrajectory;

	public static ConfigEntry<bool> DebugDrawTargeting;

	private const string VanillaSpin = "Tomahawk,Hatchet,Axe,Cleaver,Kukri,Sickle,Billhook,Pickaxe,Bardiche,Mace,Warhammer,Hammer,Sledge,Mallet,Crowbar,PipeWrench,Wrench,CircleSaw";

	private const string VanillaSpear = "Katana,Rapier,Estoc,Claymore,Espadon,Falchion,Flameberg,Grossmesser,Katzbalger,Zweihander,Gladius,Pilum,Cutlass,Machete,Kabartana,LaserSword,LongSword,BastardSword,ArmingSword,Pitchfork,Pencil,Screwdriver,Scraper,Dagger";

	private const string VanillaDisc = "Shuriken";

	public static readonly Tuned<bool> SuppressVanillaAutoAim = new Tuned<bool>(value: true);

	public static readonly Tuned<bool> DetachOnHolster = new Tuned<bool>(value: true);

	public static readonly Tuned<float> HarnessHoldAfterArrival = new Tuned<float>(3f);

	public static readonly Tuned<string> TargetLayers = new Tuned<string>("AgentBody,Interactable,AIEntity");

	public static readonly Tuned<float> CastRadius = new Tuned<float>(0.35f);

	public static readonly Tuned<float> MaxRange = new Tuned<float>(100f);

	public static readonly Tuned<float> MaxAssistAngle = new Tuned<float>(30f);

	public static readonly Tuned<bool> TargetByLook = new Tuned<bool>(value: false);

	public static readonly Tuned<float> FallbackMaxLookAngle = new Tuned<float>(15f);

	public static readonly Tuned<bool> AssistFriendlies = new Tuned<bool>(value: true);

	public static readonly Tuned<bool> RequireLineOfSight = new Tuned<bool>(value: true);

	public static readonly Tuned<int> MeatMinCells = new Tuned<int>(6);

	public static readonly Tuned<float> MeatScanDrawSeconds = new Tuned<float>(0.5f);

	public static readonly Tuned<int> MeatMinCellsPrimary = new Tuned<int>(2);

	public static readonly Tuned<float> MeatFallbackAngle = new Tuned<float>(12f);

	public static readonly Tuned<int> MeatMaxLimbs = new Tuned<int>(3);

	public static readonly Tuned<float> PenetrateThreshold = new Tuned<float>(0.35f);

	public static readonly Tuned<float> ConeDrawLength = new Tuned<float>(0.5f);

	public static readonly Tuned<string> ExtraRangeNames = new Tuned<string>("Tomahawk,Hatchet,Axe");

	public static readonly Tuned<float> ExtraRangeMultiplier = new Tuned<float>(1.75f);

	public static readonly Tuned<float> MinThrowSpeed = new Tuned<float>(3f);

	public static readonly Tuned<float> MaxSpeedMultiplier = new Tuned<float>(2f);

	public static readonly Tuned<float> ThrowBoostLight = new Tuned<float>(1.6f);

	public static readonly Tuned<float> ThrowBoostHeavy = new Tuned<float>(1.05f);

	public static readonly Tuned<float> BoostMassReference = new Tuned<float>(2.5f);

	public static readonly Tuned<float> MeleeThrowBoost = new Tuned<float>(1.25f);

	public static readonly Tuned<bool> AvoidObstaclesAbove = new Tuned<bool>(value: true);

	public static readonly Tuned<float> ObstacleClearance = new Tuned<float>(0.1f);

	publ