Decompiled source of RacesOfValheimAzuEPICompatPatch v1.1.3

RacesOfValheimAzuEPICompat.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RacesOfValheim;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RacesOfValheimAzuEPICompat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyInformationalVersion("1.1.3")]
[assembly: AssemblyProduct("RacesOfValheimAzuEPICompat")]
[assembly: AssemblyTitle("RacesOfValheimAzuEPICompat")]
[assembly: AssemblyVersion("1.1.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RacesOfValheimAzuEPICompat
{
	internal static class ArmorMaskMeshBuilder
	{
		private struct Vertex
		{
			internal Vector3 Position;

			internal Vector3 Normal;

			internal Vector4 Tangent;

			internal Vector2 Uv;

			internal Vector2 Uv2;

			internal Color Color;

			internal BoneWeight Weight;

			internal static Vertex Lerp(Vertex a, Vertex b, float t)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				Vertex result = new Vertex
				{
					Position = Vector3.Lerp(a.Position, b.Position, t)
				};
				Vector3 val = Vector3.Lerp(a.Normal, b.Normal, t);
				result.Normal = ((Vector3)(ref val)).normalized;
				result.Tangent = Vector4.Lerp(a.Tangent, b.Tangent, t);
				result.Uv = Vector2.Lerp(a.Uv, b.Uv, t);
				result.Uv2 = Vector2.Lerp(a.Uv2, b.Uv2, t);
				result.Color = Color.Lerp(a.Color, b.Color, t);
				result.Weight = LerpWeight(a.Weight, b.Weight, t);
				return result;
			}

			internal Vertex Inverted()
			{
				//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_0014: 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)
				Vertex result = this;
				result.Normal = -Normal;
				result.Tangent.w = 0f - result.Tangent.w;
				return result;
			}

			private static BoneWeight LerpWeight(BoneWeight a, BoneWeight b, float t)
			{
				//IL_0112: Unknown result type (might be due to invalid IL or missing references)
				//IL_016a: Unknown result type (might be due to invalid IL or missing references)
				float num = 1f - t;
				BoneWeightAccumulator boneWeightAccumulator = default(BoneWeightAccumulator);
				boneWeightAccumulator.Add(((BoneWeight)(ref a)).boneIndex0, ((BoneWeight)(ref a)).weight0 * num);
				boneWeightAccumulator.Add(((BoneWeight)(ref a)).boneIndex1, ((BoneWeight)(ref a)).weight1 * num);
				boneWeightAccumulator.Add(((BoneWeight)(ref a)).boneIndex2, ((BoneWeight)(ref a)).weight2 * num);
				boneWeightAccumulator.Add(((BoneWeight)(ref a)).boneIndex3, ((BoneWeight)(ref a)).weight3 * num);
				boneWeightAccumulator.Add(((BoneWeight)(ref b)).boneIndex0, ((BoneWeight)(ref b)).weight0 * t);
				boneWeightAccumulator.Add(((BoneWeight)(ref b)).boneIndex1, ((BoneWeight)(ref b)).weight1 * t);
				boneWeightAccumulator.Add(((BoneWeight)(ref b)).boneIndex2, ((BoneWeight)(ref b)).weight2 * t);
				boneWeightAccumulator.Add(((BoneWeight)(ref b)).boneIndex3, ((BoneWeight)(ref b)).weight3 * t);
				boneWeightAccumulator.TakeLargest(out var bone, out var weight);
				boneWeightAccumulator.TakeLargest(out var bone2, out var weight2);
				boneWeightAccumulator.TakeLargest(out var bone3, out var weight3);
				boneWeightAccumulator.TakeLargest(out var bone4, out var weight4);
				float num2 = weight + weight2 + weight3 + weight4;
				if (num2 <= 0f)
				{
					num2 = 1f;
				}
				BoneWeight result = default(BoneWeight);
				((BoneWeight)(ref result)).boneIndex0 = bone;
				((BoneWeight)(ref result)).weight0 = weight / num2;
				((BoneWeight)(ref result)).boneIndex1 = bone2;
				((BoneWeight)(ref result)).weight1 = weight2 / num2;
				((BoneWeight)(ref result)).boneIndex2 = bone3;
				((BoneWeight)(ref result)).weight2 = weight3 / num2;
				((BoneWeight)(ref result)).boneIndex3 = bone4;
				((BoneWeight)(ref result)).weight3 = weight4 / num2;
				return result;
			}
		}

		private struct BoneWeightAccumulator
		{
			private int _count;

			private int _bone0;

			private int _bone1;

			private int _bone2;

			private int _bone3;

			private int _bone4;

			private int _bone5;

			private int _bone6;

			private int _bone7;

			private float _weight0;

			private float _weight1;

			private float _weight2;

			private float _weight3;

			private float _weight4;

			private float _weight5;

			private float _weight6;

			private float _weight7;

			internal void Add(int bone, float weight)
			{
				if (weight <= 0f)
				{
					return;
				}
				for (int i = 0; i < _count; i++)
				{
					if (Bone(i) == bone)
					{
						SetWeight(i, Weight(i) + weight);
						return;
					}
				}
				if (_count < 8)
				{
					SetBone(_count, bone);
					SetWeight(_count, weight);
					_count++;
				}
			}

			internal void TakeLargest(out int bone, out float weight)
			{
				int num = -1;
				float num2 = 0f;
				for (int i = 0; i < _count; i++)
				{
					float num3 = Weight(i);
					if (!(num3 <= num2))
					{
						num = i;
						num2 = num3;
					}
				}
				if (num < 0)
				{
					bone = 0;
					weight = 0f;
				}
				else
				{
					bone = Bone(num);
					weight = num2;
					SetWeight(num, 0f);
				}
			}

			private int Bone(int index)
			{
				return index switch
				{
					0 => _bone0, 
					1 => _bone1, 
					2 => _bone2, 
					3 => _bone3, 
					4 => _bone4, 
					5 => _bone5, 
					6 => _bone6, 
					_ => _bone7, 
				};
			}

			private float Weight(int index)
			{
				return index switch
				{
					0 => _weight0, 
					1 => _weight1, 
					2 => _weight2, 
					3 => _weight3, 
					4 => _weight4, 
					5 => _weight5, 
					6 => _weight6, 
					_ => _weight7, 
				};
			}

			private void SetBone(int index, int value)
			{
				switch (index)
				{
				case 0:
					_bone0 = value;
					break;
				case 1:
					_bone1 = value;
					break;
				case 2:
					_bone2 = value;
					break;
				case 3:
					_bone3 = value;
					break;
				case 4:
					_bone4 = value;
					break;
				case 5:
					_bone5 = value;
					break;
				case 6:
					_bone6 = value;
					break;
				default:
					_bone7 = value;
					break;
				}
			}

			private void SetWeight(int index, float value)
			{
				switch (index)
				{
				case 0:
					_weight0 = value;
					break;
				case 1:
					_weight1 = value;
					break;
				case 2:
					_weight2 = value;
					break;
				case 3:
					_weight3 = value;
					break;
				case 4:
					_weight4 = value;
					break;
				case 5:
					_weight5 = value;
					break;
				case 6:
					_weight6 = value;
					break;
				default:
					_weight7 = value;
					break;
				}
			}
		}

		private const int MaxSubdivisionDepth = 4;

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

		internal static Mesh GetOrBuild(Mesh source, Texture mask, SkeletonArmorPart part, float cutoff)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)mask == (Object)null)
			{
				return null;
			}
			string key = ((Object)source).GetInstanceID() + ":" + ((Object)mask).GetInstanceID() + ":" + part.ToString() + ":" + cutoff;
			if (Cache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Texture2D val = MakeReadable(mask);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				Mesh val2 = Build(source, val, cutoff, part);
				if ((Object)(object)val2 != (Object)null)
				{
					Cache[key] = val2;
				}
				return val2;
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		internal static void Clear()
		{
			foreach (Mesh value in Cache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Cache.Clear();
		}

		private static Texture2D MakeReadable(Texture source)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_006c: 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_0079: Expected O, but got Unknown
			RenderTexture val = null;
			RenderTexture active = RenderTexture.active;
			try
			{
				val = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)1);
				Graphics.Blit(source, val);
				RenderTexture.active = val;
				Texture2D val2 = new Texture2D(source.width, source.height, (TextureFormat)4, false, true);
				val2.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0, false);
				val2.Apply(false, false);
				((Texture)val2).wrapMode = source.wrapMode;
				return val2;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not read Skeleton armour alpha mask '" + ((Object)source).name + "': " + ex.Message));
				}
				return null;
			}
			finally
			{
				RenderTexture.active = active;
				if ((Object)(object)val != (Object)null)
				{
					RenderTexture.ReleaseTemporary(val);
				}
			}
		}

		private static Mesh Build(Mesh source, Texture2D mask, float cutoff, SkeletonArmorPart part)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: 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_0266: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] vertices = source.vertices;
			Vector3[] normals = source.normals;
			Vector4[] tangents = source.tangents;
			Vector2[] uv = source.uv;
			Vector2[] uv2 = source.uv2;
			Color[] colors = source.colors;
			BoneWeight[] boneWeights = source.boneWeights;
			int[] triangles = source.GetTriangles(0);
			if (vertices.Length == 0 || uv.Length != vertices.Length || triangles.Length == 0)
			{
				return null;
			}
			List<Vertex> list = new List<Vertex>(triangles.Length);
			List<int> list2 = new List<int>(triangles.Length);
			Color32[] pixels = mask.GetPixels32();
			for (int i = 0; i < triangles.Length; i += 3)
			{
				Vertex a = ReadVertex(triangles[i], vertices, normals, tangents, uv, uv2, colors, boneWeights);
				Vertex b = ReadVertex(triangles[i + 1], vertices, normals, tangents, uv, uv2, colors, boneWeights);
				Vertex c = ReadVertex(triangles[i + 2], vertices, normals, tangents, uv, uv2, colors, boneWeights);
				ClipTriangle(a, b, c, 0, mask, pixels, cutoff, list, list2);
			}
			if (list2.Count == 0)
			{
				return null;
			}
			Mesh val = new Mesh
			{
				name = ((Object)source).name + "_SkeletonArmorMask_" + part,
				indexFormat = (IndexFormat)(list.Count > 65535),
				bindposes = source.bindposes
			};
			List<Vector3> list3 = new List<Vector3>(list.Count);
			List<Vector3> list4 = new List<Vector3>(list.Count);
			List<Vector4> list5 = new List<Vector4>(list.Count);
			List<Vector2> list6 = new List<Vector2>(list.Count);
			List<Vector2> list7 = new List<Vector2>(list.Count);
			List<Color> list8 = new List<Color>(list.Count);
			BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[list.Count];
			for (int j = 0; j < list.Count; j++)
			{
				Vertex vertex = list[j];
				list3.Add(vertex.Position);
				list4.Add(vertex.Normal);
				list5.Add(vertex.Tangent);
				list6.Add(vertex.Uv);
				list7.Add(vertex.Uv2);
				list8.Add(vertex.Color);
				array[j] = vertex.Weight;
			}
			val.SetVertices(list3);
			val.SetNormals(list4);
			val.SetTangents(list5);
			val.SetUVs(0, list6);
			val.SetUVs(1, list7);
			val.SetColors(list8);
			val.boneWeights = array;
			val.SetTriangles(list2, 0, true);
			val.bounds = source.bounds;
			return val;
		}

		private static void ClipTriangle(Vertex a, Vertex b, Vertex c, int depth, Texture2D mask, Color32[] pixels, float cutoff, List<Vertex> output, List<int> triangles)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0090: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			float num = Alpha(a.Uv, mask, pixels);
			float num2 = Alpha(b.Uv, mask, pixels);
			float num3 = Alpha(c.Uv, mask, pixels);
			Vector2 uv = (a.Uv + b.Uv) * 0.5f;
			Vector2 uv2 = (b.Uv + c.Uv) * 0.5f;
			Vector2 uv3 = (c.Uv + a.Uv) * 0.5f;
			float num4 = Alpha(uv, mask, pixels);
			float num5 = Alpha(uv2, mask, pixels);
			float num6 = Alpha(uv3, mask, pixels);
			float num7 = Alpha((a.Uv + b.Uv + c.Uv) / 3f, mask, pixels);
			if (!(num >= cutoff) && !(num2 >= cutoff) && !(num3 >= cutoff) && !(num4 >= cutoff) && !(num5 >= cutoff) && !(num6 >= cutoff) && !(num7 >= cutoff))
			{
				return;
			}
			bool flag = num >= cutoff && num2 >= cutoff && num3 >= cutoff && num4 >= cutoff && num5 >= cutoff && num6 >= cutoff && num7 >= cutoff;
			if (flag || depth >= 4)
			{
				if (flag || num7 >= cutoff)
				{
					AddTriangle(a, b, c, output, triangles);
				}
				return;
			}
			Vertex vertex = Vertex.Lerp(a, b, 0.5f);
			Vertex vertex2 = Vertex.Lerp(b, c, 0.5f);
			Vertex vertex3 = Vertex.Lerp(c, a, 0.5f);
			ClipTriangle(a, vertex, vertex3, depth + 1, mask, pixels, cutoff, output, triangles);
			ClipTriangle(vertex, b, vertex2, depth + 1, mask, pixels, cutoff, output, triangles);
			ClipTriangle(vertex3, vertex2, c, depth + 1, mask, pixels, cutoff, output, triangles);
			ClipTriangle(vertex, vertex2, vertex3, depth + 1, mask, pixels, cutoff, output, triangles);
		}

		private static void AddTriangle(Vertex a, Vertex b, Vertex c, List<Vertex> output, List<int> triangles)
		{
			int count = output.Count;
			output.Add(a);
			output.Add(b);
			output.Add(c);
			triangles.Add(count);
			triangles.Add(count + 1);
			triangles.Add(count + 2);
			Vertex item = a.Inverted();
			Vertex item2 = b.Inverted();
			Vertex item3 = c.Inverted();
			int count2 = output.Count;
			output.Add(item);
			output.Add(item2);
			output.Add(item3);
			triangles.Add(count2);
			triangles.Add(count2 + 2);
			triangles.Add(count2 + 1);
		}

		private static float Alpha(Vector2 uv, Texture2D texture, Color32[] pixels)
		{
			//IL_0001: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			float num = (((int)((Texture)texture).wrapMode == 0) ? (uv.x - Mathf.Floor(uv.x)) : Mathf.Clamp01(uv.x));
			float num2 = (((int)((Texture)texture).wrapMode == 0) ? (uv.y - Mathf.Floor(uv.y)) : Mathf.Clamp01(uv.y));
			int num3 = Mathf.Clamp(Mathf.RoundToInt(num * (float)(((Texture)texture).width - 1)), 0, ((Texture)texture).width - 1);
			int num4 = Mathf.Clamp(Mathf.RoundToInt(num2 * (float)(((Texture)texture).height - 1)), 0, ((Texture)texture).height - 1);
			return (float)(int)pixels[num4 * ((Texture)texture).width + num3].a / 255f;
		}

		private static Vertex ReadVertex(int index, Vector3[] positions, Vector3[] normals, Vector4[] tangents, Vector2[] uv, Vector2[] uv2, Color[] colors, BoneWeight[] weights)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_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_0088: 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_008d: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			return new Vertex
			{
				Position = positions[index],
				Normal = ((normals.Length == positions.Length) ? normals[index] : Vector3.up),
				Tangent = (Vector4)((tangents.Length == positions.Length) ? tangents[index] : new Vector4(1f, 0f, 0f, 1f)),
				Uv = uv[index],
				Uv2 = ((uv2.Length == positions.Length) ? uv2[index] : Vector2.zero),
				Color = ((colors.Length == positions.Length) ? colors[index] : Color.white),
				Weight = (BoneWeight)((weights.Length == positions.Length) ? weights[index] : default(BoneWeight))
			};
		}
	}
	internal static class DoubleSidedEquipmentMeshes
	{
		private static readonly Dictionary<int, Mesh> Cache = new Dictionary<int, Mesh>();

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

		internal static void Apply(GameObject instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			SkinnedMeshRenderer[] componentsInChildren = instance.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
				{
					val.sharedMesh = GetOrBuild(val.sharedMesh);
				}
			}
			MeshFilter[] componentsInChildren2 = instance.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null)
				{
					val2.sharedMesh = GetOrBuild(val2.sharedMesh);
				}
			}
		}

		private static Mesh GetOrBuild(Mesh source)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)source).name.EndsWith("_RoVDoubleSided", StringComparison.Ordinal))
			{
				return source;
			}
			int instanceID = ((Object)source).GetInstanceID();
			if (GeneratedMeshes.Contains(instanceID))
			{
				return source;
			}
			if (Cache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Mesh val = Object.Instantiate<Mesh>(source);
			((Object)val).name = ((Object)source).name + "_RoVDoubleSided";
			for (int i = 0; i < val.subMeshCount; i++)
			{
				if ((int)val.GetTopology(i) == 0)
				{
					int[] triangles = val.GetTriangles(i);
					int[] array = new int[triangles.Length * 2];
					Array.Copy(triangles, array, triangles.Length);
					int num = triangles.Length;
					for (int j = 0; j < triangles.Length; j += 3)
					{
						array[num + j] = triangles[j];
						array[num + j + 1] = triangles[j + 2];
						array[num + j + 2] = triangles[j + 1];
					}
					val.SetTriangles(array, i, false);
				}
			}
			val.bounds = source.bounds;
			Cache[instanceID] = val;
			GeneratedMeshes.Add(((Object)val).GetInstanceID());
			return val;
		}

		internal static void Clear()
		{
			foreach (Mesh value in Cache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Cache.Clear();
			GeneratedMeshes.Clear();
		}
	}
	internal static class MainMenuProgressionSnapshot
	{
		private const string SnapshotKey = "RoVAzuEPI_LastProgressionState";

		private static readonly string[] RaceStateZdoKeys = new string[5] { "RacesOfValheim_SkeletonState", "RacesOfValheim_AswidState", "RacesOfValheim_DvergarState", "RacesOfValheim_SvermState", "RacesOfValheim_TrentaState" };

		private static readonly MethodInfo GetPreviewPlayerMethod = AccessTools.Method(typeof(FejdStartup), "GetPreviewPlayer", (Type[])null, (Type[])null);

		private static readonly MethodInfo UpdateVisualsMethod = AccessTools.Method(typeof(VisEquipment), "UpdateVisuals", (Type[])null, (Type[])null);

		private static readonly MethodInfo UpdateColorsMethod = AccessTools.Method(typeof(VisEquipment), "UpdateColors", (Type[])null, (Type[])null);

		private static int _previewProgression;

		internal static void Capture(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && player.m_customData != null && !((Object)(object)ZoneSystem.instance == (Object)null))
			{
				int num = Mathf.Clamp(BossProgressionManager.GetCurrentProgressionState(), 1, 8);
				player.m_customData["RoVAzuEPI_LastProgressionState"] = num.ToString();
			}
		}

		internal static void Refresh(FejdStartup startup)
		{
			if ((Object)(object)startup == (Object)null)
			{
				return;
			}
			try
			{
				object? obj = GetPreviewPlayerMethod?.Invoke(startup, null);
				Player val = (Player)((obj is Player) ? obj : null);
				if ((Object)(object)val == (Object)null || val.m_customData == null || !val.m_customData.TryGetValue("RoVAzuEPI_LastProgressionState", out var value) || !int.TryParse(value, out var result))
				{
					return;
				}
				result = Mathf.Clamp(result, 1, 8);
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					ZDO zDO = component.GetZDO();
					if (val.m_customData.TryGetValue("Race", out var value2))
					{
						zDO.Set("RacesOfValheim_Race", value2);
					}
					string[] raceStateZdoKeys = RaceStateZdoKeys;
					foreach (string text in raceStateZdoKeys)
					{
						zDO.Set(text, result);
					}
					zDO.Set("RoVAzuEPI_PassiveAuraEnabled", RaceOptions.IsEnabled(val));
					zDO.Set("RoVAzuEPI_SkeletonModel", RaceOptions.SkeletonModel(val));
				}
				VisEquipment component2 = ((Component)val).GetComponent<VisEquipment>();
				if ((Object)(object)component2 == (Object)null)
				{
					return;
				}
				_previewProgression = result;
				RaceOptions.EnterVisualContext(val);
				try
				{
					UpdateColorsMethod?.Invoke(component2, null);
					UpdateVisualsMethod?.Invoke(component2, null);
					Plugin.ApplyPeriodicRaceVisuals(val);
					RaceOptions.ApplySkeletonPreviewFlame(val);
				}
				finally
				{
					RaceOptions.LeaveVisualContext();
					_previewProgression = 0;
				}
			}
			catch (Exception ex)
			{
				_previewProgression = 0;
				RaceOptions.LeaveVisualContext();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Failed to apply saved progression to the main-menu preview: " + ex));
				}
			}
		}

		internal static bool TryGetPreviewProgression(out int state)
		{
			state = _previewProgression;
			return state > 0;
		}
	}
	[HarmonyPatch(typeof(Player), "Save")]
	internal static class SaveMainMenuProgressionSnapshotPatch
	{
		private static void Prefix(Player __instance)
		{
			MainMenuProgressionSnapshot.Capture(__instance);
		}
	}
	[HarmonyPatch(typeof(BossProgressionManager), "GetCurrentProgressionState")]
	internal static class MainMenuProgressionOverridePatch
	{
		private static void Postfix(ref int __result)
		{
			if (MainMenuProgressionSnapshot.TryGetPreviewProgression(out var state))
			{
				__result = state;
			}
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")]
	[HarmonyPriority(0)]
	internal static class MainMenuSetupPreviewProgressionPatch
	{
		private static void Postfix(FejdStartup __instance)
		{
			MainMenuProgressionSnapshot.Refresh(__instance);
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "SetSelectedProfile")]
	[HarmonyPriority(0)]
	internal static class MainMenuSelectProfileProgressionPatch
	{
		private static void Postfix(FejdStartup __instance)
		{
			MainMenuProgressionSnapshot.Refresh(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class MainMenuModelReplacerLateRefreshPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RefreshAfterPrefabReplacers());
			}
		}

		private static IEnumerator RefreshAfterPrefabReplacers()
		{
			yield return null;
			yield return null;
			SkeletonModelReplacerCompat.CaptureEffectivePrefabs();
			FejdStartup val = Object.FindObjectOfType<FejdStartup>();
			if ((Object)(object)val != (Object)null && (Object)(object)ZoneSystem.instance == (Object)null)
			{
				MainMenuProgressionSnapshot.Refresh(val);
			}
		}
	}
	[BepInPlugin("danii.RacesOfValheimAzuEPICompat", "Races of Valheim - AzuEPI Compatibility", "1.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "danii.RacesOfValheimAzuEPICompat";

		public const string PluginName = "Races of Valheim - AzuEPI Compatibility";

		public const string PluginVersion = "1.1.3";

		private const float ProgressionCheckInterval = 0.25f;

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private float _nextProgressionCheck;

		private string _displayedRace;

		private int _displayedProgression = -1;

		private static Type _panelType;

		private static FieldInfo _playerPreviewField;

		private static FieldInfo _playerPreviewCompField;

		private static FieldInfo _panelInstanceField;

		private static FieldInfo _cameraField;

		private static MethodInfo _progressionMethod;

		private static MethodInfo _updateColorsMethod;

		private static MethodInfo _updateVisualsMethod;

		private static Action<Player, bool> _dvergarApplyScale;

		private static Action<Player> _dvergarApplyEyes;

		private static Action<Player> _dvergarApplyHood;

		private static Action<Player, bool> _svermApplyScale;

		private static Action<Player> _svermApplyEyes;

		private static Action<Player> _svermApplyClaws;

		private static Action<Player> _svermApplySpines;

		private static Action<Player> _svermApplyCarapace;

		private static Action<Player> _trentaApplyCrown;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			CacheReflection();
			_harmony = new Harmony("danii.RacesOfValheimAzuEPICompat");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Races of Valheim - AzuEPI Compatibility 1.1.3 loaded");
		}

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

		private void Update()
		{
			if (Time.unscaledTime < _nextProgressionCheck)
			{
				return;
			}
			_nextProgressionCheck = Time.unscaledTime + 0.25f;
			if (IsPreviewVisible())
			{
				string localRace = GetLocalRace();
				int currentProgression = GetCurrentProgression();
				if ((!(localRace == _displayedRace) || currentProgression != _displayedProgression) && ApplyRaceToPreview())
				{
					_displayedRace = localRace;
					_displayedProgression = currentProgression;
				}
			}
		}

		internal void RefreshOnOpen()
		{
			((MonoBehaviour)this).StopCoroutine("RefreshAfterOpen");
			((MonoBehaviour)this).StartCoroutine("RefreshAfterOpen");
		}

		private IEnumerator RefreshAfterOpen()
		{
			RefreshAndRememberState();
			yield return null;
			RefreshAndRememberState();
		}

		private void RefreshAndRememberState()
		{
			if (ApplyRaceToPreview())
			{
				_displayedRace = GetLocalRace();
				_displayedProgression = GetCurrentProgression();
			}
		}

		internal static bool ApplyRaceToPreview()
		{
			//IL_009f: 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)
			try
			{
				if (!IsPreviewVisible())
				{
					return false;
				}
				Player localPlayer = Player.m_localPlayer;
				Player previewPlayer = GetPreviewPlayer();
				if ((Object)(object)localPlayer == (Object)null || (Object)(object)previewPlayer == (Object)null || (Object)(object)localPlayer == (Object)(object)previewPlayer)
				{
					return false;
				}
				previewPlayer.m_customData.Clear();
				foreach (KeyValuePair<string, string> customDatum in localPlayer.m_customData)
				{
					previewPlayer.m_customData[customDatum.Key] = customDatum.Value;
				}
				((Component)previewPlayer).transform.localScale = ((Component)localPlayer).transform.localScale;
				Transform val = ((Component)localPlayer).transform.Find("Visual");
				Transform val2 = ((Component)previewPlayer).transform.Find("Visual");
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					val2.localScale = val.localScale;
				}
				VisEquipment component = ((Component)previewPlayer).GetComponent<VisEquipment>();
				if ((Object)(object)component == (Object)null)
				{
					return false;
				}
				component.m_isPlayer = true;
				_updateColorsMethod?.Invoke(component, null);
				_updateVisualsMethod?.Invoke(component, null);
				ApplyPeriodicRaceVisuals(previewPlayer);
				RaceOptions.ApplySkeletonPreviewFlame(previewPlayer, localPlayer);
				SetLayerRecursively(((Component)previewPlayer).gameObject, LayerMask.NameToLayer("UI"));
				Camera previewCamera = GetPreviewCamera();
				if (previewCamera != null)
				{
					previewCamera.Render();
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("Failed to apply race to AzuEPI preview: " + ex));
				}
				return false;
			}
		}

		private static string GetLocalRace()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && localPlayer.m_customData != null && localPlayer.m_customData.TryGetValue("Race", out var value))
			{
				return value;
			}
			return "Human";
		}

		private static int GetCurrentProgression()
		{
			if (!(_progressionMethod == null))
			{
				return (int)_progressionMethod.Invoke(null, null);
			}
			return -1;
		}

		private static bool IsPreviewVisible()
		{
			object? obj = _playerPreviewField?.GetValue(null);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			Camera previewCamera = GetPreviewCamera();
			if ((Object)(object)val != (Object)null && val.activeInHierarchy && (Object)(object)previewCamera != (Object)null)
			{
				return ((Behaviour)previewCamera).enabled;
			}
			return false;
		}

		private static Camera GetPreviewCamera()
		{
			object obj = _panelInstanceField?.GetValue(null);
			if (obj != null)
			{
				object? obj2 = _cameraField?.GetValue(obj);
				return (Camera)((obj2 is Camera) ? obj2 : null);
			}
			return null;
		}

		private static Player GetPreviewPlayer()
		{
			object? obj = _playerPreviewCompField?.GetValue(null);
			return (Player)((obj is Player) ? obj : null);
		}

		private static void CacheReflection()
		{
			_panelType = AccessTools.TypeByName("AzuEPI.Game.PlayerPreview.AzuEPICharacterPanel");
			_playerPreviewField = AccessTools.Field(_panelType, "playerPreview");
			_playerPreviewCompField = AccessTools.Field(_panelType, "playerPreviewComp");
			_panelInstanceField = AccessTools.Field(_panelType, "instance");
			_cameraField = AccessTools.Field(_panelType, "cam");
			_progressionMethod = AccessTools.Method(AccessTools.TypeByName("RacesOfValheim.BossProgressionManager"), "GetCurrentProgressionState", (Type[])null, (Type[])null);
			_updateColorsMethod = AccessTools.Method(typeof(VisEquipment), "UpdateColors", (Type[])null, (Type[])null);
			_updateVisualsMethod = AccessTools.Method(typeof(VisEquipment), "UpdateVisuals", (Type[])null, (Type[])null);
			_dvergarApplyScale = CacheRaceVisual<Action<Player, bool>>("RacesOfValheim.DvergarVisuals", "ApplyScale");
			_dvergarApplyEyes = CacheRaceVisual<Action<Player>>("RacesOfValheim.DvergarVisuals", "ApplyEyes");
			_dvergarApplyHood = CacheRaceVisual<Action<Player>>("RacesOfValheim.DvergarVisuals", "ApplyHood");
			_svermApplyScale = CacheRaceVisual<Action<Player, bool>>("RacesOfValheim.SvermVisuals", "ApplyScale");
			_svermApplyEyes = CacheRaceVisual<Action<Player>>("RacesOfValheim.SvermVisuals", "ApplyEyes");
			_svermApplyClaws = CacheRaceVisual<Action<Player>>("RacesOfValheim.SvermVisuals", "ApplyClaws");
			_svermApplySpines = CacheRaceVisual<Action<Player>>("RacesOfValheim.SvermVisuals", "ApplySpines");
			_svermApplyCarapace = CacheRaceVisual<Action<Player>>("RacesOfValheim.SvermVisuals", "ApplyCarapace");
			_trentaApplyCrown = CacheRaceVisual<Action<Player>>("RacesOfValheim.TrentaVisuals", "ApplyCrown");
		}

		private static T CacheRaceVisual<T>(string typeName, string methodName) where T : class
		{
			MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName(typeName), methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return null;
			}
			try
			{
				return Delegate.CreateDelegate(typeof(T), methodInfo) as T;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not cache race visual " + typeName + "." + methodName + ": " + ex.Message));
				}
				return null;
			}
		}

		internal static void ApplyPeriodicRaceVisuals(Player preview)
		{
			if (!preview.m_customData.TryGetValue("Race", out var value))
			{
				value = "Human";
			}
			switch (value)
			{
			case "Dvergar":
				_dvergarApplyScale?.Invoke(preview, arg2: true);
				_dvergarApplyEyes?.Invoke(preview);
				_dvergarApplyHood?.Invoke(preview);
				break;
			case "Sverm":
				_svermApplyScale?.Invoke(preview, arg2: true);
				_svermApplyEyes?.Invoke(preview);
				_svermApplyClaws?.Invoke(preview);
				_svermApplySpines?.Invoke(preview);
				_svermApplyCarapace?.Invoke(preview);
				break;
			case "Trenta":
				_trentaApplyCrown?.Invoke(preview);
				break;
			}
		}

		private static void SetLayerRecursively(GameObject root, int layer)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			root.layer = layer;
			foreach (Transform item in root.transform)
			{
				SetLayerRecursively(((Component)item).gameObject, layer);
			}
		}
	}
	[HarmonyPatch]
	internal static class AzuEPIShowPreviewPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("AzuEPI.Game.PlayerPreview.PlayerPreviewManager"), "ShowPlayerPreview", (Type[])null, (Type[])null);
		}

		private static void Postfix()
		{
			Plugin.Instance?.RefreshOnOpen();
		}
	}
	internal static class RaceOptions
	{
		internal const string EnabledKey = "RoVAzuEPI_PassiveAuraEnabled";

		internal const string SkeletonModelKey = "RoVAzuEPI_SkeletonModel";

		private static Player _visualContext;

		internal static Player VisualContext => _visualContext;

		internal static string Race(Player player)
		{
			if (player?.m_customData != null && player.m_customData.TryGetValue("Race", out var value))
			{
				return value;
			}
			return "Human";
		}

		internal static bool SupportsToggle(string race)
		{
			switch (race)
			{
			default:
				return race == "Draugh";
			case "Skeleton":
			case "Skadi":
			case "Aswid":
			case "Trenta":
				return true;
			}
		}

		internal static bool IsEnabled(Player player)
		{
			if (player?.m_customData != null && player.m_customData.TryGetValue("RoVAzuEPI_PassiveAuraEnabled", out var value) && bool.TryParse(value, out var result))
			{
				return result;
			}
			return true;
		}

		internal static void SetEnabled(Player player, bool enabled)
		{
			if (player?.m_customData != null)
			{
				player.m_customData["RoVAzuEPI_PassiveAuraEnabled"] = enabled.ToString();
				ZNetView component = ((Component)player).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner())
				{
					component.GetZDO().Set("RoVAzuEPI_PassiveAuraEnabled", enabled);
				}
				if (Race(player) == "Aswid")
				{
					AswidRace.AuraEnabled = enabled;
				}
			}
		}

		internal static string SkeletonModel(Player player)
		{
			if (player?.m_customData != null && player.m_customData.TryGetValue("RoVAzuEPI_SkeletonModel", out var value))
			{
				return value;
			}
			return "Auto";
		}

		internal static void SetSkeletonModel(Player player, string model)
		{
			if (player?.m_customData != null)
			{
				player.m_customData["RoVAzuEPI_SkeletonModel"] = model ?? "Auto";
				ZNetView component = ((Component)player).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner())
				{
					component.GetZDO().Set("RoVAzuEPI_SkeletonModel", model ?? "Auto");
				}
			}
		}

		internal static bool LocalEnabledFor(string race)
		{
			Player val = _visualContext ?? Player.m_localPlayer;
			if (!((Object)(object)val == (Object)null) && !(Race(val) != race))
			{
				return IsEnabled(val);
			}
			return true;
		}

		internal static bool EnabledFor(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				return IsEnabled(player);
			}
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				return component.GetZDO().GetBool("RoVAzuEPI_PassiveAuraEnabled", true);
			}
			return true;
		}

		internal static bool ShouldShowSkeletonHeadFlame(Player player)
		{
			if ((Object)(object)player == (Object)null || !SkeletonConfig.HeadFireVFXEnabled.Value || !EnabledFor(player) || Race(player) != "Skeleton")
			{
				return false;
			}
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			return (((Object)(object)component != (Object)null && component.IsValid() && (Object)(object)player != (Object)(object)Player.m_localPlayer) ? component.GetZDO().GetInt("RacesOfValheim_SkeletonState", 0) : BossProgressionManager.GetCurrentProgressionState()) >= 5;
		}

		internal static Transform GetSkeletonEyeAnchor(Player player)
		{
			object obj;
			if (player == null)
			{
				obj = null;
			}
			else
			{
				VisEquipment component = ((Component)player).GetComponent<VisEquipment>();
				if (component == null)
				{
					obj = null;
				}
				else
				{
					SkinnedMeshRenderer bodyModel = component.m_bodyModel;
					obj = ((bodyModel != null) ? bodyModel.bones : null);
				}
			}
			Transform[] array = (Transform[])obj;
			if (array == null)
			{
				return null;
			}
			Transform val = null;
			Transform result = null;
			Transform[] array2 = array;
			foreach (Transform val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				bool flag = ((Object)val2).name.Equals("Head", StringComparison.OrdinalIgnoreCase);
				if (flag)
				{
					result = val2;
				}
				for (int j = 0; j < val2.childCount; j++)
				{
					Transform child = val2.GetChild(j);
					if (!((Object)child).name.StartsWith("SkeletonEyeFX_") || ((Object)child).name.Contains("_Removed") || !((Component)child).gameObject.activeInHierarchy)
					{
						continue;
					}
					string text = ((Object)val2).name.ToLowerInvariant();
					if (text.Contains("eye_l") || text.Contains("eye_r") || text.Contains("lefteye") || text.Contains("righteye"))
					{
						if (!((Object)(object)val2.parent != (Object)null))
						{
							return val2;
						}
						return val2.parent;
					}
					if (flag)
					{
						val = val2;
					}
				}
			}
			if (!((Object)(object)val != (Object)null))
			{
				return result;
			}
			return val;
		}

		internal static void DisableDuplicatedHildirFire(Player player)
		{
			object obj;
			if (player == null)
			{
				obj = null;
			}
			else
			{
				VisEquipment component = ((Component)player).GetComponent<VisEquipment>();
				if (component == null)
				{
					obj = null;
				}
				else
				{
					SkinnedMeshRenderer bodyModel = component.m_bodyModel;
					obj = ((bodyModel != null) ? bodyModel.bones : null);
				}
			}
			Transform[] array = (Transform[])obj;
			if (array == null)
			{
				return;
			}
			Transform[] array2 = array;
			foreach (Transform val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				for (int j = 0; j < val.childCount; j++)
				{
					Transform child = val.GetChild(j);
					string text = ((Object)child).name.ToLowerInvariant();
					if (text.StartsWith("skeletoneyefx_skeleton_hildir_") && (text.Contains("fx_torch_carried") || text.Contains("headlamp")))
					{
						((Component)child).gameObject.SetActive(false);
					}
				}
			}
		}

		internal static void ApplySkeletonPreviewFlame(Player preview, Player settingsSource = null)
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: 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)
			if ((Object)(object)preview == (Object)null)
			{
				return;
			}
			Transform val = ((Component)preview).transform.Find("RoVAzuEPI_SkeletonHeadFlamePreview");
			GameObject val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).gameObject);
			if (Race(preview) != "Skeleton")
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetActive(false);
				}
				return;
			}
			bool num = ShouldShowSkeletonHeadFlame(settingsSource ?? preview);
			DisableDuplicatedHildirFire(preview);
			if (!num)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetActive(false);
				}
				return;
			}
			Transform skeletonEyeAnchor = GetSkeletonEyeAnchor(preview);
			if ((Object)(object)skeletonEyeAnchor == (Object)null)
			{
				return;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SkeletonVisuals), "ResolveFlameSource", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(SkeletonVisuals), "IsFire", (Type[])null, (Type[])null);
				object? obj = methodInfo?.Invoke(null, null);
				GameObject val3 = (GameObject)((obj is GameObject) ? obj : null);
				Type type = AccessTools.TypeByName("UnityEngine.ParticleSystem");
				if ((Object)(object)val3 == (Object)null || type == null)
				{
					return;
				}
				val2 = new GameObject("RoVAzuEPI_SkeletonHeadFlamePreview");
				val2.transform.SetParent(((Component)preview).transform, false);
				val2.transform.localScale = Vector3.one * 1.8f;
				int num2 = 0;
				Component[] componentsInChildren = val3.GetComponentsInChildren(type, true);
				foreach (Component val4 in componentsInChildren)
				{
					if (methodInfo2 == null || (bool)methodInfo2.Invoke(null, new object[1] { val4.gameObject }))
					{
						GameObject val5 = SkeletonVisuals.BorrowEffect(val4.gameObject, val2.transform, ((Object)val4.gameObject).name, false, "Skeleton preview");
						if (!((Object)(object)val5 == (Object)null))
						{
							val5.transform.localPosition = Vector3.zero;
							val5.transform.localRotation = Quaternion.identity;
							num2++;
						}
					}
				}
				if (num2 == 0)
				{
					Object.Destroy((Object)(object)val2);
					return;
				}
			}
			val2.SetActive(true);
			(val2.GetComponent<SkeletonPreviewFlameFollower>() ?? val2.AddComponent<SkeletonPreviewFlameFollower>()).Configure(skeletonEyeAnchor);
		}

		internal static void EnterVisualContext(Player player)
		{
			_visualContext = player;
		}

		internal static void LeaveVisualContext()
		{
			_visualContext = null;
		}

		internal static Player ReplaceVisualContext(Player player)
		{
			Player visualContext = _visualContext;
			_visualContext = player;
			return visualContext;
		}

		internal static void RestoreVisualContext(Player previous)
		{
			_visualContext = previous;
		}

		internal static void Publish(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner())
			{
				bool flag = IsEnabled(player);
				component.GetZDO().Set("RoVAzuEPI_PassiveAuraEnabled", flag);
				component.GetZDO().Set("RoVAzuEPI_SkeletonModel", SkeletonModel(player));
				if (Race(player) == "Aswid")
				{
					AswidRace.AuraEnabled = flag;
				}
			}
		}

		internal static string ContextSkeletonModel()
		{
			Player val = _visualContext ?? Player.m_localPlayer;
			if ((Object)(object)val == (Object)null)
			{
				return "Auto";
			}
			if ((Object)(object)val == (Object)(object)Player.m_localPlayer || (val.m_customData != null && val.m_customData.ContainsKey("RoVAzuEPI_SkeletonModel")))
			{
				return SkeletonModel(val);
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				return component.GetZDO().GetString("RoVAzuEPI_SkeletonModel", "Auto");
			}
			return "Auto";
		}
	}
	internal sealed class SkeletonPreviewFlameFollower : MonoBehaviour
	{
		private Transform _anchor;

		internal void Configure(Transform anchor)
		{
			_anchor = anchor;
			Follow();
		}

		private void LateUpdate()
		{
			Follow();
		}

		private void Follow()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_anchor == (Object)null))
			{
				((Component)this).transform.position = _anchor.position + _anchor.up * 0.18f;
				((Component)this).transform.rotation = _anchor.rotation;
			}
		}
	}
	internal sealed class RaceOptionsUi : MonoBehaviour
	{
		private GameObject _root;

		private Button _toggle;

		private TMP_Text _toggleText;

		private TMP_Dropdown _models;

		private bool _updating;

		internal void Refresh()
		{
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			string text = RaceOptions.Race(localPlayer);
			int num = ((!((Object)(object)localPlayer == (Object)null)) ? BossProgressionManager.GetCurrentProgressionState() : 0);
			bool flag = (Object)(object)localPlayer != (Object)null && (RaceOptions.SupportsToggle(text) || text == "Skeleton");
			if ((Object)(object)_root != (Object)null && ((Object)(object)_toggle == (Object)null || (Object)(object)_toggleText == (Object)null || (Object)(object)_models == (Object)null))
			{
				Object.Destroy((Object)(object)_root);
				_root = null;
			}
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			if ((Object)(object)_root == (Object)null || (Object)(object)_toggle == (Object)null || (Object)(object)_toggleText == (Object)null || (Object)(object)_models == (Object)null)
			{
				return;
			}
			_root.SetActive(flag);
			if (!flag)
			{
				return;
			}
			int num2;
			switch (text)
			{
			case "Skeleton":
				if (num < 5)
				{
					goto default;
				}
				goto case "Draugh";
			default:
				if (!(text == "Skadi") || num < 7)
				{
					num2 = ((text == "Trenta" && num >= 7) ? 1 : 0);
					break;
				}
				goto case "Draugh";
			case "Draugh":
			case "Aswid":
				num2 = 1;
				break;
			}
			bool active = (byte)num2 != 0;
			((Component)_toggle).gameObject.SetActive(active);
			bool flag2 = RaceOptions.IsEnabled(localPlayer);
			_toggleText.text = "Aura";
			((Graphic)((Selectable)_toggle).image).color = (flag2 ? new Color(0.55f, 0.82f, 0.48f, 0.95f) : new Color(0.65f, 0.35f, 0.32f, 0.95f));
			bool flag3 = text == "Skeleton";
			((Component)_models).gameObject.SetActive(flag3);
			if (flag3)
			{
				RefreshModels(localPlayer);
			}
		}

		private void Build()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00d6: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Transform infoPanel = instance.m_infoPanel;
			RectTransform val = (RectTransform)(object)((infoPanel is RectTransform) ? infoPanel : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			_root = new GameObject("RoV_RaceOptions", new Type[2]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup)
			});
			_root.transform.SetParent((Transform)(object)val, false);
			RectTransform val2 = (RectTransform)_root.transform;
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 1f);
			val2.anchoredPosition = new Vector2(10f, -8f);
			val2.sizeDelta = new Vector2(204f, 24f);
			_root.transform.SetAsLastSibling();
			HorizontalLayoutGroup component = _root.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).spacing = 6f;
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)component).childControlHeight = false;
			_toggle = CreateButton(_root.transform, new Vector2(60f, 22f), out _toggleText);
			((UnityEvent)_toggle.onClick).AddListener((UnityAction)delegate
			{
				Player localPlayer = Player.m_localPlayer;
				RaceOptions.SetEnabled(localPlayer, !RaceOptions.IsEnabled(localPlayer));
				Refresh();
				Plugin.Instance?.RefreshOnOpen();
			});
			_models = CreateDropdown(_root.transform);
			((UnityEvent<int>)(object)_models.onValueChanged).AddListener((UnityAction<int>)delegate(int index)
			{
				if (!_updating && !((Object)(object)Player.m_localPlayer == (Object)null) && index >= 0 && index < _models.options.Count)
				{
					RaceOptions.SetSkeletonModel(Player.m_localPlayer, ModelId(_models.options[index].text));
					Plugin.Instance?.RefreshOnOpen();
				}
			});
		}

		private void RefreshModels(Player player)
		{
			int currentProgressionState = BossProgressionManager.GetCurrentProgressionState();
			List<string> list = new List<string> { "Automatic", "Skeleton" };
			if (currentProgressionState >= 2)
			{
				list.Add("Poison skeleton");
			}
			if (currentProgressionState >= 5)
			{
				list.Add("Fire skeleton");
			}
			string text = RaceOptions.SkeletonModel(player);
			int value = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (ModelId(list[i]) == text)
				{
					value = i;
				}
			}
			_updating = true;
			_models.ClearOptions();
			_models.AddOptions(list);
			_models.value = value;
			_models.RefreshShownValue();
			_updating = false;
		}

		private static string ModelId(string label)
		{
			return label switch
			{
				"Skeleton" => "Skeleton", 
				"Poison skeleton" => "Skeleton_Poison", 
				"Fire skeleton" => "Skeleton_Hildir", 
				_ => "Auto", 
			};
		}

		private static TMP_FontAsset UiFont()
		{
			InventoryGui instance = InventoryGui.instance;
			TMP_Text val = ((instance != null) ? ((Component)instance).GetComponentInChildren<TMP_Text>(true) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.font;
		}

		private static Button CreateButton(Transform parent, Vector2 size, out TMP_Text label)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00d6: 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_00dc: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("AuraToggle", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button),
				typeof(LayoutElement)
			});
			val.transform.SetParent(parent, false);
			((RectTransform)val.transform).sizeDelta = size;
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.preferredWidth = size.x;
			component.preferredHeight = size.y;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)val.GetComponent<Image>();
			GameObject val2 = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val3.offsetMin = Vector2.zero;
			val3.offsetMax = Vector2.zero;
			label = (TMP_Text)(object)val2.GetComponent<TextMeshProUGUI>();
			label.font = UiFont();
			label.fontSize = 13f;
			label.alignment = (TextAlignmentOptions)514;
			((Graphic)label).color = Color.white;
			return component2;
		}

		private static TMP_Dropdown CreateDropdown(Transform parent)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0143: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Expected O, but got Unknown
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: 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_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Expected O, but got Unknown
			GameObject val = new GameObject("SkeletonModelDropdown", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(TMP_Dropdown),
				typeof(LayoutElement)
			});
			val.transform.SetParent(parent, false);
			((RectTransform)val.transform).sizeDelta = new Vector2(132f, 22f);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.preferredWidth = 132f;
			component.preferredHeight = 22f;
			((Graphic)val.GetComponent<Image>()).color = new Color(0.18f, 0.18f, 0.18f, 0.95f);
			CreateText(val.transform, "Label", new Vector2(6f, 0f), new Vector2(-22f, 0f), out var text);
			GameObject val2 = new GameObject("Template", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(ScrollRect)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0f, 0f);
			val3.anchorMax = new Vector2(1f, 0f);
			val3.pivot = new Vector2(0.5f, 1f);
			val3.anchoredPosition = Vector2.zero;
			val3.sizeDelta = new Vector2(0f, 112f);
			((Graphic)val2.GetComponent<Image>()).color = new Color(0.12f, 0.12f, 0.12f, 0.98f);
			GameObject val4 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Mask),
				typeof(Image)
			});
			val4.transform.SetParent(val2.transform, false);
			Stretch((RectTransform)val4.transform);
			val4.GetComponent<Mask>().showMaskGraphic = false;
			GameObject val5 = new GameObject("Content", new Type[3]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			val5.transform.SetParent(val4.transform, false);
			RectTransform val6 = (RectTransform)val5.transform;
			val6.anchorMin = new Vector2(0f, 1f);
			val6.anchorMax = new Vector2(1f, 1f);
			val6.pivot = new Vector2(0.5f, 1f);
			val6.sizeDelta = Vector2.zero;
			val5.GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			GameObject val7 = new GameObject("Item", new Type[3]
			{
				typeof(RectTransform),
				typeof(Toggle),
				typeof(LayoutElement)
			});
			val7.transform.SetParent(val5.transform, false);
			val7.GetComponent<LayoutElement>().preferredHeight = 28f;
			CreateText(val7.transform, "Item Label", new Vector2(6f, 0f), new Vector2(-4f, 0f), out var text2);
			((Selectable)val7.GetComponent<Toggle>()).targetGraphic = (Graphic)(object)text2;
			ScrollRect component2 = val2.GetComponent<ScrollRect>();
			component2.viewport = (RectTransform)val4.transform;
			component2.content = val6;
			component2.horizontal = false;
			TMP_Dropdown component3 = val.GetComponent<TMP_Dropdown>();
			((Selectable)component3).targetGraphic = (Graphic)(object)val.GetComponent<Image>();
			component3.template = val3;
			component3.captionText = text;
			component3.itemText = text2;
			val2.SetActive(false);
			return component3;
		}

		private static void CreateText(Transform parent, string name, Vector2 leftBottom, Vector2 rightTop, out TMP_Text text)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = leftBottom;
			val2.offsetMax = rightTop;
			text = (TMP_Text)(object)val.GetComponent<TextMeshProUGUI>();
			text.font = UiFont();
			text.fontSize = 13f;
			text.alignment = (TextAlignmentOptions)4097;
			((Graphic)text).color = Color.white;
		}

		private static void Stretch(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = Vector2.zero;
			rt.offsetMax = Vector2.zero;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	internal static class RaceOptionsInventoryShowPatch
	{
		private static void Postfix(InventoryGui __instance)
		{
			(((Component)__instance).GetComponent<RaceOptionsUi>() ?? ((Component)__instance).gameObject.AddComponent<RaceOptionsUi>()).Refresh();
		}
	}
	[HarmonyPatch]
	internal static class SkeletonAuraDamagePatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(SkeletonRace), "ApplyFireAura", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			return RaceOptions.LocalEnabledFor("Skeleton");
		}
	}
	[HarmonyPatch]
	internal static class SkeletonHeadFlameBuildEyeAnchorPatch
	{
		private static readonly MethodInfo ResolveSource = AccessTools.Method(typeof(SkeletonVisuals), "ResolveFlameSource", (Type[])null, (Type[])null);

		private static readonly MethodInfo IsFire = AccessTools.Method(typeof(SkeletonVisuals), "IsFire", (Type[])null, (Type[])null);

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(HeadFlame), "Build", (Type[])null, (Type[])null);
		}

		private static void Postfix(Player player, ref bool __result, ref GameObject ___m_instance, ref Transform ___m_headBone)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0078: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if (__result || (Object)(object)player == (Object)null)
			{
				return;
			}
			Transform skeletonEyeAnchor = RaceOptions.GetSkeletonEyeAnchor(player);
			object? obj = ResolveSource?.Invoke(null, null);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			Type type = AccessTools.TypeByName("UnityEngine.ParticleSystem");
			if ((Object)(object)skeletonEyeAnchor == (Object)null || (Object)(object)val == (Object)null || type == null)
			{
				return;
			}
			GameObject val2 = new GameObject("SkeletonHeadFlameVFX");
			val2.transform.SetParent(((Component)player).transform, false);
			val2.transform.localScale = Vector3.one * 1.8f;
			int num = 0;
			Component[] componentsInChildren = val.GetComponentsInChildren(type, true);
			foreach (Component val3 in componentsInChildren)
			{
				if (IsFire == null || (bool)IsFire.Invoke(null, new object[1] { val3.gameObject }))
				{
					GameObject val4 = SkeletonVisuals.BorrowEffect(val3.gameObject, val2.transform, ((Object)val3.gameObject).name, false, "Skeleton");
					if (!((Object)(object)val4 == (Object)null))
					{
						val4.transform.localPosition = Vector3.zero;
						val4.transform.localRotation = Quaternion.identity;
						num++;
					}
				}
			}
			if (num == 0)
			{
				Object.Destroy((Object)(object)val2);
				return;
			}
			___m_headBone = skeletonEyeAnchor;
			___m_instance = val2;
			__result = true;
		}
	}
	[HarmonyPatch]
	internal static class SkeletonHeadFlameEyeAnchorPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(HeadFlame), "Apply", (Type[])null, (Type[])null);
		}

		private static void Prefix(Player player, ref bool enable)
		{
			enable = RaceOptions.ShouldShowSkeletonHeadFlame(player);
		}

		private static void Postfix(Player player, GameObject ___m_instance, ref Transform ___m_headBone)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			RaceOptions.DisableDuplicatedHildirFire(player);
			if (RaceOptions.ShouldShowSkeletonHeadFlame(player) && !((Object)(object)___m_instance == (Object)null))
			{
				Transform skeletonEyeAnchor = RaceOptions.GetSkeletonEyeAnchor(player);
				if (!((Object)(object)skeletonEyeAnchor == (Object)null))
				{
					___m_headBone = skeletonEyeAnchor;
					___m_instance.transform.position = skeletonEyeAnchor.position + skeletonEyeAnchor.up * 0.18f;
					___m_instance.transform.rotation = skeletonEyeAnchor.rotation;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class SkadiAuraDamagePatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(SkadiRace), "ApplyColdAura", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			return RaceOptions.LocalEnabledFor("Skadi");
		}
	}
	[HarmonyPatch]
	internal static class SkadiAuraVisualPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(SkadiRace), "EnsureFrostAuraVFX", (Type[])null, (Type[])null);
		}

		private static void Prefix(ref bool enable)
		{
			if (!RaceOptions.LocalEnabledFor("Skadi"))
			{
				enable = false;
			}
		}
	}
	[HarmonyPatch]
	internal static class AswidAuraPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(AswidRace), "HandleVampiricAura", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			return RaceOptions.LocalEnabledFor("Aswid");
		}
	}
	[HarmonyPatch(typeof(TrentaAbilities), "TickHornetsNest")]
	internal static class TrentaAuraPatch
	{
		private static void Prefix(ref bool shouldExist)
		{
			if (!RaceOptions.LocalEnabledFor("Trenta"))
			{
				shouldExist = false;
			}
		}
	}
	[HarmonyPatch(typeof(DraughVisuals), "EnsureAura")]
	internal static class DraughStenchPatch
	{
		private static void Prefix(Player player, ref bool enable)
		{
			if (!RaceOptions.EnabledFor(player))
			{
				enable = false;
			}
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "UpdateVisuals")]
	internal static class SkeletonModelVisContextPatch
	{
		private static void Prefix(VisEquipment __instance, out Player __state)
		{
			__state = RaceOptions.ReplaceVisualContext(((Component)__instance).GetComponent<Player>());
		}

		private static void Finalizer(Player __state)
		{
			RaceOptions.RestoreVisualContext(__state);
		}
	}
	[HarmonyPatch]
	internal static class SkeletonRemoteModelContextPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(RacesVisualController), "UpdateSkeletonVisuals", (Type[])null, (Type[])null);
		}

		private static void Prefix(RacesVisualController __instance, out Player __state)
		{
			__state = RaceOptions.ReplaceVisualContext(((Component)__instance).GetComponent<Player>());
		}

		private static void Finalizer(Player __state)
		{
			RaceOptions.RestoreVisualContext(__state);
		}
	}
	[HarmonyPatch(typeof(Player), "Start")]
	internal static class RaceOptionsPublishPatch
	{
		private static void Postfix(Player __instance)
		{
			RaceOptions.Publish(__instance);
		}
	}
	[HarmonyPatch(typeof(SkeletonProgression), "GetRules")]
	internal static class SkeletonModelChoicePatch
	{
		private static void Postfix(int state, ref SkeletonRules __result)
		{
			//IL_007e: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			Player val = RaceOptions.VisualContext ?? Player.m_localPlayer;
			if (!((Object)(object)val == (Object)null) && !(RaceOptions.Race(val) != "Skeleton"))
			{
				string text = RaceOptions.ContextSkeletonModel();
				if (!(text == "Auto") && (!(text == "Skeleton_Poison") || state >= 2) && (!(text == "Skeleton_Hildir") || state >= 5))
				{
					__result.ModelPrefab = text;
					__result.ScaleMultiplier = ((text == "Skeleton_Hildir") ? SkeletonProgression.FireModelScale : Vector3.one);
				}
			}
		}
	}
	internal static class RagdollAppearance
	{
		private sealed class AppearanceSnapshot
		{
			internal int PlayerInstanceId;

			internal Vector3 Position;

			internal Vector3 Scale;

			internal Vector3 VisualScale;

			internal float ExpiresAt;

			internal readonly List<RendererSnapshot> Renderers = new List<RendererSnapshot>();
		}

		private sealed class RendererSnapshot
		{
			private string _name;

			private string _parentName;

			private Vector3 _localPosition;

			private Quaternion _localRotation;

			private Vector3 _localScale;

			private Mesh _mesh;

			private Material[] _materials;

			private string[] _boneNames;

			private string _rootBoneName;

			private bool _skinned;

			private Bounds _localBounds;

			private bool _updateWhenOffscreen;

			internal static RendererSnapshot From(SkinnedMeshRenderer renderer, HashSet<Transform> sourceBones)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				RendererSnapshot rendererSnapshot = CreateCommon((Renderer)(object)renderer, sourceBones);
				rendererSnapshot._skinned = true;
				rendererSnapshot._localBounds = ((Renderer)renderer).localBounds;
				rendererSnapshot._updateWhenOffscreen = renderer.updateWhenOffscreen;
				rendererSnapshot._rootBoneName = (((Object)(object)renderer.rootBone == (Object)null) ? null : ((Object)renderer.rootBone).name);
				rendererSnapshot._boneNames = new string[renderer.bones.Length];
				for (int i = 0; i < renderer.bones.Length; i++)
				{
					rendererSnapshot._boneNames[i] = (((Object)(object)renderer.bones[i] == (Object)null) ? null : ((Object)renderer.bones[i]).name);
				}
				return rendererSnapshot;
			}

			internal static RendererSnapshot From(MeshRenderer renderer, MeshFilter filter, HashSet<Transform> sourceBones)
			{
				RendererSnapshot rendererSnapshot = CreateCommon((Renderer)(object)renderer, sourceBones);
				rendererSnapshot._mesh = filter.sharedMesh;
				return rendererSnapshot;
			}

			private static RendererSnapshot CreateCommon(Renderer renderer, HashSet<Transform> sourceBones)
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: 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_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: 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_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_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				RendererSnapshot obj = new RendererSnapshot
				{
					_name = ((Object)((Component)renderer).gameObject).name,
					_parentName = (((Object)(object)((Component)renderer).transform.parent == (Object)null) ? null : ((Object)((Component)renderer).transform.parent).name),
					_localPosition = ((Component)renderer).transform.localPosition,
					_localRotation = ((Component)renderer).transform.localRotation,
					_localScale = ((Component)renderer).transform.localScale
				};
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				obj._mesh = ((val != null) ? val.sharedMesh : null);
				obj._materials = renderer.sharedMaterials;
				RendererSnapshot rendererSnapshot = obj;
				Transform val2 = FindNearestBone(((Component)renderer).transform, sourceBones);
				if ((Object)(object)val2 != (Object)null)
				{
					rendererSnapshot._parentName = ((Object)val2).name;
					rendererSnapshot._localPosition = val2.InverseTransformPoint(((Component)renderer).transform.position);
					rendererSnapshot._localRotation = Quaternion.Inverse(val2.rotation) * ((Component)renderer).transform.rotation;
					rendererSnapshot._localScale = DivideScale(((Component)renderer).transform.lossyScale, val2.lossyScale);
				}
				return rendererSnapshot;
			}

			private static Transform FindNearestBone(Transform candidate, HashSet<Transform> sourceBones)
			{
				Transform parent = candidate.parent;
				while ((Object)(object)parent != (Object)null)
				{
					if (sourceBones.Contains(parent))
					{
						return parent;
					}
					parent = parent.parent;
				}
				return null;
			}

			private static Vector3 DivideScale(Vector3 value, Vector3 divisor)
			{
				//IL_0000: 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_0012: 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_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				return new Vector3((Mathf.Abs(divisor.x) < 0.0001f) ? value.x : (value.x / divisor.x), (Mathf.Abs(divisor.y) < 0.0001f) ? value.y : (value.y / divisor.y), (Mathf.Abs(divisor.z) < 0.0001f) ? value.z : (value.z / divisor.z));
			}

			internal void Create(Transform fallbackParent, Dictionary<string, Transform> bones, int layer)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				//IL_004d: 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_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				Transform val = fallbackParent;
				if (_parentName != null && bones.TryGetValue(_parentName, out var value))
				{
					val = value;
				}
				GameObject val2 = new GameObject("RoVRagdoll_" + _name);
				val2.layer = layer;
				val2.transform.SetParent(val, false);
				val2.transform.localPosition = _localPosition;
				val2.transform.localRotation = _localRotation;
				val2.transform.localScale = _localScale;
				if (_skinned)
				{
					SkinnedMeshRenderer val3 = val2.AddComponent<SkinnedMeshRenderer>();
					val3.sharedMesh = _mesh;
					((Renderer)val3).sharedMaterials = _materials;
					((Renderer)val3).localBounds = _localBounds;
					val3.updateWhenOffscreen = _updateWhenOffscreen;
					val3.bones = ResolveBones(_boneNames, bones);
					if (_rootBoneName != null && bones.TryGetValue(_rootBoneName, out var value2))
					{
						val3.rootBone = value2;
					}
				}
				else
				{
					val2.AddComponent<MeshFilter>().sharedMesh = _mesh;
					((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterials = _materials;
				}
			}

			private static Transform[] ResolveBones(string[] names, Dictionary<string, Transform> bones)
			{
				if (names == null)
				{
					return Array.Empty<Transform>();
				}
				Transform[] array = (Transform[])(object)new Transform[names.Length];
				for (int i = 0; i < names.Length; i++)
				{
					if (names[i] != null)
					{
						bones.TryGetValue(names[i], out array[i]);
					}
				}
				return array;
			}
		}

		private sealed class AppliedRaceAppearance : MonoBehaviour
		{
		}

		private const float SnapshotLifetime = 15f;

		private const float MatchDistanceSquared = 16f;

		private static readonly List<AppearanceSnapshot> Pending = new List<AppearanceSnapshot>();

		private static AppearanceSnapshot _activeDeath;

		internal static void Capture(Player player, bool markActiveDeath)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			string race = GetRace(player);
			if (race == "Human")
			{
				return;
			}
			int playerInstanceId = ((Object)player).GetInstanceID();
			PruneExpired();
			AppearanceSnapshot appearanceSnapshot = Pending.Find((AppearanceSnapshot snapshot) => snapshot.PlayerInstanceId == playerInstanceId);
			if (appearanceSnapshot != null)
			{
				if (markActiveDeath)
				{
					_activeDeath = appearanceSnapshot;
				}
				return;
			}
			Transform val = ((Component)player).transform.Find("Visual");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Dictionary<Renderer, bool> hiddenRendererStates = GetHiddenRendererStates(val);
			bool transformed = hiddenRendererStates != null;
			List<Transform> excludedRendererRoots = GetExcludedRendererRoots(player, race);
			Mesh excludedBodyMesh = GetExcludedBodyMesh(player, race);
			HashSet<Transform> sourceBones = GetSourceBones(player);
			AppearanceSnapshot appearanceSnapshot2 = new AppearanceSnapshot
			{
				PlayerInstanceId = playerInstanceId,
				Position = ((Component)player).transform.position,
				Scale = GetBasePlayerScale(player, race, transformed),
				VisualScale = GetBaseVisualScale(player, race, val, transformed),
				ExpiresAt = Time.unscaledTime + 15f
			};
			SkinnedMeshRenderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sharedMesh == (Object)null) && WasVisibleBeforeTransformation((Renderer)(object)val2, hiddenRendererStates) && !IsUnderExcludedRoot(((Component)val2).transform, excludedRendererRoots) && (!((Object)(object)excludedBodyMesh != (Object)null) || !((Object)(object)val2.sharedMesh == (Object)(object)excludedBodyMesh) || IsSkeletonReplacement(((Component)val2).transform)))
				{
					RendererSnapshot item = RendererSnapshot.From(val2, sourceBones);
					appearanceSnapshot2.Renderers.Add(item);
				}
			}
			MeshRenderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val3 in componentsInChildren2)
			{
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				if (!((Object)(object)val3 == (Object)null) && WasVisibleBeforeTransformation((Renderer)(object)val3, hiddenRendererStates) && !((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && !IsUnderExcludedRoot(((Component)val3).transform, excludedRendererRoots))
				{
					appearanceSnapshot2.Renderers.Add(RendererSnapshot.From(val3, component, sourceBones));
				}
			}
			if (appearanceSnapshot2.Renderers.Count != 0)
			{
				Pending.Add(appearanceSnapshot2);
				if (markActiveDeath)
				{
					_activeDeath = appearanceSnapshot2;
				}
			}
		}

		internal static void FinishDeath()
		{
			_activeDeath = null;
		}

		internal static void HideTemporaryForm(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Transform val = ((Component)player).transform.Find("Visual");
			Renderer[] componentsInChildren = ((Component)player).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)))
				{
					val2.enabled = false;
					val2.forceRenderingOff = true;
				}
			}
		}

		internal static void Apply(Ragdoll ragdoll)
		{
			//IL_0023: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			if ((Object)(object)ragdoll == (Object)null || (Object)(object)((Component)ragdoll).GetComponent<AppliedRaceAppearance>() != (Object)null)
			{
				return;
			}
			PruneExpired();
			AppearanceSnapshot appearanceSnapshot = FindSnapshot(((Component)ragdoll).transform.position);
			if (appearanceSnapshot == null)
			{
				return;
			}
			try
			{
				((Component)ragdoll).gameObject.AddComponent<AppliedRaceAppearance>();
				Renderer[] componentsInChildren = ((Component)ragdoll).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer obj in componentsInChildren)
				{
					obj.enabled = false;
					obj.forceRenderingOff = true;
				}
				((Component)ragdoll).transform.localScale = Vector3.Scale(appearanceSnapshot.Scale, appearanceSnapshot.VisualScale);
				Dictionary<string, Transform> bones = BuildTransformMap(((Component)ragdoll).transform);
				GameObject val = new GameObject("RacesOfValheimRagdollAppearance");
				val.transform.SetParent(((Component)ragdoll).transform, false);
				val.layer = ((Component)ragdoll).gameObject.layer;
				foreach (RendererSnapshot renderer in appearanceSnapshot.Renderers)
				{
					renderer.Create(val.transform, bones, ((Component)ragdoll).gameObject.layer);
				}
				Pending.Remove(appearanceSnapshot);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Failed to apply race appearance to ragdoll: " + ex));
				}
			}
		}

		private static AppearanceSnapshot FindSnapshot(Vector3 position)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val;
			if (_activeDeath != null)
			{
				val = _activeDeath.Position - position;
				if (((Vector3)(ref val)).sqrMagnitude <= 16f)
				{
					return _activeDeath;
				}
			}
			AppearanceSnapshot result = null;
			float num = 16f;
			foreach (AppearanceSnapshot item in Pending)
			{
				val = item.Position - position;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude <= num)
				{
					result = item;
					num = sqrMagnitude;
				}
			}
			return result;
		}

		private static void PruneExpired()
		{
			float now = Time.unscaledTime;
			Pending.RemoveAll((AppearanceSnapshot snapshot) => snapshot.ExpiresAt < now);
		}

		private static string GetRace(Player player)
		{
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				string text = component.GetZDO().GetString("RacesOfValheim_Race", "Human");
				if (text != "Human")
				{
					return text;
				}
			}
			if (player.m_customData != null && player.m_customData.TryGetValue("Race", out var value))
			{
				return value;
			}
			return "Human";
		}

		private static List<Transform> GetExcludedRendererRoots(Player player, string race)
		{
			List<Transform> list = new List<Transform>();
			if (race != "Skeleton" && race != "Dvergar")
			{
				return list;
			}
			VisEquipment component = ((Component)player).GetComponent<VisEquipment>();
			if ((Object)(object)component == (Object)null)
			{
				return list;
			}
			if (race != "Skeleton" || !SkeletonArmorVisibility.IsEnabled(player, SkeletonArmorPart.Helmet))
			{
				AddEquipmentInstanceRoot(component, "m_helmetItemInstance", list);
			}
			if (race == "Skeleton")
			{
				if ((Object)(object)component.m_bodyModel != (Object)null)
				{
					list.Add(((Component)component.m_bodyModel).transform);
				}
				AddEquipmentInstanceRoot(component, "m_hairItemInstance", list);
				AddEquipmentInstanceRoot(component, "m_beardItemInstance", list);
			}
			return list;
		}

		private static Dictionary<Renderer, bool> GetHiddenRendererStates(Transform visual)
		{
			Type type = AccessTools.TypeByName("RacesOfValheim.PlayerVisualHider");
			Component val = ((type == null) ? null : ((Component)visual).GetComponent(type));
			Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
			if (val2 == null || !val2.enabled)
			{
				return null;
			}
			if (!(AccessTools.Field(type, "m_hidden")?.GetValue(val) is IEnumerable enumerable))
			{
				return null;
			}
			Dictionary<Renderer, bool> dictionary = new Dictionary<Renderer, bool>();
			foreach (object item in enumerable)
			{
				if (item != null)
				{
					Type type2 = item.GetType();
					object? obj = AccessTools.Field(type2, "Renderer")?.GetValue(item);
					Renderer val3 = (Renderer)((obj is Renderer) ? obj : null);
					object obj2 = AccessTools.Field(type2, "WasEnabled")?.GetValue(item);
					if ((Object)(object)val3 != (Object)null && obj2 is bool value)
					{
						dictionary[val3] = value;
					}
				}
			}
			return dictionary;
		}

		private static bool WasVisibleBeforeTransformation(Renderer renderer, Dictionary<Renderer, bool> hiddenRendererStates)
		{
			if (!((Component)renderer).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (hiddenRendererStates != null && hiddenRendererStates.TryGetValue(renderer, out var value))
			{
				return value;
			}
			if (renderer.enabled)
			{
				return !renderer.forceRenderingOff;
			}
			return false;
		}

		private static Vector3 GetBasePlayerScale(Player player, string race, bool transformed)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!transformed || race != "Aswid")
			{
				return ((Component)player).transform.localScale;
			}
			int networkState = GetNetworkState(player, "RacesOfValheim_AswidState");
			return Vector3.one * ((networkState >= 8) ? 1.1f : 1f);
		}

		private static Vector3 GetBaseVisualScale(Player player, string race, Transform visual, bool transformed)
		{
			//IL_0036: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			switch (race)
			{
			case "Dvergar":
				return Vector3.one * 0.78f;
			case "Furling":
				return Vector3.one * 0.81f;
			case "Trol":
			{
				int networkState = GetNetworkState(player, "RacesOfValheim_State");
				float num = ((networkState >= 6) ? 1.3f : ((networkState >= 4) ? 1.25f : 1.2f));
				return Vector3.one * num;
			}
			case "Sverm":
			{
				int networkState2 = GetNetworkState(player, "RacesOfValheim_SvermState");
				return Vector3.one * ((networkState2 >= 7) ? 1.1f : 1f);
			}
			default:
				if (!transformed)
				{
					return visual.localScale;
				}
				return Vector3.one;
			}
		}

		private static int GetNetworkState(Player player, string key)
		{
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				return component.GetZDO().GetInt(key, 1);
			}
			return GetCurrentProgressionFallback();
		}

		private static int GetCurrentProgressionFallback()
		{
			MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName("RacesOfValheim.BossProgressionManager"), "GetCurrentProgressionState", (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				return (int)methodInfo.Invoke(null, null);
			}
			return 1;
		}

		private static void AddEquipmentInstanceRoot(VisEquipment equipment, string fieldName, List<Transform> roots)
		{
			object? obj = AccessTools.Field(typeof(VisEquipment), fieldName)?.GetValue(equipment);
			GameObject val = (GameObject)((obj is GameObject) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				roots.Add(val.transform);
			}
		}

		private static Mesh GetExcludedBodyMesh(Player player, string race)
		{
			if (race != "Skeleton")
			{
				return null;
			}
			VisEquipment component = ((Component)player).GetComponent<VisEquipment>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_bodyModel == (Object)null))
			{
				return component.m_bodyModel.sharedMesh;
			}
			return null;
		}

		private static bool IsSkeletonReplacement(Transform candidate)
		{
			Transform val = candidate;
			while ((Object)(object)val != (Object)null)
			{
				if (((Object)val).name.StartsWith("SkeletonBody", StringComparison.Ordinal))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static bool IsUnderExcludedRoot(Transform candidate, List<Transform> excludedRoots)
		{
			foreach (Transform excludedRoot in excludedRoots)
			{
				if ((Object)(object)candidate == (Object)(object)excludedRoot || ca