Decompiled source of GFL2 Lind v1.0.0

LindSuit.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using JigglePhysics;
using ModelReplacement;
using ModelReplacement.AvatarBodyUpdater;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace LindSuit;

public enum AttentionKind
{
	Player,
	Enemy,
	Item
}
public struct AttentionCandidate
{
	public int Key;

	public AttentionKind Kind;

	public float Distance;

	public bool Speaking;

	public bool Eligible;

	public AttentionCandidate(int key, AttentionKind kind, float distance, bool speaking = true, bool eligible = true)
	{
		Key = key;
		Kind = kind;
		Distance = distance;
		Speaking = speaking;
		Eligible = eligible;
	}
}
public sealed class LindAttentionSelection
{
	private float lastSpeech;

	private float selectedAt;

	public int CurrentKey { get; private set; }

	public bool HasTarget { get; private set; }

	public AttentionKind CurrentKind { get; private set; }

	public void Reset()
	{
		HasTarget = false;
		CurrentKey = 0;
		lastSpeech = (selectedAt = 0f);
	}

	public int Choose(IList<AttentionCandidate> candidates, float now, float pauseHold = 1.2f)
	{
		AttentionCandidate attentionCandidate = default(AttentionCandidate);
		AttentionCandidate c = default(AttentionCandidate);
		AttentionCandidate c2 = default(AttentionCandidate);
		bool flag = false;
		bool flag2 = false;
		bool flag3 = false;
		foreach (AttentionCandidate candidate in candidates)
		{
			if (!candidate.Eligible || float.IsNaN(candidate.Distance) || float.IsInfinity(candidate.Distance) || candidate.Distance < 0f)
			{
				continue;
			}
			if (HasTarget && candidate.Key == CurrentKey && candidate.Kind == CurrentKind)
			{
				attentionCandidate = candidate;
				flag = true;
			}
			if (candidate.Kind == AttentionKind.Player)
			{
				if (candidate.Speaking && (!flag2 || candidate.Distance < c.Distance))
				{
					c = candidate;
					flag2 = true;
				}
			}
			else if (!flag3 || candidate.Kind < c2.Kind || (candidate.Kind == c2.Kind && candidate.Distance < c2.Distance))
			{
				c2 = candidate;
				flag3 = true;
			}
		}
		if (flag && attentionCandidate.Kind == AttentionKind.Player && attentionCandidate.Speaking)
		{
			lastSpeech = now;
		}
		if (flag2)
		{
			if (flag && attentionCandidate.Kind == AttentionKind.Player && attentionCandidate.Speaking && (now - selectedAt < 0.65f || c.Distance >= attentionCandidate.Distance * 0.7f))
			{
				return CurrentKey;
			}
			return Select(c, now);
		}
		if (flag && attentionCandidate.Kind == AttentionKind.Player && now - lastSpeech <= Mathf.Clamp(pauseHold, 0f, 5f))
		{
			return CurrentKey;
		}
		if (flag3)
		{
			if (flag && attentionCandidate.Kind == c2.Kind && attentionCandidate.Kind != AttentionKind.Player && (now - selectedAt < 1.5f || c2.Distance >= attentionCandidate.Distance * 0.7f))
			{
				return CurrentKey;
			}
			return Select(c2, now);
		}
		Reset();
		return 0;
	}

	private int Select(AttentionCandidate c, float now)
	{
		if (!HasTarget || c.Key != CurrentKey || c.Kind != CurrentKind)
		{
			selectedAt = now;
		}
		HasTarget = true;
		CurrentKey = c.Key;
		CurrentKind = c.Kind;
		if (c.Kind == AttentionKind.Player && c.Speaking)
		{
			lastSpeech = now;
		}
		return CurrentKey;
	}

	public static bool InView(Vector3 origin, Vector3 forward, Vector3 point, float radius)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point - origin;
		float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
		if (sqrMagnitude < 0.0225f || sqrMagnitude > radius * radius)
		{
			return false;
		}
		Vector3 val2 = Vector3.ProjectOnPlane(val, Vector3.up);
		Vector3 val3 = Vector3.ProjectOnPlane(forward, Vector3.up);
		if (Vector3.Angle(val2, val3) <= 65f)
		{
			return Mathf.Abs(Mathf.Atan2(val.y, ((Vector3)(ref val2)).magnitude) * 57.29578f) <= 60f;
		}
		return false;
	}

	public static bool ActiveSpeech(bool speaking, float amplitude)
	{
		if (speaking && !float.IsNaN(amplitude) && !float.IsInfinity(amplitude))
		{
			return amplitude >= 0.002f;
		}
		return false;
	}

	public static bool Visible(Vector3 origin, Vector3 point, int mask, Transform observer, Transform model, Transform target, RaycastHit[] hits)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_001d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point - origin;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude < 0.05f)
		{
			return true;
		}
		int num = Physics.RaycastNonAlloc(origin, val / magnitude, hits, magnitude, mask, (QueryTriggerInteraction)1);
		if (num == hits.Length)
		{
			return false;
		}
		for (int i = 0; i < num; i++)
		{
			Transform transform = ((RaycastHit)(ref hits[i])).transform;
			if (Object.op_Implicit((Object)(object)transform) && (!Object.op_Implicit((Object)(object)observer) || !transform.IsChildOf(observer)) && (!Object.op_Implicit((Object)(object)model) || !transform.IsChildOf(model)) && (!Object.op_Implicit((Object)(object)target) || !transform.IsChildOf(target)))
			{
				return false;
			}
		}
		return true;
	}
}
public sealed class LindAttention
{
	private sealed class ItemRenderer
	{
		public GrabbableObject Item;

		public Renderer Renderer;
	}

	private readonly LindAttentionSelection selection = new LindAttentionSelection();

	private readonly List<AttentionCandidate> candidates = new List<AttentionCandidate>(64);

	private readonly Dictionary<int, Object> objects = new Dictionary<int, Object>();

	private readonly RaycastHit[] hits = (RaycastHit[])(object)new RaycastHit[24];

	private static EnemyAI[] enemies = (EnemyAI[])(object)new EnemyAI[0];

	private static GrabbableObject[] items = (GrabbableObject[])(object)new GrabbableObject[0];

	private static float nextSceneScan;

	private static StartOfRound scene;

	private static readonly Dictionary<int, ItemRenderer> itemRenderers = new Dictionary<int, ItemRenderer>();

	private static readonly HashSet<int> aliveItems = new HashSet<int>();

	private static readonly List<int> staleItems = new List<int>();

	private Object target;

	private float nextScan;

	public void Reset()
	{
		selection.Reset();
		target = null;
		nextScan = 0f;
	}

	private static void ScanScene(float now)
	{
		if ((Object)(object)scene != (Object)(object)StartOfRound.Instance)
		{
			scene = StartOfRound.Instance;
			nextSceneScan = 0f;
			itemRenderers.Clear();
		}
		if (now < nextSceneScan)
		{
			return;
		}
		nextSceneScan = now + 1f;
		enemies = Object.FindObjectsOfType<EnemyAI>();
		items = Object.FindObjectsOfType<GrabbableObject>();
		aliveItems.Clear();
		GrabbableObject[] array = items;
		foreach (GrabbableObject val in array)
		{
			if (Object.op_Implicit((Object)(object)val))
			{
				aliveItems.Add(((Object)val).GetInstanceID());
			}
		}
		staleItems.Clear();
		foreach (KeyValuePair<int, ItemRenderer> itemRenderer in itemRenderers)
		{
			if (!aliveItems.Contains(itemRenderer.Key))
			{
				staleItems.Add(itemRenderer.Key);
			}
		}
		foreach (int staleItem in staleItems)
		{
			itemRenderers.Remove(staleItem);
		}
	}

	internal static void ClearSceneCache()
	{
		scene = null;
		nextSceneScan = 0f;
		enemies = (EnemyAI[])(object)new EnemyAI[0];
		items = (GrabbableObject[])(object)new GrabbableObject[0];
		itemRenderers.Clear();
		aliveItems.Clear();
		staleItems.Clear();
	}

	private static Vector3 Point(Object value)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB val = (PlayerControllerB)(object)((value is PlayerControllerB) ? value : null);
		if (val != null)
		{
			if (!Object.op_Implicit((Object)(object)val.playerEye))
			{
				return ((Component)val).transform.position + Vector3.up * 1.6f;
			}
			return val.playerEye.position;
		}
		EnemyAI val2 = (EnemyAI)(object)((value is EnemyAI) ? value : null);
		if (val2 != null)
		{
			if (!Object.op_Implicit((Object)(object)val2.eye))
			{
				return ((Component)val2).transform.position + Vector3.up;
			}
			return val2.eye.position;
		}
		GrabbableObject val3 = (GrabbableObject)(object)((value is GrabbableObject) ? value : null);
		if (val3 != null)
		{
			int instanceID = ((Object)val3).GetInstanceID();
			if (!itemRenderers.TryGetValue(instanceID, out var value2) || (Object)(object)value2.Item != (Object)(object)val3)
			{
				value2 = new ItemRenderer
				{
					Item = val3,
					Renderer = ((Component)val3).GetComponentInChildren<Renderer>()
				};
				itemRenderers[instanceID] = value2;
			}
			if (!Object.op_Implicit((Object)(object)value2.Renderer))
			{
				return ((Component)val3).transform.position;
			}
			Bounds bounds = value2.Renderer.bounds;
			return ((Bounds)(ref bounds)).center;
		}
		return Vector3.zero;
	}

	private void Add(Component value, AttentionKind kind, Vector3 origin, Vector3 forward, float range, bool speaking, PlayerControllerB owner, Transform model)
	{
		//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_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_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_006d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Point((Object)(object)value);
		if (LindAttentionSelection.InView(origin, forward, val, range))
		{
			int mask = (Object.op_Implicit((Object)(object)StartOfRound.Instance) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-5));
			if (LindAttentionSelection.Visible(origin, val, mask, ((Component)owner).transform, model, value.transform, hits))
			{
				int instanceID = ((Object)value).GetInstanceID();
				objects[instanceID] = (Object)(object)value;
				candidates.Add(new AttentionCandidate(instanceID, kind, Vector3.Distance(origin, val), speaking));
			}
		}
	}

	public bool Resolve(PlayerControllerB owner, Transform model, Vector3 origin, Vector3 forward, float now, out Vector3 direction)
	{
		//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_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: 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_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		direction = forward;
		if (!Object.op_Implicit((Object)(object)owner) || owner.isPlayerDead || !owner.isPlayerControlled || !Object.op_Implicit((Object)(object)StartOfRound.Instance))
		{
			Reset();
			return false;
		}
		if (now >= nextScan)
		{
			nextScan = now + 0.1f;
			candidates.Clear();
			objects.Clear();
			ScanScene(now);
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val == (Object)(object)owner) && val.isPlayerControlled && !val.isPlayerDead && ((Component)val).gameObject.activeInHierarchy)
				{
					bool flag = LindVoiceActivity.IsSpeaking(val);
					if (flag || (selection.HasTarget && selection.CurrentKind == AttentionKind.Player && selection.CurrentKey == ((Object)val).GetInstanceID()))
					{
						Add((Component)(object)val, AttentionKind.Player, origin, forward, Plugin.TalkingPlayersRange.Value, flag, owner, model);
					}
				}
			}
			EnemyAI[] array = enemies;
			foreach (EnemyAI val2 in array)
			{
				if (Object.op_Implicit((Object)(object)val2) && !val2.isEnemyDead && ((Behaviour)val2).isActiveAndEnabled)
				{
					Add((Component)(object)val2, AttentionKind.Enemy, origin, forward, Plugin.EnemiesRange.Value, speaking: false, owner, model);
				}
			}
			GrabbableObject[] array2 = items;
			foreach (GrabbableObject val3 in array2)
			{
				if (Object.op_Implicit((Object)(object)val3) && !val3.isHeld && !val3.isPocketed && !val3.isHeldByEnemy && ((Behaviour)val3).isActiveAndEnabled)
				{
					Add((Component)(object)val3, AttentionKind.Item, origin, forward, Plugin.ItemsRange.Value, speaking: false, owner, model);
				}
			}
			int key = selection.Choose(candidates, now, Plugin.SpeechPauseHold.Value);
			target = ((selection.HasTarget && objects.TryGetValue(key, out var value)) ? value : null);
		}
		if (!Object.op_Implicit(target))
		{
			return false;
		}
		Object obj = target;
		PlayerControllerB val4 = (PlayerControllerB)(object)((obj is PlayerControllerB) ? obj : null);
		if (val4 == null || (val4.isPlayerControlled && !val4.isPlayerDead))
		{
			Object obj2 = target;
			EnemyAI val5 = (EnemyAI)(object)((obj2 is EnemyAI) ? obj2 : null);
			if (val5 == null || !val5.isEnemyDead)
			{
				Object obj3 = target;
				GrabbableObject val6 = (GrabbableObject)(object)((obj3 is GrabbableObject) ? obj3 : null);
				if (val6 == null || (!val6.isHeld && !val6.isPocketed && !val6.isHeldByEnemy))
				{
					direction = Point(target) - origin;
					return ((Vector3)(ref direction)).sqrMagnitude > 1E-06f;
				}
			}
		}
		target = null;
		selection.Reset();
		nextScan = 0f;
		return false;
	}
}
internal static class LindVoiceActivity
{
	private static object comms;

	private static readonly Dictionary<int, float> retry = new Dictionary<int, float>();

	private static readonly Dictionary<int, object> states = new Dictionary<int, object>();

	internal static bool IsSpeaking(PlayerControllerB player)
	{
		object obj = LindFace.Read(player, "voicePlayerState") ?? LindFace.Read(LindFace.Read(player, "currentVoiceChatIngameSettings"), "_playerState");
		int instanceID = ((Object)player).GetInstanceID();
		if (obj == null && states.TryGetValue(instanceID, out var value))
		{
			obj = value;
		}
		if (obj == null && (!retry.TryGetValue(instanceID, out var value2) || Time.unscaledTime >= value2))
		{
			retry[instanceID] = Time.unscaledTime + 1f;
			comms = LindFace.Read(StartOfRound.Instance, "voiceChatModule");
			if (comms != null)
			{
				string text = (((NetworkBehaviour)player).IsOwner ? (LindFace.Read(comms, "LocalPlayerName") as string) : (LindFace.Read(player, "voicePlayerName") as string));
				if (!string.IsNullOrEmpty(text))
				{
					try
					{
						obj = LindRuntimeMembers.CallString(comms, "FindPlayer", text);
						if (obj != null)
						{
							states[instanceID] = obj;
						}
					}
					catch
					{
					}
				}
			}
		}
		bool value3;
		bool flag = LindRuntimeMembers.TryRead<bool>(obj, "IsSpeaking", out value3) && value3;
		if (LindRuntimeMembers.TryRead<bool>(obj, "IsConnected", out var value4) && !value4)
		{
			return false;
		}
		if (!LindRuntimeMembers.TryRead<float>(obj, "Amplitude", out var value5))
		{
			return flag;
		}
		return LindAttentionSelection.ActiveSpeech(flag, value5);
	}

	internal static void Clear()
	{
		comms = null;
		retry.Clear();
		states.Clear();
	}
}
public static class LindFirstPersonMesh
{
	private sealed class Entry
	{
		public Mesh Mesh;

		public int[] BoneIndices;

		public int[] MaterialSlots;
	}

	private static readonly Dictionary<Mesh, Entry> Cache = new Dictionary<Mesh, Entry>();

	public static int CachedMeshes => Cache.Count;

	private static HashSet<Transform> ArmBones(GameObject model)
	{
		//IL_0042: 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)
		Animator componentInChildren = model.GetComponentInChildren<Animator>(true);
		if (!Object.op_Implicit((Object)(object)componentInChildren) || !componentInChildren.isHuman)
		{
			throw new InvalidOperationException("Lind first-person avatar must be humanoid.");
		}
		HashSet<Transform> hashSet = new HashSet<Transform>();
		HumanBodyBones[] array = new HumanBodyBones[6];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		HumanBodyBones[] array2 = (HumanBodyBones[])(object)array;
		foreach (HumanBodyBones val in array2)
		{
			Transform boneTransform = componentInChildren.GetBoneTransform(val);
			if (Object.op_Implicit((Object)(object)boneTransform))
			{
				Transform[] componentsInChildren = ((Component)boneTransform).GetComponentsInChildren<Transform>(true);
				foreach (Transform item in componentsInChildren)
				{
					hashSet.Add(item);
				}
			}
		}
		return hashSet;
	}

	public static void Prime(GameObject model)
	{
		HashSet<Transform> arms = ArmBones(model);
		SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Get(componentsInChildren[i], arms);
		}
	}

	public static IEnumerator PrimeIncremental(GameObject model)
	{
		HashSet<Transform> arms = ArmBones(model);
		SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Get(componentsInChildren[i], arms);
			yield return null;
		}
	}

	private static bool Allowed(BoneWeight weight, bool[] bones)
	{
		if ((((BoneWeight)(ref weight)).weight0 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex0]) && (((BoneWeight)(ref weight)).weight1 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex1]) && (((BoneWeight)(ref weight)).weight2 <= 0f || bones[((BoneWeight)(ref weight)).boneIndex2]))
		{
			if (!(((BoneWeight)(ref weight)).weight3 <= 0f))
			{
				return bones[((BoneWeight)(ref weight)).boneIndex3];
			}
			return true;
		}
		return false;
	}

	private static Entry Get(SkinnedMeshRenderer renderer, HashSet<Transform> arms)
	{
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: 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_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Expected O, but got Unknown
		Mesh sharedMesh = renderer.sharedMesh;
		if (!Object.op_Implicit((Object)(object)sharedMesh))
		{
			return null;
		}
		if (Cache.TryGetValue(sharedMesh, out var value))
		{
			return value;
		}
		if (!sharedMesh.isReadable)
		{
			throw new InvalidOperationException("Lind first-person source mesh is not readable: " + ((Object)sharedMesh).name);
		}
		Transform[] bones = renderer.bones;
		bool[] array = new bool[bones.Length];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = Object.op_Implicit((Object)(object)bones[i]) && arms.Contains(bones[i]);
		}
		BoneWeight[] boneWeights = sharedMesh.boneWeights;
		if (boneWeights.Length != sharedMesh.vertexCount)
		{
			throw new InvalidOperationException("Lind arms require four-weight source skinning.");
		}
		bool[] array2 = new bool[sharedMesh.vertexCount];
		for (int j = 0; j < boneWeights.Length; j++)
		{
			array2[j] = Allowed(boneWeights[j], array);
		}
		List<int> list = new List<int>();
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		List<int[]> list2 = new List<int[]>();
		List<int> list3 = new List<int>();
		for (int k = 0; k < sharedMesh.subMeshCount; k++)
		{
			int[] triangles = sharedMesh.GetTriangles(k);
			List<int> list4 = new List<int>();
			for (int l = 0; l < triangles.Length; l += 3)
			{
				if (!array2[triangles[l]] || !array2[triangles[l + 1]] || !array2[triangles[l + 2]])
				{
					continue;
				}
				for (int m = 0; m < 3; m++)
				{
					int num = triangles[l + m];
					if (!dictionary.TryGetValue(num, out var value2))
					{
						value2 = list.Count;
						dictionary.Add(num, value2);
						list.Add(num);
					}
					list4.Add(value2);
				}
			}
			if (list4.Count > 0)
			{
				list3.Add(k);
				list2.Add(list4.ToArray());
			}
		}
		if (list.Count == 0)
		{
			Cache.Add(sharedMesh, null);
			return null;
		}
		List<int> list5 = new List<int>();
		Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
		BoneWeight[] array3 = (BoneWeight[])(object)new BoneWeight[list.Count];
		for (int n = 0; n < array3.Length; n++)
		{
			BoneWeight val = boneWeights[list[n]];
			int[] array4 = new int[4]
			{
				((BoneWeight)(ref val)).boneIndex0,
				((BoneWeight)(ref val)).boneIndex1,
				((BoneWeight)(ref val)).boneIndex2,
				((BoneWeight)(ref val)).boneIndex3
			};
			float[] array5 = new float[4]
			{
				((BoneWeight)(ref val)).weight0,
				((BoneWeight)(ref val)).weight1,
				((BoneWeight)(ref val)).weight2,
				((BoneWeight)(ref val)).weight3
			};
			for (int num2 = 0; num2 < 4; num2++)
			{
				if (array5[num2] <= 0f)
				{
					array4[num2] = 0;
					continue;
				}
				if (!dictionary2.TryGetValue(array4[num2], out var value3))
				{
					value3 = list5.Count;
					dictionary2.Add(array4[num2], value3);
					list5.Add(array4[num2]);
				}
				array4[num2] = value3;
			}
			((BoneWeight)(ref val)).boneIndex0 = array4[0];
			((BoneWeight)(ref val)).boneIndex1 = array4[1];
			((BoneWeight)(ref val)).boneIndex2 = array4[2];
			((BoneWeight)(ref val)).boneIndex3 = array4[3];
			array3[n] = val;
		}
		Mesh val2 = new Mesh
		{
			name = ((Object)sharedMesh).name + "_LindFirstPerson",
			indexFormat = (IndexFormat)(list.Count > 65535)
		};
		val2.vertices = Subset(sharedMesh.vertices, list);
		if (sharedMesh.normals.Length == sharedMesh.vertexCount)
		{
			val2.normals = Subset(sharedMesh.normals, list);
		}
		if (sharedMesh.tangents.Length == sharedMesh.vertexCount)
		{
			val2.tangents = Subset(sharedMesh.tangents, list);
		}
		if (sharedMesh.colors32.Length == sharedMesh.vertexCount)
		{
			val2.colors32 = Subset(sharedMesh.colors32, list);
		}
		for (int num3 = 0; num3 < 8; num3++)
		{
			List<Vector4> list6 = new List<Vector4>();
			sharedMesh.GetUVs(num3, list6);
			if (list6.Count == sharedMesh.vertexCount)
			{
				val2.SetUVs(num3, Subset(list6.ToArray(), list));
			}
		}
		val2.boneWeights = array3;
		val2.bindposes = Subset(sharedMesh.bindposes, list5);
		val2.subMeshCount = list2.Count;
		for (int num4 = 0; num4 < list2.Count; num4++)
		{
			val2.SetTriangles(list2[num4], num4, false);
		}
		val2.RecalculateBounds();
		value = new Entry
		{
			Mesh = val2,
			BoneIndices = list5.ToArray(),
			MaterialSlots = list3.ToArray()
		};
		Cache.Add(sharedMesh, value);
		return value;
	}

	private static T[] Subset<T>(T[] source, List<int> indices)
	{
		T[] array = new T[indices.Count];
		for (int i = 0; i < indices.Count; i++)
		{
			array[i] = source[indices[i]];
		}
		return array;
	}

	public static GameObject Convert(GameObject model)
	{
		HashSet<Transform> arms = ArmBones(model);
		SkinnedMeshRenderer[] componentsInChildren = model.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val in componentsInChildren)
		{
			Entry entry = Get(val, arms);
			if (entry == null)
			{
				((Renderer)val).enabled = false;
				Remove((Object)(object)val);
				continue;
			}
			Transform[] bones = val.bones;
			Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
			Transform[] array = (Transform[])(object)new Transform[entry.BoneIndices.Length];
			Material[] array2 = (Material[])(object)new Material[entry.MaterialSlots.Length];
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = bones[entry.BoneIndices[j]];
			}
			for (int k = 0; k < array2.Length; k++)
			{
				array2[k] = sharedMaterials[entry.MaterialSlots[k]];
			}
			val.sharedMesh = entry.Mesh;
			val.bones = array;
			((Renderer)val).sharedMaterials = array2;
			val.quality = (SkinQuality)4;
			val.updateWhenOffscreen = true;
			((Renderer)val).shadowCastingMode = (ShadowCastingMode)0;
		}
		StripSimulation(model);
		return model;
	}

	public static void StripSimulation(GameObject model)
	{
		Collider[] componentsInChildren = model.GetComponentsInChildren<Collider>(true);
		foreach (Collider obj in componentsInChildren)
		{
			obj.enabled = false;
			Remove((Object)(object)obj);
		}
		MonoBehaviour[] componentsInChildren2 = model.GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val in componentsInChildren2)
		{
			switch (((object)val).GetType().FullName)
			{
			case "LindSuit.LindLollipopMount":
			case "LindSuit.LindSecondaryMotion":
			case "LindSuit.LindHeadTracking":
			case "LindSuit.LindFootGrounding":
			case "LindSuit.LindFace":
			case "LindSuit.LindToonFrame":
			case "JigglePhysics.JiggleRigBuilder":
				((Behaviour)val).enabled = false;
				Remove((Object)(object)val);
				break;
			}
		}
	}

	private static void Remove(Object component)
	{
		if (Application.isPlaying)
		{
			Object.Destroy(component);
		}
		else
		{
			Object.DestroyImmediate(component);
		}
	}

	public static void Clear()
	{
		foreach (Entry value in Cache.Values)
		{
			if (value != null && Object.op_Implicit((Object)(object)value.Mesh))
			{
				Remove((Object)(object)value.Mesh);
			}
		}
		Cache.Clear();
	}
}
public static class LindFirstPersonPatch
{
	public static void Install(Harmony harmony)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Expected O, but got Unknown
		Type type = typeof(BodyReplacementBase).Assembly.GetType("ModelReplacement.Scripts.MeshHelper", throwOnError: true);
		MethodInfo methodInfo = AccessTools.Method(type, "ConvertModelToViewModel", new Type[1] { typeof(GameObject) }, (Type[])null);
		if (methodInfo == null)
		{
			throw new MissingMethodException(type.FullName, "ConvertModelToViewModel");
		}
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(LindFirstPersonPatch), "BeforeConvert", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(BodyReplacementBase), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LindFirstPersonPatch), "AfterBodyCreated", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static bool BeforeConvert(GameObject __0, ref GameObject __result)
	{
		if (!Object.op_Implicit((Object)(object)__0) || !((Object)__0).name.StartsWith("Lind_", StringComparison.Ordinal))
		{
			return true;
		}
		__result = LindFirstPersonMesh.Convert(__0);
		return false;
	}

	private static void AfterBodyCreated(BodyReplacementBase __instance)
	{
		if (__instance is LindBody)
		{
			object? value = AccessTools.Field(typeof(BodyReplacementBase), "replacementModel").GetValue(__instance);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			object? value2 = AccessTools.Field(typeof(BodyReplacementBase), "replacementModelShadow").GetValue(__instance);
			GameObject val2 = (GameObject)((value2 is GameObject) ? value2 : null);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2))
			{
				LindFirstPersonMesh.StripSimulation(val2);
				val2.AddComponent<LindShadowPose>().Initialize(val);
			}
		}
	}
}
[Serializable]
public class LindSolePoint
{
	public string[] bones;

	public Vector3[] points;

	public float[] weights;
}
[Serializable]
public class LindSoleOutfit
{
	public string id;

	public LindSolePoint[] points;
}
[Serializable]
public class LindSoleData
{
	public LindSoleOutfit[] outfits;
}
public class LindFootGrounding : MonoBehaviour
{
	private struct BoundPoint
	{
		public int[] bones;

		public Vector3[] points;

		public float[] weights;
	}

	private class BoundSole
	{
		public BoundPoint[] samples;

		public Transform[] bones;

		public Matrix4x4[] matrices;
	}

	private BoundSole native;

	private BoundSole model;

	private Transform hips;

	private bool ready;

	public float LastCorrection { get; private set; }

	private static BoundSole Bind(LindSoleOutfit data, Transform[] bones)
	{
		string[] names = data.points.SelectMany((LindSolePoint p) => p.bones).Distinct().ToArray();
		return new BoundSole
		{
			bones = names.Select((string n) => bones.First((Transform b) => ((Object)b).name == n)).ToArray(),
			matrices = (Matrix4x4[])(object)new Matrix4x4[names.Length],
			samples = data.points.Select((LindSolePoint p) => new BoundPoint
			{
				bones = p.bones.Select((string n) => Array.IndexOf(names, n)).ToArray(),
				points = p.points,
				weights = p.weights
			}).ToArray()
		};
	}

	public void Initialize(SkinnedMeshRenderer player, LindSoleData data)
	{
		if (!ready && Object.op_Implicit((Object)(object)player) && data != null)
		{
			string id = (((Object)this).name.StartsWith("Lind_Default") ? "Default" : (((Object)this).name.StartsWith("Lind_S001") ? "S001" : "S002"));
			native = Bind(data.outfits.First((LindSoleOutfit o) => o.id == "Vanilla"), player.bones);
			model = Bind(data.outfits.First((LindSoleOutfit o) => o.id == id), ((Component)this).GetComponentsInChildren<Transform>(true));
			hips = ((Component)this).GetComponent<Animator>().GetBoneTransform((HumanBodyBones)0);
			ready = true;
		}
	}

	private static float Floor(BoundSole values)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//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_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_007e: 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_008d: 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_009d: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < values.bones.Length; i++)
		{
			values.matrices[i] = values.bones[i].localToWorldMatrix;
		}
		float num = float.PositiveInfinity;
		BoundPoint[] samples = values.samples;
		for (int j = 0; j < samples.Length; j++)
		{
			BoundPoint boundPoint = samples[j];
			float num2 = 0f;
			for (int k = 0; k < boundPoint.bones.Length; k++)
			{
				Matrix4x4 val = values.matrices[boundPoint.bones[k]];
				Vector3 val2 = boundPoint.points[k];
				num2 += (val.m10 * val2.x + val.m11 * val2.y + val.m12 * val2.z + val.m13) * boundPoint.weights[k];
			}
			num = Mathf.Min(num, num2);
		}
		return num;
	}

	public void Step()
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		if (ready && Object.op_Implicit((Object)(object)hips))
		{
			float num = Floor(native) - Floor(model);
			if (!float.IsNaN(num) && !float.IsInfinity(num))
			{
				LastCorrection = num;
				Transform obj = hips;
				obj.position += Vector3.up * num;
			}
		}
	}
}
[DefaultExecutionOrder(200)]
public class LindHeadTracking : MonoBehaviour
{
	public PlayerControllerB Player;

	private readonly LindAttention attention = new LindAttention();

	public Quaternion? WorldAimFrame;

	public bool TrackingEnabled = true;

	private Transform neck;

	private Transform head;

	private Quaternion headToLook;

	private Quaternion neckBase;

	private Quaternion headBase;

	private Quaternion neckApplied;

	private Quaternion headApplied;

	private Quaternion neutralNeck;

	private Quaternion neutralHead;

	private bool ready;

	private bool applied;

	private int previousFrame = int.MinValue;

	private float yaw;

	private float pitch;

	private float aimWeight;

	public const float MaximumYaw = 50f;

	public const float MaximumUpPitch = 35f;

	public const float MaximumDownPitch = 45f;

	public const float MaximumCorrection = 55f;

	public const float NeckShare = 0.3f;

	public bool HasAttentionTarget { get; private set; }

	public Vector3 AttentionDirection { get; private set; }

	public float CurrentYaw => yaw;

	public float CurrentPitch => pitch;

	public float LastCorrectionAngle { get; private set; }

	public bool Ready => ready;

	public Vector3 LookForward
	{
		get
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!ready)
			{
				return ((Component)this).transform.forward;
			}
			return head.rotation * headToLook * Vector3.forward;
		}
	}

	public Vector3 LookUp
	{
		get
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!ready)
			{
				return ((Component)this).transform.up;
			}
			return head.rotation * headToLook * Vector3.up;
		}
	}

	private void Awake()
	{
		Initialize();
	}

	private void Initialize()
	{
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: 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_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		if (ready)
		{
			return;
		}
		Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
		Animator componentInChildren = ((Component)this).GetComponentInChildren<Animator>();
		neck = ((Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.isHuman) ? componentInChildren.GetBoneTransform((HumanBodyBones)9) : null);
		head = ((Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.isHuman) ? componentInChildren.GetBoneTransform((HumanBodyBones)10) : null);
		if (!Object.op_Implicit((Object)(object)neck))
		{
			neck = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "DEF-spine.005"));
		}
		if (!Object.op_Implicit((Object)(object)head))
		{
			head = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "DEF-spine.006"));
		}
		ready = Object.op_Implicit((Object)(object)neck) && Object.op_Implicit((Object)(object)head) && head.IsChildOf(neck);
		if (ready)
		{
			Transform val = ((IEnumerable<Transform>)componentsInChildren).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "LindGazeFrame"));
			headToLook = Quaternion.Inverse(head.rotation) * (Object.op_Implicit((Object)(object)val) ? val.rotation : Quaternion.identity);
			neckBase = (neutralNeck = neck.localRotation);
			headBase = (neutralHead = head.localRotation);
		}
	}

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

	private static bool Finite(Vector3 value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if (Finite(value.x) && Finite(value.y))
		{
			return Finite(value.z);
		}
		return false;
	}

	private static bool SameRotation(Quaternion a, Quaternion b)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_0023: 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_0033: 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_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)
		float num = ((!(Quaternion.Dot(a, b) < 0f)) ? 1 : (-1));
		float num2 = a.x - num * b.x;
		float num3 = a.y - num * b.y;
		float num4 = a.z - num * b.z;
		float num5 = a.w - num * b.w;
		return num2 * num2 + num3 * num3 + num4 * num4 + num5 * num5 < 1E-09f;
	}

	private void RestoreAppliedPose()
	{
		//IL_0017: 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_0040: 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_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if (ready && applied)
		{
			if (SameRotation(neck.localRotation, neckApplied))
			{
				neck.localRotation = neckBase;
			}
			if (SameRotation(head.localRotation, headApplied))
			{
				head.localRotation = headBase;
			}
			applied = false;
		}
	}

	public void PrepareForAvatarPose()
	{
		RestoreAppliedPose();
	}

	public void StepFromDirection(Vector3 direction, float deltaTime, int frameToken, bool tracking = true)
	{
		//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)
		//IL_002d: 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_0043: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		Initialize();
		if (!ready)
		{
			return;
		}
		RestoreAppliedPose();
		neckBase = neck.localRotation;
		headBase = head.localRotation;
		bool flag = tracking && TrackingEnabled && Finite(direction) && ((Vector3)(ref direction)).sqrMagnitude > 1E-08f;
		Quaternion val = (Quaternion)(((??)WorldAimFrame) ?? ((Component)this).transform.rotation);
		if (previousFrame != frameToken)
		{
			previousFrame = frameToken;
			float num = yaw;
			float num2 = pitch;
			if (flag)
			{
				Vector3 val2 = Quaternion.Inverse(val) * ((Vector3)(ref direction)).normalized;
				num = Mathf.Clamp(Mathf.Atan2(val2.x, val2.z) * 57.29578f, -50f, 50f);
				num2 = Mathf.Clamp(Mathf.Atan2(val2.y, Mathf.Sqrt(val2.x * val2.x + val2.z * val2.z)) * 57.29578f, -45f, 35f);
			}
			float num3 = 1f - Mathf.Exp((0f - Mathf.Clamp(deltaTime, 0f, 0.1f)) * 10f);
			yaw = Mathf.Lerp(yaw, num, num3);
			pitch = Mathf.Lerp(pitch, num2, num3);
			aimWeight = Mathf.Lerp(aimWeight, (float)(flag ? 1 : 0), num3);
		}
		LastCorrectionAngle = 0f;
		if (TrackingEnabled && !(aimWeight < 1E-06f))
		{
			Vector3 val3 = val * Quaternion.Euler(0f - pitch, yaw, 0f) * Vector3.forward;
			Quaternion val4 = Quaternion.FromToRotation(LookForward, val3);
			val4 = Quaternion.RotateTowards(Quaternion.identity, val4, 55f);
			val4 = Quaternion.Slerp(Quaternion.identity, val4, aimWeight);
			LastCorrectionAngle = Quaternion.Angle(Quaternion.identity, val4);
			neck.rotation = Quaternion.Slerp(Quaternion.identity, val4, 0.3f) * neck.rotation;
			head.rotation = Quaternion.Slerp(Quaternion.identity, val4, 0.7f) * head.rotation;
			neckApplied = neck.localRotation;
			headApplied = head.localRotation;
			applied = true;
		}
	}

	public void Step()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		TrackingEnabled = Plugin.HeadTracking.Value;
		bool flag = Object.op_Implicit((Object)(object)Player) && TrackingEnabled && !Player.isPlayerDead && Player.isPlayerControlled;
		Initialize();
		WorldAimFrame = (Object.op_Implicit((Object)(object)Player) ? new Quaternion?(((Component)Player).transform.rotation) : ((Quaternion?)null));
		Vector3 val = (Quaternion)(((??)WorldAimFrame) ?? ((Component)this).transform.rotation) * Vector3.forward;
		Vector3 direction = val;
		HasAttentionTarget = flag && ready && attention.Resolve(Player, ((Component)this).transform, head.position, val, Time.unscaledTime, out direction);
		AttentionDirection = direction;
		if (!flag)
		{
			attention.Reset();
		}
		StepFromDirection(direction, Time.deltaTime, Time.frameCount, HasAttentionTarget);
	}

	public void PrepareNeutralTrackingPose()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		Initialize();
		if (ready)
		{
			RestoreAppliedPose();
			neck.localRotation = neutralNeck;
			head.localRotation = neutralHead;
		}
	}

	private void LateUpdate()
	{
		Step();
	}

	public void ResetAim()
	{
		RestoreAppliedPose();
		yaw = (pitch = (aimWeight = 0f));
		previousFrame = int.MinValue;
		LastCorrectionAngle = 0f;
		HasAttentionTarget = false;
		attention.Reset();
	}

	private void OnDisable()
	{
		ResetAim();
	}
}
[Serializable]
public class LindLollipopData
{
	public Vector3[] points;

	public int[] boneIds;

	public float[] influences;

	public Vector3 positionOffset;

	public Quaternion rotationOffset;
}
[DefaultExecutionOrder(450)]
public class LindLollipopMount : MonoBehaviour
{
	public SkinnedMeshRenderer source;

	public Transform mount;

	public Vector3[] points;

	public BoneWeight[] weights;

	public Vector3 positionOffset;

	public Quaternion rotationOffset;

	private Transform[] bones;

	private Matrix4x4[] bind;

	public static LindLollipopMount Attach(GameObject model, LindLollipopData data)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: 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_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		if (data == null)
		{
			throw new ArgumentNullException("data");
		}
		LindLollipopMount component = model.GetComponent<LindLollipopMount>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return component;
		}
		component = model.AddComponent<LindLollipopMount>();
		component.source = model.GetComponentsInChildren<SkinnedMeshRenderer>().Single((SkinnedMeshRenderer r) => ((Object)r).name == "Default_Body");
		component.mount = model.GetComponentsInChildren<Transform>().Single((Transform t) => ((Object)t).name == "accessory_lollipop_mount");
		component.points = data.points;
		component.weights = (BoneWeight[])(object)new BoneWeight[3];
		for (int num = 0; num < 3; num++)
		{
			int num2 = num * 4;
			BoneWeight[] array = component.weights;
			int num3 = num;
			BoneWeight val = default(BoneWeight);
			((BoneWeight)(ref val)).boneIndex0 = data.boneIds[num2];
			((BoneWeight)(ref val)).boneIndex1 = data.boneIds[num2 + 1];
			((BoneWeight)(ref val)).boneIndex2 = data.boneIds[num2 + 2];
			((BoneWeight)(ref val)).boneIndex3 = data.boneIds[num2 + 3];
			((BoneWeight)(ref val)).weight0 = data.influences[num2];
			((BoneWeight)(ref val)).weight1 = data.influences[num2 + 1];
			((BoneWeight)(ref val)).weight2 = data.influences[num2 + 2];
			((BoneWeight)(ref val)).weight3 = data.influences[num2 + 3];
			array[num3] = val;
		}
		component.positionOffset = data.positionOffset;
		component.rotationOffset = data.rotationOffset;
		component.Sync();
		return component;
	}

	private void Awake()
	{
		Initialize();
	}

	private void Initialize()
	{
		if (bones == null && Object.op_Implicit((Object)(object)source))
		{
			bones = source.bones;
			bind = source.sharedMesh.bindposes;
		}
	}

	private Vector3 Skin(int index)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_003d: 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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		Vector3 point = points[index];
		BoneWeight val = weights[index];
		return Point(((BoneWeight)(ref val)).boneIndex0, point) * ((BoneWeight)(ref val)).weight0 + Point(((BoneWeight)(ref val)).boneIndex1, point) * ((BoneWeight)(ref val)).weight1 + Point(((BoneWeight)(ref val)).boneIndex2, point) * ((BoneWeight)(ref val)).weight2 + Point(((BoneWeight)(ref val)).boneIndex3, point) * ((BoneWeight)(ref val)).weight3;
	}

	private Vector3 Point(int bone, Vector3 point)
	{
		//IL_0014: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		return bones[bone].TransformPoint(((Matrix4x4)(ref bind[bone])).MultiplyPoint3x4(point));
	}

	public bool SurfaceFrame(out Vector3 center, out Quaternion rotation)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		Initialize();
		center = Vector3.zero;
		rotation = Quaternion.identity;
		if (bones == null || points == null || points.Length != 3)
		{
			return false;
		}
		Vector3 val = Skin(0);
		Vector3 val2 = Skin(1);
		Vector3 val3 = Skin(2);
		Vector3 val4 = val2 - val;
		Vector3 val5 = Vector3.Cross(val4, val3 - val);
		if (((Vector3)(ref val4)).sqrMagnitude < 1E-12f || ((Vector3)(ref val5)).sqrMagnitude < 1E-16f)
		{
			return false;
		}
		center = (val + val2 + val3) / 3f;
		rotation = Quaternion.LookRotation(((Vector3)(ref val5)).normalized, ((Vector3)(ref val4)).normalized);
		return true;
	}

	public void Sync()
	{
		//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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)mount) && SurfaceFrame(out var center, out var rotation))
		{
			mount.SetPositionAndRotation(center + rotation * positionOffset * ((Component)this).transform.lossyScale.x, rotation * rotationOffset);
		}
	}

	private void LateUpdate()
	{
		Sync();
	}
}
public static class LindRuntimeMembers
{
	private static class Cache<T>
	{
		internal static readonly Dictionary<Type, Dictionary<string, Func<object, T>>> Types = new Dictionary<Type, Dictionary<string, Func<object, T>>>();
	}

	private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static readonly Dictionary<Type, Dictionary<string, Func<object, string, object>>> Calls = new Dictionary<Type, Dictionary<string, Func<object, string, object>>>();

	public static Func<object, T> Getter<T>(Type type, string name)
	{
		if (!Cache<T>.Types.TryGetValue(type, out var value))
		{
			value = new Dictionary<string, Func<object, T>>();
			Cache<T>.Types.Add(type, value);
		}
		if (value.TryGetValue(name, out var value2))
		{
			return value2;
		}
		value2 = Build<T>(type, name);
		value.Add(name, value2);
		return value2;
	}

	private static Func<object, T> Build<T>(Type type, string name)
	{
		Func<object, T> result = null;
		FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "target");
		UnaryExpression expression = Expression.Convert(parameterExpression, type);
		Expression expression2 = null;
		if (field != null && typeof(T).IsAssignableFrom(field.FieldType))
		{
			expression2 = Expression.Convert(Expression.Field(expression, field), typeof(T));
		}
		if (property != null && property.GetIndexParameters().Length == 0 && property.GetGetMethod(nonPublic: true) != null && typeof(T).IsAssignableFrom(property.PropertyType))
		{
			UnaryExpression unaryExpression = Expression.Convert(Expression.Property(expression, property), typeof(T));
			expression2 = ((expression2 == null) ? unaryExpression : (typeof(T).IsValueType ? expression2 : Expression.Coalesce(expression2, unaryExpression)));
		}
		if (expression2 != null)
		{
			try
			{
				result = Expression.Lambda<Func<object, T>>(expression2, new ParameterExpression[1] { parameterExpression }).Compile();
			}
			catch
			{
				result = delegate(object o)
				{
					object obj2 = field?.GetValue(o) ?? property?.GetValue(o, null);
					return (obj2 is T) ? ((T)obj2) : default(T);
				};
			}
		}
		return result;
	}

	public static object Read(object target, string name)
	{
		if (target == null)
		{
			return null;
		}
		return Getter<object>(target.GetType(), name)?.Invoke(target);
	}

	public static bool TryRead<T>(object target, string name, out T value)
	{
		value = default(T);
		if (target == null)
		{
			return false;
		}
		Func<object, T> func = Getter<T>(target.GetType(), name);
		if (func == null)
		{
			return false;
		}
		value = func(target);
		return true;
	}

	public static object CallString(object target, string name, string argument)
	{
		if (target == null)
		{
			return null;
		}
		Type type = target.GetType();
		if (!Calls.TryGetValue(type, out var value))
		{
			value = new Dictionary<string, Func<object, string, object>>();
			Calls.Add(type, value);
		}
		if (!value.TryGetValue(name, out var value2))
		{
			value2 = BuildCall(type, name);
			value.Add(name, value2);
		}
		return value2?.Invoke(target, argument);
	}

	private static Func<object, string, object> BuildCall(Type type, string name)
	{
		MethodInfo method = type.GetMethod(name, new Type[1] { typeof(string) });
		if (method == null || method.ReturnType == typeof(void))
		{
			return null;
		}
		ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "target");
		ParameterExpression parameterExpression2 = Expression.Parameter(typeof(string), "argument");
		try
		{
			return Expression.Lambda<Func<object, string, object>>(Expression.Convert(Expression.Call(Expression.Convert(parameterExpression, type), method, parameterExpression2), typeof(object)), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
		}
		catch
		{
			return (object o, string s) => method.Invoke(o, new object[1] { s });
		}
	}

	public static void Clear()
	{
		Cache<object>.Types.Clear();
		Cache<bool>.Types.Clear();
		Cache<float>.Types.Clear();
		Calls.Clear();
	}
}
[DefaultExecutionOrder(350)]
public class LindSecondaryMotion : MonoBehaviour
{
	private class Chain
	{
		public Transform[] bones;

		public Transform tip;

		public Vector3[] localPositions;

		public Vector3[] points;

		public Vector3[] velocity;

		public Vector3[] target;

		public Quaternion[] localRotations;

		public Quaternion[] rotations;

		public Collider[] contacts;

		public int[] contactIds;

		public Contact[] contactBuffer;

		public Contact[][] guideBuffers;

		public bool hair;

		public float cone;

		public float padding;

		public float shoulderPadding;

		public float spring;

		public float damping;

		public float gravity;

		public Vector3 previousAnchor;

		public bool initialized;
	}

	private struct Contact
	{
		public Vector3 center;

		public Vector3 end;

		public Vector3 preferred;

		public Vector3 min;

		public Vector3 max;

		public float radius;

		public bool capsule;
	}

	private struct Constraint
	{
		public Vector3 axis;

		public Vector3 preferred;

		public float bound;
	}

	private class BodyRegion
	{
		public Transform bone;

		public Transform tip;

		public Vector3 rest;

		public Vector3 position;

		public Vector3 velocity;

		public Vector3 previousTarget;

		public bool initialized;

		public bool breast;
	}

	private class HairSurface
	{
		public SkinnedMeshRenderer renderer;

		public bool hair;

		public Collider[] contacts;

		public Mesh source;

		public Mesh mesh;

		public Vector3[] original;

		public Vector3[] vertices;

		public BoneWeight[] weights;

		public Matrix4x4[] bind;

		public Matrix4x4[] matrices;

		public Transform[] bones;

		public Contact[] contactBuffer;

		public int[] moving;

		public int[] usedBones;

		public int[] contactIds;

		public bool changed;
	}

	private class SourceSurface
	{
		public Mesh source;

		public Vector3[] original;

		public BoneWeight[] weights;

		public Matrix4x4[] bind;

		public int[] moving;

		public int[] usedBones;
	}

	private Constraint[] constraints;

	private Contact[] reachableContacts;

	private static readonly Dictionary<Mesh, SourceSurface> surfaceCache = new Dictionary<Mesh, SourceSurface>();

	private readonly List<Chain> chains = new List<Chain>();

	private readonly List<HairSurface> hairSurfaces = new List<HairSurface>();

	private readonly List<BodyRegion> bodyRegions = new List<BodyRegion>();

	private Collider[] frameColliders;

	private Contact[] frameContacts;

	public int ChainCount => chains.Count;

	public float MaximumParticlePenetration { get; private set; }

	public float MaximumSegmentPenetration { get; private set; }

	public int CollisionCorrections { get; private set; }

	public int SlowCollisionSearches { get; private set; }

	public string WorstContact { get; private set; }

	public int SurfaceContactCorrections { get; private set; }

	public int BodyRegionCount => bodyRegions.Count;

	public float PeakBreastDisplacement { get; private set; }

	public float PeakButtDisplacement { get; private set; }

	public float MaximumBodyOffsetRatio { get; private set; }

	public bool BodyPhysicsFinite { get; private set; } = true;

	private static SourceSurface SurfaceData(SkinnedMeshRenderer renderer, bool hair, HashSet<string> pinned)
	{
		//IL_009f: 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_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		Mesh sharedMesh = renderer.sharedMesh;
		if (surfaceCache.TryGetValue(sharedMesh, out var value))
		{
			return value;
		}
		Transform[] bones = renderer.bones;
		bool[] array = new bool[bones.Length];
		for (int i = 0; i < bones.Length; i++)
		{
			string name = ((Object)bones[i]).name;
			array[i] = (hair ? name.StartsWith("phys_hair") : (!pinned.Contains(name) && (name.StartsWith("phys_scarf") || name.StartsWith("phys_dress"))));
		}
		BoneWeight[] boneWeights = sharedMesh.boneWeights;
		List<int> list = new List<int>();
		for (int j = 0; j < boneWeights.Length; j++)
		{
			BoneWeight val = boneWeights[j];
			if ((array[((BoneWeight)(ref val)).boneIndex0] ? ((BoneWeight)(ref val)).weight0 : 0f) + (array[((BoneWeight)(ref val)).boneIndex1] ? ((BoneWeight)(ref val)).weight1 : 0f) + (array[((BoneWeight)(ref val)).boneIndex2] ? ((BoneWeight)(ref val)).weight2 : 0f) + (array[((BoneWeight)(ref val)).boneIndex3] ? ((BoneWeight)(ref val)).weight3 : 0f) > 0.01f)
			{
				list.Add(j);
			}
		}
		HashSet<int> hashSet = new HashSet<int>();
		foreach (int item in list)
		{
			BoneWeight val2 = boneWeights[item];
			if (((BoneWeight)(ref val2)).weight0 > 0f)
			{
				hashSet.Add(((BoneWeight)(ref val2)).boneIndex0);
			}
			if (((BoneWeight)(ref val2)).weight1 > 0f)
			{
				hashSet.Add(((BoneWeight)(ref val2)).boneIndex1);
			}
			if (((BoneWeight)(ref val2)).weight2 > 0f)
			{
				hashSet.Add(((BoneWeight)(ref val2)).boneIndex2);
			}
			if (((BoneWeight)(ref val2)).weight3 > 0f)
			{
				hashSet.Add(((BoneWeight)(ref val2)).boneIndex3);
			}
		}
		value = new SourceSurface
		{
			source = sharedMesh,
			original = sharedMesh.vertices,
			weights = boneWeights,
			bind = sharedMesh.bindposes,
			moving = list.ToArray(),
			usedBones = hashSet.OrderBy((int result) => result).ToArray()
		};
		surfaceCache.Add(sharedMesh, value);
		return value;
	}

	public static void PrimeSurfaceData(GameObject prefab)
	{
		HashSet<string> pinned = new HashSet<string>(from r in prefab.GetComponentsInChildren<JiggleRigBuilder>(true)
			select r.GetRootTransform() into t
			where Object.op_Implicit((Object)(object)t)
			select ((Object)t).name);
		foreach (SkinnedMeshRenderer item in from r in prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true)
			where ((Object)r).name.Contains("_Hair") || ((Object)r).name.Contains("_Dress") || ((Object)r).name.Contains("_Body")
			select r)
		{
			SurfaceData(item, ((Object)item).name.Contains("_Hair"), pinned);
		}
	}

	public static void ClearSurfaceCache()
	{
		surfaceCache.Clear();
	}

	public void Initialize()
	{
		//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)
		if (chains.Count > 0)
		{
			return;
		}
		foreach (Transform item in from b in ((Component)this).GetComponentsInChildren<Transform>(true)
			where ((Object)b).name.StartsWith("phys_breast.") || ((Object)b).name.StartsWith("phys_butt.")
			select b)
		{
			Transform val = ((IEnumerable<Transform>)((Component)item).GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.StartsWith("phys_body_tip_")));
			if (Object.op_Implicit((Object)(object)val))
			{
				bodyRegions.Add(new BodyRegion
				{
					bone = item,
					tip = val,
					rest = item.localPosition,
					breast = ((Object)item).name.StartsWith("phys_breast.")
				});
			}
		}
		JiggleRigBuilder[] componentsInChildren = ((Component)this).GetComponentsInChildren<JiggleRigBuilder>(true);
		foreach (JiggleRigBuilder val2 in componentsInChildren)
		{
			((Behaviour)val2).enabled = false;
			Transform rootTransform = val2.GetRootTransform();
			if (!Object.op_Implicit((Object)(object)rootTransform))
			{
				continue;
			}
			List<Transform> list = new List<Transform> { rootTransform };
			Transform val3 = rootTransform;
			Transform tip = null;
			string stem = ((Object)rootTransform).name.Substring(0, ((Object)rootTransform).name.LastIndexOf("_"));
			while (val3.childCount > 0)
			{
				Transform val4 = ((IEnumerable)val3).Cast<Transform>().FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.StartsWith(stem + "_") || ((Object)t).name.StartsWith("phys_tip_")));
				if (!Object.op_Implicit((Object)(object)val4))
				{
					break;
				}
				if (((Object)val4).name.StartsWith("phys_tip_"))
				{
					tip = val4;
					break;
				}
				val3 = val4;
				list.Add(val3);
			}
			if (list.Count >= 2)
			{
				bool flag = ((Object)rootTransform).name.StartsWith("phys_hair");
				bool flag2 = ((Object)rootTransform).name.StartsWith("phys_scarf");
				bool flag3 = ((Object)rootTransform).name.StartsWith("phys_hair_bang");
				bool flag4 = ((Object)rootTransform).name.StartsWith("phys_hair_upper");
				bool flag5 = ((Object)rootTransform).name.StartsWith("phys_hair_tuft");
				Collider[] array = val2.colliders.Where((Collider c) => Object.op_Implicit((Object)(object)c) && (c is SphereCollider || c is CapsuleCollider)).ToArray();
				Contact[][] array2 = new Contact[list.Count][];
				for (int num2 = 0; num2 < array2.Length; num2++)
				{
					array2[num2] = new Contact[array.Length];
				}
				chains.Add(new Chain
				{
					bones = list.ToArray(),
					tip = tip,
					hair = flag,
					target = (Vector3[])(object)new Vector3[list.Count + 1],
					rotations = (Quaternion[])(object)new Quaternion[list.Count],
					points = (Vector3[])(object)new Vector3[list.Count + 1],
					velocity = (Vector3[])(object)new Vector3[list.Count + 1],
					contactBuffer = new Contact[array.Length],
					guideBuffers = array2,
					localPositions = list.Select((Transform b) => b.localPosition).ToArray(),
					localRotations = list.Select((Transform b) => b.localRotation).ToArray(),
					contacts = array,
					cone = (float)(flag3 ? 6 : (flag4 ? 8 : (flag5 ? 20 : (flag ? 18 : (flag2 ? 32 : 28))))) * ((float)Math.PI / 180f),
					padding = (flag ? 0.18f : (flag2 ? 0.18f : 0.08f)),
					shoulderPadding = 0.25f,
					spring = (flag3 ? 180 : (flag4 ? 160 : (flag5 ? 110 : 95))),
					damping = ((flag3 || flag4) ? 18 : (flag5 ? 13 : 10)),
					gravity = (flag3 ? 0.005f : (flag4 ? 0.012f : (flag5 ? 0.008f : 0.035f)))
				});
			}
		}
		frameColliders = chains.SelectMany((Chain c) => c.contacts).Distinct().ToArray();
		frameContacts = new Contact[frameColliders.Length];
		Dictionary<Collider, int> contactIndices = frameColliders.Select((Collider c, int i) => new { c, i }).ToDictionary(x => x.c, x => x.i);
		foreach (Chain chain in chains)
		{
			chain.contactIds = chain.contacts.Select((Collider c) => contactIndices[c]).ToArray();
		}
		constraints = new Constraint[(chains.Count == 0) ? 1 : chains.Max((Chain c) => c.contacts.Length)];
		reachableContacts = new Contact[constraints.Length];
		HashSet<string> pinned = new HashSet<string>(chains.Select((Chain c) => ((Object)c.bones[0]).name));
		(from c in ((Component)this).GetComponentsInChildren<Collider>(true)
			where c is SphereCollider || c is CapsuleCollider
			select c).ToArray();
		foreach (SkinnedMeshRenderer item2 in from r in ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true)
			where ((Object)r).name.Contains("_Hair") || ((Object)r).name.Contains("_Dress") || ((Object)r).name.Contains("_Body")
			select r)
		{
			bool isHair = ((Object)item2).name.Contains("_Hair");
			SourceSurface sourceSurface = SurfaceData(item2, isHair, pinned);
			if (sourceSurface.moving.Length != 0)
			{
				Mesh val5 = Object.Instantiate<Mesh>(sourceSurface.source);
				((Object)val5).name = ((Object)sourceSurface.source).name + " (Lind hair contacts)";
				val5.MarkDynamic();
				item2.sharedMesh = val5;
				Collider[] array3 = (from c in (from rig in ((Component)this).GetComponentsInChildren<JiggleRigBuilder>(true)
						where ((Object)rig.GetRootTransform()).name.StartsWith("phys_hair") == isHair
						select rig).SelectMany((JiggleRigBuilder rig) => rig.colliders)
					where Object.op_Implicit((Object)(object)c) && (c is SphereCollider || c is CapsuleCollider)
					select c).Distinct().ToArray();
				Transform[] bones = item2.bones;
				hairSurfaces.Add(new HairSurface
				{
					renderer = item2,
					hair = isHair,
					contacts = array3,
					contactBuffer = new Contact[array3.Length],
					source = sourceSurface.source,
					mesh = val5,
					original = sourceSurface.original,
					vertices = (Vector3[])sourceSurface.original.Clone(),
					weights = sourceSurface.weights,
					bind = sourceSurface.bind,
					moving = sourceSurface.moving,
					usedBones = sourceSurface.usedBones,
					contactIds = array3.Select((Collider c) => contactIndices[c]).ToArray(),
					bones = bones,
					matrices = (Matrix4x4[])(object)new Matrix4x4[bones.Length]
				});
			}
		}
	}

	private void ResetBody()
	{
		//IL_003c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
		foreach (BodyRegion bodyRegion in bodyRegions)
		{
			if (Object.op_Implicit((Object)(object)bodyRegion.bone))
			{
				bodyRegion.bone.localPosition = bodyRegion.rest;
			}
			bodyRegion.initialized = false;
			bodyRegion.velocity = Vector3.zero;
		}
	}

	private void OnDisable()
	{
		ResetBody();
	}

	public void ResetPose()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		ResetBody();
		foreach (Chain chain in chains)
		{
			for (int i = 0; i < chain.bones.Length; i++)
			{
				chain.bones[i].localPosition = chain.localPositions[i];
				chain.bones[i].localRotation = chain.localRotations[i];
			}
			chain.initialized = false;
		}
		foreach (HairSurface hairSurface in hairSurfaces)
		{
			hairSurface.mesh.vertices = hairSurface.original;
			hairSurface.changed = false;
		}
	}

	public void StepBodyPhysics(float elapsed)
	{
		//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_006c: 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_007a: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: 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_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_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: 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_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		Initialize();
		float num = Mathf.Clamp(elapsed, 0f, 0.08f);
		if (num <= 0f)
		{
			return;
		}
		foreach (BodyRegion bodyRegion in bodyRegions)
		{
			Transform bone = bodyRegion.bone;
			if (!Object.op_Implicit((Object)(object)bone) || !Object.op_Implicit((Object)(object)bone.parent))
			{
				continue;
			}
			Vector3 val = bone.parent.TransformPoint(bodyRegion.rest);
			float num2 = Vector3.Distance(bone.position, bodyRegion.tip.position) * (bodyRegion.breast ? 0.3f : 0.22f);
			if (bodyRegion.initialized)
			{
				Vector3 val2 = val - bodyRegion.previousTarget;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 0.36f))
				{
					goto IL_00da;
				}
			}
			bodyRegion.position = val;
			bodyRegion.velocity = Vector3.zero;
			bodyRegion.initialized = true;
			goto IL_00da;
			IL_00da:
			bodyRegion.previousTarget = val;
			float num3 = (bodyRegion.breast ? 14 : 18);
			float num4 = (bodyRegion.breast ? 0.72f : 0.82f);
			int num5 = Mathf.Max(1, Mathf.CeilToInt(num / 0.008f));
			float num6 = num / (float)num5;
			for (int i = 0; i < num5; i++)
			{
				Vector3 val3 = (val - bodyRegion.position) * (num3 * num3) - bodyRegion.velocity * (2f * num4 * num3);
				bodyRegion.velocity += val3 * num6;
				bodyRegion.position += bodyRegion.velocity * num6;
			}
			Vector3 val4 = Vector3.ClampMagnitude(bodyRegion.position - val, num2);
			bodyRegion.position = val + val4;
			bone.position = bodyRegion.position;
			MaximumBodyOffsetRatio = Mathf.Max(MaximumBodyOffsetRatio, ((Vector3)(ref val4)).magnitude / Mathf.Max(num2, 1E-08f));
			if (bodyRegion.breast)
			{
				PeakBreastDisplacement = Mathf.Max(PeakBreastDisplacement, ((Vector3)(ref val4)).magnitude);
			}
			else
			{
				PeakButtDisplacement = Mathf.Max(PeakButtDisplacement, ((Vector3)(ref val4)).magnitude);
			}
			BodyPhysicsFinite &= !float.IsNaN(val4.x) && !float.IsInfinity(val4.x) && !float.IsNaN(val4.y) && !float.IsInfinity(val4.y) && !float.IsNaN(val4.z) && !float.IsInfinity(val4.z);
			if (((Vector3)(ref val4)).magnitude >= num2 * 0.999f && Vector3.Dot(bodyRegion.velocity, val4) > 0f)
			{
				bodyRegion.velocity -= ((Vector3)(ref val4)).normalized * Vector3.Dot(bodyRegion.velocity, ((Vector3)(ref val4)).normalized);
			}
		}
	}

	private void OnDestroy()
	{
		foreach (HairSurface hairSurface in hairSurfaces)
		{
			if (Object.op_Implicit((Object)(object)hairSurface.renderer) && (Object)(object)hairSurface.renderer.sharedMesh == (Object)(object)hairSurface.mesh)
			{
				hairSurface.renderer.sharedMesh = hairSurface.source;
			}
			if (Object.op_Implicit((Object)(object)hairSurface.mesh))
			{
				Object.Destroy((Object)(object)hairSurface.mesh);
			}
		}
	}

	private void CorrectHairSurface()
	{
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_033b: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_036a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: 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_02f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		SurfaceContactCorrections = 0;
		foreach (HairSurface hairSurface in hairSurfaces)
		{
			Contact[] contactBuffer = hairSurface.contactBuffer;
			if (!Object.op_Implicit((Object)(object)hairSurface.renderer) || !((Renderer)hairSurface.renderer).enabled || !((Component)hairSurface.renderer).gameObject.activeInHierarchy)
			{
				continue;
			}
			for (int i = 0; i < contactBuffer.Length; i++)
			{
				contactBuffer[i] = frameContacts[hairSurface.contactIds[i]];
			}
			Matrix4x4[] matrices = hairSurface.matrices;
			int[] usedBones = hairSurface.usedBones;
			foreach (int num in usedBones)
			{
				matrices[num] = hairSurface.bones[num].localToWorldMatrix * hairSurface.bind[num];
			}
			Array.Copy(hairSurface.original, hairSurface.vertices, hairSurface.original.Length);
			bool flag = false;
			usedBones = hairSurface.moving;
			foreach (int num2 in usedBones)
			{
				BoneWeight val = hairSurface.weights[num2];
				Vector3 val2 = hairSurface.original[num2];
				Matrix4x4 val3 = matrices[((BoneWeight)(ref val)).boneIndex0];
				Matrix4x4 val4 = matrices[((BoneWeight)(ref val)).boneIndex1];
				Matrix4x4 val5 = matrices[((BoneWeight)(ref val)).boneIndex2];
				Matrix4x4 val6 = matrices[((BoneWeight)(ref val)).boneIndex3];
				Vector3 val7 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(val2) * ((BoneWeight)(ref val)).weight0 + ((Matrix4x4)(ref val4)).MultiplyPoint3x4(val2) * ((BoneWeight)(ref val)).weight1 + ((Matrix4x4)(ref val5)).MultiplyPoint3x4(val2) * ((BoneWeight)(ref val)).weight2 + ((Matrix4x4)(ref val6)).MultiplyPoint3x4(val2) * ((BoneWeight)(ref val)).weight3;
				Vector3 val8 = val7;
				for (int k = 0; k < ((contactBuffer.Length > 20) ? 16 : 4); k++)
				{
					bool flag2 = false;
					Contact[] array = contactBuffer;
					for (int l = 0; l < array.Length; l++)
					{
						Contact contact = array[l];
						if (!(contact.radius <= 0f) && !(val8.x < contact.min.x) && !(val8.x > contact.max.x) && !(val8.y < contact.min.y) && !(val8.y > contact.max.y) && !(val8.z < contact.min.z) && !(val8.z > contact.max.z))
						{
							Vector3 val9 = ClosestContact(val8, contact);
							Vector3 val10 = val8 - val9;
							float num3 = contact.radius * (hairSurface.hair ? 1.02f : 1f);
							float sqrMagnitude = ((Vector3)(ref val10)).sqrMagnitude;
							if (sqrMagnitude < num3 * num3)
							{
								float num4 = Mathf.Sqrt(sqrMagnitude);
								val8 = val9 + ((num4 > 1E-08f) ? (val10 / num4) : Vector3.up) * num3;
								flag2 = true;
							}
						}
					}
					if (!flag2)
					{
						break;
					}
				}
				Vector3 val11 = val8 - val7;
				if (!(((Vector3)(ref val11)).sqrMagnitude < 1E-12f))
				{
					Matrix4x4 val12 = default(Matrix4x4);
					for (int m = 0; m < 4; m++)
					{
						((Matrix4x4)(ref val12)).SetColumn(m, ((Matrix4x4)(ref val3)).GetColumn(m) * ((BoneWeight)(ref val)).weight0 + ((Matrix4x4)(ref val4)).GetColumn(m) * ((BoneWeight)(ref val)).weight1 + ((Matrix4x4)(ref val5)).GetColumn(m) * ((BoneWeight)(ref val)).weight2 + ((Matrix4x4)(ref val6)).GetColumn(m) * ((BoneWeight)(ref val)).weight3);
					}
					Vector3[] vertices = hairSurface.vertices;
					Matrix4x4 inverse = ((Matrix4x4)(ref val12)).inverse;
					vertices[num2] = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(val8);
					flag = true;
					SurfaceContactCorrections++;
				}
			}
			if (flag || hairSurface.changed)
			{
				hairSurface.mesh.vertices = hairSurface.vertices;
			}
			hairSurface.changed = flag;
		}
	}

	private static Contact Bounded(Contact c)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: 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)
		Vector3 val = Vector3.one * (c.radius * 1.02f);
		c.min = Vector3.Min(c.center, c.end) - val;
		c.max = Vector3.Max(c.center, c.end) + val;
		return c;
	}

	private static Contact ReadContact(Collider collider, float padding)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Expected O, but got Unknown
		//IL_0042: 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_004c: 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_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_0086: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type