Decompiled source of CustomSosigModelFramework v1.0.0

CustomSosigModelFramework.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

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

internal static class AnatomicalJointLimiter
{
	public static Quaternion ClampRelativeToBind(Quaternion current, Quaternion bind, Vector3 twistAxis, float maxSwingDegrees, float maxTwistDegrees)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_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_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0031: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: 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_0142: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		if (((Vector3)(ref twistAxis)).sqrMagnitude < 1E-06f)
		{
			return current;
		}
		((Vector3)(ref twistAxis)).Normalize();
		Quaternion val = Quaternion.Inverse(bind) * current;
		if (val.w < 0f)
		{
			val = Negate(val);
		}
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(val.x, val.y, val.z);
		Vector3 val3 = twistAxis * Vector3.Dot(val2, twistAxis);
		Quaternion val4 = NormalizeSafe(new Quaternion(val3.x, val3.y, val3.z, val.w));
		Quaternion val5 = val * Quaternion.Inverse(val4);
		float num = default(float);
		Vector3 val6 = default(Vector3);
		((Quaternion)(ref val5)).ToAngleAxis(ref num, ref val6);
		if (num > 180f)
		{
			num = 360f - num;
			val6 = -val6;
		}
		if (((Vector3)(ref val6)).sqrMagnitude < 1E-06f)
		{
			val6 = Vector3.right;
		}
		Quaternion val7 = Quaternion.AngleAxis(Mathf.Min(num, Mathf.Max(0f, maxSwingDegrees)), ((Vector3)(ref val6)).normalized);
		Vector3 val8 = default(Vector3);
		float num2 = default(float);
		((Quaternion)(ref val4)).ToAngleAxis(ref num2, ref val8);
		if (num2 > 180f)
		{
			num2 -= 360f;
		}
		if (Vector3.Dot(val8, twistAxis) < 0f)
		{
			num2 = 0f - num2;
		}
		num2 = Mathf.Clamp(num2, 0f - Mathf.Max(0f, maxTwistDegrees), Mathf.Max(0f, maxTwistDegrees));
		Quaternion val9 = Quaternion.AngleAxis(num2, twistAxis);
		return bind * (val7 * val9);
	}

	private static Quaternion NormalizeSafe(Quaternion value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Sqrt(value.x * value.x + value.y * value.y + value.z * value.z + value.w * value.w);
		if (num < 1E-06f)
		{
			return Quaternion.identity;
		}
		float num2 = 1f / num;
		return new Quaternion(value.x * num2, value.y * num2, value.z * num2, value.w * num2);
	}

	private static Quaternion Negate(Quaternion value)
	{
		//IL_0000: 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_000e: 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_001c: Unknown result type (might be due to invalid IL or missing references)
		return new Quaternion(0f - value.x, 0f - value.y, 0f - value.z, 0f - value.w);
	}
}
internal sealed class ArmorHitboxOverlay
{
	internal readonly GameObject Root;

	private readonly Mesh _mesh;

	private ArmorHitboxOverlay(GameObject root, Mesh mesh)
	{
		Root = root;
		_mesh = mesh;
	}

	internal static ArmorHitboxOverlay Create(Collider hitbox, Material material, int visualLayer)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: 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_008d: 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)
		//IL_00a5: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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_00ea: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)hitbox == (Object)null || (Object)(object)material == (Object)null)
		{
			return null;
		}
		BoxCollider val = (BoxCollider)(object)((hitbox is BoxCollider) ? hitbox : null);
		CapsuleCollider val2 = (CapsuleCollider)(object)((hitbox is CapsuleCollider) ? hitbox : null);
		Mesh val3;
		Vector3 center;
		Vector3 localScale;
		if ((Object)(object)val != (Object)null)
		{
			val3 = CreateBoxMesh();
			center = val.center;
			localScale = val.size;
		}
		else
		{
			if (!((Object)(object)val2 != (Object)null) || val2.direction != 1)
			{
				return null;
			}
			val3 = CreateCapsuleMesh(val2.radius, val2.height);
			center = val2.center;
			localScale = Vector3.one;
		}
		GameObject val4 = new GameObject("Armor Hitbox Overlay")
		{
			layer = visualLayer
		};
		val4.transform.SetParent(((Component)hitbox).transform, false);
		val4.transform.localPosition = center;
		val4.transform.localScale = localScale;
		val4.AddComponent<MeshFilter>().sharedMesh = val3;
		MeshRenderer obj = val4.AddComponent<MeshRenderer>();
		((Renderer)obj).sharedMaterial = material;
		((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)obj).receiveShadows = false;
		val4.SetActive(false);
		return new ArmorHitboxOverlay(val4, val3);
	}

	internal void Dispose()
	{
		if ((Object)(object)Root != (Object)null)
		{
			Object.Destroy((Object)(object)Root);
		}
		if ((Object)(object)_mesh != (Object)null)
		{
			Object.Destroy((Object)(object)_mesh);
		}
	}

	private static Mesh CreateBoxMesh()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//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_0044: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		Mesh val = new Mesh();
		((Object)val).name = "Custom Sosig armor box overlay";
		val.vertices = (Vector3[])(object)new Vector3[8]
		{
			new Vector3(-0.5f, -0.5f, -0.5f),
			new Vector3(0.5f, -0.5f, -0.5f),
			new Vector3(0.5f, 0.5f, -0.5f),
			new Vector3(-0.5f, 0.5f, -0.5f),
			new Vector3(-0.5f, -0.5f, 0.5f),
			new Vector3(0.5f, -0.5f, 0.5f),
			new Vector3(0.5f, 0.5f, 0.5f),
			new Vector3(-0.5f, 0.5f, 0.5f)
		};
		val.triangles = new int[36]
		{
			4, 5, 6, 4, 6, 7, 1, 0, 3, 1,
			3, 2, 0, 4, 7, 0, 7, 3, 5, 1,
			2, 5, 2, 6, 3, 7, 6, 3, 6, 2,
			0, 1, 5, 0, 5, 4
		};
		val.RecalculateNormals();
		val.RecalculateBounds();
		return val;
	}

	private static Mesh CreateCapsuleMesh(float radius, float height)
	{
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Expected O, but got Unknown
		//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)
		int num = 12;
		float num2 = Mathf.Max(0f, height * 0.5f - radius);
		Vector3[] array = (Vector3[])(object)new Vector3[num * 12];
		int[] array2 = new int[(num - 1) * 12 * 6];
		for (int i = 0; i < num; i++)
		{
			bool num3 = i > 5;
			int num4 = (num3 ? (i - 5 - 1) : i);
			float num5 = (num3 ? ((float)num4 * (float)Math.PI * 0.5f / 5f) : (-(float)Math.PI / 2f + (float)num4 * (float)Math.PI * 0.5f / 5f));
			float num6 = (num3 ? num2 : (0f - num2)) + Mathf.Sin(num5) * radius;
			float num7 = Mathf.Cos(num5) * radius;
			for (int j = 0; j < 12; j++)
			{
				float num8 = (float)j * (float)Math.PI * 2f / 12f;
				array[i * 12 + j] = new Vector3(Mathf.Cos(num8) * num7, num6, Mathf.Sin(num8) * num7);
			}
		}
		int num9 = 0;
		for (int k = 0; k < num - 1; k++)
		{
			for (int l = 0; l < 12; l++)
			{
				int num10 = (l + 1) % 12;
				int num11 = k * 12 + l;
				int num12 = k * 12 + num10;
				int num13 = (k + 1) * 12 + l;
				int num14 = (k + 1) * 12 + num10;
				array2[num9++] = num11;
				array2[num9++] = num13;
				array2[num9++] = num12;
				array2[num9++] = num12;
				array2[num9++] = num13;
				array2[num9++] = num14;
			}
		}
		Mesh val = new Mesh
		{
			name = "Custom Sosig armor capsule overlay",
			vertices = array,
			triangles = array2
		};
		val.RecalculateNormals();
		val.RecalculateBounds();
		return val;
	}
}
internal sealed class BloodImpactVfx : MonoBehaviour
{
	private const int PoolSize = 24;

	private readonly List<ParticleSystem> _bursts = new List<ParticleSystem>(24);

	private readonly List<ParticleSystem> _droplets = new List<ParticleSystem>(24);

	private Material _burstMaterial;

	private Material _dropletMaterial;

	private Texture2D _burstTexture;

	private Texture2D _dropletTexture;

	private int _next;

	internal void Initialize(string maskPath, string noisePath)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		Shader val = Shader.Find("Particles/Alpha Blended");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Legacy Shaders/Particles/Alpha Blended");
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)"No legacy alpha-blended shader for the custom blood effect.");
			return;
		}
		_burstTexture = BuildBurstTexture(maskPath, noisePath);
		_dropletTexture = BuildDropletTexture();
		_burstMaterial = new Material(val);
		((Object)_burstMaterial).name = "Custom Sosig tutorial-mask blood burst";
		_burstMaterial.mainTexture = (Texture)(object)_burstTexture;
		_dropletMaterial = new Material(val);
		((Object)_dropletMaterial).name = "Custom Sosig blood droplets";
		_dropletMaterial.mainTexture = (Texture)(object)_dropletTexture;
		Plugin.Log.LogInfo((object)("Custom blood VFX ready: " + ((maskPath == null) ? "procedural fallback" : "supplied mask and noise") + "."));
	}

	internal void Spawn(Vector3 point, Vector3 normal)
	{
		//IL_00a4: 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_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_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_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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)
		//IL_00eb: 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)
		if (!((Object)(object)_burstMaterial == (Object)null))
		{
			ParticleSystem val;
			ParticleSystem val2;
			if (_bursts.Count < 24)
			{
				val = CreateSystem(burst: true);
				val2 = CreateSystem(burst: false);
				_bursts.Add(val);
				_droplets.Add(val2);
			}
			else
			{
				val = _bursts[_next];
				val2 = _droplets[_next];
				val.Stop(true, (ParticleSystemStopBehavior)0);
				val2.Stop(true, (ParticleSystemStopBehavior)0);
			}
			_next = (_next + 1) % 24;
			Vector3 val3 = ((((Vector3)(ref normal)).sqrMagnitude > 0.001f) ? ((Vector3)(ref normal)).normalized : Vector3.up);
			Quaternion rotation = Quaternion.LookRotation(val3);
			((Component)val).transform.position = point + val3 * 0.014f;
			((Component)val).transform.rotation = rotation;
			((Component)val2).transform.position = point + val3 * 0.01f;
			((Component)val2).transform.rotation = rotation;
			val.Play(true);
			val2.Play(true);
			val.Emit(2);
			val2.Emit(7);
		}
	}

	private static Texture2D LoadTexture(string path)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Expected O, but got Unknown
		if (string.IsNullOrEmpty(path))
		{
			return null;
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		if (!val.LoadImage(File.ReadAllBytes(path)))
		{
			Object.Destroy((Object)(object)val);
			throw new IOException("Could not decode blood VFX texture: " + path);
		}
		return val;
	}

	private static Texture2D BuildBurstTexture(string maskPath, string noisePath)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_00a6: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = LoadTexture(maskPath);
		Texture2D val2 = LoadTexture(noisePath);
		Texture2D val3 = new Texture2D(128, 128, (TextureFormat)4, false);
		((Object)val3).name = "Custom Sosig supplied blood mask";
		Color[] array = (Color[])(object)new Color[16384];
		for (int i = 0; i < 128; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				float num = ((float)j + 0.5f) / 128f;
				float num2 = ((float)i + 0.5f) / 128f;
				float num3 = (((Object)(object)val != (Object)null) ? val.GetPixelBilinear(num, num2).r : Mathf.Clamp01(1f - Vector2.Distance(new Vector2(num, num2), new Vector2(0.5f, 0.5f)) * 2f));
				float num4 = (((Object)(object)val2 != (Object)null) ? val2.GetPixelBilinear(num * 1.7f, num2 * 1.7f).r : 1f);
				float num5 = Mathf.Clamp01((num3 - 0.08f) * 1.35f) * Mathf.Lerp(0.65f, 1f, num4);
				array[i * 128 + j] = new Color(1f, 1f, 1f, num5);
			}
		}
		val3.SetPixels(array);
		val3.Apply(false, true);
		if ((Object)(object)val != (Object)null)
		{
			Object.Destroy((Object)(object)val);
		}
		if ((Object)(object)val2 != (Object)null)
		{
			Object.Destroy((Object)(object)val2);
		}
		return val3;
	}

	private static Texture2D BuildDropletTexture()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0081: 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)
		Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false);
		((Object)val).name = "Custom Sosig blood droplet alpha";
		Color[] array = (Color[])(object)new Color[256];
		for (int i = 0; i < 16; i++)
		{
			for (int j = 0; j < 16; j++)
			{
				float num = ((float)j - 7.5f) / 7.5f;
				float num2 = ((float)i - 7.5f) / 7.5f;
				array[i * 16 + j] = new Color(1f, 1f, 1f, Mathf.Clamp01((0.9f - Mathf.Sqrt(num * num + num2 * num2)) * 9f));
			}
		}
		val.SetPixels(array);
		val.Apply(false, true);
		return val;
	}

	private ParticleSystem CreateSystem(bool burst)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		//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_0079: 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_00a3: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: 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_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_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Expected O, but got Unknown
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: 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_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: 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_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: 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_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(burst ? "Custom Sosig Masked Blood Burst" : "Custom Sosig Blood Droplets");
		val.transform.SetParent(((Component)this).transform, false);
		ParticleSystem val2 = val.AddComponent<ParticleSystem>();
		MainModule main = val2.main;
		((MainModule)(ref main)).loop = false;
		((MainModule)(ref main)).playOnAwake = false;
		((MainModule)(ref main)).duration = 0.55f;
		((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
		((MainModule)(ref main)).startLifetime = (burst ? new MinMaxCurve(0.15f, 0.26f) : new MinMaxCurve(0.22f, 0.48f));
		((MainModule)(ref main)).startSpeed = (burst ? new MinMaxCurve(0.06f, 0.25f) : new MinMaxCurve(0.8f, 2.1f));
		((MainModule)(ref main)).startSize = (burst ? new MinMaxCurve(0.2f, 0.32f) : new MinMaxCurve(0.006f, 0.016f));
		((MainModule)(ref main)).startColor = (burst ? new MinMaxGradient(new Color(0.37f, 0.008f, 0.012f, 0.9f), new Color(0.58f, 0.025f, 0.02f, 1f)) : new MinMaxGradient(new Color(0.22f, 0.004f, 0.007f, 0.8f), new Color(0.5f, 0.018f, 0.012f, 1f)));
		((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(burst ? 0.15f : 1f);
		((MainModule)(ref main)).maxParticles = (burst ? 4 : 20);
		EmissionModule emission = val2.emission;
		((EmissionModule)(ref emission)).enabled = false;
		ShapeModule shape = val2.shape;
		((ShapeModule)(ref shape)).enabled = true;
		((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4;
		((ShapeModule)(ref shape)).angle = (burst ? 15f : 30f);
		((ShapeModule)(ref shape)).radius = 0.005f;
		ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
		((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
		Gradient val3 = new Gradient();
		val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
		{
			new GradientColorKey(Color.white, 0f),
			new GradientColorKey(Color.white, 1f)
		}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
		{
			new GradientAlphaKey(0f, 0f),
			new GradientAlphaKey(1f, 0.12f),
			new GradientAlphaKey(0.75f, 0.65f),
			new GradientAlphaKey(0f, 1f)
		});
		((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val3);
		ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
		((Renderer)component).sharedMaterial = (burst ? _burstMaterial : _dropletMaterial);
		component.renderMode = (ParticleSystemRenderMode)(!burst);
		if (!burst)
		{
			component.lengthScale = 1.4f;
			component.velocityScale = 0.25f;
		}
		return val2;
	}

	private void OnDestroy()
	{
		if ((Object)(object)_burstMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_burstMaterial);
		}
		if ((Object)(object)_dropletMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_dropletMaterial);
		}
		if ((Object)(object)_burstTexture != (Object)null)
		{
			Object.Destroy((Object)(object)_burstTexture);
		}
		if ((Object)(object)_dropletTexture != (Object)null)
		{
			Object.Destroy((Object)(object)_dropletTexture);
		}
	}
}
internal sealed class CustomSosigHitbox : MonoBehaviour, IFVRDamageable
{
	private static bool _firstDamageLogged;

	private static readonly FieldInfo WearablesField = AccessTools.Field(typeof(SosigLink), "m_wearables");

	private SosigLink _target;

	private Rigidbody _body;

	private int _damageMultiplier = 1;

	private bool _armorEligible;

	private bool _bloodImpacts;

	private string _addonId;

	internal bool HasArmorProtection
	{
		get
		{
			if (_armorEligible)
			{
				return (Object)(object)FindProtectiveWearable() != (Object)null;
			}
			return false;
		}
	}

	private SosigWearable FindProtectiveWearable()
	{
		if ((Object)(object)_target == (Object)null || !_target.HasWearables())
		{
			return null;
		}
		List<SosigWearable> list = (((object)WearablesField != null) ? (WearablesField.GetValue(_target) as List<SosigWearable>) : null);
		if (list != null)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if (IsActiveArmor(list[i]))
				{
					return list[i];
				}
			}
			return null;
		}
		SosigWearable randomWearable = _target.GetRandomWearable();
		if (!IsActiveArmor(randomWearable))
		{
			return null;
		}
		return randomWearable;
	}

	private static bool IsActiveArmor(SosigWearable armor)
	{
		if ((Object)(object)armor == (Object)null || armor.Cols == null)
		{
			return false;
		}
		foreach (Collider col in armor.Cols)
		{
			if ((Object)(object)col != (Object)null && col.enabled && ((Component)col).gameObject.activeInHierarchy)
			{
				return true;
			}
		}
		return false;
	}

	public void Initialize(SosigLink target, Rigidbody body, int damageMultiplier, bool armorEligible, bool bloodImpacts, string addonId)
	{
		_target = target;
		_body = body;
		_damageMultiplier = Mathf.Max(1, damageMultiplier);
		_armorEligible = armorEligible;
		_bloodImpacts = bloodImpacts;
		_addonId = addonId;
	}

	public void Damage(Damage damage)
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		//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_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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)
		//IL_00a9: Expected O, but got Unknown
		if ((Object)(object)_target == (Object)null)
		{
			return;
		}
		if (_armorEligible && (int)damage.Class == 1 && _target.HasWearables())
		{
			SosigWearable val = null;
			Vector3 normalized = ((Vector3)(ref damage.hitNormal)).normalized;
			if (!(((Vector3)(ref normalized)).sqrMagnitude > 0.001f) || !_target.HitsWearable(damage.point + normalized * 0.5f, -normalized, 1.5f, ref val) || !IsActiveArmor(val))
			{
				val = FindProtectiveWearable();
			}
			if ((Object)(object)val != (Object)null)
			{
				val.Damage(new Damage(damage));
				((MonoBehaviour)this).StartCoroutine(ApplyDeathImpulse(damage));
				return;
			}
		}
		Damage val2 = new Damage(damage);
		if (_damageMultiplier > 1)
		{
			val2.Dam_Blunt *= (float)_damageMultiplier;
			val2.Dam_Piercing *= (float)_damageMultiplier;
			val2.Dam_Cutting *= (float)_damageMultiplier;
			val2.Dam_TotalKinetic *= (float)_damageMultiplier;
			val2.Dam_Thermal *= (float)_damageMultiplier;
			val2.Dam_Chilling *= (float)_damageMultiplier;
			val2.Dam_EMP *= (float)_damageMultiplier;
			val2.Dam_TotalEnergetic *= (float)_damageMultiplier;
			val2.Dam_Stunning *= (float)_damageMultiplier;
			val2.Dam_Blinding *= (float)_damageMultiplier;
		}
		if (!_firstDamageLogged)
		{
			_firstDamageLogged = true;
			Plugin.Log.LogInfo((object)("First custom hitbox damage routed to Sosig body part " + ((object)Unsafe.As<SosigBodyPart, SosigBodyPart>(ref _target.BodyPart)/*cast due to .constrained prefix*/).ToString() + " with multiplier x" + _damageMultiplier + "."));
		}
		if (_bloodImpacts)
		{
			Plugin.SpawnBloodImpact(_addonId, damage.point, damage.hitNormal);
		}
		_target.Damage(val2);
		((MonoBehaviour)this).StartCoroutine(ApplyDeathImpulse(damage));
	}

	private IEnumerator ApplyDeathImpulse(Damage damage)
	{
		yield return (object)new WaitForSeconds(0.1f);
		if (!((Object)(object)_body == (Object)null) && !_body.isKinematic)
		{
			float num = damage.Dam_TotalKinetic / 20f;
			if (!(num <= 0f))
			{
				_body.AddForceAtPosition(-((Vector3)(ref damage.hitNormal)).normalized * num, damage.point, (ForceMode)1);
			}
		}
	}
}
[HarmonyPatch(typeof(FVRWristMenu2), "Awake")]
internal static class CustomSosigsWristMenuPatch
{
	private static void Postfix(FVRWristMenu2 __instance)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00cb: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || __instance.Sections == null || __instance.Sections.Count == 0 || (Object)(object)__instance.BaseButton == (Object)null || (Object)(object)Plugin.Instance == (Object)null)
		{
			return;
		}
		GameObject val = null;
		try
		{
			val = new GameObject("Custom Sosigs", new Type[1] { typeof(RectTransform) });
			RectTransform component = ((Component)__instance.Sections[0]).GetComponent<RectTransform>();
			RectTransform component2 = val.GetComponent<RectTransform>();
			((Transform)component2).SetParent(((Component)__instance.Sections[0]).transform.parent, false);
			if ((Object)(object)component != (Object)null)
			{
				component2.anchorMin = component.anchorMin;
				component2.anchorMax = component.anchorMax;
				component2.pivot = component.pivot;
				component2.anchoredPosition = component.anchoredPosition;
				component2.sizeDelta = component.sizeDelta;
				((Transform)component2).localRotation = ((Transform)component).localRotation;
				((Transform)component2).localScale = ((Transform)component).localScale;
			}
			CustomSosigsSection customSosigsSection = val.AddComponent<CustomSosigsSection>();
			((FVRWristMenuSection)customSosigsSection).Menu = __instance;
			((FVRWristMenuSection)customSosigsSection).ButtonText = "Custom Sosigs";
			customSosigsSection.Build(__instance.BaseButton);
			val.SetActive(false);
			__instance.Sections.Add((FVRWristMenuSection)(object)customSosigsSection);
			__instance.RegenerateButtons();
			Plugin.Log.LogInfo((object)("Registered Custom Sosigs Wrist Menu section with " + customSosigsSection.ModelCount + " installed model choices."));
		}
		catch (Exception ex)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
			Plugin.Log.LogError((object)("Could not register Custom Sosigs Wrist Menu section: " + ex));
		}
	}
}
internal sealed class CustomSosigsSection : FVRWristMenuSection
{
	private sealed class Choice
	{
		internal readonly string Id;

		internal readonly Text Label;

		internal Choice(string id, Text label)
		{
			Id = id;
			Label = label;
		}
	}

	private const int ChoiceColumns = 3;

	private const float ChoiceColumnSpacing = 115f;

	private const float ChoiceRowSpacing = 60f;

	private const float FirstChoiceRowY = 90f;

	private readonly List<Choice> _choices = new List<Choice>();

	private Text _armorToggleLabel;

	internal int ModelCount => Math.Max(0, _choices.Count - 2);

	internal void Build(GameObject template)
	{
		AddChoice(template, "Sosig", "Sosig");
		AddChoice(template, "Random", "Random");
		foreach (Plugin.RuntimeModel installedModel in Plugin.InstalledModels)
		{
			string label = (string.IsNullOrEmpty(installedModel.Addon.menuName) ? installedModel.Addon.displayName : installedModel.Addon.menuName);
			AddChoice(template, installedModel.Addon.id, label);
		}
		AddArmorToggle(template);
		RefreshSelection();
	}

	private void AddArmorToggle(GameObject template)
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00a1: 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_00bf: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Expected O, but got Unknown
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Expected O, but got Unknown
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(template, ((Component)this).transform, false);
		((Object)val).name = "Armor Hitbox Visibility Toggle";
		FVRWristMenuSectionButton component = val.GetComponent<FVRWristMenuSectionButton>();
		_armorToggleLabel = (((Object)(object)component != (Object)null) ? component.ButtonText : val.GetComponent<Text>());
		Button component2 = val.GetComponent<Button>();
		RectTransform component3 = val.GetComponent<RectTransform>();
		if ((Object)(object)_armorToggleLabel == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			throw new InvalidOperationException("H3VR wrist button template cannot create the armor hitbox toggle.");
		}
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		component3.pivot = val2;
		Vector2 anchorMin = (component3.anchorMax = val2);
		component3.anchorMin = anchorMin;
		component3.sizeDelta = new Vector2(108f, 55f);
		((Transform)component3).localScale = ((Transform)component3).localScale * 0.6f;
		int num = (_choices.Count + 3 - 1) / 3;
		component3.anchoredPosition = new Vector2(0f, 90f - (float)num * 60f);
		_armorToggleLabel.fontSize = 17;
		Image component4 = val.GetComponent<Image>();
		if ((Object)(object)component4 != (Object)null)
		{
			((Graphic)component4).color = new Color(0.08f, 0.22f, 0.35f, 0.9f);
		}
		component2.onClick = new ButtonClickedEvent();
		((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
		{
			Plugin.ToggleArmorHitboxes();
			RefreshSelection();
		});
		val.SetActive(true);
	}

	private void AddChoice(GameObject template, string id, string label)
	{
		//IL_00b9: 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_00c2: 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_00ca: 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_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Expected O, but got Unknown
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Expected O, but got Unknown
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: 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_0171: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(template, ((Component)this).transform, false);
		((Object)val).name = "Model Choice - " + id;
		FVRWristMenuSectionButton component = val.GetComponent<FVRWristMenuSectionButton>();
		Text val2 = (((Object)(object)component != (Object)null) ? component.ButtonText : val.GetComponent<Text>());
		Button component2 = val.GetComponent<Button>();
		RectTransform component3 = val.GetComponent<RectTransform>();
		if ((Object)(object)val2 == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			throw new InvalidOperationException("H3VR wrist button template is missing a Text, Button, or RectTransform.");
		}
		int count = _choices.Count;
		Vector2 val3 = default(Vector2);
		((Vector2)(ref val3))..ctor(0.5f, 0.5f);
		component3.pivot = val3;
		Vector2 anchorMin = (component3.anchorMax = val3);
		component3.anchorMin = anchorMin;
		component3.sizeDelta = new Vector2(108f, 55f);
		component3.anchoredPosition = new Vector2((float)(count % 3 - 1) * 115f, 90f - (float)(count / 3) * 60f);
		val2.text = label;
		if (label.Length > 7)
		{
			RectTransform rectTransform = ((Graphic)val2).rectTransform;
			if ((Object)(object)rectTransform != (Object)(object)component3)
			{
				rectTransform.anchorMin = Vector2.zero;
				rectTransform.anchorMax = Vector2.one;
				rectTransform.offsetMin = new Vector2(3f, 0f);
				rectTransform.offsetMax = new Vector2(-3f, 0f);
			}
			val2.fontSize = 14;
			val2.resizeTextForBestFit = true;
			val2.resizeTextMinSize = 10;
			val2.resizeTextMaxSize = 14;
			val2.horizontalOverflow = (HorizontalWrapMode)0;
			val2.verticalOverflow = (VerticalWrapMode)0;
		}
		component2.onClick = new ButtonClickedEvent();
		((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
		{
			Plugin.SelectModel(id);
			RefreshSelection();
		});
		val.SetActive(true);
		_choices.Add(new Choice(id, val2));
	}

	public override void Enable()
	{
		RefreshSelection();
	}

	private void RefreshSelection()
	{
		//IL_0058: 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_00c1: 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)
		foreach (Choice choice in _choices)
		{
			if ((Object)(object)choice.Label != (Object)null)
			{
				((Graphic)choice.Label).color = (Color)(string.Equals(choice.Id, Plugin.SelectedModel, StringComparison.OrdinalIgnoreCase) ? new Color(0.2f, 0.85f, 1f, 1f) : Color.white);
			}
		}
		if ((Object)(object)_armorToggleLabel != (Object)null)
		{
			_armorToggleLabel.text = "Armor Hitbox";
			((Graphic)_armorToggleLabel).color = (Color)(Plugin.ShowArmorHitboxes ? new Color(0.2f, 0.85f, 1f, 1f) : Color.white);
		}
	}
}
internal sealed class LocomotionClock
{
	public bool Walking { get; private set; }

	public float Weight { get; private set; }

	public float Phase { get; private set; }

	public void Advance(float speed, float deltaTime, bool controlled, bool crouched)
	{
		if (!(deltaTime <= 0f) && !float.IsNaN(speed) && !float.IsInfinity(speed))
		{
			speed = Math.Max(0f, speed);
			if (!controlled || speed < 0.08f)
			{
				Walking = false;
			}
			else if (speed > 0.18f)
			{
				Walking = true;
			}
			float num = (Walking ? 1f : 0f);
			float num2 = deltaTime * 5f;
			Weight += Math.Max(0f - num2, Math.Min(num2, num - Weight));
			if (controlled && Walking)
			{
				Phase += deltaTime * speed / (crouched ? 0.85f : 1.4f);
			}
		}
	}
}
[Serializable]
internal sealed class ModelAddon
{
	public int schemaVersion;

	public string id;

	public string displayName;

	public string menuName;

	public string impactEffect;

	public string bloodMask;

	public string bloodNoise;

	public string mesh;

	public float heightMeters = 1.72f;

	public float armorHitboxScale = 1f;

	public AddonMaterial[] materials;

	public AddonAnimation[] animations;

	public BoneAlias[] boneAliases;

	public AddonSurface surface;

	public EyeDefinition eyes;

	[NonSerialized]
	public string DirectoryPath;

	public string AssetPath(string relative)
	{
		if (string.IsNullOrEmpty(relative) || Path.IsPathRooted(relative))
		{
			throw new IOException("Invalid addon asset path: " + relative);
		}
		string text = Path.GetFullPath(DirectoryPath).TrimEnd(new char[1] { Path.DirectorySeparatorChar });
		char directorySeparatorChar = Path.DirectorySeparatorChar;
		string text2 = text + directorySeparatorChar;
		string fullPath = Path.GetFullPath(Path.Combine(text2, relative));
		if (!fullPath.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
		{
			throw new IOException("Addon asset escapes its package: " + relative);
		}
		if (!File.Exists(fullPath))
		{
			throw new FileNotFoundException("Addon asset missing: " + relative, fullPath);
		}
		return fullPath;
	}

	public string AnimationPath(string legacyName)
	{
		string text = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(legacyName));
		if (text.StartsWith("mixamo_"))
		{
			text = text.Substring(7);
		}
		else if (text.StartsWith("lpsp_"))
		{
			text = text.Substring(5);
		}
		AddonAnimation[] array = animations;
		foreach (AddonAnimation addonAnimation in array)
		{
			if (addonAnimation.role == text)
			{
				return AssetPath(addonAnimation.file);
			}
		}
		throw new IOException("Addon '" + id + "' is missing animation role '" + text + "'.");
	}

	public string CanonicalBone(string source)
	{
		if (boneAliases != null)
		{
			BoneAlias[] array = boneAliases;
			foreach (BoneAlias boneAlias in array)
			{
				if (boneAlias.source == source)
				{
					return "ValveBiped.Bip01_" + boneAlias.role;
				}
			}
		}
		return source;
	}

	public void Validate()
	{
		if (schemaVersion != 1 || string.IsNullOrEmpty(id) || string.IsNullOrEmpty(displayName))
		{
			throw new IOException("Invalid addon schema/id/name.");
		}
		if (heightMeters < 0.5f || heightMeters > 3f)
		{
			throw new IOException("Addon height must be 0.5-3m.");
		}
		if (armorHitboxScale == 0f)
		{
			armorHitboxScale = 1f;
		}
		if (armorHitboxScale < 0.25f || armorHitboxScale > 1.5f)
		{
			throw new IOException("Addon armorHitboxScale must be between 0.25 and 1.5.");
		}
		if (!string.IsNullOrEmpty(impactEffect) && !string.Equals(impactEffect, "native", StringComparison.OrdinalIgnoreCase) && !string.Equals(impactEffect, "meat", StringComparison.OrdinalIgnoreCase))
		{
			throw new IOException("Addon impactEffect must be 'native' or 'meat'.");
		}
		if (!string.IsNullOrEmpty(bloodMask))
		{
			AssetPath(bloodMask);
		}
		if (!string.IsNullOrEmpty(bloodNoise))
		{
			AssetPath(bloodNoise);
		}
		AssetPath(mesh);
		if (materials == null || materials.Length == 0 || animations == null)
		{
			throw new IOException("Addon materials/animations missing.");
		}
		if (surface != null && (surface.smoothness < 0f || surface.smoothness > 1f || surface.metallic < 0f || surface.metallic > 1f))
		{
			throw new IOException("Addon surface smoothness/metallic must be between 0 and 1.");
		}
		AddonMaterial[] array = materials;
		foreach (AddonMaterial addonMaterial in array)
		{
			AssetPath(addonMaterial.albedo);
			if (!string.IsNullOrEmpty(addonMaterial.normal))
			{
				AssetPath(addonMaterial.normal);
			}
		}
		HashSet<string> hashSet = new HashSet<string>();
		AddonAnimation[] array2 = animations;
		foreach (AddonAnimation addonAnimation in array2)
		{
			if (string.IsNullOrEmpty(addonAnimation.role) || !hashSet.Add(addonAnimation.role))
			{
				throw new IOException("Duplicate/invalid animation role.");
			}
			AssetPath(addonAnimation.file);
		}
		if (eyes != null && eyes.enabled && (eyes.materialIndex < 0 || eyes.materialIndex >= materials.Length || eyes.centers == null || eyes.centers.Length == 0 || eyes.radiusU <= 0f || eyes.radiusV <= 0f))
		{
			throw new IOException("Invalid addon eye definition.");
		}
		if (eyes == null || eyes.centers == null)
		{
			return;
		}
		EyeCenter[] centers = eyes.centers;
		foreach (EyeCenter eyeCenter in centers)
		{
			if (eyeCenter.u - eyes.radiusU < 0f || eyeCenter.u + eyes.radiusU > 1f || eyeCenter.v - eyes.radiusV < 0f || eyeCenter.v + eyes.radiusV > 1f)
			{
				throw new IOException("Eye regions must fit the normalized UV tile.");
			}
		}
	}

	public void ValidateSkeleton(RuntimeSkinnedAsset asset)
	{
		HashSet<string> hashSet = new HashSet<string>();
		RuntimeSkinnedAsset.BoneDefinition[] bones = asset.Bones;
		foreach (RuntimeSkinnedAsset.BoneDefinition boneDefinition in bones)
		{
			if (!hashSet.Add(boneDefinition.Name))
			{
				throw new IOException("Duplicate canonical skeleton bone: " + boneDefinition.Name);
			}
		}
		string[] array = new string[20]
		{
			"Pelvis", "Spine", "Spine1", "Spine2", "Neck1", "Head1", "L_Clavicle", "L_UpperArm", "L_Forearm", "L_Hand",
			"R_Clavicle", "R_UpperArm", "R_Forearm", "R_Hand", "L_Thigh", "L_Calf", "L_Foot", "R_Thigh", "R_Calf", "R_Foot"
		};
		foreach (string text in array)
		{
			if (!hashSet.Contains("ValveBiped.Bip01_" + text))
			{
				throw new IOException("Humanoid bone role missing: " + text + ". Add boneAliases or fix the skeleton.");
			}
		}
		RuntimeSkinnedAsset.MeshDefinition[] meshes = asset.Meshes;
		foreach (RuntimeSkinnedAsset.MeshDefinition meshDefinition in meshes)
		{
			if (meshDefinition.MaterialIndex < 0 || meshDefinition.MaterialIndex >= materials.Length)
			{
				throw new IOException("Model material index is absent from addon manifest.");
			}
		}
	}

	public static Dictionary<string, ModelAddon> Discover(string pluginRoot)
	{
		Dictionary<string, ModelAddon> dictionary = new Dictionary<string, ModelAddon>(StringComparer.OrdinalIgnoreCase);
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		string[] files = Directory.GetFiles(pluginRoot, "customsosig-model.json", SearchOption.AllDirectories);
		foreach (string text in files)
		{
			try
			{
				ModelAddon modelAddon = JsonUtility.FromJson<ModelAddon>(File.ReadAllText(text));
				if (modelAddon == null)
				{
					throw new IOException("Empty manifest.");
				}
				modelAddon.DirectoryPath = Path.GetDirectoryName(text);
				modelAddon.Validate();
				if (dictionary.ContainsKey(modelAddon.id))
				{
					hashSet.Add(modelAddon.id);
					Plugin.Log.LogError((object)("Duplicate model addon id: " + modelAddon.id));
					continue;
				}
				dictionary.Add(modelAddon.id, modelAddon);
				Plugin.Log.LogInfo((object)("Discovered model addon: " + modelAddon.id + " (" + modelAddon.displayName + ")."));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Rejected addon " + text + ": " + ex.Message));
			}
		}
		foreach (string item in hashSet)
		{
			dictionary.Remove(item);
		}
		return dictionary;
	}

	public static ModelAddon Find(string pluginRoot, string selectedId)
	{
		if (!Discover(pluginRoot).TryGetValue(selectedId, out var value))
		{
			throw new IOException("Selected model addon '" + selectedId + "' is unavailable or duplicated. Install it or change Models.ActiveModel; vanilla Sosigs will be preserved.");
		}
		return value;
	}
}
[Serializable]
internal sealed class AddonMaterial
{
	public string name;

	public string albedo;

	public string normal;
}
[Serializable]
internal sealed class AddonSurface
{
	public float smoothness = 0.5f;

	public float metallic;
}
[Serializable]
internal sealed class AddonAnimation
{
	public string role;

	public string file;
}
[Serializable]
internal sealed class BoneAlias
{
	public string source;

	public string role;
}
[Serializable]
internal sealed class EyeDefinition
{
	public bool enabled;

	public int materialIndex;

	public float radiusU;

	public float radiusV;

	public float darkThreshold = 0.42f;

	public EyeCenter[] centers;
}
[Serializable]
internal sealed class EyeCenter
{
	public float u;

	public float v;
}
internal static class ModelArmorEnvelope
{
	internal struct Shape
	{
		internal readonly float CenterY;

		internal readonly float Radius;

		internal readonly float Height;

		internal readonly int VertexCount;

		internal Shape(float centerY, float radius, float height, int vertexCount)
		{
			CenterY = centerY;
			Radius = radius;
			Height = height;
			VertexCount = vertexCount;
		}
	}

	private sealed class Segment
	{
		internal string Label;

		internal string Start;

		internal string End;

		internal bool Armor;

		internal Vector3 Origin;

		internal Vector3 Axis;

		internal float Minimum = float.MaxValue;

		internal float Maximum = float.MinValue;

		internal float Radius;

		internal int Count;

		internal Segment(string label, string start, string end, bool armor)
		{
			Label = label;
			Start = start;
			End = end;
			Armor = armor;
		}
	}

	private const string Prefix = "ValveBiped.Bip01_";

	private const float SkinClearance = 0.035f;

	internal static Dictionary<string, Shape> Build(RuntimeSkinnedAsset asset)
	{
		//IL_015e: 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_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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: 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_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: 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_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0402: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_040c: Unknown result type (might be due to invalid IL or missing references)
		Dictionary<string, Shape> dictionary = new Dictionary<string, Shape>();
		if (asset == null || asset.Bones == null || asset.Meshes == null)
		{
			return dictionary;
		}
		Segment[] array = new Segment[11]
		{
			new Segment("Hips", "Pelvis", "Spine2", armor: true),
			new Segment("Chest", "Spine2", "Neck1", armor: true),
			new Segment("Head", "Head1", null, armor: true),
			new Segment("LeftUpperArm", "L_UpperArm", "L_Forearm", armor: false),
			new Segment("LeftLowerArm", "L_Forearm", "L_Hand", armor: false),
			new Segment("RightUpperArm", "R_UpperArm", "R_Forearm", armor: false),
			new Segment("RightLowerArm", "R_Forearm", "R_Hand", armor: false),
			new Segment("LeftUpperLeg", "L_Thigh", "L_Calf", armor: true),
			new Segment("LeftLowerLeg", "L_Calf", "L_Foot", armor: true),
			new Segment("RightUpperLeg", "R_Thigh", "R_Calf", armor: true),
			new Segment("RightLowerLeg", "R_Calf", "R_Foot", armor: true)
		};
		Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
		Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[asset.Bones.Length];
		for (int i = 0; i < asset.Bones.Length; i++)
		{
			RuntimeSkinnedAsset.BoneDefinition boneDefinition = asset.Bones[i];
			dictionary2[boneDefinition.Name] = i;
			Matrix4x4 val = Matrix4x4.TRS(boneDefinition.LocalPosition, boneDefinition.LocalRotation, boneDefinition.LocalScale);
			array2[i] = ((boneDefinition.ParentIndex >= 0) ? (array2[boneDefinition.ParentIndex] * val) : val);
		}
		Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
		Vector3 val2;
		for (int j = 0; j < array.Length; j++)
		{
			Segment segment = array[j];
			if (dictionary2.TryGetValue("ValveBiped.Bip01_" + segment.Start, out var value))
			{
				dictionary3[value] = j;
				segment.Origin = ((Matrix4x4)(ref array2[value])).MultiplyPoint3x4(Vector3.zero);
				int value2;
				if (segment.End == null)
				{
					val2 = ((Matrix4x4)(ref array2[value])).MultiplyVector(Vector3.up);
					segment.Axis = ((Vector3)(ref val2)).normalized;
				}
				else if (dictionary2.TryGetValue("ValveBiped.Bip01_" + segment.End, out value2))
				{
					val2 = ((Matrix4x4)(ref array2[value2])).MultiplyPoint3x4(Vector3.zero) - segment.Origin;
					segment.Axis = ((Vector3)(ref val2)).normalized;
				}
			}
		}
		int[] array3 = new int[asset.Bones.Length];
		for (int k = 0; k < array3.Length; k++)
		{
			array3[k] = -1;
			for (int num = k; num >= 0; num = asset.Bones[num].ParentIndex)
			{
				if (dictionary3.TryGetValue(num, out var value3))
				{
					array3[k] = value3;
					break;
				}
			}
		}
		RuntimeSkinnedAsset.MeshDefinition[] meshes = asset.Meshes;
		foreach (RuntimeSkinnedAsset.MeshDefinition obj in meshes)
		{
			Vector3[] vertices = obj.Mesh.vertices;
			BoneWeight[] boneWeights = obj.Mesh.boneWeights;
			for (int m = 0; m < vertices.Length; m++)
			{
				BoneWeight val3 = boneWeights[m];
				int num2 = ((BoneWeight)(ref val3)).boneIndex0;
				float num3 = ((BoneWeight)(ref val3)).weight0;
				if (((BoneWeight)(ref val3)).weight1 > num3)
				{
					num2 = ((BoneWeight)(ref val3)).boneIndex1;
					num3 = ((BoneWeight)(ref val3)).weight1;
				}
				if (((BoneWeight)(ref val3)).weight2 > num3)
				{
					num2 = ((BoneWeight)(ref val3)).boneIndex2;
					num3 = ((BoneWeight)(ref val3)).weight2;
				}
				if (((BoneWeight)(ref val3)).weight3 > num3)
				{
					num2 = ((BoneWeight)(ref val3)).boneIndex3;
				}
				if (num2 < 0 || num2 >= array3.Length)
				{
					continue;
				}
				int num4 = array3[num2];
				if (num4 >= 0)
				{
					Segment segment2 = array[num4];
					if (segment2.Armor && !(((Vector3)(ref segment2.Axis)).sqrMagnitude < 0.9f))
					{
						Vector3 val4 = vertices[m] - segment2.Origin;
						float num5 = Vector3.Dot(val4, segment2.Axis);
						val2 = val4 - segment2.Axis * num5;
						float magnitude = ((Vector3)(ref val2)).magnitude;
						segment2.Minimum = Mathf.Min(segment2.Minimum, num5);
						segment2.Maximum = Mathf.Max(segment2.Maximum, num5);
						segment2.Radius = Mathf.Max(segment2.Radius, magnitude);
						segment2.Count++;
					}
				}
			}
		}
		Segment[] array4 = array;
		foreach (Segment segment3 in array4)
		{
			if (segment3.Armor && segment3.Count >= 16)
			{
				float radius = segment3.Radius + 0.035f;
				float height = segment3.Maximum - segment3.Minimum + 0.07f;
				dictionary[segment3.Label] = new Shape((segment3.Minimum + segment3.Maximum) * 0.5f, radius, height, segment3.Count);
			}
		}
		return dictionary;
	}
}
[BepInPlugin("NotGodlike.h3vr.customsosigmodelframework", "CustomSosigModelFramework", "1.2.7")]
public sealed class Plugin : BaseUnityPlugin
{
	internal sealed class RuntimeModel
	{
		internal readonly ModelAddon Addon;

		internal readonly RuntimeSkinnedAsset Asset;

		internal readonly AnimationSet Animations;

		internal readonly Material[] Materials;

		internal readonly Material EyeMaterial;

		internal readonly BloodImpactVfx BloodVfx;

		internal RuntimeModel(ModelAddon addon, RuntimeSkinnedAsset asset, AnimationSet animations, Material[] materials, Material eyeMaterial, BloodImpactVfx bloodVfx)
		{
			Addon = addon;
			Asset = asset;
			Animations = animations;
			Materials = materials;
			EyeMaterial = eyeMaterial;
			BloodVfx = bloodVfx;
		}
	}

	internal sealed class Settings
	{
		public bool Enabled;

		public bool HideOriginal;

		public bool UseCustomHitboxes;

		public float Height;

		public float FeetBelowLowerLink;

		public float YawDegrees;

		public string ColorHex;

		public float Metallic;

		public float Smoothness;

		public bool UseNormalMaps;

		public bool BlueEyeEmission;

		public float EyeEmissionIntensity;

		public float FollowSharpness;

		public bool EnableProceduralMotion;

		public float BobMeters;

		public float SwayDegrees;

		public float GaitDegrees;

		public float HandIkWeight;

		public float JointLimitWeight;

		public bool DriveHeldWeaponsFromAnimation;

		public float HandTargetFollowSharpness;
	}

	internal sealed class AnimationSet
	{
		public readonly Dictionary<string, RuntimeBoneClip> CombatMotion = new Dictionary<string, RuntimeBoneClip>();

		public readonly RuntimeBoneClip Walk;

		public readonly RuntimeBoneClip Backwards;

		public readonly RuntimeBoneClip StrafeLeft;

		public readonly RuntimeBoneClip StrafeRight;

		public readonly RuntimeBoneClip StrafeLeftFast;

		public readonly RuntimeBoneClip StrafeRightFast;

		public readonly RuntimeBoneClip Hit;

		public readonly RuntimeBoneClip Death;

		public readonly RuntimeBoneClip CrouchIdle;

		public readonly RuntimeBoneClip CrouchForwardLeft;

		public readonly RuntimeBoneClip CrouchForwardRight;

		public readonly RuntimeBoneClip CrouchLeft;

		public readonly RuntimeBoneClip CrouchBackward;

		public readonly RuntimeBoneClip StandToCrouch;

		public readonly RuntimeBoneClip CrouchToStand;

		public readonly RuntimeBoneClip Falling;

		public RuntimeBoneClip KnockedDown;

		public readonly RuntimeBoneClip RelaxedIdle;

		public readonly RuntimeBoneClip RifleIdle;

		public readonly RuntimeBoneClip RifleAim;

		public readonly RuntimeBoneClip RifleFire;

		public readonly RuntimeBoneClip RifleReload;

		public readonly RuntimeBoneClip HandgunIdle;

		public readonly RuntimeBoneClip HandgunAim;

		public readonly RuntimeBoneClip HandgunFire;

		public readonly RuntimeBoneClip HandgunReload;

		public AnimationSet(RuntimeBoneClip walk, RuntimeBoneClip backwards, RuntimeBoneClip strafeLeft, RuntimeBoneClip strafeRight, RuntimeBoneClip strafeLeftFast, RuntimeBoneClip strafeRightFast, RuntimeBoneClip hit, RuntimeBoneClip death, RuntimeBoneClip crouchIdle, RuntimeBoneClip crouchForwardLeft, RuntimeBoneClip crouchForwardRight, RuntimeBoneClip crouchLeft, RuntimeBoneClip crouchBackward, RuntimeBoneClip standToCrouch, RuntimeBoneClip crouchToStand, RuntimeBoneClip falling, RuntimeBoneClip relaxedIdle, RuntimeBoneClip rifleIdle, RuntimeBoneClip rifleAim, RuntimeBoneClip rifleFire, RuntimeBoneClip rifleReload, RuntimeBoneClip handgunIdle, RuntimeBoneClip handgunAim, RuntimeBoneClip handgunFire, RuntimeBoneClip handgunReload)
		{
			Walk = walk;
			Backwards = backwards;
			StrafeLeft = strafeLeft;
			StrafeRight = strafeRight;
			StrafeLeftFast = strafeLeftFast;
			StrafeRightFast = strafeRightFast;
			Hit = hit;
			Death = death;
			CrouchIdle = crouchIdle;
			CrouchForwardLeft = crouchForwardLeft;
			CrouchForwardRight = crouchForwardRight;
			CrouchLeft = crouchLeft;
			CrouchBackward = crouchBackward;
			StandToCrouch = standToCrouch;
			CrouchToStand = crouchToStand;
			Falling = falling;
			RelaxedIdle = relaxedIdle;
			RifleIdle = rifleIdle;
			RifleAim = rifleAim;
			RifleFire = rifleFire;
			RifleReload = rifleReload;
			HandgunIdle = handgunIdle;
			HandgunAim = handgunAim;
			HandgunFire = handgunFire;
			HandgunReload = handgunReload;
		}
	}

	public const string PluginGuid = "NotGodlike.h3vr.customsosigmodelframework";

	public const string PluginName = "CustomSosigModelFramework";

	public const string PluginVersion = "1.2.7";

	internal const string VanillaMode = "Sosig";

	internal const string RandomMode = "Random";

	internal static ModelAddon ActiveAddon;

	internal static Material EyeSurfaceMaterial;

	internal static ManualLogSource Log;

	internal static RuntimeSkinnedAsset SkinnedAsset;

	internal static AnimationSet Animations;

	internal static Material[] SharedMaterials;

	internal static Settings RuntimeSettings;

	internal static Plugin Instance;

	private static readonly Dictionary<string, RuntimeModel> Models = new Dictionary<string, RuntimeModel>(StringComparer.OrdinalIgnoreCase);

	private static readonly List<RuntimeModel> RandomPool = new List<RuntimeModel>();

	private ConfigEntry<string> _selectedModel;

	private ConfigEntry<bool> _showArmorHitboxes;

	private Material _armorOverlayMaterial;

	private readonly Dictionary<MatDef, MatDef> _silentImpactMaterials = new Dictionary<MatDef, MatDef>();

	private GameObject _silentMustardBurst;

	private bool _armorOverlayShaderWarningLogged;

	private int _selectionRevision;

	private Harmony _harmony;

	internal static bool HasModels => Models.Count > 0;

	internal static string SelectedModel
	{
		get
		{
			if (!((Object)(object)Instance != (Object)null) || Instance._selectedModel == null)
			{
				return "Sosig";
			}
			return Instance._selectedModel.Value;
		}
	}

	internal static bool ShowArmorHitboxes
	{
		get
		{
			if ((Object)(object)Instance != (Object)null && Instance._showArmorHitboxes != null)
			{
				return Instance._showArmorHitboxes.Value;
			}
			return false;
		}
	}

	internal static IEnumerable<RuntimeModel> InstalledModels => RandomPool;

	internal static GameObject SilentMustardBurst
	{
		get
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				return null;
			}
			if ((Object)(object)Instance._silentMustardBurst == (Object)null)
			{
				GameObject val = new GameObject("Custom Sosig silent mustard burst template");
				val.transform.SetParent(((Component)Instance).transform, false);
				val.transform.localPosition = Vector3.zero;
				val.AddComponent<SilentMustardBurst>();
				Instance._silentMustardBurst = val;
			}
			return Instance._silentMustardBurst;
		}
	}

	private void Awake()
	{
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		RuntimeSettings = BindSettings();
		_selectedModel = ((BaseUnityPlugin)this).Config.Bind<string>("Models", "ActiveModel", "NotGodlike.metrocop", "Wrist Menu selection: Sosig, Random, or an installed model addon ID.");
		_showArmorHitboxes = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "ShowArmorHitboxes", false, "Show translucent blue protection zones on custom Sosig models. Toggle in Wrist Menu > Custom Sosigs.");
		if (!RuntimeSettings.Enabled)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"CustomSosigModelFramework is disabled in config.");
			return;
		}
		try
		{
			Models.Clear();
			RandomPool.Clear();
			foreach (ModelAddon value in ModelAddon.Discover(Paths.PluginPath).Values)
			{
				try
				{
					RuntimeModel runtimeModel = LoadModel(value);
					Models.Add(value.id, runtimeModel);
					RandomPool.Add(runtimeModel);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Rejected model addon '" + value.id + "' during loading: " + ex));
				}
			}
			RandomPool.Sort((RuntimeModel left, RuntimeModel right) => string.Compare(left.Addon.id, right.Addon.id, StringComparison.OrdinalIgnoreCase));
			if (!IsValidSelection(_selectedModel.Value))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Selected model '" + _selectedModel.Value + "' is unavailable; using vanilla Sosigs. The missing addon will not appear in Wrist Menu."));
				_selectedModel.Value = "Sosig";
			}
			_harmony = new Harmony("NotGodlike.h3vr.customsosigmodelframework");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("CustomSosigModelFramework loaded " + Models.Count + " model addons. Selected mode: " + _selectedModel.Value + "."));
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to initialize CustomSosigModelFramework: " + ex2));
			((Behaviour)this).enabled = false;
		}
	}

	private RuntimeModel LoadModel(ModelAddon addon)
	{
		ActiveAddon = addon;
		EyeSurfaceMaterial = null;
		SkinnedAsset = RuntimeSkinnedAsset.Load(ActiveAddon.AssetPath(ActiveAddon.mesh), addon);
		ActiveAddon.ValidateSkeleton(SkinnedAsset);
		Animations = new AnimationSet(RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_walk.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_backward.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_strafe_left.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_strafe_right.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_strafe_left_fast.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_strafe_right_fast.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_hit.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_death.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_idle.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_forward_left.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_forward_right.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_left.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_backward.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_stand_to_crouch.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_crouch_to_stand.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_falling.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_relaxed_idle.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_rifle_idle.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_rifle_aim.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_rifle_fire.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_rifle_reload.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_handgun_idle.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_handgun_aim.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_handgun_fire.csanim.gz"), SkinnedAsset.Bones.Length), RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_handgun_reload.csanim.gz"), SkinnedAsset.Bones.Length));
		SharedMaterials = CreateMaterials(RuntimeSettings.UseNormalMaps, RuntimeSettings.Metallic, RuntimeSettings.Smoothness);
		Animations.KnockedDown = RuntimeBoneClip.Load(ActiveAddon.AnimationPath("mixamo_knocked_down.csanim.gz"), SkinnedAsset.Bones.Length);
		string[] array = new string[9] { "rifle_jog", "handgun_jog", "jog_forward", "jog_backward", "jog_left_forward", "jog_right_forward", "jog_left_backward", "jog_right_backward", "breathing" };
		foreach (string text in array)
		{
			Animations.CombatMotion.Add(text, RuntimeBoneClip.Load(ActiveAddon.AnimationPath("lpsp_" + text + ".csanim.gz"), SkinnedAsset.Bones.Length));
		}
		BloodImpactVfx bloodImpactVfx = null;
		if (string.Equals(addon.impactEffect, "meat", StringComparison.OrdinalIgnoreCase))
		{
			bloodImpactVfx = ((Component)this).gameObject.AddComponent<BloodImpactVfx>();
			bloodImpactVfx.Initialize(string.IsNullOrEmpty(addon.bloodMask) ? null : addon.AssetPath(addon.bloodMask), string.IsNullOrEmpty(addon.bloodNoise) ? null : addon.AssetPath(addon.bloodNoise));
		}
		ModelArmorEnvelope.Shape value = default(ModelArmorEnvelope.Shape);
		bool flag = SkinnedAsset.ArmorEnvelopes != null && SkinnedAsset.ArmorEnvelopes.TryGetValue("Chest", out value);
		ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
		string[] obj = new string[10]
		{
			"Loaded ",
			ActiveAddon.displayName,
			" rig with ",
			SkinnedAsset.Bones.Length.ToString(),
			" bones, ",
			SkinnedAsset.Meshes.Length.ToString(),
			" mesh primitives, and ",
			((SkinnedAsset.ArmorEnvelopes != null) ? SkinnedAsset.ArmorEnvelopes.Count : 0).ToString(),
			" adaptive armor zones",
			null
		};
		object obj2;
		if (!flag)
		{
			obj2 = ".";
		}
		else
		{
			float radius = value.Radius;
			obj2 = " (chest radius " + radius.ToString("F3") + "m).";
		}
		obj[9] = (string)obj2;
		logger.LogInfo((object)string.Concat(obj));
		return new RuntimeModel(addon, SkinnedAsset, Animations, SharedMaterials, EyeSurfaceMaterial, bloodImpactVfx);
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		if ((Object)(object)_armorOverlayMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_armorOverlayMaterial);
		}
		foreach (MatDef value in _silentImpactMaterials.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
		}
		_silentImpactMaterials.Clear();
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	internal static MatDef GetSilentImpactMaterial(MatDef source)
	{
		//IL_005f: 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)
		if ((Object)(object)Instance == (Object)null)
		{
			return source;
		}
		if ((Object)(object)source == (Object)null)
		{
			source = PM.DefaultMatDef;
		}
		if ((Object)(object)source == (Object)null)
		{
			return null;
		}
		if (Instance._silentImpactMaterials.TryGetValue(source, out var value))
		{
			return value;
		}
		value = Object.Instantiate<MatDef>(source);
		((Object)value).name = ((Object)source).name + " - Custom Sosig silent impact";
		value.ImpactEffectType = (BallisticImpactEffectType)(-1);
		value.BulletHoleType = (BulletHoleDecalType)0;
		Instance._silentImpactMaterials.Add(source, value);
		return value;
	}

	internal static void SpawnBloodImpact(string addonId, Vector3 point, Vector3 normal)
	{
		//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)
		if (addonId != null && Models.TryGetValue(addonId, out var value) && (Object)(object)value.BloodVfx != (Object)null)
		{
			value.BloodVfx.Spawn(point, normal);
		}
	}

	internal static bool IsSilentMustardBurstTemplate(GameObject candidate)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			return (Object)(object)candidate == (Object)(object)Instance._silentMustardBurst;
		}
		return false;
	}

	internal static Material GetArmorOverlayMaterial()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Instance == (Object)null)
		{
			return null;
		}
		if ((Object)(object)Instance._armorOverlayMaterial != (Object)null)
		{
			return Instance._armorOverlayMaterial;
		}
		Shader val = Shader.Find("Hidden/Internal-Colored");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Transparent");
		}
		if ((Object)(object)val == (Object)null)
		{
			if (!Instance._armorOverlayShaderWarningLogged)
			{
				Instance._armorOverlayShaderWarningLogged = true;
				Log.LogWarning((object)"No transparent shader is available for armor hitbox overlays.");
			}
			return null;
		}
		Material val2 = new Material(val);
		((Object)val2).name = "Custom Sosig translucent blue armor hitboxes";
		val2.color = new Color(0.03f, 0.38f, 1f, 0.28f);
		val2.SetInt("_SrcBlend", 5);
		val2.SetInt("_DstBlend", 10);
		val2.SetInt("_Cull", 0);
		val2.SetInt("_ZWrite", 0);
		val2.SetInt("_ZTest", 8);
		val2.renderQueue = 4000;
		Instance._armorOverlayMaterial = val2;
		return val2;
	}

	internal static void ToggleArmorHitboxes()
	{
		if ((Object)(object)Instance == (Object)null || Instance._showArmorHitboxes == null)
		{
			return;
		}
		Instance._showArmorHitboxes.Value = !Instance._showArmorHitboxes.Value;
		((BaseUnityPlugin)Instance).Config.Save();
		SosigVisualProxy[] array = Object.FindObjectsOfType<SosigVisualProxy>();
		foreach (SosigVisualProxy sosigVisualProxy in array)
		{
			if ((Object)(object)sosigVisualProxy != (Object)null)
			{
				sosigVisualProxy.RefreshArmorOverlays();
			}
		}
		Log.LogInfo((object)("Armor hitbox visualization: " + (ShowArmorHitboxes ? "on" : "off") + "."));
	}

	private static bool IsValidSelection(string id)
	{
		if (string.IsNullOrEmpty(id))
		{
			return false;
		}
		if (!string.Equals(id, "Sosig", StringComparison.OrdinalIgnoreCase) && !string.Equals(id, "Random", StringComparison.OrdinalIgnoreCase))
		{
			return Models.ContainsKey(id);
		}
		return true;
	}

	internal static void SelectModel(string id)
	{
		if ((Object)(object)Instance == (Object)null || !IsValidSelection(id) || string.Equals(SelectedModel, id, StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		Instance._selectedModel.Value = id;
		((BaseUnityPlugin)Instance).Config.Save();
		int revision = ++Instance._selectionRevision;
		Sosig[] array = Object.FindObjectsOfType<Sosig>();
		Sosig[] array2 = array;
		foreach (Sosig val in array2)
		{
			if (!((Object)(object)val == (Object)null))
			{
				SosigVisualProxy component = ((Component)val).GetComponent<SosigVisualProxy>();
				if ((Object)(object)component != (Object)null)
				{
					component.Detach();
					Object.Destroy((Object)(object)component);
				}
			}
		}
		if (!string.Equals(id, "Sosig", StringComparison.OrdinalIgnoreCase))
		{
			((MonoBehaviour)Instance).StartCoroutine(Instance.AttachExistingNextFrame(array, revision));
		}
		Log.LogInfo((object)("Wrist Menu selected " + id + "; updated " + array.Length + " existing Sosigs."));
	}

	private IEnumerator AttachExistingNextFrame(Sosig[] sosigs, int revision)
	{
		yield return null;
		if (revision != _selectionRevision)
		{
			yield break;
		}
		foreach (Sosig val in sosigs)
		{
			if ((Object)(object)val != (Object)null)
			{
				TryAttachProxy(val, "Wrist Menu");
			}
		}
	}

	internal static void TryAttachProxy(Sosig sosig, string spawnSource)
	{
		if ((Object)(object)sosig == (Object)null || RuntimeSettings == null || !RuntimeSettings.Enabled || string.Equals(SelectedModel, "Sosig", StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		SosigVisualProxy sosigVisualProxy = null;
		try
		{
			if ((Object)(object)((Component)sosig).GetComponent<SosigVisualProxy>() != (Object)null)
			{
				return;
			}
			RuntimeModel value;
			if (string.Equals(SelectedModel, "Random", StringComparison.OrdinalIgnoreCase))
			{
				if (RandomPool.Count == 0)
				{
					return;
				}
				value = RandomPool[Random.Range(0, RandomPool.Count)];
			}
			else if (!Models.TryGetValue(SelectedModel, out value))
			{
				return;
			}
			sosigVisualProxy = ((Component)sosig).gameObject.AddComponent<SosigVisualProxy>();
			sosigVisualProxy.Initialize(sosig, value.Asset, value.Animations, value.Materials, value.EyeMaterial, value.Addon.displayName, value.Addon.heightMeters, value.Addon.armorHitboxScale, RuntimeSettings, string.Equals(value.Addon.impactEffect, "meat", StringComparison.OrdinalIgnoreCase), value.Addon.id);
			Log.LogInfo((object)("Attached custom visual proxy to Sosig '" + ((Object)sosig).name + "' via " + spawnSource + "."));
		}
		catch (Exception ex)
		{
			if ((Object)(object)sosigVisualProxy != (Object)null)
			{
				sosigVisualProxy.Detach();
				Object.Destroy((Object)(object)sosigVisualProxy);
			}
			Log.LogError((object)("Could not attach a custom visual to Sosig '" + ((Object)sosig).name + "' via " + spawnSource + ": " + ex));
		}
	}

	private Settings BindSettings()
	{
		return new Settings
		{
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replace every newly spawned Sosig visual.").Value,
			HideOriginal = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideOriginal", true, "Hide vanilla Sosig body and wearable renderers, but keep held weapons visible.").Value,
			UseCustomHitboxes = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseCustomHitboxes", true, "Put COD Zombies-style damage hitboxes on the animated custom skeleton.").Value,
			Height = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "HeightMeters", 1.72f, "Rendered custom model height in meters.").Value,
			FeetBelowLowerLink = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "FeetBelowLowerLink", 0.43f, "Distance from the lower Sosig link center to the model feet.").Value,
			YawDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "YawDegrees", 0f, "Extra rotation around the model's vertical axis.").Value,
			ColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "Color", "#FFFFFF", "RGB or RGBA tint applied over the Model addon textures.").Value,
			Metallic = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "Metallic", 0.2f, "Standard shader metallic value.").Value,
			Smoothness = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "Smoothness", 0.72f, "Standard shader smoothness value.").Value,
			UseNormalMaps = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "UseNormalMaps", true, "Load the supplied body and mask normal maps.").Value,
			BlueEyeEmission = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "BlueEyeEmission", true, "Enable blue emissive Model addon eye lenses; bloom depends on the game camera.").Value,
			EyeEmissionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "EyeEmissionIntensity", 3f, "Blue lens emission intensity. Does not add scene lights.").Value,
			FollowSharpness = ((BaseUnityPlugin)this).Config.Bind<float>("Motion", "FollowSharpness", 28f, "How quickly the proxy follows the Sosig links.").Value,
			EnableProceduralMotion = ((BaseUnityPlugin)this).Config.Bind<bool>("Motion", "EnableProceduralMotion", true, "Add subtle bob and sway while the Sosig moves.").Value,
			BobMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Motion", "BobMeters", 0f, "Optional procedural vertical bob. Keep at zero for a floor-locked model.").Value,
			SwayDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Motion", "SwayDegrees", 1.8f, "Maximum procedural roll sway.").Value,
			GaitDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Motion", "GaitDegrees", 24f, "Maximum procedural leg swing angle.").Value,
			HandIkWeight = ((BaseUnityPlugin)this).Config.Bind<float>("MotionV2", "HandIkCorrectionWeight", 0.3f, "Small final hand-to-weapon correction applied after authored firearm animation.").Value,
			JointLimitWeight = ((BaseUnityPlugin)this).Config.Bind<float>("MotionV2", "JointLimitCorrectionWeight", 0.15f, "Safety correction after authored animation and hand IK. Keep low so valid weapon poses are preserved.").Value,
			DriveHeldWeaponsFromAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("MotionV3", "DriveHeldWeaponsFromAnimation", true, "Align the custom model's visual hands to native Sosig gun targets. Native aiming and firing remain authoritative.").Value,
			HandTargetFollowSharpness = ((BaseUnityPlugin)this).Config.Bind<float>("MotionV3", "HandTargetFollowSharpness", 22f, "Legacy compatibility setting. Native gun targets are no longer driven by authored animation.").Value
		};
	}

	private static Material[] CreateMaterials(bool useNormalMaps, float metallic, float smoothness)
	{
		//IL_000a: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Expected O, but got Unknown
		//IL_0167: 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)
		Color tint = ParseColor(RuntimeSettings.ColorHex);
		if (ActiveAddon.surface != null)
		{
			metallic = ActiveAddon.surface.metallic;
			smoothness = ActiveAddon.surface.smoothness;
		}
		Material[] array = (Material[])(object)new Material[ActiveAddon.materials.Length];
		for (int i = 0; i < array.Length; i++)
		{
			AddonMaterial addonMaterial = ActiveAddon.materials[i];
			array[i] = CreateMaterial(addonMaterial.name ?? ActiveAddon.displayName, ActiveAddon.AssetPath(addonMaterial.albedo), string.IsNullOrEmpty(addonMaterial.normal) ? string.Empty : ActiveAddon.AssetPath(addonMaterial.normal), tint, useNormalMaps, metallic, smoothness);
		}
		int num;
		int num2;
		if (RuntimeSettings.BlueEyeEmission && ActiveAddon.eyes != null)
		{
			num = (ActiveAddon.eyes.enabled ? 1 : 0);
			if (num != 0)
			{
				num2 = ActiveAddon.eyes.materialIndex;
				goto IL_0103;
			}
		}
		else
		{
			num = 0;
		}
		num2 = 0;
		goto IL_0103;
		IL_0103:
		int num3 = num2;
		if (num != 0)
		{
			ConfigureEyeSurfaces((Texture2D)array[num3].mainTexture);
		}
		if (num != 0 && array[num3].HasProperty("_EmissionMap"))
		{
			Texture2D val = CreateEyeEmissionMask((Texture2D)array[num3].mainTexture);
			array[num3].SetTexture("_EmissionMap", (Texture)(object)val);
			array[num3].SetColor("_EmissionColor", new Color(0.015f, 0.32f, 1f) * Mathf.Max(0f, RuntimeSettings.EyeEmissionIntensity));
			array[num3].EnableKeyword("_EMISSION");
			array[num3].globalIlluminationFlags = (MaterialGlobalIlluminationFlags)0;
		}
		return array;
	}

	private static void ConfigureEyeSurfaces(Texture2D albedo)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_0043: 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_00cd: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: 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_0173: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: 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_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Unlit/Color");
		if ((Object)(object)val == (Object)null)
		{
			Log.LogWarning((object)"Unlit/Color unavailable; eye surface fallback unavailable.");
			return;
		}
		EyeSurfaceMaterial = new Material(val);
		EyeSurfaceMaterial.color = new Color(0.02f, 0.4f, 1f) * Mathf.Max(1f, RuntimeSettings.EyeEmissionIntensity);
		RuntimeSkinnedAsset.MeshDefinition[] meshes = SkinnedAsset.Meshes;
		foreach (RuntimeSkinnedAsset.MeshDefinition meshDefinition in meshes)
		{
			if (meshDefinition.MaterialIndex != ActiveAddon.eyes.materialIndex)
			{
				continue;
			}
			Mesh mesh = meshDefinition.Mesh;
			Vector2[] uv = mesh.uv;
			int[] triangles = mesh.triangles;
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			for (int j = 0; j < triangles.Length; j += 3)
			{
				Vector2 val2 = (uv[triangles[j]] + uv[triangles[j + 1]] + uv[triangles[j + 2]]) / 3f;
				val2.x = Mathf.Repeat(val2.x, 1f);
				val2.y = Mathf.Repeat(val2.y, 1f);
				bool flag = false;
				EyeCenter[] centers = ActiveAddon.eyes.centers;
				foreach (EyeCenter eyeCenter in centers)
				{
					float num = (val2.x - eyeCenter.u) / ActiveAddon.eyes.radiusU;
					float num2 = (val2.y - eyeCenter.v) / ActiveAddon.eyes.radiusV;
					if (num * num + num2 * num2 < 1f)
					{
						flag = true;
					}
				}
				Color pixelBilinear = albedo.GetPixelBilinear(val2.x, val2.y);
				List<int> obj = ((flag && Mathf.Max(pixelBilinear.r, Mathf.Max(pixelBilinear.g, pixelBilinear.b)) < ActiveAddon.eyes.darkThreshold) ? list : list2);
				obj.Add(triangles[j]);
				obj.Add(triangles[j + 1]);
				obj.Add(triangles[j + 2]);
			}
			if (list.Count == 0)
			{
				Log.LogWarning((object)"No eye lens triangles selected.");
				continue;
			}
			mesh.subMeshCount = 2;
			mesh.SetTriangles(list2.ToArray(), 0);
			mesh.SetTriangles(list.ToArray(), 1);
			Log.LogInfo((object)("Unlit blue eye surfaces: " + list.Count / 3 + " lens triangles."));
		}
	}

	private static Texture2D CreateEyeEmissionMask(Texture2D albedo)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Expected O, but got Unknown
		//IL_0079: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: 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_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(512, 512, (TextureFormat)3, true, true);
		((Object)val).name = "Model addon blue eye lens emission";
		((Texture)val).wrapMode = (TextureWrapMode)0;
		Color[] array = (Color[])(object)new Color[262144];
		Vector2[] array2 = (Vector2[])(object)new Vector2[ActiveAddon.eyes.centers.Length];
		for (int i = 0; i < array2.Length; i++)
		{
			array2[i] = new Vector2(ActiveAddon.eyes.centers[i].u, ActiveAddon.eyes.centers[i].v);
		}
		Vector2[] array3 = array2;
		foreach (Vector2 val2 in array3)
		{
			float radiusU = ActiveAddon.eyes.radiusU;
			float radiusV = ActiveAddon.eyes.radiusV;
			for (int k = Mathf.FloorToInt((val2.y - radiusV) * 512f); k <= Mathf.CeilToInt((val2.y + radiusV) * 512f); k++)
			{
				for (int l = Mathf.FloorToInt((val2.x - radiusU) * 512f); l <= Mathf.CeilToInt((val2.x + radiusU) * 512f); l++)
				{
					float num = ((float)l + 0.5f) / 512f;
					float num2 = ((float)k + 0.5f) / 512f;
					float num3 = (num - val2.x) / radiusU;
					float num4 = (num2 - val2.y) / radiusV;
					if (!(num3 * num3 + num4 * num4 > 1f))
					{
						Color pixelBilinear = albedo.GetPixelBilinear(num, num2);
						float num5 = Mathf.Max(pixelBilinear.r, Mathf.Max(pixelBilinear.g, pixelBilinear.b));
						float num6 = 1f - Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(ActiveAddon.eyes.darkThreshold - 0.1f, ActiveAddon.eyes.darkThreshold, num5));
						array[k * 512 + l] = Color.white * num6;
					}
				}
			}
		}
		val.SetPixels(array);
		val.Apply(true, true);
		return val;
	}

	private static Material CreateMaterial(string name, string albedoPath, string normalPath, Color tint, bool useNormalMaps, float metallic, float smoothness)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Standard");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Diffuse");
		}
		if ((Object)(object)val == (Object)null)
		{
			throw new InvalidOperationException("Neither Standard nor Diffuse shader is available.");
		}
		Material val2 = new Material(val);
		((Object)val2).name = "CustomSosigModelFramework - " + name;
		val2.color = tint;
		val2.mainTexture = (Texture)(object)LoadTexture(albedoPath, linear: false);
		if (useNormalMaps && val2.HasProperty("_BumpMap") && File.Exists(normalPath))
		{
			val2.SetTexture("_BumpMap", (Texture)(object)LoadTexture(normalPath, linear: true));
			val2.EnableKeyword("_NORMALMAP");
		}
		if (val2.HasProperty("_Metallic"))
		{
			val2.SetFloat("_Metallic", Mathf.Clamp01(metallic));
		}
		if (val2.HasProperty("_Glossiness"))
		{
			val2.SetFloat("_Glossiness", Mathf.Clamp01(smoothness));
		}
		return val2;
	}

	private static Texture2D LoadTexture(string path, bool linear)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		//IL_007d: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Expected O, but got Unknown
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("Model addon texture was not found.", path);
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)3, true, linear);
		if (!val.LoadImage(File.ReadAllBytes(path)))
		{
			throw new IOException("Unity failed to decode texture: " + path);
		}
		if (linear)
		{
			Color[] pixels = val.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i].a = pixels[i].r;
			}
			Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, true, true);
			val2.SetPixels(pixels);
			val2.Apply(true, false);
			Object.Destroy((Object)(object)val);
			val = val2;
		}
		((Object)val).name = Path.GetFileNameWithoutExtension(path);
		((Texture)val).wrapMode = (TextureWrapMode)0;
		((Texture)val).anisoLevel = 4;
		return val;
	}

	private static Color ParseColor(string text)
	{
		//IL_0074: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		string text2 = (text ?? string.Empty).Trim().TrimStart(new char[1] { '#' });
		if (text2.Length != 6 && text2.Length != 8)
		{
			return new Color(0.91f, 0.09f, 0.17f, 1f);
		}
		if (!uint.TryParse(text2, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
		{
			return new Color(0.91f, 0.09f, 0.17f, 1f);
		}
		if (text2.Length == 6)
		{
			return new Color((float)((result >> 16) & 0xFF) / 255f, (float)((result >> 8) & 0xFF) / 255f, (float)(result & 0xFF) / 255f, 1f);
		}
		return new Color((float)((result >> 24) & 0xFF) / 255f, (float)((result >> 16) & 0xFF) / 255f, (float)((result >> 8) & 0xFF) / 255f, (float)(result & 0xFF) / 255f);
	}
}
internal sealed class RuntimeBoneClip
{
	private sealed class BoneTrack
	{
		public readonly int BoneIndex;

		public readonly Quaternion[] Rotations;

		public BoneTrack(int boneIndex, Quaternion[] rotations)
		{
			BoneIndex = boneIndex;
			Rotations = rotations;
		}
	}

	public readonly string Name;

	public readonly float Duration;

	public readonly float FramesPerSecond;

	private readonly int _frameCount;

	private readonly BoneTrack[] _tracks;

	private RuntimeBoneClip(string name, float duration, float framesPerSecond, int frameCount, BoneTrack[] tracks)
	{
		Name = name;
		Duration = duration;
		FramesPerSecond = framesPerSecond;
		_frameCount = frameCount;
		_tracks = tracks;
	}

	public static RuntimeBoneClip Load(string path, int skeletonBoneCount)
	{
		//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)
		if (!File.Exists(path))
		{
			throw new FileNotFoundException("Retargeted bone animation was not found.", path);
		}
		using FileStream stream = File.OpenRead(path);
		using GZipStream input = new GZipStream(stream, CompressionMode.Decompress);
		using BinaryReader binaryReader = new BinaryReader(input);
		string text = Encoding.ASCII.GetString(binaryReader.ReadBytes(4));
		if (text != "CSA1")
		{
			throw new IOException("Unexpected bone animation signature: " + text);
		}
		int num = binaryReader.ReadInt32();
		if (num != 1)
		{
			throw ne