Decompiled source of WeaponSling v0.9.0

Mods/SlingMod.dll

Decompiled 28 minutes ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using SlingMod;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "Sling", "0.9.0", "SlingMod", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SlingMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.9.0.0")]
[assembly: AssemblyInformationalVersion("0.9.0")]
[assembly: AssemblyProduct("SlingMod")]
[assembly: AssemblyTitle("SlingMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SlingMod
{
	internal enum LaserAxis
	{
		Forward,
		Up,
		Right,
		Back,
		Down,
		Left
	}
	internal static class Calibration
	{
		private enum Stage
		{
			Idle,
			Rear,
			Front,
			Test
		}

		private static Stage stage = Stage.Idle;

		private static Rigidbody target;

		private static Vector3 localA;

		private static Vector3 localB;

		private static float deadline;

		private static bool wasPlace;

		private static bool wasBack;

		private static Beam beam;

		private static Dot cursor;

		private static Dot markA;

		private static readonly Color LaserColor = new Color(0.3f, 0.9f, 1f);

		private static readonly Color AimColor = new Color(1f, 0.9f, 0.2f);

		private static readonly Color HitColor = new Color(0.3f, 1f, 0.4f);

		private static readonly Color RearColor = new Color(0.3f, 0.5f, 1f);

		public static bool Active => stage != Stage.Idle;

		private static Btn PlaceButton => (Btn)Mathf.Clamp(SlingSettings.CalibButton.Value, 0, 3);

		public static void StartForLastHeld()
		{
			if (StrapManager.RequireEnabled())
			{
				Rigidbody val = StrapManager.BodyOf(StrapManager.LastGrabbed);
				if ((Object)(object)val == (Object)null)
				{
					Notify.Send("Sling", "Pick up the gun first, then press this again.");
					return;
				}
				StrapManager.RemoveFromItem(val);
				TapeTool.Stop(announce: false);
				target = val;
				stage = Stage.Rear;
				deadline = Time.time + 180f;
				wasPlace = true;
				wasBack = true;
				EnsureVisuals();
				markA.Hide();
				Notify.Send("Calibration 1/2", "Close the menu. Place the REAR end of the strap: aim at the gun and press " + ControllerButton.NameOf(PlaceButton) + ".", 5f);
			}
		}

		public static void StartLaserTest()
		{
			if (StrapManager.RequireEnabled())
			{
				TapeTool.Stop(announce: false);
				stage = Stage.Test;
				target = null;
				deadline = Time.time + 20f;
				wasPlace = true;
				wasBack = true;
				EnsureVisuals();
				markA.Hide();
				Notify.Send("Laser test", "20 seconds. If the beam does not follow your hand, change Laser direction in the menu.", 4f);
			}
		}

		public static void Cancel(bool announce)
		{
			bool num = stage != Stage.Idle;
			stage = Stage.Idle;
			target = null;
			HideAll();
			if (num && announce)
			{
				Notify.Send("Calibration", "Cancelled.");
			}
		}

		public static void Update()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e9: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: 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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: 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_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			if (stage == Stage.Idle)
			{
				return;
			}
			if (Time.time > deadline)
			{
				Cancel(announce: true);
				return;
			}
			if (stage != Stage.Test && ((Object)(object)target == (Object)null || !Player.HandsExist))
			{
				Cancel(announce: true);
				return;
			}
			bool flag = SlingSettings.CalibHand.Value == 1;
			Hand val = (flag ? Player.RightHand : Player.LeftHand);
			if ((Object)(object)target != (Object)null && (Object)(object)val != (Object)null && (Object)(object)StrapManager.BodyOf(Player.GetObjectInHand(val)) == (Object)(object)target)
			{
				flag = !flag;
				val = (flag ? Player.RightHand : Player.LeftHand);
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)val).transform.position;
			Vector3 val2 = LaserDirection(((Component)val).transform);
			position += val2 * 0.04f;
			float num = Mathf.Max(0.5f, SlingSettings.LaserRange.Value);
			Vector3 point;
			bool flag2 = Cast(position, val2, num, out point);
			Vector3 val3 = (flag2 ? point : (position + val2 * num));
			beam.Show(position, val3, 0.004f, LaserColor);
			cursor.Show(Visuals.Lift(val3, 0.004f), SlingSettings.DotSize.Value * (flag2 ? 1f : 0.7f), flag2 ? HitColor : AimColor);
			if (stage == Stage.Test)
			{
				return;
			}
			if (stage == Stage.Front)
			{
				markA.Show(Visuals.Lift(((Component)target).transform.TransformPoint(localA), 0.004f), SlingSettings.DotSize.Value, RearColor);
			}
			bool num2 = ControllerButton.IsPressed(PlaceButton, flag);
			bool flag3 = num2 && !wasPlace;
			wasPlace = num2;
			bool flag4 = ControllerButton.IsPressed(Btn.Secondary, flag);
			bool num3 = flag4 && !wasBack;
			wasBack = flag4;
			if (num3)
			{
				if (stage == Stage.Front)
				{
					stage = Stage.Rear;
					markA.Hide();
					Notify.Send("Calibration 1/2", "Back one step. Place the REAR end.");
				}
				else
				{
					Cancel(announce: true);
				}
			}
			else
			{
				if (!flag3)
				{
					return;
				}
				if (!flag2)
				{
					Notify.Send("Calibration", "Aim the laser at the gun.");
					return;
				}
				Vector3 val4 = ((Component)target).transform.InverseTransformPoint(point);
				if (stage == Stage.Rear)
				{
					localA = val4;
					stage = Stage.Front;
					markA.Show(Visuals.Lift(point, 0.004f), SlingSettings.DotSize.Value, RearColor);
					Feedback.Pulse(flag);
					Notify.Send("Calibration 2/2", "Place the FRONT end of the strap.", 4f);
				}
				else if (Vector3.Distance(((Component)target).transform.TransformPoint(localA), point) < 0.05f)
				{
					Notify.Send("Calibration", "The ends are too close together. Pick another spot.");
				}
				else
				{
					localB = val4;
					Rigidbody rb = target;
					Vector3 val5 = localA;
					Vector3 val6 = localB;
					Feedback.Pulse(flag);
					Feedback.Sound(point, attach: true);
					Cancel(announce: false);
					StrapManager.AddCalibrated(rb, val5, val6);
				}
			}
		}

		internal static Vector3 LaserDirection(Transform hand)
		{
			//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_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_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_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_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_0058: 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_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)
			//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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = hand.TransformDirection((Vector3)((LaserAxis)SlingSettings.LaserAxis.Value switch
			{
				LaserAxis.Up => Vector3.up, 
				LaserAxis.Right => Vector3.right, 
				LaserAxis.Back => Vector3.back, 
				LaserAxis.Down => Vector3.down, 
				LaserAxis.Left => Vector3.left, 
				_ => Vector3.forward, 
			}));
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			float value = SlingSettings.LaserTilt.Value;
			if (Mathf.Abs(value) > 0.01f)
			{
				Vector3 val2 = Vector3.Cross(Vector3.up, normalized);
				if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
				{
					val2 = hand.right;
				}
				val = Quaternion.AngleAxis(0f - value, ((Vector3)(ref val2)).normalized) * normalized;
				normalized = ((Vector3)(ref val)).normalized;
			}
			return normalized;
		}

		private static bool Cast(Vector3 origin, Vector3 dir, float range, out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_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)
			point = Vector3.zero;
			bool result = false;
			float num = float.MaxValue;
			foreach (RaycastHit item in (Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(origin, dir, range, -1, (QueryTriggerInteraction)1))
			{
				RaycastHit current = item;
				Collider collider = ((RaycastHit)(ref current)).collider;
				if (!((Object)(object)collider == (Object)null) && (!((Object)(object)target != (Object)null) || BelongsToTarget(collider)) && ((RaycastHit)(ref current)).distance < num)
				{
					num = ((RaycastHit)(ref current)).distance;
					point = ((RaycastHit)(ref current)).point;
					result = true;
				}
			}
			return result;
		}

		private static bool BelongsToTarget(Collider c)
		{
			if (!((Object)(object)c.attachedRigidbody == (Object)(object)target))
			{
				return ((Component)c).transform.IsChildOf(((Component)target).transform);
			}
			return true;
		}

		private static void EnsureVisuals()
		{
			if (beam == null)
			{
				beam = new Beam("SlingLaser");
			}
			if (cursor == null)
			{
				cursor = new Dot("SlingCursor");
			}
			if (markA == null)
			{
				markA = new Dot("SlingRearMark");
			}
		}

		private static void HideAll()
		{
			if (beam != null)
			{
				beam.Hide();
			}
			if (cursor != null)
			{
				cursor.Hide();
			}
			if (markA != null)
			{
				markA.Hide();
			}
		}
	}
	internal enum Btn
	{
		Trigger,
		Grip,
		Primary,
		Secondary
	}
	internal sealed class ControllerButton
	{
		private static readonly ControllerButton[] all = new ControllerButton[4]
		{
			new ControllerButton("Trigger", new string[5] { "GetTriggerButton", "GetIndexButton", "GetTrigger", "GetTriggerAxis", "GetIndexAxis" }, new string[2] { "trigger", "index" }, () => SlingSettings.TriggerMethod.Value, () => SlingSettings.ButtonThreshold.Value),
			new ControllerButton("Grip", new string[5] { "GetGrabbingGrip", "GetGrabbedState", "GetGripButton", "GetGrip", "GetGrabButton" }, new string[2] { "grab", "grip" }, () => SlingSettings.GripMethod.Value, () => SlingSettings.GripThreshold.Value),
			new ControllerButton("Primary (A/X)", new string[3] { "GetPrimaryInteractionButton", "GetAButton", "GetPrimaryButton" }, new string[1] { "primary" }, () => SlingSettings.PrimaryMethod.Value, () => SlingSettings.ButtonThreshold.Value),
			new ControllerButton("Secondary (B/Y)", new string[3] { "GetSecondaryInteractionButton", "GetBButton", "GetSecondaryButton" }, new string[1] { "secondary" }, () => SlingSettings.SecondaryMethod.Value, () => SlingSettings.ButtonThreshold.Value)
		};

		private static bool dumped;

		private readonly string label;

		private readonly string[] preferred;

		private readonly string[] keywords;

		private readonly Func<string> forcedName;

		private readonly Func<float> threshold;

		private Type resolvedFor;

		private MemberInfo member;

		private bool failed;

		public static bool IsPressed(Btn button, bool right)
		{
			return all[(int)button].Pressed(right);
		}

		public static string NameOf(Btn button)
		{
			return all[(int)button].label;
		}

		private ControllerButton(string label, string[] preferred, string[] keywords, Func<string> forcedName, Func<float> threshold)
		{
			this.label = label;
			this.preferred = preferred;
			this.keywords = keywords;
			this.forcedName = forcedName;
			this.threshold = threshold;
		}

		private bool Pressed(bool right)
		{
			if (failed || !Player.ControllersExist)
			{
				return false;
			}
			object obj = (right ? Player.RightController : Player.LeftController);
			if (obj == null)
			{
				return false;
			}
			Type type = obj.GetType();
			if (type != resolvedFor)
			{
				Resolve(type);
			}
			if (member == null)
			{
				return false;
			}
			try
			{
				object obj2 = Read(member, obj);
				if (obj2 is bool result)
				{
					return result;
				}
				if (obj2 is float num)
				{
					return num > threshold();
				}
				if (obj2 is int num2)
				{
					return num2 > 0;
				}
			}
			catch (Exception ex)
			{
				failed = true;
				MelonLogger.Error($"[Sling] Reading the {label} button via {type.Name}.{member.Name} failed, that button is disabled: {ex.Message}");
			}
			return false;
		}

		private void Resolve(Type type)
		{
			resolvedFor = type;
			member = null;
			if (!dumped)
			{
				dumped = true;
				DumpCandidates(type);
			}
			string text = forcedName();
			if (!string.IsNullOrWhiteSpace(text))
			{
				member = FindByName(type, text.Trim());
				if (member == null)
				{
					MelonLogger.Warning($"[Sling] Override '{text}' for the {label} button was not found on {type.Name}, trying auto-detect.");
				}
			}
			if (member == null)
			{
				string[] array = preferred;
				foreach (string name in array)
				{
					member = FindByName(type, name);
					if (member != null)
					{
						break;
					}
				}
			}
			if (member == null)
			{
				foreach (MemberInfo item in Members(type))
				{
					string text2 = item.Name.ToLowerInvariant();
					bool flag = false;
					string[] array = keywords;
					foreach (string value in array)
					{
						if (text2.Contains(value))
						{
							flag = true;
							break;
						}
					}
					bool flag2 = text2.Contains("down") || text2.Contains("up") || text2.Contains("release") || text2.Contains("tap") || text2.Contains("haptic") || text2.StartsWith("set");
					if (flag && !flag2)
					{
						member = item;
						break;
					}
				}
			}
			if (member == null)
			{
				failed = true;
				MelonLogger.Error($"[Sling] Could not find the {label} button on {type.FullName}. " + "Look at the candidate list above in the log and put the right name into UserData/MelonPreferences.cfg [Sling].");
			}
			else
			{
				MelonLogger.Msg($"[Sling] {label} button: {type.Name}.{member.Name}");
			}
		}

		private static MemberInfo FindByName(Type type, string name)
		{
			foreach (MemberInfo item in Members(type))
			{
				if (item.Name == name)
				{
					return item;
				}
			}
			return null;
		}

		private static bool IsReadableType(Type r)
		{
			if (!(r == typeof(bool)) && !(r == typeof(float)))
			{
				return r == typeof(int);
			}
			return true;
		}

		private static IEnumerable<MemberInfo> Members(Type type)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.IsSpecialName && methodInfo.GetParameters().Length == 0 && IsReadableType(methodInfo.ReturnType))
				{
					yield return methodInfo;
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0 && IsReadableType(propertyInfo.PropertyType))
				{
					yield return propertyInfo;
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (IsReadableType(fieldInfo.FieldType))
				{
					yield return fieldInfo;
				}
			}
		}

		private static object Read(MemberInfo m, object target)
		{
			if (m is MethodInfo methodInfo)
			{
				return methodInfo.Invoke(target, null);
			}
			if (m is PropertyInfo propertyInfo)
			{
				return propertyInfo.GetValue(target);
			}
			return ((FieldInfo)m).GetValue(target);
		}

		private static void DumpCandidates(Type type)
		{
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(59, 1, stringBuilder2);
			handler.AppendLiteral("[Sling] Controller type ");
			handler.AppendFormatted(type.FullName);
			handler.AppendLiteral(". Readable bool/float/int members: ");
			stringBuilder2.Append(ref handler);
			int num = 0;
			foreach (MemberInfo item in Members(type))
			{
				stringBuilder.Append(item.Name).Append(", ");
				if (++num >= 120)
				{
					break;
				}
			}
			MelonLogger.Msg(stringBuilder.ToString());
		}
	}
	internal static class Diagnostics
	{
		public static void Write()
		{
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				stringBuilder.AppendLine("Sling 0.9.0 report, " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
				stringBuilder.AppendLine("Mod enabled: " + SlingSettings.Enabled.Value);
				stringBuilder.AppendLine("Shader: vertex colours " + (Visuals.VertexColors ? "yes (full lighting)" : "NO (flat colours only)"));
				stringBuilder.AppendLine("Head found: " + ((Object)(object)Player.Head != (Object)null) + ", body frame: " + (BodyFrame.Valid ? "valid" : "not valid"));
				stringBuilder.AppendLine("Level light: source " + SceneLight.Source + ", measured " + SceneLight.Luminance.ToString("0.000") + ", brightest seen " + SceneLight.Peak.ToString("0.000") + ", strap brightness " + Shading.Brightness.ToString("0.00") + " (strength setting " + SlingSettings.SceneLight.Value.ToString("0.00") + ")");
				stringBuilder.AppendLine("Mounts: mode " + SlingSettings.MountMode.Value + " (0 off, 1 auto, 2 always), style " + SlingSettings.MountStyle.Value + ", hook animation " + SlingSettings.HookAnimation.Value + ", breakaway " + SlingSettings.Breakaway.Value);
				stringBuilder.AppendLine("Look: " + Look.FromGlobal().Serialize() + ", wear " + SlingSettings.WearLevel.Value + ", patch " + SlingSettings.Patch.Value + ", neon mode " + SlingSettings.NeonMode.Value + ", low detail " + SlingSettings.LowDetail.Value);
				stringBuilder.AppendLine("0.9.0: floor/walls " + SlingSettings.WorldCollision.Value + ", loose objects " + SlingSettings.PropCollision.Value + ", hands " + SlingSettings.HandCollision.Value + ", weight " + SlingSettings.WeightFeel.Value.ToString("0.00") + ", move strap by hand " + SlingSettings.SwapByHand.Value + ", second point " + SlingSettings.TwoPoint.Value + ", marks on the strap " + SlingSettings.StrapHints.Value);
				stringBuilder.AppendLine("Feedback: " + Feedback.Describe());
				string[] array = Textures.PictureFiles();
				stringBuilder.AppendLine("Pictures found: " + array.Length + ", chosen number " + SlingSettings.CustomPicture.Value);
				StrapManager.Describe(stringBuilder);
			}
			catch (Exception ex)
			{
				stringBuilder.AppendLine("(the report itself failed: " + ex.Message + ")");
			}
			string text = stringBuilder.ToString();
			MelonLogger.Msg("[Sling] " + text);
			try
			{
				File.WriteAllText(Path.Combine(Paths.DataDir, "report.txt"), text);
				Notify.Send("Report written", "UserData/WeaponSling/report.txt (and the log)", 3f);
			}
			catch (Exception ex2)
			{
				Notify.Send("Sling", "Could not write report.txt: " + ex2.Message);
			}
		}
	}
	internal static class Feedback
	{
		private static Type hapticsFor;

		private static MemberInfo hapticsMember;

		private static MethodInfo hapticsMethod;

		private static object[] hapticsArgs;

		private static ParameterInfo[] hapticsParams;

		private static bool hapticsFailed;

		private static AudioClip attachClip;

		private static AudioClip detachClip;

		private static AudioClip ripClip;

		private static bool soundFailed;

		private static AudioClip clankClip;

		private static AudioClip latchClip;

		private static AudioClip creakClip;

		private static AudioClip rattleClip;

		private static AudioClip rustleClip;

		private static float nextMaterialSound;

		public static string Describe()
		{
			return "haptics " + (hapticsFailed ? "FAILED (not available)" : ((hapticsMethod != null) ? "ok" : "not tried yet")) + ", sounds " + (soundFailed ? "FAILED (turned off)" : "ok so far");
		}

		public static void Pulse(bool right)
		{
			Pulse(right, 0.6f);
		}

		public static void Pulse(bool right, float amount)
		{
			if (!SlingSettings.Haptics.Value || hapticsFailed || !Player.ControllersExist)
			{
				return;
			}
			try
			{
				object obj = (right ? Player.RightController : Player.LeftController);
				if (obj == null)
				{
					return;
				}
				Type type = obj.GetType();
				if (type != hapticsFor)
				{
					ResolveHaptics(type);
				}
				if (hapticsMethod == null)
				{
					return;
				}
				object[] array = hapticsArgs;
				if (hapticsParams != null && Mathf.Abs(amount - 0.6f) > 0.001f)
				{
					array = new object[hapticsParams.Length];
					for (int i = 0; i < array.Length; i++)
					{
						Type parameterType = hapticsParams[i].ParameterType;
						array[i] = ((parameterType == typeof(float)) ? ((object)Mathf.Clamp(amount, 0.05f, 1f)) : hapticsArgs[i]);
					}
				}
				object obj2 = ((hapticsMember is PropertyInfo propertyInfo) ? propertyInfo.GetValue(obj) : ((FieldInfo)hapticsMember).GetValue(obj));
				if (obj2 != null)
				{
					hapticsMethod.Invoke(obj2, array);
				}
			}
			catch (Exception ex)
			{
				hapticsFailed = true;
				MelonLogger.Warning("[Sling] Controller haptics failed and were turned off: " + ex.Message);
			}
		}

		private static void ResolveHaptics(Type controllerType)
		{
			hapticsFor = controllerType;
			hapticsMember = null;
			hapticsMethod = null;
			string[] methodNames = new string[7] { "Haptic_Tap", "Haptic_Hit", "Haptic_Fire", "Tap", "Hit", "Pulse", "Buzz" };
			PropertyInfo[] properties = controllerType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (TryHapticsType(propertyInfo.PropertyType, propertyInfo))
				{
					return;
				}
			}
			FieldInfo[] fields = controllerType.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (TryHapticsType(fieldInfo.FieldType, fieldInfo))
				{
					return;
				}
			}
			MelonLogger.Msg("[Sling] No haptics member found on the controller; the buzz is skipped.");
			hapticsFailed = true;
			bool TryHapticsType(Type t, MemberInfo owner)
			{
				string text = t.Name.ToLowerInvariant();
				if (!text.Contains("haptic") && !text.Contains("haptor"))
				{
					return false;
				}
				string[] array = methodNames;
				foreach (string text2 in array)
				{
					MethodInfo[] methods = t.GetMethods(BindingFlags.Instance | BindingFlags.Public);
					foreach (MethodInfo methodInfo in methods)
					{
						if (!(methodInfo.Name != text2))
						{
							object[] array2 = BuildArgs(methodInfo.GetParameters());
							if (array2 != null)
							{
								hapticsMember = owner;
								hapticsMethod = methodInfo;
								hapticsArgs = array2;
								hapticsParams = methodInfo.GetParameters();
								MelonLogger.Msg($"[Sling] Haptics: {controllerType.Name}.{owner.Name}.{methodInfo.Name}({methodInfo.GetParameters().Length} args)");
								return true;
							}
						}
					}
				}
				return false;
			}
		}

		private static object[] BuildArgs(ParameterInfo[] ps)
		{
			object[] array = new object[ps.Length];
			for (int i = 0; i < ps.Length; i++)
			{
				Type parameterType = ps[i].ParameterType;
				if (parameterType == typeof(float))
				{
					array[i] = 0.6f;
					continue;
				}
				if (parameterType == typeof(int))
				{
					array[i] = 1;
					continue;
				}
				if (parameterType == typeof(bool))
				{
					array[i] = false;
					continue;
				}
				return null;
			}
			return array;
		}

		public static void Rip(Vector3 position)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!SlingSettings.Sounds.Value || soundFailed)
			{
				return;
			}
			try
			{
				if ((Object)(object)ripClip == (Object)null)
				{
					ripClip = MakeRip();
				}
				if ((Object)(object)ripClip == (Object)null)
				{
					soundFailed = true;
				}
				else
				{
					AudioSource.PlayClipAtPoint(ripClip, position, Mathf.Clamp01(SlingSettings.SoundVolume.Value));
				}
			}
			catch (Exception ex)
			{
				soundFailed = true;
				MelonLogger.Warning("[Sling] Sound failed and was turned off: " + ex.Message);
			}
		}

		private static AudioClip MakeRip()
		{
			int num = 27342;
			float[] array = new float[num];
			Random random = new Random(11);
			float num2 = 0f;
			for (int i = 0; i < num; i++)
			{
				float num3 = (float)i / (float)num;
				float num4 = (float)(random.NextDouble() * 2.0 - 1.0);
				num2 += (num4 - num2) * 0.45f;
				float num5 = 0.55f + 0.45f * (float)Math.Sin(Math.PI * 2.0 * (26.0 - 10.0 * (double)num3) * ((double)i / 44100.0));
				float num6 = Mathf.Clamp01((float)i / 200f);
				float num7 = Mathf.Clamp01((1f - num3) / 0.18f);
				float num8 = num2 * num5 * num6 * num7 * (0.9f - 0.4f * num3);
				if (num3 > 0.93f && num3 < 0.95f)
				{
					num8 += (float)Math.Sin((double)i * 0.35) * 0.35f;
				}
				array[i] = num8 * 0.7f;
			}
			return ToClip("SlingRip", array, 44100);
		}

		public static void Sound(Vector3 position, bool attach)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (!SlingSettings.Sounds.Value || soundFailed)
			{
				return;
			}
			try
			{
				if ((Object)(object)attachClip == (Object)null)
				{
					attachClip = MakeClip("SlingAttach", 0.09f, 700f, 380f, 0.3f, 6f);
					detachClip = MakeClip("SlingDetach", 0.12f, 300f, 650f, 0.45f, 5f);
				}
				AudioClip val = (attach ? attachClip : detachClip);
				if ((Object)(object)val == (Object)null)
				{
					soundFailed = true;
				}
				else
				{
					AudioSource.PlayClipAtPoint(val, position, Mathf.Clamp01(SlingSettings.SoundVolume.Value));
				}
			}
			catch (Exception ex)
			{
				soundFailed = true;
				MelonLogger.Warning("[Sling] Sound failed and was turned off: " + ex.Message);
			}
		}

		private static AudioClip MakeClip(string name, float seconds, float freqStart, float freqEnd, float noise, float decay)
		{
			int num = (int)(44100f * seconds);
			float[] array = new float[num];
			Random random = new Random(7);
			double num2 = 0.0;
			for (int i = 0; i < num; i++)
			{
				float num3 = (float)i / (float)num;
				float num4 = Mathf.Lerp(freqStart, freqEnd, num3);
				num2 += Math.PI * 2.0 * (double)num4 / 44100.0;
				float num5 = Mathf.Clamp01((float)i / 30f);
				float num6 = Mathf.Exp((0f - decay) * num3) * num5;
				float num7 = (float)Math.Sin(num2) * 0.6f + (float)(random.NextDouble() * 2.0 - 1.0) * noise;
				array[i] = num7 * num6 * 0.8f;
			}
			return ToClip(name, array, 44100);
		}

		public static void Clank(Vector3 position)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!SlingSettings.Sounds.Value || !SlingSettings.Clank.Value || soundFailed)
			{
				return;
			}
			try
			{
				if ((Object)(object)clankClip == (Object)null)
				{
					clankClip = MakeClank();
				}
				if ((Object)(object)clankClip == (Object)null)
				{
					soundFailed = true;
				}
				else
				{
					AudioSource.PlayClipAtPoint(clankClip, position, Mathf.Clamp01(SlingSettings.SoundVolume.Value));
				}
			}
			catch (Exception ex)
			{
				soundFailed = true;
				MelonLogger.Warning("[Sling] Sound failed and was turned off: " + ex.Message);
			}
		}

		private static AudioClip MakeClank()
		{
			int num = 9702;
			float[] array = new float[num];
			Random random = new Random(3);
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i / (float)num;
				double num3 = (double)i / 44100.0;
				float num4 = (float)(Math.Sin(Math.PI * 3700.0 * num3) * 0.5 + Math.Sin(Math.PI * 5520.0 * num3) * 0.35 + Math.Sin(Math.PI * 8620.0 * num3) * 0.2);
				float num5 = Mathf.Exp(-13f * num2) * Mathf.Clamp01((float)i / 20f);
				float num6 = ((i < 300) ? ((float)(random.NextDouble() * 2.0 - 1.0) * (1f - (float)i / 300f) * 0.6f) : 0f);
				array[i] = (num4 * num5 + num6) * 0.55f;
			}
			return ToClip("SlingClank", array, 44100);
		}

		public static void Latch(Vector3 position)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!SlingSettings.Sounds.Value || soundFailed)
			{
				return;
			}
			try
			{
				if ((Object)(object)latchClip == (Object)null)
				{
					latchClip = MakeLatch();
				}
				PlayClip(latchClip, position, 1f);
			}
			catch (Exception ex)
			{
				soundFailed = true;
				MelonLogger.Warning("[Sling] Sound failed and was turned off: " + ex.Message);
			}
		}

		public static void StrapMaterial(int strapKind, Vector3 position, float strength)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (!SlingSettings.Sounds.Value || !SlingSettings.MaterialSounds.Value || soundFailed || Time.time < nextMaterialSound)
			{
				return;
			}
			nextMaterialSound = Time.time + 0.35f;
			try
			{
				float num = Mathf.Clamp01(strength);
				AudioClip clip;
				switch (strapKind)
				{
				case 6:
					clip = (((Object)(object)rattleClip != (Object)null) ? rattleClip : (rattleClip = MakeRattle()));
					break;
				case 2:
					clip = (((Object)(object)creakClip != (Object)null) ? creakClip : (creakClip = MakeCreak()));
					num *= 0.8f;
					break;
				case 7:
					return;
				default:
					clip = (((Object)(object)rustleClip != (Object)null) ? rustleClip : (rustleClip = MakeRustle()));
					num *= 0.55f;
					break;
				}
				PlayClip(clip, position, num);
			}
			catch (Exception ex)
			{
				soundFailed = true;
				MelonLogger.Warning("[Sling] Sound failed and was turned off: " + ex.Message);
			}
		}

		private static void PlayClip(AudioClip clip, Vector3 position, float volume)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)clip == (Object)null)
			{
				soundFailed = true;
			}
			else
			{
				AudioSource.PlayClipAtPoint(clip, position, Mathf.Clamp01(SlingSettings.SoundVolume.Value * volume));
			}
		}

		private static AudioClip MakeLatch()
		{
			int num = 9702;
			float[] array = new float[num];
			Random random = new Random(5);
			for (int i = 0; i < num; i++)
			{
				double num2 = (double)i / 44100.0;
				float num3 = 0f;
				if (num2 < 0.05)
				{
					float num4 = Mathf.Exp(-70f * (float)num2);
					num3 += ((float)Math.Sin(Math.PI * 6600.0 * num2) * 0.5f + (float)(random.NextDouble() * 2.0 - 1.0) * 0.35f) * num4;
				}
				double num5 = num2 - 0.07;
				if (num5 >= 0.0)
				{
					float num6 = Mathf.Exp(-26f * (float)num5) * Mathf.Clamp01((float)(num5 * 4000.0));
					num3 += ((float)Math.Sin(Math.PI * 2500.0 * num5) * 0.55f + (float)Math.Sin(Math.PI * 4340.0 * num5) * 0.3f + (float)(random.NextDouble() * 2.0 - 1.0) * 0.18f) * num6;
				}
				array[i] = Mathf.Clamp(num3 * 0.6f, -1f, 1f);
			}
			return ToClip("SlingLatch", array, 44100);
		}

		private static AudioClip MakeCreak()
		{
			int num = 16758;
			float[] array = new float[num];
			Random random = new Random(9);
			double num2 = 0.0;
			for (int i = 0; i < num; i++)
			{
				float num3 = (float)i / (float)num;
				float num4 = 170f + 90f * num3 + 25f * (float)Math.Sin(Math.PI * 14.0 * (double)num3);
				num2 += Math.PI * 2.0 * (double)num4 / 44100.0;
				float num5 = 0.5f + 0.5f * (float)Math.Sin(Math.PI * 2.0 * (26.0 + 14.0 * (double)num3) * ((double)i / 44100.0));
				num5 = ((num5 > 0.5f) ? 1f : (num5 * 1.6f));
				float num6 = (float)(Math.Sin(num2) * 0.6 + Math.Sin(num2 * 2.0) * 0.25 + Math.Sin(num2 * 3.0) * 0.12);
				float num7 = (float)(random.NextDouble() * 2.0 - 1.0) * 0.08f;
				float num8 = Mathf.Clamp01((float)i / 900f) * Mathf.Clamp01((1f - num3) / 0.35f);
				array[i] = (num6 + num7) * num5 * num8 * 0.38f;
			}
			return ToClip("SlingCreak", array, 44100);
		}

		private static AudioClip MakeRattle()
		{
			int num = 18522;
			float[] array = new float[num];
			Random random = new Random(21);
			int num2 = 7;
			for (int i = 0; i < num2; i++)
			{
				int num3 = (int)(((float)i / (float)num2 + (float)random.NextDouble() * 0.09f) * (float)num * 0.9f);
				float num4 = 0.35f + (float)random.NextDouble() * 0.45f;
				double num5 = 2300.0 + random.NextDouble() * 2400.0;
				double num6 = num5 * 1.51;
				for (int j = 0; j < 4200 && num3 + j < num; j++)
				{
					double num7 = (double)j / 44100.0;
					float num8 = Mathf.Exp(-70f * (float)num7) * Mathf.Clamp01((float)j / 12f);
					float num9 = (float)(Math.Sin(Math.PI * 2.0 * num5 * num7) * 0.6 + Math.Sin(Math.PI * 2.0 * num6 * num7) * 0.35);
					array[num3 + j] += num9 * num8 * num4 * 0.45f;
				}
			}
			for (int k = 0; k < num; k++)
			{
				array[k] = Mathf.Clamp(array[k], -1f, 1f);
			}
			return ToClip("SlingRattle", array, 44100);
		}

		private static AudioClip MakeRustle()
		{
			int num = 14994;
			float[] array = new float[num];
			Random random = new Random(33);
			float num2 = 0f;
			float num3 = 0f;
			for (int i = 0; i < num; i++)
			{
				float num4 = (float)i / (float)num;
				float num5 = (float)(random.NextDouble() * 2.0 - 1.0);
				num2 += (num5 - num2) * 0.3f;
				num3 += (num2 - num3) * 0.1f;
				float num6 = num2 - num3;
				float num7 = (float)Math.Sin(Math.PI * (double)num4);
				num7 *= 0.6f + 0.4f * (float)Math.Sin(Math.PI * 34.0 * (double)num4 + 1.0);
				array[i] = num6 * num7 * 1.5f;
			}
			return ToClip("SlingRustle", array, 44100);
		}

		private static AudioClip ToClip(string name, float[] data, int rate)
		{
			AudioClip val = AudioClip.Create(name, data.Length, 1, rate, false);
			((Object)val).hideFlags = (HideFlags)32;
			MethodInfo[] methods = typeof(AudioClip).GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "SetData")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 2 && !(parameters[1].ParameterType != typeof(int)))
				{
					object obj = Reflect.ConvertTo(data, parameters[0].ParameterType);
					if (obj != null)
					{
						methodInfo.Invoke(val, new object[2] { obj, 0 });
						return val;
					}
				}
			}
			MelonLogger.Warning("[Sling] AudioClip.SetData not usable; sounds are skipped.");
			return null;
		}
	}
	internal static class GunMemory
	{
		internal sealed class Entry
		{
			public string Key;

			public bool HasPoints;

			public Vector3 A;

			public Vector3 B;

			public bool HasStyle;

			public Color Color = Color.white;

			public int Texture;

			public int Model = -1;

			public Look Look;

			public float Length;

			public bool AutoOff;

			public bool StrapFlag;

			public readonly List<TapeSpec> Tapes = new List<TapeSpec>();

			public bool UsesStrap
			{
				get
				{
					if (!StrapFlag && !HasPoints && !HasStyle)
					{
						return Length > 0f;
					}
					return true;
				}
			}

			public Look GetLook()
			{
				//IL_001c: 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)
				if (Look != null)
				{
					return Look.Clone();
				}
				Look look = Look.FromGlobal();
				look.Color = Color;
				look.Texture = Textures.Clamp(Texture);
				if (Model >= 0)
				{
					look.Model = StrapKinds.Clamp(Model);
				}
				return look;
			}
		}

		private static readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>();

		private static bool loaded;

		private static string FilePath => Path.Combine(Paths.DataDir, "guns.txt");

		public static int Count
		{
			get
			{
				EnsureLoaded();
				return entries.Count;
			}
		}

		public static string KeyFor(Rigidbody rb)
		{
			if ((Object)(object)rb == (Object)null)
			{
				return "";
			}
			string text = ((Object)((Component)rb).gameObject).name ?? "";
			text = text.Replace("(Clone)", "").Trim();
			int num = text.LastIndexOf('(');
			if (num > 0 && text.EndsWith(")") && int.TryParse(text.Substring(num + 1, text.Length - num - 2), out var _))
			{
				text = text.Substring(0, num).Trim();
			}
			return text.Replace('\t', ' ').Replace('\n', ' ');
		}

		public static bool TryGet(string key, out Entry entry)
		{
			EnsureLoaded();
			return entries.TryGetValue(key, out entry);
		}

		public static void SavePoints(string key, Vector3 a, Vector3 b)
		{
			//IL_0023: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			if (SlingSettings.RememberGuns.Value && !string.IsNullOrEmpty(key))
			{
				Entry orAdd = GetOrAdd(key);
				orAdd.HasPoints = true;
				orAdd.A = a;
				orAdd.B = b;
				Write();
			}
		}

		public static void SaveStyle(string key, Look look)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (SlingSettings.RememberGuns.Value && !string.IsNullOrEmpty(key) && look != null)
			{
				Entry orAdd = GetOrAdd(key);
				orAdd.HasStyle = true;
				orAdd.Look = look.Clone();
				orAdd.Color = look.Color;
				orAdd.Texture = look.Texture;
				orAdd.Model = look.Model;
				Write();
			}
		}

		public static void SaveLength(string key, float factor)
		{
			if (!SlingSettings.RememberGuns.Value || string.IsNullOrEmpty(key))
			{
				return;
			}
			if (factor <= 0f)
			{
				EnsureLoaded();
				if (entries.TryGetValue(key, out var value) && !(value.Length <= 0f))
				{
					value.Length = 0f;
					value.StrapFlag = true;
					Write();
				}
			}
			else
			{
				Entry orAdd = GetOrAdd(key);
				orAdd.Length = factor;
				orAdd.StrapFlag = true;
				Write();
			}
		}

		public static void SetAutoOff(string key, bool off)
		{
			if (SlingSettings.RememberGuns.Value && !string.IsNullOrEmpty(key))
			{
				Entry orAdd = GetOrAdd(key);
				orAdd.AutoOff = off;
				if (!off)
				{
					orAdd.StrapFlag = true;
				}
				Write();
			}
		}

		public static void ClearStyle(string key)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (SlingSettings.RememberGuns.Value && !string.IsNullOrEmpty(key))
			{
				EnsureLoaded();
				if (entries.TryGetValue(key, out var value) && value.HasStyle)
				{
					value.HasStyle = false;
					value.Look = null;
					value.Texture = 0;
					value.Model = -1;
					value.Color = Color.white;
					value.StrapFlag = true;
					Write();
				}
			}
		}

		public static void SaveTapes(string key, List<TapeSpec> specs)
		{
			if (!SlingSettings.RememberGuns.Value || string.IsNullOrEmpty(key))
			{
				return;
			}
			EnsureLoaded();
			if (specs.Count == 0)
			{
				if (entries.TryGetValue(key, out var value) && value.Tapes.Count != 0)
				{
					value.Tapes.Clear();
					Prune(value);
					Write();
				}
				return;
			}
			Entry orAdd = GetOrAdd(key);
			orAdd.Tapes.Clear();
			foreach (TapeSpec spec in specs)
			{
				orAdd.Tapes.Add(spec.Clone());
			}
			Write();
		}

		private static void Prune(Entry e)
		{
			if (!e.HasPoints && !e.HasStyle && !e.AutoOff && !e.StrapFlag && e.Length <= 0f && e.Tapes.Count == 0)
			{
				entries.Remove(e.Key);
			}
		}

		public static void Forget(string key)
		{
			EnsureLoaded();
			if (entries.Remove(key))
			{
				Write();
			}
		}

		public static void ForgetAll()
		{
			EnsureLoaded();
			entries.Clear();
			Write();
		}

		private static Entry GetOrAdd(string key)
		{
			EnsureLoaded();
			if (!entries.TryGetValue(key, out var value))
			{
				value = new Entry
				{
					Key = key
				};
				entries[key] = value;
			}
			return value;
		}

		private static void EnsureLoaded()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//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_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			if (loaded)
			{
				return;
			}
			loaded = true;
			try
			{
				if (!File.Exists(FilePath))
				{
					return;
				}
				string[] array = File.ReadAllLines(FilePath);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length == 0 || text.StartsWith("#"))
					{
						continue;
					}
					string[] array2 = text.Split('\t');
					Entry entry = new Entry
					{
						Key = array2[0].Trim()
					};
					if (entry.Key.Length == 0)
					{
						continue;
					}
					bool flag = false;
					for (int j = 1; j < array2.Length; j++)
					{
						int num = array2[j].IndexOf('=');
						if (num <= 0)
						{
							continue;
						}
						string text2 = array2[j].Substring(0, num).Trim();
						string text3 = array2[j].Substring(num + 1).Trim();
						float[] array3 = ParseFloats(text3);
						if (text2 == "pts" && array3.Length == 6)
						{
							entry.HasPoints = true;
							entry.A = new Vector3(array3[0], array3[1], array3[2]);
							entry.B = new Vector3(array3[3], array3[4], array3[5]);
						}
						else if (text2 == "color" && array3.Length >= 3)
						{
							entry.HasStyle = true;
							entry.Color = new Color(array3[0], array3[1], array3[2]);
						}
						else if (text2 == "tex" && array3.Length >= 1)
						{
							entry.Texture = (int)array3[0];
						}
						else if (text2 == "model" && array3.Length >= 1)
						{
							entry.Model = (int)array3[0];
						}
						else if (text2 == "look")
						{
							if (Look.TryParse(text3, out var look))
							{
								entry.HasStyle = true;
								entry.Look = look;
							}
						}
						else if (text2 == "len" && array3.Length >= 1)
						{
							entry.Length = Mathf.Clamp(array3[0], 0.4f, 2.5f);
						}
						else if (text2 == "auto" && array3.Length >= 1)
						{
							entry.AutoOff = array3[0] < 0.5f;
						}
						else if (text2 == "strap" && array3.Length >= 1)
						{
							flag = true;
							entry.StrapFlag = array3[0] > 0.5f;
						}
						else if (text2 == "tape" && array3.Length >= 12)
						{
							List<TapeSpec> tapes = entry.Tapes;
							TapeSpec obj = new TapeSpec
							{
								Center = new Vector3(array3[0], array3[1], array3[2])
							};
							Vector3 val = new Vector3(array3[3], array3[4], array3[5]);
							obj.Axis = ((Vector3)(ref val)).normalized;
							obj.Color = new Color(array3[6], array3[7], array3[8]);
							obj.Width = Mathf.Clamp(array3[9], 0.01f, 0.15f);
							obj.Turns = Mathf.Clamp((int)array3[10], 1, 8);
							obj.Offset = Mathf.Clamp(array3[11], 0f, 0.03f);
							obj.Pattern = ((array3.Length > 12) ? Mathf.Clamp((int)array3[12], 0, 2) : 0);
							tapes.Add(obj);
						}
					}
					if (!flag && entry.Tapes.Count == 0)
					{
						entry.StrapFlag = true;
					}
					entries[entry.Key] = entry;
				}
				MelonLogger.Msg($"[Sling] Gun memory: {entries.Count} gun(s) loaded from {FilePath}");
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Sling] Could not read guns.txt: " + ex.Message);
			}
		}

		private static void Write()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("# Weapon Sling: remembered guns. One gun per line, fields separated by tabs. Safe to edit or delete.");
				foreach (Entry value in entries.Values)
				{
					stringBuilder.Append(value.Key);
					if (value.HasPoints)
					{
						stringBuilder.Append("\tpts=").Append(Join(value.A.x, value.A.y, value.A.z, value.B.x, value.B.y, value.B.z));
					}
					if (value.HasStyle)
					{
						stringBuilder.Append("\tcolor=").Append(Join(value.Color.r, value.Color.g, value.Color.b));
						stringBuilder.Append("\ttex=").Append(value.Texture.ToString(CultureInfo.InvariantCulture));
						stringBuilder.Append("\tmodel=").Append(value.Model.ToString(CultureInfo.InvariantCulture));
						if (value.Look != null)
						{
							stringBuilder.Append("\tlook=").Append(value.Look.Serialize());
						}
					}
					if (value.Length > 0f)
					{
						stringBuilder.Append("\tlen=").Append(value.Length.ToString("R", CultureInfo.InvariantCulture));
					}
					if (value.AutoOff)
					{
						stringBuilder.Append("\tauto=0");
					}
					stringBuilder.Append("\tstrap=").Append(value.StrapFlag ? "1" : "0");
					foreach (TapeSpec tape in value.Tapes)
					{
						stringBuilder.Append("\ttape=").Append(Join(tape.Center.x, tape.Center.y, tape.Center.z, tape.Axis.x, tape.Axis.y, tape.Axis.z, tape.Color.r, tape.Color.g, tape.Color.b, tape.Width, tape.Turns, tape.Offset, tape.Pattern));
					}
					stringBuilder.AppendLine();
				}
				File.WriteAllText(FilePath, stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Sling] Could not write guns.txt: " + ex.Message);
			}
		}

		private static string Join(params float[] values)
		{
			string[] array = new string[values.Length];
			for (int i = 0; i < values.Length; i++)
			{
				array[i] = values[i].ToString("R", CultureInfo.InvariantCulture);
			}
			return string.Join(",", array);
		}

		private static float[] ParseFloats(string s)
		{
			string[] array = s.Split(',');
			List<float> list = new List<float>(array.Length);
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (float.TryParse(array2[i].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					list.Add(result);
				}
			}
			return list.ToArray();
		}
	}
	internal sealed class Look
	{
		public int Model;

		public Color Color = new Color(0.08f, 0.08f, 0.08f);

		public int Texture;

		public int Charm;

		public int Charm2;

		public int Fitting;

		public int Adjuster;

		public int Finish;

		public Color Accent = new Color(0.95f, 0.4f, 0.05f);

		public int Stripe;

		public Look Clone()
		{
			Look look = new Look();
			look.CopyFrom(this);
			return look;
		}

		public void CopyFrom(Look o)
		{
			//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_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)
			Model = o.Model;
			Color = o.Color;
			Texture = o.Texture;
			Charm = o.Charm;
			Charm2 = o.Charm2;
			Fitting = o.Fitting;
			Adjuster = o.Adjuster;
			Finish = o.Finish;
			Accent = o.Accent;
			Stripe = o.Stripe;
		}

		public static Look FromGlobal()
		{
			Look look = new Look();
			look.FillFromGlobal();
			return look;
		}

		public void FillFromGlobal()
		{
			//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)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			Model = StrapKinds.Clamp(SlingSettings.StrapModel.Value);
			Color = StrapStyle.Current;
			Texture = Textures.Clamp(SlingSettings.TextureMode.Value);
			Charm = Mathf.Clamp(SlingSettings.Charm.Value, 0, StrapKinds.CharmNames.Length - 1);
			Charm2 = Mathf.Clamp(SlingSettings.Charm2.Value, 0, StrapKinds.CharmNames.Length - 1);
			Fitting = Mathf.Clamp(SlingSettings.EndFitting.Value, 0, 6);
			Adjuster = Mathf.Clamp(SlingSettings.Adjuster.Value, 0, 6);
			Finish = Mathf.Clamp(SlingSettings.Finish.Value, 0, 6);
			Accent = new Color(SlingSettings.AccentR.Value, SlingSettings.AccentG.Value, SlingSettings.AccentB.Value);
			Stripe = Mathf.Clamp(SlingSettings.Stripe.Value, 0, StrapKinds.StripeNames.Length - 1);
		}

		public void ApplyToGlobal()
		{
			SlingSettings.StrapModel.Value = StrapKinds.Clamp(Model);
			SlingSettings.ColorR.Value = Color.r;
			SlingSettings.ColorG.Value = Color.g;
			SlingSettings.ColorB.Value = Color.b;
			SlingSettings.TextureMode.Value = Textures.Clamp(Texture);
			SlingSettings.Charm.Value = Mathf.Clamp(Charm, 0, StrapKinds.CharmNames.Length - 1);
			SlingSettings.Charm2.Value = Mathf.Clamp(Charm2, 0, StrapKinds.CharmNames.Length - 1);
			SlingSettings.EndFitting.Value = Mathf.Clamp(Fitting, 0, 6);
			SlingSettings.Adjuster.Value = Mathf.Clamp(Adjuster, 0, 6);
			SlingSettings.Finish.Value = Mathf.Clamp(Finish, 0, 6);
			SlingSettings.AccentR.Value = Accent.r;
			SlingSettings.AccentG.Value = Accent.g;
			SlingSettings.AccentB.Value = Accent.b;
			SlingSettings.Stripe.Value = Mathf.Clamp(Stripe, 0, StrapKinds.StripeNames.Length - 1);
		}

		public string Serialize()
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			return Model.ToString(invariantCulture) + "," + Texture.ToString(invariantCulture) + "," + Charm.ToString(invariantCulture) + "," + Fitting.ToString(invariantCulture) + "," + Adjuster.ToString(invariantCulture) + "," + Finish.ToString(invariantCulture) + "," + Stripe.ToString(invariantCulture) + "," + Color.r.ToString("R", invariantCulture) + "," + Color.g.ToString("R", invariantCulture) + "," + Color.b.ToString("R", invariantCulture) + "," + Accent.r.ToString("R", invariantCulture) + "," + Accent.g.ToString("R", invariantCulture) + "," + Accent.b.ToString("R", invariantCulture) + "," + Charm2.ToString(invariantCulture);
		}

		public static bool TryParse(string text, out Look look)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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)
			look = null;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split(',');
			if (array.Length < 13)
			{
				return false;
			}
			float[] array2 = new float[13];
			for (int i = 0; i < 13; i++)
			{
				if (!float.TryParse(array[i].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i]))
				{
					return false;
				}
			}
			Look look2 = new Look();
			look2.Model = StrapKinds.Clamp((int)array2[0]);
			look2.Texture = Textures.Clamp((int)array2[1]);
			look2.Charm = Mathf.Clamp((int)array2[2], 0, StrapKinds.CharmNames.Length - 1);
			look2.Fitting = Mathf.Clamp((int)array2[3], 0, 6);
			look2.Adjuster = Mathf.Clamp((int)array2[4], 0, 6);
			look2.Finish = Mathf.Clamp((int)array2[5], 0, 6);
			look2.Stripe = Mathf.Clamp((int)array2[6], 0, StrapKinds.StripeNames.Length - 1);
			look2.Color = new Color(Mathf.Clamp01(array2[7]), Mathf.Clamp01(array2[8]), Mathf.Clamp01(array2[9]));
			look2.Accent = new Color(Mathf.Clamp01(array2[10]), Mathf.Clamp01(array2[11]), Mathf.Clamp01(array2[12]));
			if (array.Length > 13 && float.TryParse(array[13].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				look2.Charm2 = Mathf.Clamp((int)result, 0, StrapKinds.CharmNames.Length - 1);
			}
			look = look2;
			return true;
		}

		public string Describe()
		{
			string text = StrapKinds.Names[StrapKinds.Clamp(Model)];
			if (Charm != 0)
			{
				text = text + ", " + StrapKinds.CharmNames[Mathf.Clamp(Charm, 0, StrapKinds.CharmNames.Length - 1)];
			}
			if (Charm2 != 0)
			{
				text = text + " + " + StrapKinds.CharmNames[Mathf.Clamp(Charm2, 0, StrapKinds.CharmNames.Length - 1)];
			}
			return text;
		}
	}
	internal sealed class MeshData
	{
		public readonly List<Vector3> V = new List<Vector3>();

		public readonly List<Vector2> UV = new List<Vector2>();

		public readonly List<Color> C = new List<Color>();

		public readonly List<int> T = new List<int>();

		public readonly List<Vector3> N = new List<Vector3>();

		public readonly List<Color> Base = new List<Color>();

		public readonly List<byte> Mat = new List<byte>();

		public readonly List<float> Rough = new List<float>();

		public readonly List<float> Ao = new List<float>();

		public int Add(Vector3 p, Vector2 uv, Color c)
		{
			//IL_0006: 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_001e: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			V.Add(p);
			UV.Add(uv);
			C.Add(c);
			N.Add(Vector3.zero);
			Base.Add(c);
			Mat.Add(0);
			Rough.Add(0f);
			Ao.Add(1f);
			return V.Count - 1;
		}

		public int AddLit(Vector3 p, Vector3 n, Vector2 uv, Color baseColor, byte mat, float rough, float ao)
		{
			//IL_0006: 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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			V.Add(p);
			UV.Add(uv);
			C.Add(baseColor);
			N.Add(n);
			Base.Add(baseColor);
			Mat.Add(mat);
			Rough.Add(rough);
			Ao.Add(ao);
			return V.Count - 1;
		}

		public void Tri(int a, int b, int c)
		{
			T.Add(a);
			T.Add(b);
			T.Add(c);
			T.Add(a);
			T.Add(c);
			T.Add(b);
		}

		public void Quad(int a, int b, int c, int d)
		{
			Tri(a, b, c);
			Tri(a, c, d);
		}

		public void Append(MeshData other, Vector3 offset)
		{
			//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_0026: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			int count = V.Count;
			for (int i = 0; i < other.V.Count; i++)
			{
				V.Add(other.V[i] + offset);
				UV.Add(other.UV[i]);
				C.Add(other.C[i]);
				N.Add(other.N[i]);
				Base.Add(other.Base[i]);
				Mat.Add(other.Mat[i]);
				Rough.Add(other.Rough[i]);
				Ao.Add(other.Ao[i]);
			}
			for (int j = 0; j < other.T.Count; j++)
			{
				T.Add(other.T[j] + count);
			}
		}

		public void Fill(Mesh mesh)
		{
			mesh.Clear();
			mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(V.ToArray());
			mesh.uv = Il2CppStructArray<Vector2>.op_Implicit(UV.ToArray());
			mesh.colors = Il2CppStructArray<Color>.op_Implicit(C.ToArray());
			mesh.triangles = Il2CppStructArray<int>.op_Implicit(T.ToArray());
			mesh.RecalculateBounds();
		}

		public static float Shade(Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = new Vector3(0.3f, 0.8f, 0.5f);
			float num = Mathf.Clamp01(Vector3.Dot(normal, ((Vector3)(ref val)).normalized) * 0.5f + 0.5f);
			return 0.45f + 0.55f * num;
		}

		public static MeshData Torus(float major, float minor, int segments, int sides, Color baseColor)
		{
			//IL_0037: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			MeshData meshData = new MeshData();
			Vector3 val = default(Vector3);
			for (int i = 0; i <= segments; i++)
			{
				float num = (float)i / (float)segments * (float)Math.PI * 2f;
				((Vector3)(ref val))..ctor(Mathf.Cos(num), Mathf.Sin(num), 0f);
				Vector3 val2 = val * major;
				for (int j = 0; j <= sides; j++)
				{
					float num2 = (float)j / (float)sides * (float)Math.PI * 2f;
					Vector3 val3 = val * Mathf.Cos(num2) + Vector3.forward * Mathf.Sin(num2);
					float num3 = Shade(val3);
					meshData.Add(val2 + val3 * minor, new Vector2((float)i / (float)segments, (float)j / (float)sides), new Color(baseColor.r * num3, baseColor.g * num3, baseColor.b * num3, 1f));
				}
			}
			int num4 = sides + 1;
			for (int k = 0; k < segments; k++)
			{
				for (int l = 0; l < sides; l++)
				{
					int num5 = k * num4 + l;
					meshData.Quad(num5, num5 + num4, num5 + num4 + 1, num5 + 1);
				}
			}
			return meshData;
		}

		public static void EllipseTubeVertices(Vector3[] v, Color[] c, int start, Vector3 center, Vector3 axisA, Vector3 axisB, float a, float b, float wire, Color baseColor, int segs, int sides, Vector3 light)
		{
			//IL_0000: 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_0004: 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_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_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_0044: 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_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_0057: 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_0069: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f2: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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)
			Vector3 val = Vector3.Cross(axisA, axisB);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			for (int i = 0; i < segs; i++)
			{
				float num = (float)i / (float)segs * (float)Math.PI * 2f;
				float num2 = Mathf.Cos(num);
				float num3 = Mathf.Sin(num);
				Vector3 val2 = axisA * (a * num2) + axisB * (b * num3);
				val = axisA * (num2 / a) + axisB * (num3 / b);
				Vector3 normalized2 = ((Vector3)(ref val)).normalized;
				for (int j = 0; j < sides; j++)
				{
					float num4 = (float)j / (float)sides * (float)Math.PI * 2f;
					Vector3 val3 = normalized2 * Mathf.Cos(num4) + normalized * Mathf.Sin(num4);
					float num5 = 0.45f + 0.55f * Mathf.Clamp01(Vector3.Dot(val3, light) * 0.5f + 0.5f);
					int num6 = start + i * sides + j;
					v[num6] = center + val2 + val3 * wire;
					c[num6] = new Color(baseColor.r * num5, baseColor.g * num5, baseColor.b * num5, 1f);
				}
			}
		}

		public void EllipseTubeQuads(int start, int segs, int sides)
		{
			for (int i = 0; i < segs; i++)
			{
				int num = (i + 1) % segs;
				for (int j = 0; j < sides; j++)
				{
					int num2 = (j + 1) % sides;
					Quad(start + i * sides + j, start + num * sides + j, start + num * sides + num2, start + i * sides + num2);
				}
			}
		}

		public void AddEllipseTube(Vector3 center, Vector3 axisA, Vector3 axisB, float a, float b, float wire, Color baseColor, int segs, int sides)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[segs * sides];
			Color[] array2 = (Color[])(object)new Color[segs * sides];
			Vector3 val = new Vector3(0.3f, 0.8f, 0.5f);
			EllipseTubeVertices(array, array2, 0, center, axisA, axisB, a, b, wire, baseColor, segs, sides, ((Vector3)(ref val)).normalized);
			int count = V.Count;
			for (int i = 0; i < array.Length; i++)
			{
				Add(array[i], Vector2.zero, array2[i]);
			}
			EllipseTubeQuads(count, segs, sides);
		}

		public void AddCone(float topY, float topR, float botY, float botR, int sides, Color baseColor)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0083: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			int count = V.Count;
			Vector3 val = default(Vector3);
			Color c = default(Color);
			for (int i = 0; i < sides; i++)
			{
				float num = (float)i / (float)sides * (float)Math.PI * 2f;
				((Vector3)(ref val))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num));
				float num2 = Shade(val) * ((i % 2 == 0) ? 1f : 0.8f);
				((Color)(ref c))..ctor(baseColor.r * num2, baseColor.g * num2, baseColor.b * num2, 1f);
				Add(new Vector3(val.x * topR, topY, val.z * topR), new Vector2((float)i / (float)sides, 1f), c);
				Add(new Vector3(val.x * botR, botY, val.z * botR), new Vector2((float)i / (float)sides, 0f), c);
			}
			for (int j = 0; j < sides; j++)
			{
				int num3 = count + j * 2;
				int num4 = count + (j + 1) % sides * 2;
				Quad(num3, num3 + 1, num4 + 1, num4);
			}
		}

		public void AddBox(Vector3 center, Vector3 size, Color baseColor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_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_00bd: 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_00c5: 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_00da: 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_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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = size * 0.5f;
			AddFace(center, Vector3.right, new Vector3(0f, val.y, 0f), new Vector3(0f, 0f, val.z), val.x, baseColor);
			AddFace(center, Vector3.left, new Vector3(0f, val.y, 0f), new Vector3(0f, 0f, val.z), val.x, baseColor);
			AddFace(center, Vector3.up, new Vector3(val.x, 0f, 0f), new Vector3(0f, 0f, val.z), val.y, baseColor);
			AddFace(center, Vector3.down, new Vector3(val.x, 0f, 0f), new Vector3(0f, 0f, val.z), val.y, baseColor);
			AddFace(center, Vector3.forward, new Vector3(val.x, 0f, 0f), new Vector3(0f, val.y, 0f), val.z, baseColor);
			AddFace(center, Vector3.back, new Vector3(val.x, 0f, 0f), new Vector3(0f, val.y, 0f), val.z, baseColor);
		}

		private void AddFace(Vector3 center, Vector3 normal, Vector3 u, Vector3 v, float distance, Color baseColor)
		{
			//IL_0000: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0047: 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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			float num = Shade(normal);
			Color c = default(Color);
			((Color)(ref c))..ctor(baseColor.r * num, baseColor.g * num, baseColor.b * num, 1f);
			Vector3 val = center + normal * distance;
			int a = Add(val - u - v, new Vector2(0f, 0f), c);
			int b = Add(val + u - v, new Vector2(1f, 0f), c);
			int c2 = Add(val + u + v, new Vector2(1f, 1f), c);
			int d = Add(val - u + v, new Vector2(0f, 1f), c);
			Quad(a, b, c2, d);
		}
	}
	internal static class MeshObject
	{
		public static GameObject Create(string name, Mesh mesh, Material material, out MeshRenderer renderer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			renderer = val.AddComponent<MeshRenderer>();
			if ((Object)(object)material != (Object)null)
			{
				((Renderer)renderer).sharedMaterial = material;
			}
			((Renderer)renderer).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)renderer).receiveShadows = false;
			return val;
		}
	}
	public class Mod : MelonMod
	{
		public const string ModVersion = "0.9.0";

		public override void OnInitializeMelon()
		{
			SlingSettings.Init();
			Safe.Run("menu", SlingMenu.Build);
			Hooking.OnGrabObject += OnGrab;
			Hooking.OnLevelUnloaded += OnLevelUnloaded;
			MelonLogger.Msg("Sling 0.9.0 loaded. Open BoneMenu > Sling. Data folder: " + Paths.DataDir);
		}

		private static void OnGrab(GameObject grabbed, Hand hand)
		{
			Safe.Run("grab", delegate
			{
				StrapManager.OnGrabbed(grabbed);
			});
		}

		private static void OnLevelUnloaded()
		{
			Safe.Run("unload", StrapManager.ClearAll);
			Safe.Run("unload tape", TapeTool.OnLevelUnloaded);
		}

		public override void OnUpdate()
		{
			Safe.Run("update", StrapManager.Update);
			Safe.Run("calibration", Calibration.Update);
			Safe.Run("tape", TapeTool.Update);
		}

		public override void OnFixedUpdate()
		{
			float dt = Time.fixedDeltaTime;
			Safe.Run("fixed", delegate
			{
				StrapManager.FixedStep(dt);
			});
		}

		public override void OnLateUpdate()
		{
			Safe.Run("render", StrapManager.Render);
		}

		public override void OnApplicationQuit()
		{
			SlingSettings.Save();
		}
	}
	internal static class Mounts
	{
		private sealed class View
		{
			public GameObject Go;

			public Mesh Mesh;

			public readonly Relit Lit = new Relit();

			public float Amount;

			public float Highlight;

			public float Kick;

			public int BuiltKey = -1;
		}

		public static readonly string[] StyleNames = new string[3] { "D-ring on a tab", "Round ring", "Webbing loops" };

		private static readonly View[] spotViews = new View[11];

		private static readonly View[] hipViews = new View[2];

		private static readonly float[] spotUntil = new float[11];

		private static readonly float[] hipUntil = new float[2];

		private static Material material;

		private static MeshData shared;

		private static int sharedKey = -1;

		private static int finishHint = 1;

		private static bool failed;

		public static bool Active => SlingSettings.MountMode.Value != 0;

		private static int HipIndex(WearSlot shoulder)
		{
			return (shoulder != WearSlot.LeftShoulder) ? 1 : 0;
		}

		public static Vector3 Normal(WearSlot slot, bool hip)
		{
			//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_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_000f: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_009b: 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_00a8: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 right = BodyFrame.Right;
			Vector3 forward = BodyFrame.Forward;
			if (hip)
			{
				return right * ((slot == WearSlot.LeftShoulder) ? 1f : (-1f));
			}
			Vector3 val;
			switch (slot)
			{
			case WearSlot.LeftShoulder:
				val = -right * 0.6f + Vector3.up * 0.8f;
				return ((Vector3)(ref val)).normalized;
			case WearSlot.RightShoulder:
				val = right * 0.6f + Vector3.up * 0.8f;
				return ((Vector3)(ref val)).normalized;
			case WearSlot.Back:
				return -forward;
			case WearSlot.LeftHip:
			case WearSlot.LeftThigh:
				return -right;
			case WearSlot.RightHip:
			case WearSlot.RightThigh:
				return right;
			default:
				return forward;
			}
		}

		private static Vector3 UpOf(Vector3 normal)
		{
			//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_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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.ProjectOnPlane(Vector3.up, normal);
			if (((Vector3)(ref val)).sqrMagnitude < 0.05f)
			{
				val = BodyFrame.Forward;
			}
			return ((Vector3)(ref val)).normalized;
		}

		public static Vector3 BarAxis(WearSlot slot, bool hip)
		{
			//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_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_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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Normal(slot, hip);
			Vector3 val2 = Vector3.Cross(UpOf(val), val);
			return ((Vector3)(ref val2)).normalized;
		}

		public static Vector3 RingPoint(WearSlot slot, bool hip)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_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)
			return (hip ? WearPoints.HipAnchor(slot) : WearPoints.Anchor(slot)) + Normal(slot, hip) * 0.0095f;
		}

		private static void Frame(WearSlot slot, bool hip, out Vector3 pos, out Quaternion rot)
		{
			//IL_000d: 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_0012: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			pos = (hip ? WearPoints.HipAnchor(slot) : WearPoints.Anchor(slot));
			Vector3 val = Normal(slot, hip);
			rot = Quaternion.LookRotation(val, UpOf(val));
		}

		public static void Occupy(WearSlot slot, bool hip)
		{
			float num = Time.unscaledTime + 0.8f;
			if (hip)
			{
				hipUntil[HipIndex(slot)] = num;
			}
			else
			{
				spotUntil[(int)slot] = num;
			}
		}

		public static void Kick(WearSlot slot, bool hip)
		{
			View view = (hip ? hipViews[HipIndex(slot)] : spotViews[(int)slot]);
			if (view != null)
			{
				view.Kick = 1f;
			}
		}

		public static void SetFinish(int finish)
		{
			finishHint = Mathf.Clamp(finish, 0, 5);
		}

		public static void Update(float dt, bool holding, Vector3 handPos, int skip = -1)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			int value = SlingSettings.MountMode.Value;
			if (!SlingSettings.Enabled.Value || value == 0 || !BodyFrame.Valid || failed)
			{
				HideAll();
				return;
			}
			try
			{
				EnsureShared();
				Shading.BeginFrame();
				float unscaledTime = Time.unscaledTime;
				WearSlot slot = WearSlot.LeftShoulder;
				float dist;
				bool flag = holding && WearPoints.TryNearest(handPos, SlingSettings.WearRadius.Value, out slot, out dist, skip);
				for (int i = 0; i < spotViews.Length; i++)
				{
					WearPoints.Spot spot = WearPoints.Spots[i];
					bool want = unscaledTime < spotUntil[i] || (spot.Enabled.Value && (value == 2 || holding));
					Step(ref spotViews[i], "SlingMount" + i, spot.Slot, hip: false, want, flag && slot == spot.Slot, dt);
				}
				for (int j = 0; j < hipViews.Length; j++)
				{
					WearSlot slot2 = ((j != 0) ? WearSlot.RightShoulder : WearSlot.LeftShoulder);
					Step(ref hipViews[j], "SlingMountHip" + j, slot2, hip: true, unscaledTime < hipUntil[j], lit: false, dt);
				}
			}
			catch (Exception ex)
			{
				failed = true;
				HideAll();
				MelonLogger.Warning($"[Sling] The body mounts failed ({ex.GetType().Name}: {ex.Message}); they stay off until the game is restarted.");
			}
		}

		private static void Step(ref View v, string name, WearSlot slot, bool hip, bool want, bool lit, float dt)
		{
			//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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			if (v == null)
			{
				if (!want)
				{
					return;
				}
				v = CreateView(name);
				if (v == null)
				{
					return;
				}
			}
			v.Amount = Mathf.MoveTowards(v.Amount, want ? 1f : 0f, (want ? 7f : 4.5f) * dt);
			v.Highlight = Mathf.MoveTowards(v.Highlight, lit ? 1f : 0f, 8f * dt);
			v.Kick = Mathf.Max(0f, v.Kick - dt * 2.2f);
			if (v.Amount <= 0.001f)
			{
				if (v.Go.activeSelf)
				{
					v.Go.SetActive(false);
				}
				return;
			}
			if (!v.Go.activeSelf)
			{
				v.Go.SetActive(true);
			}
			if (v.BuiltKey != sharedKey)
			{
				v.Lit.Set(shared, v.Mesh);
				v.BuiltKey = sharedKey;
			}
			v.Lit.MinInterval = (SlingSettings.LowDetail.Value ? 0.25f : 0.08f);
			Frame(slot, hip, out var pos, out var rot);
			float num = v.Kick * Mathf.Sin(Time.unscaledTime * 40f);
			rot = Quaternion.AngleAxis(9f * num, BarAxis(slot, hip)) * rot;
			float num2 = EaseOutBack(v.Amount) * (1f + 0.22f * v.Highlight) * (1f + 0.08f * v.Kick);
			v.Go.transform.SetPositionAndRotation(pos, rot);
			v.Go.transform.localScale = Vector3.one * Mathf.Max(0.001f, num2);
			v.Lit.Update(v.Go.transform);
		}

		private static float EaseOutBack(float x)
		{
			x = Mathf.Clamp01(x);
			float num = x - 1f;
			return 1f + 2.70158f * num * num * num + 1.70158f * num * num;
		}

		private static View CreateView(string name)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			EnsureMaterial();
			if ((Object)(object)material == (Object)null)
			{
				return null;
			}
			View view = new View();
			view.Mesh = new Mesh();
			view.Go = MeshObject.Create(name, view.Mesh, material, out var _);
			Object.DontDestroyOnLoad((Object)(object)view.Go);
			view.Go.SetActive(false);
			return view;
		}

		private static void EnsureMaterial()
		{
			//IL_002b: 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)
			if (!((Object)(object)material != (Object)null))
			{
				material = Visuals.NewMaterial((Color)(Visuals.VertexColors ? Color.white : new Color(0.55f, 0.56f, 0.58f)));
				if ((Object)(object)material != (Object)null)
				{
					material.renderQueue = 3002;
				}
			}
		}

		private static void EnsureShared()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(SlingSettings.MountStyle.Value, 0, StyleNames.Length - 1);
			int num2 = num * 1000 + finishHint * 10 + Mathf.Clamp(Finishes.Wear, 0, 3);
			if (num2 != sharedKey || shared == null)
			{
				shared = Parts.Mount(num, finishHint);
				sharedKey = num2;
				if (!Visuals.VertexColors && (Object)(object)material != (Object)null)
				{
					Finishes.Get(finishHint, out var metal, out var _);
					material.color = metal.Base;
				}
			}
		}

		private static void HideAll()
		{
			for (int i = 0; i < spotViews.Length; i++)
			{
				HideView(spotViews[i]);
			}
			for (int j = 0; j < hipViews.Length; j++)
			{
				HideView(hipViews[j]);
			}
		}

		private static void HideView(View v)
		{
			if (v != null)
			{
				v.Amount = 0f;
				v.Highlight = 0f;
				if ((Object)(object)v.Go != (Object)null && v.Go.activeSelf)
				{
					v.Go.SetActive(false);
				}
			}
		}

		public static void DestroyAll()
		{
			for (int i = 0; i < spotViews.Length; i++)
			{
				DestroyView(ref spotViews[i]);
			}
			for (int j = 0; j < hipViews.Length; j++)
			{
				DestroyView(ref hipViews[j]);
			}
			if ((Object)(object)material != (Object)null)
			{
				Object.Destroy((Object)(object)material);
			}
			material = null;
			shared = null;
			sharedKey = -1;
		}

		private static void DestroyView(ref View v)
		{
			if (v != null)
			{
				if ((Object)(object)v.Go != (Object)null)
				{
					Object.Destroy((Object)(object)v.Go);
				}
				if ((Object)(object)v.Mesh != (Object)null)
				{
					Object.Destroy((Object)(object)v.Mesh);
				}
				v = null;
			}
		}
	}
	internal sealed class StrapClip
	{
		private struct Metric
		{
			public bool Ready;

			public float Reach;

			public float Catch;

			public float Scale;
		}

		private static readonly Metric[] metrics = new Metric[6];

		private GameObject go;

		private Mesh mesh;

		private Material mat;

		private readonly Relit relit = new Relit();

		private int builtKind = -1;

		private int builtFinish = -1;

		private int builtWear = -1;

		private bool failed;

		public static int KindFor(int fit)
		{
			if (fit == 4 || fit == 5)
			{
				return fit;
			}
			return 2;
		}

		private static Metric MetricOf(int kind)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Metric metric = metrics[kind];
			if (metric.Ready)
			{
				return metric;
			}
			Parts.Fitting(kind, 0, 0f, 0f, Color.white, out var reach, out var _);
			metric.Ready = true;
			metric.Reach = reach;
			switch (kind)
			{
			case 4:
				metric.Catch = 0.0066f;
				metric.Scale = 0.62f;
				break;
			case 5:
				metric.Catch = 0.005f;
				metric.Scale = 0.8f;
				break;
			default:
				metric.Catch = 0.0064f;
				metric.Scale = 0.85f;
				break;
			}
			metrics[kind] = metric;
			return metric;
		}

		public static float PinDistance(int fit)
		{
			Metric metric = MetricOf(KindFor(fit));
			return (metric.Reach - metric.Catch) * metric.Scale;
		}

		public void Show(int fit, int finish, Vector3 pin, Vector3 dir, Vector3 axis, float grow, float tilt)
		{
			//IL_0047: 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_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_004f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			/