Decompiled source of FATECapes v0.1.7

BepInEx/plugins/FateCoop.Capes/FateCoop.Capes.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PartGhost")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 PartGhost")]
[assembly: AssemblyFileVersion("0.1.7.0")]
[assembly: AssemblyInformationalVersion("0.1.7")]
[assembly: AssemblyProduct("FateCoop.Capes")]
[assembly: AssemblyTitle("FateCoop.Capes")]
[assembly: AssemblyVersion("0.1.7.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FateCoop.Capes
{
	[BepInPlugin("local.fatecoop.capes", "FATE Capes", "0.1.7")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class CapeRig
		{
			internal Mesh Mesh;

			internal int Spine;

			internal Vector3[] Joints;
		}

		private sealed class CapeSwing : MonoBehaviour
		{
			private SkinnedMeshRenderer target;

			private Transform[] originalBones;

			private Transform[] chain;

			private Vector3[] restTips;

			private Vector3[] tips;

			private Vector3[] previous;

			private Vector3[] lastRests;

			private Vector3 lastRoot;

			internal void Attach(SkinnedMeshRenderer renderer, CapeRig rig)
			{
				//IL_003e: 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_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				target = renderer;
				originalBones = renderer.bones;
				chain = (Transform[])(object)new Transform[4];
				for (int i = 0; i <= 3; i++)
				{
					chain[i] = new GameObject("FateCoop_CapeLink" + i).transform;
					chain[i].SetParent((i == 0) ? originalBones[rig.Spine] : chain[i - 1], false);
					chain[i].localPosition = ((i == 0) ? rig.Joints[0] : (rig.Joints[i] - rig.Joints[i - 1]));
				}
				renderer.bones = originalBones.Concat(chain.Take(3)).ToArray();
				renderer.sharedMesh = rig.Mesh;
				restTips = (from link in chain.Skip(1)
					select link.localPosition).ToArray();
				Settle();
			}

			internal void Remove()
			{
				target.bones = originalBones;
				Object.Destroy((Object)(object)((Component)chain[0]).gameObject);
				Object.DestroyImmediate((Object)(object)this);
			}

			private void Settle()
			{
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				tips = (from link in chain.Skip(1)
					select link.position).ToArray();
				previous = tips.ToArray();
				lastRests = tips.ToArray();
				lastRoot = chain[0].position;
			}

			private void LateUpdate()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: 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_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Unknown result type (might be due to invalid IL or missing references)
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_015a: 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_0172: Unknown result type (might be due to invalid IL or missing references)
				//IL_0177: 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_0180: 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_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01af: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b5: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01db: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e0: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01eb: 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_01f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f9: 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_020c: 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_022a: Unknown result type (might be due to invalid IL or missing references)
				//IL_022f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0234: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				float num = Mathf.Min(Time.deltaTime, 0.05f);
				if (num <= 0f)
				{
					return;
				}
				Vector3 position = chain[0].position;
				Vector3 val = position - lastRoot;
				lastRoot = position;
				if (((Vector3)(ref val)).sqrMagnitude > 1f)
				{
					Transform[] array = chain;
					for (int i = 0; i < array.Length; i++)
					{
						array[i].localRotation = Quaternion.identity;
					}
					Settle();
					return;
				}
				for (int j = 0; j < 3; j++)
				{
					Transform val2 = chain[j];
					val2.localRotation = Quaternion.identity;
					Vector3 position2 = val2.position;
					Vector3 val3 = val2.TransformPoint(restTips[j]);
					Vector3 val4 = val3 - lastRests[j];
					lastRests[j] = val3;
					ref Vector3 reference = ref tips[j];
					reference += val4;
					ref Vector3 reference2 = ref previous[j];
					reference2 += val4;
					Vector3 val5 = (tips[j] - previous[j]) * Mathf.Exp(-9f * num);
					previous[j] = tips[j];
					ref Vector3 reference3 = ref tips[j];
					reference3 += val5 - val4 * 3f * num + (val3 - tips[j]) * 35f * num * num;
					Vector3[] array2 = tips;
					int num2 = j;
					Vector3 val6 = tips[j] - position2;
					Vector3 normalized = ((Vector3)(ref val6)).normalized;
					val6 = val3 - position2;
					array2[num2] = position2 + normalized * ((Vector3)(ref val6)).magnitude;
					val2.localRotation = Quaternion.FromToRotation(restTips[j], val2.InverseTransformPoint(tips[j]));
				}
			}
		}

		private sealed class BackWatcher : MonoBehaviour
		{
			private static readonly HashSet<int> Rigged = new HashSet<int>();

			private static readonly string[] BackWords = new string[7] { "back", "cape", "cloak", "wing", "quiver", "pack", "mantle" };

			private const float DumpRange = 30f;

			private float next;

			private int tick;

			private bool dumped;

			private string scene = "";

			private void Update()
			{
				if (Time.unscaledTime < next)
				{
					return;
				}
				next = Time.unscaledTime + 2f;
				tick++;
				try
				{
					Scan();
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[FATE Capes] scan failed: " + ex));
				}
			}

			private void Scan()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				if (name != scene)
				{
					scene = name;
					dumped = false;
					tick = 1;
				}
				SkinnedMeshRenderer[] array = Object.FindObjectsOfType<SkinnedMeshRenderer>(true);
				if (tick == 1 || tick % 10 == 0)
				{
					Debug.Log((object)("[FATE Capes] tick " + tick + " scene=" + name + " skinned=" + array.Length));
				}
				if (!dumped && array.Length != 0)
				{
					dumped = true;
					Dump(array, name);
				}
				SkinnedMeshRenderer[] array2 = array;
				foreach (SkinnedMeshRenderer val in array2)
				{
					if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || !((Component)val).gameObject.activeInHierarchy)
					{
						continue;
					}
					string path = PathOf(((Component)val).transform).ToLowerInvariant();
					string mesh = ((Object)val.sharedMesh).name.ToLowerInvariant();
					if (BackWords.Any((string word) => path.Contains(word) || mesh.Contains(word)))
					{
						int instanceID = ((Object)val).GetInstanceID();
						if (!Rigged.Contains(instanceID) || !((Object)(object)((Component)val).GetComponent<CapeSwing>() != (Object)null))
						{
							Rigged.Add(instanceID);
							RigRenderer(val, "auto:" + ((Object)val.sharedMesh).name);
						}
					}
				}
			}

			private static void Dump(SkinnedMeshRenderer[] all, string scene)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				Camera main = Camera.main;
				Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.position : Vector3.zero);
				Debug.Log((object)("[FATE Capes] dump scene=" + scene + " skinned=" + all.Length + " camera=" + ((Object)(object)main != (Object)null)));
				int num = 0;
				foreach (SkinnedMeshRenderer val2 in all)
				{
					if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null)
					{
						continue;
					}
					Bounds bounds = ((Renderer)val2).bounds;
					if (!(Vector3.Distance(val, ((Bounds)(ref bounds)).center) > 30f))
					{
						if (num++ >= 80)
						{
							Debug.Log((object)"[FATE Capes]   ...more");
							break;
						}
						Debug.Log((object)("[FATE Capes]   '" + PathOf(((Component)val2).transform) + "' mesh=" + ((Object)val2.sharedMesh).name + " bones=" + val2.bones.Length + " shown=" + ((Component)val2).gameObject.activeInHierarchy));
					}
				}
				if (num == 0)
				{
					Debug.Log((object)("[FATE Capes]   nothing within " + 30f + "m of the camera"));
				}
			}

			private static void RigRenderer(SkinnedMeshRenderer renderer, string key)
			{
				CapeSwing capeSwing = default(CapeSwing);
				if (((Component)renderer).TryGetComponent<CapeSwing>(ref capeSwing))
				{
					capeSwing.Remove();
				}
				Mesh sharedMesh = renderer.sharedMesh;
				if (!CapeRigs.TryGetValue(sharedMesh, out CapeRig value))
				{
					value = (CapeRigs[sharedMesh] = RigCape(sharedMesh, renderer.bones));
					if (value == null)
					{
						IEnumerable<string> values = from bone in renderer.bones.Take(6)
							select (!((Object)(object)bone == (Object)null)) ? ((Object)bone).name : "-";
						Debug.LogWarning((object)("[FATE Capes] no rig for mesh '" + ((Object)sharedMesh).name + "' (" + renderer.bones.Length + " bones: " + string.Join(",", values) + "), key=" + key));
						return;
					}
				}
				if (value != null)
				{
					((Component)renderer).gameObject.AddComponent<CapeSwing>().Attach(renderer, value);
					Debug.Log((object)("[FATE Capes] rigged mesh '" + ((Object)sharedMesh).name + "' for '" + key + "'"));
				}
			}

			private static string PathOf(Transform t)
			{
				string text = ((Object)t).name;
				Transform parent = t.parent;
				while ((Object)(object)parent != (Object)null)
				{
					text = ((Object)parent).name + "/" + text;
					parent = parent.parent;
				}
				return text;
			}
		}

		private const int CapeLinks = 3;

		private const float CapePinned = 0.15f;

		private const float CapeDrag = 3f;

		private const float CapeStiffness = 35f;

		private const float CapeDamping = 9f;

		private const float CapeTeleportDistance = 1f;

		private static readonly HashSet<string> RigidBackItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"Item_BloodQuiver", "Item_ForestQuiver", "Item_GoblinQuiver", "Item_LightQuiver", "Item_RoyalQuiver", "Item_BroadwingMagicalWings", "Item_TravelerBackpack", "Item_BlazenShield", "Item_Twilight", "Item_Crabfork",
			"Item_Uber", "Item_Skullcutt", "Item_IronSickle", "Item_IronCleaver", "Item_Doomstick"
		};

		private static readonly FieldRef<CharacterCustomizationDefaults, CustomizationCategory> BackRef = AccessTools.FieldRefAccess<CharacterCustomizationDefaults, CustomizationCategory>("back");

		private static readonly Dictionary<Mesh, CapeRig?> CapeRigs = new Dictionary<Mesh, CapeRig>();

		public const string Guid = "local.fatecoop.capes";

		public const string DisplayName = "FATE Capes";

		public const string Version = "0.1.7";

		private Harmony? harmony;

		private ConfigEntry<bool> enableCape;

		private static bool active = true;

		private static CharacterCustomizationDefaults? lastDefaults;

		private static string? lastBackKey;

		private static BackWatcher? watcher;

		private void InstallCapeHooks()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			harmony.Patch((MethodBase)AccessTools.Method(typeof(CharacterCustomizationDefaults), "SetBack", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterSetBack", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void AfterSetBack(CharacterCustomizationDefaults __instance, string backKey)
		{
			lastDefaults = __instance;
			lastBackKey = backKey;
			try
			{
				Apply(__instance, backKey);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[FATE Capes] cape rig failed for '" + backKey + "': " + ex));
			}
		}

		private static void Apply(CharacterCustomizationDefaults defaults, string? backKey)
		{
			CustomizationCategory val = BackRef.Invoke(defaults);
			if (val == null || (Object)(object)val.defaultMesh == (Object)null)
			{
				return;
			}
			SkinnedMeshRenderer skinnedMesh = val.SkinnedMesh;
			CapeSwing capeSwing = default(CapeSwing);
			if (((Component)skinnedMesh).TryGetComponent<CapeSwing>(ref capeSwing))
			{
				capeSwing.Remove();
			}
			if (!active || string.IsNullOrEmpty(backKey) || RigidBackItems.Contains(backKey.TrimEnd()) || !((Component)skinnedMesh).gameObject.activeSelf)
			{
				return;
			}
			Mesh sharedMesh = skinnedMesh.sharedMesh;
			if (!CapeRigs.TryGetValue(sharedMesh, out CapeRig value))
			{
				value = (CapeRigs[sharedMesh] = RigCape(sharedMesh, skinnedMesh.bones));
				if (value == null)
				{
					Debug.LogWarning((object)("[FATE Capes] no rig for mesh '" + ((Object)sharedMesh).name + "': no spine bone or no vertices"));
				}
				else
				{
					Debug.Log((object)("[FATE Capes] rigged mesh '" + ((Object)sharedMesh).name + "' for '" + backKey + "'"));
				}
			}
			if (value != null)
			{
				((Component)skinnedMesh).gameObject.AddComponent<CapeSwing>().Attach(skinnedMesh, value);
			}
		}

		private static CapeRig? RigCape(Mesh source, Transform[] bones)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = ReadableCopy(source);
			Matrix4x4[] bindposes = val.bindposes;
			Vector3[] vertices = val.vertices;
			if (vertices.Length == 0)
			{
				return null;
			}
			int spine = Array.FindIndex(bones, (Transform bone) => ((Object)bone).name.EndsWith("_Spine1", StringComparison.Ordinal));
			if (spine < 0)
			{
				return null;
			}
			Vector3 val2 = joint("_Head") - joint("_Pelvis");
			Vector3 up = ((Vector3)(ref val2)).normalized;
			float[] source2 = vertices.Select((Vector3 vertex) => Vector3.Dot(vertex, up)).ToArray();
			float top = source2.Max();
			float length = top - source2.Min();
			if (!(length > 0f))
			{
				return null;
			}
			float[] depth = source2.Select((float height) => (top - height) / length).ToArray();
			Vector3[] array = (from i in Enumerable.Range(0, 4)
				select centre(0.15f + 0.85f * (float)i / 3f)).ToArray();
			int first = bindposes.Length;
			val.bindposes = bindposes.Concat(from point in array.Take(3)
				select Matrix4x4.Translate(-point) * bindposes[spine]).ToArray();
			val.boneWeights = ((IEnumerable<BoneWeight>)val.boneWeights).Select((Func<BoneWeight, int, BoneWeight>)delegate(BoneWeight weight, int i)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: 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_0086: Unknown result type (might be due to invalid IL or missing references)
				if (depth[i] < 0.15f)
				{
					return weight;
				}
				float num = Mathf.Min((depth[i] - 0.15f) / 0.85f * 3f, 2.999f);
				int num2 = (int)num;
				float num3 = num - (float)num2;
				int num4 = Math.Min(num2 + 1, 2);
				BoneWeight result;
				if (num4 != num2)
				{
					result = default(BoneWeight);
					((BoneWeight)(ref result)).boneIndex0 = first + num2;
					((BoneWeight)(ref result)).weight0 = 1f - num3;
					((BoneWeight)(ref result)).boneIndex1 = first + num4;
					((BoneWeight)(ref result)).weight1 = num3;
					return result;
				}
				result = default(BoneWeight);
				((BoneWeight)(ref result)).boneIndex0 = first + num2;
				((BoneWeight)(ref result)).weight0 = 1f;
				return result;
			}).ToArray();
			return new CapeRig
			{
				Mesh = val,
				Spine = spine,
				Joints = array
			};
			Vector3 centre(float along)
			{
				//IL_006a: 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_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				float reach = 0.08f;
				List<Vector3> list;
				while (true)
				{
					list = vertices.Where((Vector3 vertex, int i) => Mathf.Abs(depth[i] - along) <= reach).ToList();
					if (list.Count > 0)
					{
						break;
					}
					reach += 0.05f;
				}
				return ((Matrix4x4)(ref bindposes[spine])).MultiplyPoint3x4(list.Aggregate(Vector3.zero, (Vector3 sum, Vector3 vertex) => sum + vertex) / (float)list.Count);
			}
			Vector3 joint(string suffix)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				Matrix4x4 inverse = ((Matrix4x4)(ref bindposes[Array.FindIndex(bones, (Transform bone) => ((Object)bone).name.EndsWith(suffix, StringComparison.Ordinal))])).inverse;
				return ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(Vector3.zero);
			}
		}

		private static Mesh ReadableCopy(Mesh locked)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_003c: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			locked.vertexBufferTarget = (Target)(locked.vertexBufferTarget | 0x20);
			locked.indexBufferTarget = (Target)(locked.indexBufferTarget | 0x20);
			Mesh val = new Mesh
			{
				name = ((Object)locked).name,
				indexFormat = locked.indexFormat
			};
			val.SetVertexBufferParams(locked.vertexCount, locked.GetVertexAttributes());
			for (int i = 0; i < locked.vertexBufferCount; i++)
			{
				GraphicsBuffer vertexBuffer = locked.GetVertexBuffer(i);
				try
				{
					byte[] array = new byte[vertexBuffer.count * vertexBuffer.stride];
					vertexBuffer.GetData((Array)array);
					val.SetVertexBufferData<byte>(array, 0, 0, array.Length, i, (MeshUpdateFlags)0);
				}
				finally
				{
					((IDisposable)vertexBuffer)?.Dispose();
				}
			}
			GraphicsBuffer indexBuffer = locked.GetIndexBuffer();
			try
			{
				byte[] array2 = new byte[indexBuffer.count * indexBuffer.stride];
				indexBuffer.GetData((Array)array2);
				val.SetIndexBufferParams(indexBuffer.count, locked.indexFormat);
				val.SetIndexBufferData<byte>(array2, 0, 0, array2.Length, (MeshUpdateFlags)0);
			}
			finally
			{
				((IDisposable)indexBuffer)?.Dispose();
			}
			val.subMeshCount = locked.subMeshCount;
			for (int j = 0; j < locked.subMeshCount; j++)
			{
				val.SetSubMesh(j, locked.GetSubMesh(j), (MeshUpdateFlags)0);
			}
			val.bindposes = locked.bindposes;
			val.boneWeights = locked.boneWeights;
			val.RecalculateBounds();
			return val;
		}

		private void Awake()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			enableCape = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Cape physics on capes, cloaks and wings. Off leaves every back item rigid, the way the game ships it.");
			active = enableCape.Value;
			harmony = new Harmony("local.fatecoop.capes");
			try
			{
				InstallCapeHooks();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
				harmony.UnpatchSelf();
				return;
			}
			StartWatcher();
			enableCape.SettingChanged += delegate
			{
				active = enableCape.Value;
				if ((Object)(object)lastDefaults != (Object)null)
				{
					Apply(lastDefaults, lastBackKey);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Cape physics " + (active ? "on." : "off.")));
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Capes ready: " + (active ? "on." : "off.")));
		}

		private void OnDestroy()
		{
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private static void StartWatcher()
		{
			SceneManager.sceneLoaded += delegate
			{
				EnsureWatcher();
			};
			EnsureWatcher();
		}

		private static void EnsureWatcher()
		{
			//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_001e: Expected O, but got Unknown
			if (!((Object)(object)watcher != (Object)null))
			{
				GameObject val = new GameObject("FateCoop_CapeWatch");
				Object.DontDestroyOnLoad((Object)val);
				watcher = val.AddComponent<BackWatcher>();
				Debug.Log((object)"[FATE Capes] watcher started.");
			}
		}
	}
}