Decompiled source of Soft Capes v1.0.0

BepInEx/plugins/SoftCapes/SoftCapes.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using MagicaCloth2;
using Microsoft.CodeAnalysis;
using SoftCapesRelease;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SoftCapes
{
	internal sealed class AshCollarPatch
	{
		private readonly Mesh mesh;

		private readonly int[] original;

		private readonly int[] filtered;

		internal AshCollarPatch(Mesh mesh, int[] original, int[] filtered)
		{
			this.mesh = mesh;
			this.original = original;
			this.filtered = filtered;
		}

		internal void Apply()
		{
			mesh.SetTriangles(filtered, 0, false);
		}

		internal void Restore()
		{
			if ((Object)(object)mesh != (Object)null && mesh.isReadable && mesh.subMeshCount == 1 && AshCollarTopology.Same(mesh.GetTriangles(0), filtered))
			{
				mesh.SetTriangles(original, 0, false);
			}
		}
	}
	internal static class AshCollarTopology
	{
		internal static readonly int[] Expected = new int[1416]
		{
			0, 1, 2, 0, 3, 1, 3, 4, 1, 5,
			3, 0, 5, 0, 6, 5, 6, 7, 5, 7,
			8, 9, 5, 8, 9, 3, 5, 9, 8, 10,
			3, 11, 4, 9, 11, 3, 11, 12, 4, 11,
			13, 12, 14, 9, 10, 14, 11, 9, 14, 13,
			11, 14, 10, 15, 16, 14, 15, 16, 13, 14,
			16, 15, 17, 16, 17, 18, 16, 18, 19, 19,
			18, 20, 16, 21, 13, 21, 16, 19, 19, 20,
			22, 22, 20, 23, 13, 21, 24, 13, 24, 25,
			21, 19, 26, 24, 21, 26, 26, 19, 22, 24,
			26, 27, 27, 26, 28, 26, 22, 28, 27, 28,
			29, 22, 23, 30, 28, 22, 30, 30, 23, 31,
			29, 28, 32, 28, 30, 32, 29, 32, 33, 30,
			31, 34, 32, 30, 34, 34, 31, 35, 33, 32,
			36, 32, 34, 36, 33, 36, 37, 34, 35, 38,
			36, 34, 38, 38, 35, 39, 37, 36, 40, 36,
			38, 40, 37, 40, 41, 38, 39, 42, 40, 38,
			42, 42, 39, 43, 42, 43, 44, 41, 40, 45,
			40, 42, 45, 45, 42, 44, 41, 45, 46, 45,
			44, 47, 46, 45, 47, 46, 47, 48, 49, 50,
			51, 49, 52, 50, 53, 52, 49, 52, 54, 50,
			53, 55, 52, 52, 56, 54, 55, 56, 52, 55,
			57, 56, 58, 59, 60, 58, 61, 59, 62, 61,
			58, 61, 63, 59, 62, 64, 61, 61, 65, 63,
			64, 65, 61, 64, 66, 65, 67, 68, 69, 67,
			70, 68, 71, 70, 67, 70, 72, 68, 71, 73,
			70, 70, 74, 72, 73, 74, 70, 73, 75, 74,
			76, 77, 78, 76, 79, 77, 80, 79, 76, 79,
			81, 77, 80, 82, 79, 79, 83, 81, 82, 83,
			79, 82, 84, 83, 85, 86, 87, 85, 88, 86,
			85, 89, 88, 85, 90, 89, 90, 91, 89, 90,
			92, 91, 92, 93, 91, 92, 94, 93, 94, 95,
			93, 94, 96, 95, 96, 97, 95, 96, 98, 97,
			99, 100, 101, 99, 102, 100, 102, 103, 100, 102,
			104, 103, 102, 105, 104, 99, 106, 102, 102, 106,
			105, 99, 107, 106, 106, 108, 105, 107, 109, 106,
			106, 109, 108, 107, 110, 109, 109, 111, 108, 110,
			112, 109, 109, 112, 111, 110, 113, 112, 112, 114,
			111, 113, 115, 112, 112, 115, 114, 115, 116, 114,
			113, 117, 115, 115, 118, 116, 117, 118, 115, 117,
			119, 118, 120, 121, 122, 120, 123, 121, 123, 124,
			121, 123, 125, 124, 125, 126, 124, 125, 127, 126,
			127, 128, 126, 127, 129, 128, 129, 130, 128, 129,
			131, 130, 131, 132, 130, 131, 133, 132, 134, 135,
			136, 134, 136, 137, 137, 136, 138, 139, 134, 137,
			139, 140, 134, 139, 141, 140, 139, 142, 141, 143,
			142, 139, 143, 139, 137, 143, 144, 142, 137, 138,
			145, 143, 137, 145, 145, 138, 146, 145, 146, 147,
			148, 144, 143, 148, 143, 145, 148, 145, 147, 148,
			149, 144, 150, 149, 148, 150, 148, 147, 150, 151,
			149, 150, 152, 151, 150, 153, 152, 153, 154, 152,
			150, 147, 155, 155, 153, 150, 153, 156, 154, 156,
			157, 154, 147, 158, 155, 147, 159, 158, 155, 160,
			153, 158, 160, 155, 160, 156, 153, 158, 161, 160,
			161, 162, 160, 160, 162, 156, 161, 163, 162, 156,
			164, 157, 162, 164, 156, 164, 165, 157, 163, 166,
			162, 162, 166, 164, 163, 167, 166, 164, 168, 165,
			166, 168, 164, 168, 169, 165, 167, 170, 166, 166,
			170, 168, 167, 171, 170, 168, 172, 169, 170, 172,
			168, 172, 173, 169, 171, 174, 170, 170, 174, 172,
			171, 175, 174, 172, 176, 173, 174, 176, 172, 176,
			177, 173, 176, 178, 177, 175, 179, 174, 174, 179,
			176, 179, 178, 176, 175, 180, 179, 179, 181, 178,
			180, 181, 179, 180, 182, 181, 183, 184, 185, 183,
			185, 186, 187, 183, 186, 186, 185, 188, 187, 186,
			189, 186, 188, 190, 189, 186, 190, 189, 190, 191,
			192, 193, 194, 192, 194, 195, 196, 192, 195, 195,
			194, 197, 196, 195, 198, 195, 197, 199, 198, 195,
			199, 198, 199, 200, 201, 202, 203, 201, 203, 204,
			205, 201, 204, 204, 203, 206, 205, 204, 207, 204,
			206, 208, 207, 204, 208, 207, 208, 209, 210, 211,
			212, 210, 212, 213, 214, 210, 213, 213, 212, 215,
			214, 213, 216, 213, 215, 217, 216, 213, 217, 216,
			217, 218, 219, 220, 221, 219, 221, 222, 219, 222,
			223, 219, 223, 224, 224, 223, 225, 224, 225, 226,
			226, 225, 227, 226, 227, 228, 228, 227, 229, 228,
			229, 230, 230, 229, 231, 230, 231, 232, 233, 234,
			235, 233, 235, 236, 236, 235, 237, 236, 237, 238,
			236, 238, 239, 233, 236, 240, 236, 239, 240, 233,
			240, 241, 240, 239, 242, 241, 240, 243, 240, 242,
			243, 241, 243, 244, 243, 242, 245, 244, 243, 246,
			243, 245, 246, 244, 246, 247, 246, 245, 248, 247,
			246, 249, 246, 248, 249, 249, 248, 250, 247, 249,
			251, 249, 250, 252, 251, 249, 252, 251, 252, 253,
			254, 255, 256, 254, 256, 257, 257, 256, 258, 257,
			258, 259, 259, 258, 260, 259, 260, 261, 261, 260,
			262, 261, 262, 263, 263, 262, 264, 263, 264, 265,
			265, 264, 266, 265, 266, 267, 268, 269, 270, 268,
			270, 271, 271, 272, 268, 271, 273, 272, 273, 274,
			272, 273, 275, 274, 275, 276, 274, 275, 277, 276,
			277, 278, 276, 277, 279, 278, 279, 280, 278, 279,
			281, 280, 281, 282, 280, 281, 283, 282, 284, 282,
			283, 284, 283, 285, 286, 287, 288, 286, 289, 287,
			286, 290, 289, 286, 291, 290, 287, 289, 292, 287,
			292, 293, 294, 293, 292, 294, 292, 295, 292, 296,
			295, 289, 297, 292, 292, 297, 296, 289, 290, 297,
			297, 298, 296, 297, 299, 298, 290, 299, 297, 299,
			300, 298, 291, 301, 290, 290, 301, 299, 291, 302,
			301, 299, 303, 300, 301, 303, 299, 303, 304, 300,
			302, 305, 301, 301, 305, 303, 302, 306, 305, 303,
			307, 304, 305, 307, 303, 307, 308, 304, 306, 309,
			305, 305, 309, 307, 306, 310, 309, 307, 311, 308,
			309, 311, 307, 311, 312, 308, 311, 313, 312, 310,
			314, 309, 309, 314, 311, 314, 313, 311, 310, 315,
			314, 314, 316, 313, 315, 316, 314, 315, 317, 316,
			318, 319, 320, 318, 321, 319, 318, 322, 321, 318,
			323, 322, 323, 324, 322, 323, 325, 324, 325, 326,
			324, 325, 327, 326, 324, 326, 328, 329, 328, 326,
			329, 330, 328, 324, 328, 331, 322, 324, 331, 331,
			328, 330, 322, 331, 332, 321, 322, 332, 331, 330,
			333, 332, 331, 333, 333, 330, 334, 333, 334, 335,
			336, 333, 335, 332, 333, 336, 336, 335, 337, 321,
			332, 338, 338, 332, 336, 339, 336, 337, 338, 336,
			339, 339, 337, 340, 339, 340, 341, 339, 341, 342,
			338, 339, 342, 321, 338, 343, 338, 342, 343, 321,
			343, 319, 319, 343, 342, 319, 342, 344, 345, 346,
			347, 345, 348, 346, 348, 345, 349, 348, 349, 350,
			350, 349, 351, 350, 351, 352, 352, 351, 353, 352,
			353, 354, 354, 353, 355, 354, 355, 356, 356, 355,
			357, 356, 357, 358, 358, 357, 359, 358, 359, 360,
			361, 360, 359, 361, 362, 360, 363, 364, 365, 363,
			365, 366, 363, 366, 367, 363, 367, 368, 365, 369,
			366, 365, 370, 369, 371, 369, 370, 371, 372, 369,
			369, 372, 373, 366, 369, 374, 369, 373, 374, 366,
			374, 367, 374, 373, 375, 374, 375, 376, 367, 374,
			376, 376, 375, 377, 368, 367, 378, 367, 376, 378,
			368, 378, 379, 376, 377, 380, 378, 376, 380, 380,
			377, 381, 379, 378, 382, 378, 380, 382, 379, 382,
			383, 380, 381, 384, 382, 380, 384, 384, 381, 385,
			383, 382, 386, 382, 384, 386, 383, 386, 387, 384,
			385, 388, 386, 384, 388, 388, 385, 389, 388, 389,
			390, 387, 386, 391, 386, 388, 391, 391, 388, 390,
			387, 391, 392, 391, 390, 393, 392, 391, 393, 392,
			393, 394, 395, 396, 397, 395, 397, 398, 395, 398,
			399, 395, 399, 400, 400, 399, 401, 400, 401, 402,
			402, 401, 403, 402, 403, 404, 405, 406, 407, 405,
			407, 408, 409, 408, 407, 409, 407, 410, 410, 407,
			411, 410, 411, 412, 410, 412, 413, 409, 410, 414,
			410, 413, 414, 409, 414, 415, 414, 413, 416, 415,
			414, 417, 414, 416, 417, 417, 416, 418, 415, 417,
			419, 417, 418, 420, 419, 417, 420, 419, 420, 421,
			422, 421, 420, 422, 423, 421
		};

		internal static readonly HashSet<int> RemovedFaces = new HashSet<int>
		{
			98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
			108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
			118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
			128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
			138, 139, 140, 141, 142, 143, 144, 145, 244, 245,
			246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
			256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
			266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
			276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
			286, 287, 288, 289, 290, 291
		};

		internal static int[] Filter(int vertexCount, int[] triangles)
		{
			if (vertexCount != 424 || !Same(triangles, Expected))
			{
				return null;
			}
			List<int> list = new List<int>();
			for (int i = 0; i < triangles.Length; i += 3)
			{
				if (!RemovedFaces.Contains(i / 3))
				{
					list.Add(triangles[i]);
					list.Add(triangles[i + 1]);
					list.Add(triangles[i + 2]);
				}
			}
			return list.ToArray();
		}

		internal static bool Same(int[] a, int[] b)
		{
			if (a == null || b == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				if (a[i] != b[i])
				{
					return false;
				}
			}
			return true;
		}
	}
	[BepInPlugin("maving.softcapes", "Soft Capes", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Profile
		{
			internal ConfigEntry<float> Bending;

			internal ConfigEntry<float> Restoration;

			internal ConfigEntry<float> Angle;

			internal float B;

			internal float R;

			internal float A;
		}

		private static readonly FieldInfo ShoulderHash = typeof(VisEquipment).GetField("m_currentShoulderItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ShoulderInstances = typeof(VisEquipment).GetField("m_shoulderItemInstances", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private readonly Dictionary<MagicaCloth, TuningSnapshot> applied = new Dictionary<MagicaCloth, TuningSnapshot>();

		private readonly Dictionary<string, Profile> profiles = new Dictionary<string, Profile>();

		private float nextCheck;

		private ConfigEntry<KeyCode> toggleKey;

		private ConfigEntry<bool> hideAshCollar;

		private readonly Dictionary<MagicaCloth, AshCollarPatch> collars = new Dictionary<MagicaCloth, AshCollarPatch>();

		private readonly HashSet<MagicaCloth> rejectedCollars = new HashSet<MagicaCloth>();

		private bool soft = true;

		private bool ready;

		private string lastStatus;

		private Profile BindProfile(string section, float b, float r, float a)
		{
			return new Profile
			{
				Bending = ((BaseUnityPlugin)this).Config.Bind<float>(section, "BendingMultiplier", b, "Bending relative to original, 0–1. Toggle off/on reloads."),
				Restoration = ((BaseUnityPlugin)this).Config.Bind<float>(section, "RestorationMultiplier", r, "Shape restoration relative to original, 0–1."),
				Angle = ((BaseUnityPlugin)this).Config.Bind<float>(section, "AngleLimitMultiplier", a, "Allowed angle relative to original, 1–3.")
			};
		}

		private void Awake()
		{
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)289, "Toggle key (for example F6, F7 or F8). None disables the hotkey. Save and use the current key off/on to reload, or restart the game.");
			soft = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StartEnabled", true, "Enable this component at game startup. Hotkey toggles affect only the current session.").Value;
			hideAshCollar = ((BaseUnityPlugin)this).Config.Bind<bool>("Ash", "HideRaisedCollar", true, "Hide the raised Ashen collar. Toggle off/on reloads; OFF restores the collar. Does not change cloth vertices or physics.");
			profiles.Add("CapeLox", BindProfile("Lox", 0.15f, 0.15f, 2f));
			profiles.Add("CapeFeather", BindProfile("Feather", 0.1f, 0.1f, 2.5f));
			profiles.Add("CapeWolf", BindProfile("Wolf", 0.15f, 0.15f, 2f));
			profiles.Add("CapeLinen", BindProfile("Linen", 0.05f, 0f, 3f));
			profiles.Add("CapeTrollHide", BindProfile("Troll", 0f, 0f, 3f));
			profiles.Add("CapeDeerHide", BindProfile("Deer", 0f, 0f, 3f));
			profiles.Add("CapeAsh", BindProfile("Ash", 0.5f, 0.5f, 2.5f));
			profiles.Add("CapeAsksvin", BindProfile("Asksvin", 0.05f, 0.05f, 2.5f));
			profiles.Add("CapeDeepNorth", BindProfile("DeepNorth", 0.15f, 0.15f, 2f));
			profiles.Add("CapeDeepNorthMage", BindProfile("DeepNorthMage", 0.15f, 0.15f, 2f));
			try
			{
				if (ShoulderHash == null || ShoulderInstances == null)
				{
					throw new MissingFieldException("VisEquipment shoulder fields unavailable.");
				}
				ReadSettings();
				ready = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Soft Capes 1.0.0 ready: 10 supported local capes. Toggle key: " + ((object)toggleKey.Value/*cast due to .constrained prefix*/).ToString() + ". Compares soft/original modern physics. Remove Classic Capes and older test builds before using this release."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Soft Capes inactive: " + ex));
			}
		}

		private void ReadSettings()
		{
			((BaseUnityPlugin)this).Config.Reload();
			foreach (Profile value in profiles.Values)
			{
				TuningSnapshot.Validate(value.Bending.Value, value.Restoration.Value, value.Angle.Value);
			}
			foreach (Profile value2 in profiles.Values)
			{
				value2.B = value2.Bending.Value;
				value2.R = value2.Restoration.Value;
				value2.A = value2.Angle.Value;
			}
		}

		private void Update()
		{
			//IL_0043: 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)
			if (!ready)
			{
				return;
			}
			string text = ReleaseGuard.FindConflict((BaseUnityPlugin)(object)this);
			if (text != null)
			{
				RestoreAll();
				ready = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("Disabled to avoid conflicting cape changes: remove " + text + " and restart the game."));
				return;
			}
			try
			{
				bool flag = (int)toggleKey.Value != 0 && Input.GetKeyDown(toggleKey.Value);
				if (flag)
				{
					if (soft)
					{
						soft = false;
						RestoreAll();
					}
					else
					{
						ReadSettings();
						soft = true;
					}
					nextCheck = 0f;
				}
				if (!(Time.unscaledTime < nextCheck))
				{
					nextCheck = Time.unscaledTime + 0.25f;
					Refresh();
					if (flag && (Object)(object)Player.m_localPlayer != (Object)null)
					{
						((Character)Player.m_localPlayer).Message((MessageType)2, lastStatus, 0, (Sprite)null, false);
					}
				}
			}
			catch (Exception ex)
			{
				soft = false;
				RestoreAll();
				Status("Soft Capes: error; original physics restored. See log.");
				((BaseUnityPlugin)this).Logger.LogError((object)("Soft Capes stopped; configured toggle key retries: " + ex));
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, lastStatus, 0, (Sprite)null, false);
				}
			}
		}

		private void Refresh()
		{
			HashSet<MagicaCloth> hashSet = new HashSet<MagicaCloth>();
			Profile value = null;
			string text = null;
			Player localPlayer = Player.m_localPlayer;
			if (soft && (Object)(object)localPlayer != (Object)null)
			{
				VisEquipment componentInChildren = ((Component)localPlayer).GetComponentInChildren<VisEquipment>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					int num = (int)ShoulderHash.GetValue(componentInChildren);
					GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(num) : null);
					text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null);
					if (text != null && profiles.TryGetValue(text, out value) && ShoulderInstances.GetValue(componentInChildren) is List<GameObject> list)
					{
						foreach (GameObject item in list)
						{
							if ((Object)(object)item == (Object)null || !item.activeInHierarchy)
							{
								continue;
							}
							MagicaCloth[] componentsInChildren = item.GetComponentsInChildren<MagicaCloth>();
							foreach (MagicaCloth val2 in componentsInChildren)
							{
								if (((Behaviour)val2).isActiveAndEnabled && val2.IsValid())
								{
									hashSet.Add(val2);
								}
							}
						}
					}
				}
			}
			foreach (MagicaCloth item2 in new List<MagicaCloth>(applied.Keys))
			{
				if (!hashSet.Contains(item2))
				{
					RestoreOne(item2);
				}
			}
			foreach (MagicaCloth item3 in hashSet)
			{
				if (text == "CapeAsh" && hideAshCollar.Value)
				{
					TryHideCollar(item3);
				}
				if (!applied.ContainsKey(item3))
				{
					ClothSerializeData serializeData = item3.SerializeData;
					TuningSnapshot tuningSnapshot = new TuningSnapshot(serializeData);
					applied.Add(item3, tuningSnapshot);
					tuningSnapshot.Apply(serializeData, value.B, value.R, value.A);
					item3.SetParameterChange();
					((BaseUnityPlugin)this).Logger.LogInfo((object)(text + " tuned: bending " + F(tuningSnapshot.Bending) + " -> " + F(serializeData.triangleBendingConstraint.stiffness) + "; restoration " + F(tuningSnapshot.Restoration) + " -> " + F(serializeData.angleRestorationConstraint.stiffness.value) + "; angle " + F(tuningSnapshot.Angle) + " -> " + F(serializeData.angleLimitConstraint.limitAngle.value)));
				}
			}
			Status((!soft) ? "Soft Capes OFF (original modern physics)" : ((applied.Count > 0) ? ("Soft Capes ON (" + text + ")") : ((value != null) ? "Soft Capes waiting: wait for cloth loading or re-equip the cape." : "Soft Capes ON: equip a supported cape.")));
		}

		private void TryHideCollar(MagicaCloth cloth)
		{
			if (collars.ContainsKey(cloth) || rejectedCollars.Contains(cloth))
			{
				return;
			}
			SkinnedMeshRenderer[] componentsInChildren = ((Component)cloth).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				Mesh customMesh = cloth.GetCustomMesh((Renderer)(object)val);
				if ((Object)(object)customMesh == (Object)null || (Object)(object)customMesh != (Object)(object)val.sharedMesh || (Object)(object)customMesh == (Object)(object)cloth.GetOriginalMesh((Renderer)(object)val))
				{
					continue;
				}
				if (!customMesh.isReadable || customMesh.subMeshCount != 1)
				{
					RejectCollar(cloth);
					break;
				}
				int[] triangles = customMesh.GetTriangles(0);
				int[] array = AshCollarTopology.Filter(customMesh.vertexCount, triangles);
				if (array == null)
				{
					RejectCollar(cloth);
					break;
				}
				AshCollarPatch ashCollarPatch = new AshCollarPatch(customMesh, triangles, array);
				collars.Add(cloth, ashCollarPatch);
				ashCollarPatch.Apply();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("CapeAsh raised collar hidden: " + (triangles.Length - array.Length) / 3 + " faces; cloth vertices unchanged."));
				break;
			}
		}

		private void RejectCollar(MagicaCloth cloth)
		{
			rejectedCollars.Add(cloth);
			((BaseUnityPlugin)this).Logger.LogWarning((object)"CapeAsh collar unchanged: mesh layout does not match the verified model.");
		}

		private static string F(float value)
		{
			return value.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private void Status(string status)
		{
			if (!(lastStatus == status))
			{
				lastStatus = status;
				((BaseUnityPlugin)this).Logger.LogInfo((object)status);
			}
		}

		private void RestoreOne(MagicaCloth cloth)
		{
			try
			{
				if (collars.TryGetValue(cloth, out var value))
				{
					value.Restore();
				}
				if ((Object)(object)cloth != (Object)null)
				{
					if (applied.TryGetValue(cloth, out var value2))
					{
						value2.Restore(cloth.SerializeData);
					}
					cloth.SetParameterChange();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not restore cloth; re-equip the cape: " + ex));
			}
			finally
			{
				applied.Remove(cloth);
				collars.Remove(cloth);
				rejectedCollars.Remove(cloth);
			}
		}

		private void RestoreAll()
		{
			HashSet<MagicaCloth> hashSet = new HashSet<MagicaCloth>(applied.Keys);
			hashSet.UnionWith(collars.Keys);
			foreach (MagicaCloth item in hashSet)
			{
				RestoreOne(item);
			}
			rejectedCollars.Clear();
		}

		private void OnDisable()
		{
			RestoreAll();
		}

		private void OnDestroy()
		{
			RestoreAll();
		}
	}
	internal sealed class TuningSnapshot
	{
		internal readonly float Bending;

		internal readonly float Restoration;

		internal readonly float Angle;

		internal TuningSnapshot(ClothSerializeData data)
		{
			Bending = data.triangleBendingConstraint.stiffness;
			Restoration = data.angleRestorationConstraint.stiffness.value;
			Angle = data.angleLimitConstraint.limitAngle.value;
		}

		internal void Apply(ClothSerializeData data, float bending, float restoration, float angle)
		{
			Validate(bending, restoration, angle);
			data.triangleBendingConstraint.stiffness = Math.Min(1f, Bending * bending);
			data.angleRestorationConstraint.stiffness.value = Math.Min(1f, Restoration * restoration);
			data.angleLimitConstraint.limitAngle.value = Math.Min(180f, Angle * angle);
		}

		internal void Restore(ClothSerializeData data)
		{
			data.triangleBendingConstraint.stiffness = Bending;
			data.angleRestorationConstraint.stiffness.value = Restoration;
			data.angleLimitConstraint.limitAngle.value = Angle;
		}

		internal static void Validate(float bending, float restoration, float angle)
		{
			if (!InRange(bending, 0f, 1f) || !InRange(restoration, 0f, 1f) || !InRange(angle, 1f, 3f))
			{
				throw new ArgumentException("BendingMultiplier and RestorationMultiplier must be 0–1; AngleLimitMultiplier must be 1–3. Use finite decimal values.");
			}
		}

		private static bool InRange(float value, float min, float max)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value) && value >= min)
			{
				return value <= max;
			}
			return false;
		}
	}
}
namespace SoftCapesRelease
{
	internal static class ReleaseGuard
	{
		internal static string FindConflict(BaseUnityPlugin self)
		{
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (!((Object)(object)value.Instance == (Object)null) && !((Object)(object)value.Instance == (Object)(object)self) && ((Behaviour)value.Instance).enabled)
				{
					string name = value.Metadata.Name;
					if (name == "Classic Capes")
					{
						return name;
					}
					if (name == "Soft Capes" && value.Metadata.GUID != "maving.softcapes")
					{
						return "an older Soft Capes build";
					}
					if (name == "Cape Collisions" && value.Metadata.GUID != "maving.capecollisions")
					{
						return "an older Cape Collisions build";
					}
				}
			}
			return null;
		}
	}
}

BepInEx/plugins/SoftCapes/CapeCollisions.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using MagicaCloth2;
using Microsoft.CodeAnalysis;
using SoftCapesRelease;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CapeCollisions
{
	internal static class ArmSettings
	{
		internal static void Validate(float ratio, float leftPadding, float rightPadding)
		{
			if (!Between(ratio, 0.1f, 0.5f) || !Between(leftPadding, 0f, 0.12f) || !Between(rightPadding, 0f, 0.12f))
			{
				throw new ArgumentException("RadiusRatio must be 0.1–0.5 and LeftPadding/RightPadding 0–0.12 meters; finite numbers only.");
			}
		}

		private static bool Between(float x, float min, float max)
		{
			if (!float.IsNaN(x) && !float.IsInfinity(x) && x >= min)
			{
				return x <= max;
			}
			return false;
		}

		internal static float Radius(float length, float ratio, float padding)
		{
			return length * ratio + padding;
		}

		internal static float Height(float length, float radius)
		{
			return length + 2f * radius;
		}
	}
	[BepInPlugin("maving.capecollisions", "Cape Collisions", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Profile
		{
			internal ConfigEntry<float> Ratio;

			internal ConfigEntry<float> Left;

			internal ConfigEntry<float> Right;

			internal float R;

			internal float L;

			internal float P;
		}

		private sealed class Arm
		{
			internal Transform Start;

			internal Transform End;

			internal MagicaCapsuleCollider Collider;

			internal float Ratio;

			internal float Padding;

			internal float LastLength = -1f;
		}

		private sealed class Attachment
		{
			internal ListPatch<ColliderComponent> Patch;

			internal readonly List<Arm> Arms = new List<Arm>();

			internal bool Registered;
		}

		private static readonly FieldInfo ShoulderHash = typeof(VisEquipment).GetField("m_currentShoulderItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ShoulderInstances = typeof(VisEquipment).GetField("m_shoulderItemInstances", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private readonly Dictionary<MagicaCloth, Attachment> attachments = new Dictionary<MagicaCloth, Attachment>();

		private readonly Dictionary<string, Profile> profiles = new Dictionary<string, Profile>();

		private float nextCheck;

		private ConfigEntry<KeyCode> toggleKey;

		private bool active = true;

		private bool ready;

		private string status;

		private Profile BindProfile(string section)
		{
			return new Profile
			{
				Ratio = ((BaseUnityPlugin)this).Config.Bind<float>(section, "RadiusRatio", 0.24f, "Base upper-arm radius ratio, 0.1–0.5."),
				Left = ((BaseUnityPlugin)this).Config.Bind<float>(section, "LeftPadding", 0.02f, "Extra left radius in meters, 0–0.12. Toggle off/on reloads."),
				Right = ((BaseUnityPlugin)this).Config.Bind<float>(section, "RightPadding", 0.02f, "Extra right radius in meters, 0–0.12. Toggle off/on reloads.")
			};
		}

		private void Awake()
		{
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)288, "Toggle key (for example F6, F7 or F8). None disables the hotkey. Save and use the current key off/on to reload, or restart the game.");
			active = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StartEnabled", true, "Enable this component at game startup. Hotkey toggles affect only the current session.").Value;
			profiles.Add("CapeLox", BindProfile("UpperArms"));
			profiles.Add("CapeFeather", BindProfile("FeatherUpperArms"));
			profiles.Add("CapeWolf", BindProfile("WolfUpperArms"));
			profiles.Add("CapeLinen", BindProfile("LinenUpperArms"));
			profiles.Add("CapeTrollHide", BindProfile("TrollUpperArms"));
			profiles.Add("CapeDeerHide", BindProfile("DeerUpperArms"));
			profiles.Add("CapeAsh", BindProfile("AshUpperArms"));
			profiles.Add("CapeAsksvin", BindProfile("AsksvinUpperArms"));
			profiles.Add("CapeDeepNorth", BindProfile("DeepNorthUpperArms"));
			profiles.Add("CapeDeepNorthMage", BindProfile("DeepNorthMageUpperArms"));
			try
			{
				if (ShoulderHash == null || ShoulderInstances == null)
				{
					throw new MissingFieldException("VisEquipment shoulder fields unavailable.");
				}
				Reload();
				ready = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Cape Collisions 1.0.0 ready. Toggle key: " + ((object)toggleKey.Value/*cast due to .constrained prefix*/).ToString() + ". Toggles extra upper-arm collisions for 10 supported local capes. Soft Capes settings are independent."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Cape Collisions inactive: " + ex));
			}
		}

		private void Reload()
		{
			((BaseUnityPlugin)this).Config.Reload();
			foreach (Profile value in profiles.Values)
			{
				ArmSettings.Validate(value.Ratio.Value, value.Left.Value, value.Right.Value);
			}
			foreach (Profile value2 in profiles.Values)
			{
				value2.R = value2.Ratio.Value;
				value2.L = value2.Left.Value;
				value2.P = value2.Right.Value;
			}
		}

		private void Update()
		{
			//IL_0043: 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)
			if (!ready)
			{
				return;
			}
			string text = ReleaseGuard.FindConflict((BaseUnityPlugin)(object)this);
			if (text != null)
			{
				RestoreAll();
				ready = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("Disabled to avoid conflicting cape changes: remove " + text + " and restart the game."));
				return;
			}
			try
			{
				bool flag = (int)toggleKey.Value != 0 && Input.GetKeyDown(toggleKey.Value);
				if (flag)
				{
					if (active)
					{
						active = false;
						RestoreAll();
					}
					else
					{
						Reload();
						active = true;
					}
					nextCheck = 0f;
				}
				if (!(Time.unscaledTime < nextCheck))
				{
					nextCheck = Time.unscaledTime + 0.25f;
					Refresh();
					if (flag)
					{
						ShowStatus();
					}
				}
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
		}

		private void Refresh()
		{
			HashSet<MagicaCloth> hashSet = new HashSet<MagicaCloth>();
			Profile value = null;
			string text = null;
			Player localPlayer = Player.m_localPlayer;
			VisEquipment val = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).GetComponentInChildren<VisEquipment>() : null);
			if (active && (Object)(object)val != (Object)null && (Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab((int)ShoulderHash.GetValue(val));
				text = (((Object)(object)itemPrefab != (Object)null) ? ((Object)itemPrefab).name : null);
				if (text != null && profiles.TryGetValue(text, out value) && ShoulderInstances.GetValue(val) is List<GameObject> list)
				{
					foreach (GameObject item in list)
					{
						if ((Object)(object)item == (Object)null || !item.activeInHierarchy)
						{
							continue;
						}
						MagicaCloth[] componentsInChildren = item.GetComponentsInChildren<MagicaCloth>();
						foreach (MagicaCloth val2 in componentsInChildren)
						{
							if (((Behaviour)val2).isActiveAndEnabled && val2.IsValid())
							{
								hashSet.Add(val2);
							}
						}
					}
				}
			}
			foreach (MagicaCloth item2 in new List<MagicaCloth>(attachments.Keys))
			{
				if (!hashSet.Contains(item2))
				{
					RestoreOne(item2);
				}
			}
			foreach (MagicaCloth item3 in hashSet)
			{
				if (!attachments.TryGetValue(item3, out var value2))
				{
					Add(item3, val, value, text);
				}
				else if (!value2.Registered && value2.Arms.TrueForAll((Arm a) => (Object)(object)a.Collider != (Object)null && ((ColliderComponent)a.Collider).UseTeamCount > 0))
				{
					value2.Registered = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Verified: " + value2.Arms.Count + " added arm colliders registered in MagicaCloth simulation."));
				}
			}
			MagicaManager.OnPreSimulation = (Action)Delegate.Remove(MagicaManager.OnPreSimulation, new Action(FollowArms));
			if (attachments.Count > 0)
			{
				MagicaManager.OnPreSimulation = (Action)Delegate.Combine(MagicaManager.OnPreSimulation, new Action(FollowArms));
			}
			SetStatus((!active) ? "Cape Collisions OFF" : ((attachments.Count > 0) ? ("Cape Collisions ON (" + text + ")") : "Cape Collisions ON: waiting for a supported cape."));
		}

		private void Add(MagicaCloth cloth, VisEquipment vis, Profile profile, string capeName)
		{
			SerializeData colliderCollisionConstraint = cloth.SerializeData.colliderCollisionConstraint;
			Attachment attachment = new Attachment
			{
				Patch = new ListPatch<ColliderComponent>(colliderCollisionConstraint.colliderList)
			};
			attachments.Add(cloth, attachment);
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal);
			SkinnedMeshRenderer[] componentsInChildren = ((Component)cloth).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Transform[] bones = componentsInChildren[i].bones;
				foreach (Transform val in bones)
				{
					if ((Object)(object)val != (Object)null)
					{
						dictionary[((Object)val).name] = val;
					}
				}
			}
			if (!dictionary.ContainsKey("LeftArm") || !dictionary.ContainsKey("RightArm"))
			{
				Transform[] bones = ((Component)vis).GetComponentsInChildren<Transform>(true);
				foreach (Transform val2 in bones)
				{
					if (!dictionary.ContainsKey(((Object)val2).name))
					{
						dictionary.Add(((Object)val2).name, val2);
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)(capeName + " original collider list: " + attachment.Patch.Installed.Count + " entries."));
			AddArm(attachment, dictionary, "LeftArm", "LeftForeArm", profile.R, profile.L);
			AddArm(attachment, dictionary, "RightArm", "RightForeArm", profile.R, profile.P);
			colliderCollisionConstraint.colliderList = attachment.Patch.Installed;
			cloth.SetParameterChange();
			((BaseUnityPlugin)this).Logger.LogInfo((object)(capeName + " arm collision patch: " + attachment.Arms.Count + " added; " + colliderCollisionConstraint.colliderList.Count + " total. Existing collider objects unchanged."));
		}

		private void AddArm(Attachment attachment, Dictionary<string, Transform> bones, string startName, string endName, float ratio, float padding)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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)
			if (!bones.TryGetValue(startName, out var value) || !bones.TryGetValue(endName, out var value2))
			{
				throw new InvalidOperationException("Missing upper-arm bones: " + startName + "/" + endName);
			}
			foreach (ColliderComponent item in attachment.Patch.Installed)
			{
				if (!((Object)(object)item == (Object)null))
				{
					bool num = OnUpperArm(((Component)item).transform, value, value2);
					bool flag = (int)item.symmetryMode != 0 && (OnUpperArm(item.symmetryTarget, value, value2) || OnUpperArm(item.ActiveSymmetryTarget, value, value2));
					if (num || flag)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)(startName + " already has a cloth collider; skipping duplicate."));
						return;
					}
				}
			}
			GameObject val = new GameObject("CapeCollisions_" + startName);
			val.SetActive(false);
			Arm arm = new Arm
			{
				Start = value,
				End = value2,
				Ratio = ratio,
				Padding = padding
			};
			try
			{
				arm.Collider = val.AddComponent<MagicaCapsuleCollider>();
				arm.Collider.direction = (Direction)1;
				arm.Collider.alignedOnCenter = true;
				((ColliderComponent)arm.Collider).symmetryMode = (ColliderSymmetryMode)0;
				arm.Collider.reverseDirection = false;
				((ColliderComponent)arm.Collider).center = Vector3.zero;
				MoveArm(arm);
				attachment.Arms.Add(arm);
				attachment.Patch.Add((ColliderComponent)(object)arm.Collider);
				val.SetActive(true);
			}
			catch
			{
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		private static bool OnUpperArm(Transform t, Transform start, Transform end)
		{
			if ((Object)(object)t != (Object)null && ((Object)(object)t == (Object)(object)start || t.IsChildOf(start)) && (Object)(object)t != (Object)(object)end)
			{
				return !t.IsChildOf(end);
			}
			return false;
		}

		private void FollowArms()
		{
			try
			{
				foreach (Attachment value in attachments.Values)
				{
					foreach (Arm arm in value.Arms)
					{
						MoveArm(arm);
					}
				}
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
		}

		private void MoveArm(Arm arm)
		{
			//IL_0031: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)arm.Collider == (Object)null || (Object)(object)arm.Start == (Object)null || (Object)(object)arm.End == (Object)null)
			{
				return;
			}
			Vector3 val = arm.End.position - arm.Start.position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (!(magnitude < 0.001f))
			{
				Transform transform = ((Component)arm.Collider).transform;
				transform.position = (arm.Start.position + arm.End.position) * 0.5f;
				transform.rotation = Quaternion.FromToRotation(Vector3.up, val / magnitude);
				transform.localScale = Vector3.one;
				if (Math.Abs(magnitude - arm.LastLength) > 0.0001f)
				{
					float num = ArmSettings.Radius(magnitude, arm.Ratio, arm.Padding);
					arm.Collider.SetSize(num, num, ArmSettings.Height(magnitude, num));
					((ColliderComponent)arm.Collider).UpdateParameters();
					arm.LastLength = magnitude;
				}
			}
		}

		private void RestoreOne(MagicaCloth cloth)
		{
			Attachment attachment = attachments[cloth];
			try
			{
				if ((Object)(object)cloth != (Object)null)
				{
					SerializeData colliderCollisionConstraint = cloth.SerializeData.colliderCollisionConstraint;
					colliderCollisionConstraint.colliderList = attachment.Patch.RemoveFrom(colliderCollisionConstraint.colliderList);
					cloth.SetParameterChange();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Collider list cleanup failed; re-equip cape: " + ex));
			}
			finally
			{
				foreach (Arm arm in attachment.Arms)
				{
					if ((Object)(object)arm.Collider != (Object)null)
					{
						((Component)arm.Collider).gameObject.SetActive(false);
						Object.Destroy((Object)(object)((Component)arm.Collider).gameObject);
					}
				}
				attachments.Remove(cloth);
			}
		}

		private void RestoreAll()
		{
			MagicaManager.OnPreSimulation = (Action)Delegate.Remove(MagicaManager.OnPreSimulation, new Action(FollowArms));
			foreach (MagicaCloth item in new List<MagicaCloth>(attachments.Keys))
			{
				RestoreOne(item);
			}
		}

		private void SetStatus(string value)
		{
			if (!(status == value))
			{
				status = value;
				((BaseUnityPlugin)this).Logger.LogInfo((object)value);
			}
		}

		private void ShowStatus()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, status, 0, (Sprite)null, false);
			}
		}

		private void Fail(Exception ex)
		{
			active = false;
			RestoreAll();
			SetStatus("Cape Collisions OFF: error (see log)");
			((BaseUnityPlugin)this).Logger.LogError((object)("Cape Collisions stopped; configured toggle key retries: " + ex));
			ShowStatus();
		}

		private void OnDisable()
		{
			RestoreAll();
		}

		private void OnDestroy()
		{
			RestoreAll();
		}
	}
	internal sealed class ListPatch<T> where T : class
	{
		internal readonly List<T> Original;

		internal readonly List<T> Installed;

		private readonly List<T> additions = new List<T>();

		internal ListPatch(List<T> original)
		{
			Original = original;
			Installed = ((original == null) ? new List<T>() : new List<T>(original));
		}

		internal void Add(T item)
		{
			additions.Add(item);
			Installed.Add(item);
		}

		internal List<T> RemoveFrom(List<T> current)
		{
			if (current == null)
			{
				return null;
			}
			List<T> list = new List<T>();
			foreach (T item in current)
			{
				if (!additions.Exists((T own) => own == item))
				{
					list.Add(item);
				}
			}
			if (Original != null && list.Count == Original.Count)
			{
				bool flag = true;
				for (int num = 0; num < list.Count; num++)
				{
					flag &= list[num] == Original[num];
				}
				if (flag)
				{
					return Original;
				}
			}
			return list;
		}
	}
}
namespace SoftCapesRelease
{
	internal static class ReleaseGuard
	{
		internal static string FindConflict(BaseUnityPlugin self)
		{
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (!((Object)(object)value.Instance == (Object)null) && !((Object)(object)value.Instance == (Object)(object)self) && ((Behaviour)value.Instance).enabled)
				{
					string name = value.Metadata.Name;
					if (name == "Classic Capes")
					{
						return name;
					}
					if (name == "Soft Capes" && value.Metadata.GUID != "maving.softcapes")
					{
						return "an older Soft Capes build";
					}
					if (name == "Cape Collisions" && value.Metadata.GUID != "maving.capecollisions")
					{
						return "an older Cape Collisions build";
					}
				}
			}
			return null;
		}
	}
}