Decompiled source of LegoSkin v5.0.1

plugins/Furter-LegoSkin/Furter.LegoSkin.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Furter.LegoSkin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Furter.LegoSkin")]
[assembly: AssemblyTitle("Furter.LegoSkin")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Furter.LegoSkin
{
	[BepInPlugin("Furter.LegoSkin", "LEGO Skin", "5.0.0")]
	public class LegoSkinPlugin : BaseUnityPlugin
	{
		public static ConfigEntry<float> CamDistance;

		public static ConfigEntry<float> CamHeight;

		public static ConfigEntry<float> CamFov;

		public static ConfigEntry<float> LegoScale;

		public static ConfigEntry<string> SelectedCharacter;

		public static bool CameraEnabled = true;

		public static int CameraMode = 0;

		public static readonly string[] CameraModeNames = new string[8] { "1st Person", "BF2 3rd Person", "Bird's Eye", "GoPro Front", "GoPro Side", "GoPro Low", "Orthographic", "Cinematic" };

		public static LegoSkinPlugin Instance;

		private string _pluginDir;

		private List<string> _characters = new List<string>();

		private int _charIndex;

		private Harmony _harmony;

		private bool _legoApplied;

		private Character _lastCharacter;

		private bool _bonesDumped;

		private Dictionary<Character, string> _remoteSkins = new Dictionary<Character, string>();

		private float _syncTimer;

		private List<string> _allHeadDirs = new List<string>();

		private int _headIndex;

		private List<string> _allAccessoryPaths = new List<string>();

		private int _accessoryIndex = -1;

		private GameObject _currentHeadMesh;

		private GameObject _currentAccessory;

		private Transform _headPivot;

		private int _handColorIndex;

		private static readonly Color[] HandColors = (Color[])(object)new Color[9]
		{
			new Color(0.95f, 0.8f, 0.2f, 1f),
			new Color(0.85f, 0.65f, 0.13f, 1f),
			new Color(0.45f, 0.3f, 0.14f, 1f),
			new Color(0.3f, 0.18f, 0.1f, 1f),
			new Color(0.95f, 0.9f, 0.8f, 1f),
			new Color(0.15f, 0.15f, 0.15f, 1f),
			new Color(0.9f, 0.9f, 0.9f, 1f),
			new Color(0.8f, 0f, 0f, 1f),
			new Color(0f, 0.5f, 0f, 1f)
		};

		private static MethodInfo _loadImageMethod;

		private static MethodInfo _playEmoteMethod;

		private string CurrentModelsDir
		{
			get
			{
				if (_characters.Count <= 0)
				{
					return null;
				}
				return Path.Combine(_pluginDir, _characters[_charIndex]);
			}
		}

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Expected O, but got Unknown
			Instance = this;
			CamDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Distance", 2f, new ConfigDescription("Camera distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			CamHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Height", 0.3f, new ConfigDescription("Camera height", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 5f), Array.Empty<object>()));
			CamFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FieldOfView", 75f, new ConfigDescription("Camera FOV", (AcceptableValueBase)(object)new AcceptableValueRange<float>(15f, 170f), Array.Empty<object>()));
			LegoScale = ((BaseUnityPlugin)this).Config.Bind<float>("LEGO", "Scale", 2f, new ConfigDescription("Extra scale multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>()));
			SelectedCharacter = ((BaseUnityPlugin)this).Config.Bind<string>("LEGO", "Character", "TwoFace", "Active character");
			_pluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			ScanCharacters();
			_playEmoteMethod = typeof(CharacterAnimations).GetMethod("PlayEmote", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
			if (type != null)
			{
				_loadImageMethod = type.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				});
			}
			_harmony = new Harmony("Furter.LegoSkin");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"LEGO Skin v5.0.0 -- {_characters.Count} characters");
		}

		private void ScanCharacters()
		{
			_characters.Clear();
			_allHeadDirs.Clear();
			_allAccessoryPaths.Clear();
			string[] directories = Directory.GetDirectories(_pluginDir);
			foreach (string text in directories)
			{
				string fileName = Path.GetFileName(text);
				if (File.Exists(Path.Combine(text, "head.obj")))
				{
					_characters.Add(fileName);
					_allHeadDirs.Add(text);
				}
				string[] files = Directory.GetFiles(text, "*.obj");
				foreach (string text2 in files)
				{
					string text3 = Path.GetFileNameWithoutExtension(text2).ToLower();
					if (text3.StartsWith("helmet") || text3.StartsWith("mask") || text3.StartsWith("hat") || text3.StartsWith("glasses") || text3.StartsWith("hair") || text3.StartsWith("accessory") || text3.StartsWith("visor") || text3.StartsWith("hood") || text3.StartsWith("crown") || text3.StartsWith("cap"))
					{
						_allAccessoryPaths.Add(text2);
					}
				}
			}
			_characters.Sort();
			_allHeadDirs.Sort();
			_charIndex = _characters.IndexOf(SelectedCharacter.Value);
			if (_charIndex < 0)
			{
				_charIndex = 0;
			}
			_headIndex = _charIndex;
		}

		private void Update()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)286))
			{
				CameraMode = (CameraMode + 1) % CameraModeNames.Length;
				CameraEnabled = CameraMode != 0;
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					main.orthographic = CameraMode == 6;
					if (CameraMode != 6)
					{
						main.orthographicSize = 5f;
					}
				}
				CinematicOverlay cinematicOverlay = Object.FindAnyObjectByType<CinematicOverlay>();
				if (CameraMode == 7)
				{
					if ((Object)(object)cinematicOverlay == (Object)null)
					{
						new GameObject("CinematicOverlay").AddComponent<CinematicOverlay>();
					}
				}
				else if ((Object)(object)cinematicOverlay != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)cinematicOverlay).gameObject);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Camera: " + CameraModeNames[CameraMode]));
			}
			if (Input.GetKeyDown((KeyCode)287) && _characters.Count > 1)
			{
				_charIndex = (_charIndex + 1) % _characters.Count;
				SelectedCharacter.Value = _characters[_charIndex];
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Switched to: " + _characters[_charIndex]));
				CleanupLego();
				_legoApplied = false;
				BroadcastSkin();
			}
			if (Input.GetKeyDown((KeyCode)288))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"F7 Refresh — reloading LEGO skin");
				ScanCharacters();
				CleanupLego();
				_legoApplied = false;
			}
			if (Input.GetKeyDown((KeyCode)289))
			{
				Player localPlayer = Player.localPlayer;
				if ((Object)(object)((localPlayer != null) ? localPlayer.character : null) != (Object)null)
				{
					DumpCharacterMesh(localPlayer.character);
				}
			}
			if (Input.GetKeyDown((KeyCode)290) && _allHeadDirs.Count > 0)
			{
				_headIndex = (_headIndex + 1) % _allHeadDirs.Count;
				string fileName = Path.GetFileName(_allHeadDirs[_headIndex]);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Head swap -> " + fileName));
				SwapHead(_allHeadDirs[_headIndex]);
			}
			if (Input.GetKeyDown((KeyCode)285) && _allAccessoryPaths.Count > 0)
			{
				_accessoryIndex++;
				if (_accessoryIndex >= _allAccessoryPaths.Count)
				{
					_accessoryIndex = -1;
				}
				if (_accessoryIndex < 0)
				{
					RemoveAccessory();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Accessory removed");
				}
				else
				{
					string text = _allAccessoryPaths[_accessoryIndex];
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Accessory -> " + Path.GetFileName(text)));
					ApplyAccessory(text);
				}
			}
			if (Input.GetKeyDown((KeyCode)284))
			{
				CycleHandColor();
			}
			if (Input.GetKeyDown((KeyCode)291))
			{
				string text2 = Path.Combine(_pluginDir, "Screenshots");
				Directory.CreateDirectory(text2);
				string text3 = $"lego_{DateTime.Now:yyyyMMdd_HHmmss_fff}.png";
				ScreenCapture.CaptureScreenshot(Path.Combine(text2, text3));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Screenshot: " + text3));
			}
			Player localPlayer2 = Player.localPlayer;
			if ((Object)(object)localPlayer2 == (Object)null || (Object)(object)localPlayer2.character == (Object)null)
			{
				_legoApplied = false;
				_lastCharacter = null;
			}
			else
			{
				Character character = localPlayer2.character;
				if (!_legoApplied || (Object)(object)character != (Object)(object)_lastCharacter)
				{
					if ((Object)(object)character != (Object)(object)_lastCharacter)
					{
						CleanupLego();
						_legoApplied = false;
					}
					_lastCharacter = character;
					ApplyLegoSkin(character);
					BroadcastSkin();
				}
			}
			_syncTimer += Time.deltaTime;
			if (_syncTimer >= 0.5f)
			{
				_syncTimer = 0f;
				SyncRemotePlayers();
			}
		}

		private void BroadcastSkin()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			try
			{
				if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom && _characters.Count > 0)
				{
					Hashtable val = new Hashtable();
					val[(object)"LegoSkin"] = _characters[_charIndex];
					PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Broadcast skin: " + _characters[_charIndex]));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Broadcast failed: " + ex.Message));
			}
		}

		private void SyncRemotePlayers()
		{
			try
			{
				if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
				{
					return;
				}
				List<Character> list = new List<Character>();
				foreach (KeyValuePair<Character, string> remoteSkin in _remoteSkins)
				{
					if ((Object)(object)remoteSkin.Key == (Object)null)
					{
						list.Add(remoteSkin.Key);
					}
				}
				foreach (Character item in list)
				{
					_remoteSkins.Remove(item);
				}
				Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0);
				foreach (Player val in array)
				{
					if ((Object)(object)val == (Object)(object)Player.localPlayer || (Object)(object)((val != null) ? val.character : null) == (Object)null)
					{
						continue;
					}
					PhotonView val2 = ((Component)val).GetComponent<PhotonView>();
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val).GetComponentInChildren<PhotonView>();
					}
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val).GetComponentInParent<PhotonView>();
					}
					if (((val2 != null) ? val2.Owner : null) == null || !((Dictionary<object, object>)(object)val2.Owner.CustomProperties).TryGetValue((object)"LegoSkin", out object value))
					{
						continue;
					}
					string text = value as string;
					if (!string.IsNullOrEmpty(text) && (!_remoteSkins.TryGetValue(val.character, out var value2) || !(value2 == text)))
					{
						string text2 = Path.Combine(_pluginDir, text);
						if (Directory.Exists(text2))
						{
							CleanupLegoOn(val.character);
							ApplyLegoSkin(val.character, text2);
							_remoteSkins[val.character] = text;
							((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied remote skin: " + text + " on " + ((Object)val).name));
						}
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Remote sync error: " + ex.Message));
			}
		}

		private void CleanupLegoOn(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = ((Component)character).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "LegoRoot")
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			RestoreOriginalBody(character);
		}

		private void RestoreOriginalBody(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return;
			}
			SkinnedMeshRenderer mainRenderer = character.refs.mainRenderer;
			if ((Object)(object)mainRenderer != (Object)null)
			{
				((Renderer)mainRenderer).shadowCastingMode = (ShadowCastingMode)1;
			}
			Renderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (((Object)((Component)val).gameObject).name.Contains("Lego_") || ((Object)((Component)val).gameObject).name.Contains("LegoMouth"))
				{
					continue;
				}
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
				if (val2 != null)
				{
					((Renderer)val2).shadowCastingMode = (ShadowCastingMode)1;
					continue;
				}
				MeshRenderer val3 = (MeshRenderer)(object)((val is MeshRenderer) ? val : null);
				if (val3 != null)
				{
					((Renderer)val3).shadowCastingMode = (ShadowCastingMode)1;
				}
			}
		}

		private Transform FindBone(Transform[] bones, params string[] patterns)
		{
			if (bones == null)
			{
				return null;
			}
			foreach (string text in patterns)
			{
				foreach (Transform val in bones)
				{
					if ((Object)(object)val != (Object)null && ((Object)val).name.ToLower().Contains(text.ToLower()))
					{
						return val;
					}
				}
			}
			return null;
		}

		private Transform FindBoneExact(Transform[] bones, params string[] names)
		{
			if (bones == null)
			{
				return null;
			}
			foreach (string text in names)
			{
				foreach (Transform val in bones)
				{
					if ((Object)(object)val != (Object)null && ((Object)val).name == text)
					{
						return val;
					}
				}
			}
			return null;
		}

		private Texture2D LoadTexture(string path)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!File.Exists(path))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Texture file not found: " + path));
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (_loadImageMethod != null)
			{
				if (!(bool)_loadImageMethod.Invoke(null, new object[2] { val, array }))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"LoadImage failed for: {Path.GetFileName(path)} ({array.Length} bytes)");
					Object.Destroy((Object)(object)val);
					return null;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded texture: {Path.GetFileName(path)} ({((Texture)val).width}x{((Texture)val).height})");
				((Texture)val).filterMode = (FilterMode)1;
				return val;
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)"ImageConversion.LoadImage not available");
			Object.Destroy((Object)(object)val);
			return null;
		}

		private Material CreateMaterial(Material baseMat, Texture2D tex, Color baseColor, bool needsAlpha = false, Texture2D normalMap = null, bool isChrome = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(baseMat);
			if ((Object)(object)tex != (Object)null)
			{
				val.mainTexture = (Texture)(object)tex;
				val.SetTexture("_BaseMap", (Texture)(object)tex);
				val.SetColor("_BaseColor", Color.white);
				val.color = Color.white;
			}
			else
			{
				Texture2D val2 = new Texture2D(4, 4, (TextureFormat)4, false);
				Color[] array = (Color[])(object)new Color[16];
				for (int i = 0; i < 16; i++)
				{
					array[i] = baseColor;
				}
				val2.SetPixels(array);
				val2.Apply();
				((Texture)val2).filterMode = (FilterMode)0;
				val.mainTexture = (Texture)(object)val2;
				val.SetTexture("_BaseMap", (Texture)(object)val2);
				val.SetColor("_BaseColor", Color.white);
				val.color = Color.white;
			}
			val.SetFloat("_Smoothness", isChrome ? 0.92f : 0.35f);
			val.SetFloat("_Metallic", isChrome ? 0.85f : 0f);
			val.SetFloat("_GlossMapScale", 1f);
			if ((Object)(object)normalMap != (Object)null)
			{
				val.SetTexture("_BumpMap", (Texture)(object)normalMap);
				val.SetFloat("_BumpScale", 1f);
				val.EnableKeyword("_NORMALMAP");
			}
			if (needsAlpha)
			{
				val.SetFloat("_AlphaClip", 1f);
				val.SetFloat("_Cutoff", 0.5f);
				val.EnableKeyword("_ALPHATEST_ON");
				val.renderQueue = 2450;
			}
			return val;
		}

		private Material[] BuildMaterials(string modelsDir, string partFile, Material baseMat, Dictionary<string, Texture2D> texCache, Dictionary<string, Material> matCache, ObjResult result, bool isChrome = false)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, MtlInfo> dictionary = ObjLoader.ParseMtl(Path.Combine(modelsDir, partFile + ".mtl"));
			Material[] array = (Material[])(object)new Material[result.MaterialNames.Length];
			for (int i = 0; i < result.MaterialNames.Length; i++)
			{
				string text = result.MaterialNames[i];
				MtlInfo mtlInfo = (dictionary.ContainsKey(text) ? dictionary[text] : null);
				if (mtlInfo == null && dictionary.Count > 0)
				{
					using Dictionary<string, MtlInfo>.Enumerator enumerator = dictionary.GetEnumerator();
					if (enumerator.MoveNext())
					{
						KeyValuePair<string, MtlInfo> current = enumerator.Current;
						mtlInfo = current.Value;
						text = current.Key;
					}
				}
				string text2 = mtlInfo?.TexFile;
				Color baseColor = ((mtlInfo != null && mtlInfo.HasKdColor) ? mtlInfo.KdColor : Color.white);
				bool flag = partFile.Contains("head") && text2 != null && (text2.Contains("Face") || text2.Contains("face"));
				string key = text + (flag ? "_alpha" : "");
				if (!matCache.ContainsKey(key))
				{
					Texture2D tex = null;
					if (text2 != null)
					{
						if (!texCache.ContainsKey(text2))
						{
							texCache[text2] = LoadTexture(Path.Combine(modelsDir, text2));
						}
						tex = texCache[text2];
					}
					Texture2D normalMap = null;
					string text3 = mtlInfo?.NormalFile;
					if (text3 != null)
					{
						if (!texCache.ContainsKey(text3))
						{
							texCache[text3] = LoadTexture(Path.Combine(modelsDir, text3));
						}
						normalMap = texCache[text3];
					}
					matCache[key] = CreateMaterial(baseMat, tex, baseColor, flag, normalMap, isChrome);
				}
				array[i] = matCache[key];
			}
			return array;
		}

		private void ApplyLegoSkin(Character character, string overrideDir = null)
		{
			//IL_08f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_090a: Unknown result type (might be due to invalid IL or missing references)
			//IL_090f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0935: Unknown result type (might be due to invalid IL or missing references)
			//IL_093c: Expected O, but got Unknown
			//IL_0952: Unknown result type (might be due to invalid IL or missing references)
			//IL_0959: Unknown result type (might be due to invalid IL or missing references)
			//IL_0976: Unknown result type (might be due to invalid IL or missing references)
			//IL_0989: Unknown result type (might be due to invalid IL or missing references)
			//IL_0997: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0924: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abc: Expected O, but got Unknown
			//IL_0b66: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c7d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c36: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c5f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c0a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d4e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d07: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d30: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cb2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cdb: Unknown result type (might be due to invalid IL or missing references)
			//IL_104f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1055: Expected O, but got Unknown
			//IL_0ed6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0edb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f22: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f27: Unknown result type (might be due to invalid IL or missing references)
			//IL_144a: Unknown result type (might be due to invalid IL or missing references)
			//IL_144f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1462: Unknown result type (might be due to invalid IL or missing references)
			//IL_1468: Unknown result type (might be due to invalid IL or missing references)
			//IL_1472: Unknown result type (might be due to invalid IL or missing references)
			//IL_1478: Unknown result type (might be due to invalid IL or missing references)
			//IL_1482: Unknown result type (might be due to invalid IL or missing references)
			//IL_1488: Unknown result type (might be due to invalid IL or missing references)
			//IL_1492: Unknown result type (might be due to invalid IL or missing references)
			//IL_108c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1093: Expected O, but got Unknown
			//IL_10b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_10c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_10d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_1258: Unknown result type (might be due to invalid IL or missing references)
			//IL_125f: Expected O, but got Unknown
			//IL_127c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1281: Unknown result type (might be due to invalid IL or missing references)
			//IL_1292: Unknown result type (might be due to invalid IL or missing references)
			//IL_12a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_13f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_13f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_1388: Unknown result type (might be due to invalid IL or missing references)
			//IL_138d: Unknown result type (might be due to invalid IL or missing references)
			string text = overrideDir ?? CurrentModelsDir;
			if (text == null || !Directory.Exists(text))
			{
				return;
			}
			SkinnedMeshRenderer mainRenderer = character.refs.mainRenderer;
			Transform[] array = ((mainRenderer != null) ? mainRenderer.bones : null);
			Transform val = ((mainRenderer != null) ? mainRenderer.rootBone : null);
			if (!_bonesDumped && array != null)
			{
				_bonesDumped = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"=== PEAK Skeleton: {array.Length} bones ===");
				Transform[] array2 = array;
				foreach (Transform val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("  Bone: " + ((Object)val2).name + " (parent: " + (((Object)(object)val2.parent != (Object)null) ? ((Object)val2.parent).name : "none") + ")"));
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("  RootBone: " + ((Object)val).name));
				}
				Type type = ((object)character).GetType();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"=== Death/Ragdoll Methods ===");
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					string text2 = methodInfo.Name.ToLower();
					if (text2.Contains("die") || text2.Contains("death") || text2.Contains("dead") || text2.Contains("ragdoll") || text2.Contains("skeleton") || text2.Contains("kill") || text2.Contains("respawn") || text2.Contains("alive") || text2.Contains("health") || text2.Contains("damage") || text2.Contains("knockdown") || text2.Contains("downed"))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("  " + methodInfo.Name + "(" + string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name + " " + p.Name)) + ") -> " + methodInfo.ReturnType.Name));
					}
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					string text3 = fieldInfo.Name.ToLower();
					if (text3.Contains("die") || text3.Contains("death") || text3.Contains("dead") || text3.Contains("ragdoll") || text3.Contains("skeleton") || text3.Contains("alive") || text3.Contains("health") || text3.Contains("downed"))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("  Field: " + fieldInfo.Name + " (" + fieldInfo.FieldType.Name + ")"));
					}
				}
				PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					string text4 = propertyInfo.Name.ToLower();
					if (text4.Contains("die") || text4.Contains("death") || text4.Contains("dead") || text4.Contains("ragdoll") || text4.Contains("skeleton") || text4.Contains("alive") || text4.Contains("health") || text4.Contains("downed"))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("  Prop: " + propertyInfo.Name + " (" + propertyInfo.PropertyType.Name + ")"));
					}
				}
			}
			Transform val3 = FindBoneExact(array, "Hip") ?? FindBone(array, "hip", "pelvis");
			Transform val4 = FindBoneExact(array, "Mid") ?? FindBone(array, "mid", "spine");
			Transform val5 = FindBoneExact(array, "Head") ?? FindBone(array, "head");
			Transform val6 = FindBoneExact(array, "Arm_L") ?? FindBone(array, "arm_l", "upperarm_l", "shoulder_l");
			Transform val7 = FindBoneExact(array, "Arm_R") ?? FindBone(array, "arm_r", "upperarm_r", "shoulder_r");
			Transform val8 = FindBoneExact(array, "Leg_L") ?? FindBone(array, "leg_l", "thigh_l");
			Transform val9 = FindBoneExact(array, "Leg_R") ?? FindBone(array, "leg_r", "thigh_r");
			Transform val10 = FindBoneExact(array, "Hand_L") ?? FindBone(array, "hand_l");
			Transform val11 = FindBoneExact(array, "Hand_R") ?? FindBone(array, "hand_r");
			Transform val12 = val3 ?? val ?? ((Component)character).transform;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Bones: Hip=" + ((val3 != null) ? ((Object)val3).name : null) + " Mid=" + ((val4 != null) ? ((Object)val4).name : null) + " Head=" + ((val5 != null) ? ((Object)val5).name : null) + " ArmL=" + ((val6 != null) ? ((Object)val6).name : null) + " ArmR=" + ((val7 != null) ? ((Object)val7).name : null) + " LegL=" + ((val8 != null) ? ((Object)val8).name : null) + " LegR=" + ((val9 != null) ? ((Object)val9).name : null)));
			float result = 1f;
			string path = Path.Combine(text, "scale.txt");
			if (File.Exists(path))
			{
				float.TryParse(File.ReadAllText(path).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result);
				if (result <= 0f)
				{
					result = 1f;
				}
			}
			float num = 4.06f;
			string path2 = Path.Combine(text, "head.obj");
			if (File.Exists(path2))
			{
				float num2 = 0f;
				string[] array3 = File.ReadAllLines(path2);
				foreach (string text5 in array3)
				{
					if (text5.StartsWith("v "))
					{
						string[] array4 = text5.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
						if (array4.Length >= 3 && float.TryParse(array4[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && result2 > num2)
						{
							num2 = result2;
						}
					}
				}
				if (num2 > 1f)
				{
					num = num2;
				}
			}
			float num3 = 1.7f / num * LegoScale.Value * result;
			float result3 = 180f;
			string path3 = Path.Combine(text, "rotation.txt");
			if (File.Exists(path3))
			{
				float.TryParse(File.ReadAllText(path3).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result3);
			}
			bool flag = Mathf.Abs(result3 - 180f) < 1f;
			bool flag2 = !flag;
			if (File.Exists(Path.Combine(text, "noflipz.txt")))
			{
				flag2 = false;
			}
			float result4 = 0f;
			string path4 = Path.Combine(text, "yaw_offset.txt");
			if (File.Exists(path4))
			{
				float.TryParse(File.ReadAllText(path4).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result4);
			}
			float num4 = val12.position.y - 0.9f;
			RaycastHit val13 = default(RaycastHit);
			if (Physics.Raycast(val12.position, Vector3.down, ref val13, 5f))
			{
				num4 = ((RaycastHit)(ref val13)).point.y;
			}
			GameObject val14 = new GameObject("LegoRoot");
			val14.transform.SetParent(val12, false);
			val14.transform.localScale = Vector3.one * num3;
			val14.transform.localRotation = Quaternion.Euler(0f, result3, 0f);
			val14.transform.position = new Vector3(val12.position.x, num4, val12.position.z);
			LegoStabilizer legoStabilizer = val14.AddComponent<LegoStabilizer>();
			legoStabilizer.hipBone = val12;
			legoStabilizer.baseYRotation = result3 + result4;
			legoStabilizer.heightOffset = 0f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Scale={num3:F3} ModelH={num:F2} CharScale={result:F2} GroundY={num4:F2}");
			Shader val15 = null;
			if ((Object)(object)mainRenderer != (Object)null && (Object)(object)((Renderer)mainRenderer).sharedMaterial != (Object)null)
			{
				val15 = ((Renderer)mainRenderer).sharedMaterial.shader;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Using game shader: " + ((Object)val15).name));
			}
			if ((Object)(object)val15 == (Object)null)
			{
				val15 = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard");
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Fallback shader: " + (((val15 != null) ? ((Object)val15).name : null) ?? "NULL")));
			}
			Material val16 = new Material(val15);
			Dictionary<string, Texture2D> texCache = new Dictionary<string, Texture2D>();
			Dictionary<string, Material> matCache = new Dictionary<string, Material>();
			bool num5 = File.Exists(Path.Combine(text, "arms_l.obj"));
			bool flag3 = File.Exists(Path.Combine(text, "legs_l.obj"));
			bool isChrome = File.Exists(Path.Combine(text, "chrome.txt"));
			bool flag4 = File.Exists(Path.Combine(text, "cape.txt"));
			float num6 = num;
			float num7 = num6 * 0.714f;
			float num8 = num6 * 0.493f;
			float num9 = num6 * 0.148f;
			float num10 = num6 * 0.591f;
			float num11 = num6 * 0.086f;
			float num12 = num6 * 0.222f;
			List<PartDef> list = new List<PartDef>
			{
				new PartDef("torso", "Mid", new Vector3(0f, num8, 0f), 0.4f),
				new PartDef("hips", null, Vector3.zero, 0f),
				new PartDef("head", "Head", new Vector3(0f, num7, 0f), 0.5f)
			};
			if (num5)
			{
				if (flag)
				{
					list.Add(new PartDef("arms_l", "Arm_R", new Vector3(0f - num9, num10, 0f), 1f));
					list.Add(new PartDef("arms_r", "Arm_L", new Vector3(num9, num10, 0f), 1f));
				}
				else
				{
					list.Add(new PartDef("arms_l", "Arm_L", new Vector3(0f - num9, num10, 0f), 1f));
					list.Add(new PartDef("arms_r", "Arm_R", new Vector3(num9, num10, 0f), 1f));
				}
			}
			else
			{
				list.Add(new PartDef("arms", null, Vector3.zero, 0f));
			}
			if (flag3)
			{
				if (flag)
				{
					list.Add(new PartDef("legs_l", "Leg_R", new Vector3(0f - num11, num12, 0f), 0.7f));
					list.Add(new PartDef("legs_r", "Leg_L", new Vector3(num11, num12, 0f), 0.7f));
				}
				else
				{
					list.Add(new PartDef("legs_l", "Leg_L", new Vector3(0f - num11, num12, 0f), 0.7f));
					list.Add(new PartDef("legs_r", "Leg_R", new Vector3(num11, num12, 0f), 0.7f));
				}
			}
			else
			{
				list.Add(new PartDef("legs", null, Vector3.zero, 0f));
			}
			Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
			if ((Object)(object)val4 != (Object)null)
			{
				dictionary["Mid"] = val4;
			}
			if ((Object)(object)val5 != (Object)null)
			{
				dictionary["Head"] = val5;
			}
			if ((Object)(object)val6 != (Object)null)
			{
				dictionary["Arm_L"] = val6;
			}
			if ((Object)(object)val7 != (Object)null)
			{
				dictionary["Arm_R"] = val7;
			}
			if ((Object)(object)val8 != (Object)null)
			{
				dictionary["Leg_L"] = val8;
			}
			if ((Object)(object)val9 != (Object)null)
			{
				dictionary["Leg_R"] = val9;
			}
			if ((Object)(object)val10 != (Object)null)
			{
				dictionary["Hand_L"] = val10;
			}
			if ((Object)(object)val11 != (Object)null)
			{
				dictionary["Hand_R"] = val11;
			}
			foreach (PartDef item in list)
			{
				string path5 = Path.Combine(text, item.file + ".obj");
				if (!File.Exists(path5))
				{
					continue;
				}
				ObjResult objResult = ObjLoader.Load(path5);
				if (objResult.Mesh.vertexCount == 0)
				{
					continue;
				}
				if (flag2)
				{
					Vector3[] vertices = objResult.Mesh.vertices;
					Vector3[] normals = objResult.Mesh.normals;
					for (int j = 0; j < vertices.Length; j++)
					{
						vertices[j] = new Vector3(vertices[j].x, vertices[j].y, 0f - vertices[j].z);
					}
					for (int k = 0; k < normals.Length; k++)
					{
						normals[k] = new Vector3(normals[k].x, normals[k].y, 0f - normals[k].z);
					}
					objResult.Mesh.vertices = vertices;
					objResult.Mesh.normals = normals;
					for (int l = 0; l < objResult.Mesh.subMeshCount; l++)
					{
						int[] triangles = objResult.Mesh.GetTriangles(l);
						for (int m = 0; m < triangles.Length; m += 3)
						{
							int num13 = triangles[m];
							triangles[m] = triangles[m + 2];
							triangles[m + 2] = num13;
						}
						objResult.Mesh.SetTriangles(triangles, l);
					}
					objResult.Mesh.RecalculateBounds();
				}
				string text6 = item.file;
				string path6 = Path.Combine(text, text6 + ".mtl");
				if (!File.Exists(path6))
				{
					string text7 = item.file.Split(new char[1] { '_' })[0];
					path6 = Path.Combine(text, text7 + ".mtl");
					text6 = text7;
				}
				Material[] materials = (Material[])((!File.Exists(path6)) ? ((Array)new Material[1]
				{
					new Material(val16)
				}) : ((Array)BuildMaterials(text, text6, val16, texCache, matCache, objResult, isChrome)));
				if (item.boneName != null && dictionary.ContainsKey(item.boneName))
				{
					GameObject val17 = new GameObject("Lego_" + item.file + "_pivot");
					val17.transform.SetParent(val14.transform, false);
					val17.transform.localPosition = item.pivot;
					val17.transform.localScale = Vector3.one;
					val17.transform.localRotation = Quaternion.identity;
					LegoBoneTracker legoBoneTracker = val17.AddComponent<LegoBoneTracker>();
					legoBoneTracker.targetBone = dictionary[item.boneName];
					legoBoneTracker.influence = item.influence;
					legoBoneTracker.flipModel = flag;
					if (item.file == "head")
					{
						legoBoneTracker.isHead = true;
					}
					if (item.file == "torso")
					{
						legoBoneTracker.isTorso = true;
						legoBoneTracker.characterTransform = val12;
					}
					if (item.file.StartsWith("arms"))
					{
						legoBoneTracker.isArm = true;
						legoBoneTracker.characterTransform = val12;
						bool flag5 = (flag ? item.file.Contains("_r") : item.file.Contains("_l"));
						legoBoneTracker.armSide = (flag5 ? 1f : (-1f));
						legoBoneTracker.isLeftArm = flag5;
						string key = ((item.boneName == "Arm_L") ? "Hand_L" : "Hand_R");
						if (dictionary.ContainsKey(key))
						{
							legoBoneTracker.handBone = dictionary[key];
						}
					}
					if (item.file.StartsWith("legs"))
					{
						legoBoneTracker.isLeg = true;
						legoBoneTracker.legSide = (item.file.Contains("_r") ? 1f : (-1f));
						legoBoneTracker.characterTransform = val12;
					}
					GameObject val18 = new GameObject("Lego_" + item.file);
					val18.transform.SetParent(val17.transform, false);
					val18.transform.localPosition = -item.pivot;
					val18.transform.localScale = Vector3.one;
					val18.transform.localRotation = Quaternion.identity;
					val18.AddComponent<MeshFilter>().mesh = objResult.Mesh;
					MeshRenderer obj = val18.AddComponent<MeshRenderer>();
					((Renderer)obj).materials = materials;
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
					((Renderer)obj).receiveShadows = true;
					if (item.file == "head")
					{
						_headPivot = val17.transform;
						_currentHeadMesh = val18;
						val18.AddComponent<LegoHeadFader>();
						string path7 = Path.Combine(text, "mouth.txt");
						if (File.Exists(path7))
						{
							if (File.ReadAllText(path7).Trim().ToLower() == "mesh" && File.Exists(Path.Combine(text, "mouth_open.obj")) && File.Exists(Path.Combine(text, "mouth_closed.obj")))
							{
								LegoMouthMesh legoMouthMesh = val17.AddComponent<LegoMouthMesh>();
								legoMouthMesh.negateZ = flag2;
								legoMouthMesh.character = character;
								legoMouthMesh.modelsDir = text;
								legoMouthMesh.headPivot = item.pivot;
								((BaseUnityPlugin)this).Logger.LogInfo((object)"  Mouth: mesh mode (vertex lerp)");
							}
							else
							{
								LegoMouthIndicator legoMouthIndicator = val17.AddComponent<LegoMouthIndicator>();
								legoMouthIndicator.flipModel = flag;
								legoMouthIndicator.character = character;
							}
						}
					}
					if (item.file == "torso" && flag4 && objResult.Mesh.subMeshCount >= 2)
					{
						ExtractClothCape(objResult.Mesh, materials, val17.transform, -item.pivot);
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"  {item.file} -> {item.boneName} (pivot, {objResult.Mesh.vertexCount}v)");
				}
				else
				{
					GameObject val19 = new GameObject("Lego_" + item.file);
					val19.transform.SetParent(val14.transform, false);
					val19.transform.localPosition = Vector3.zero;
					val19.transform.localScale = Vector3.one;
					val19.transform.localRotation = Quaternion.identity;
					val19.AddComponent<MeshFilter>().mesh = objResult.Mesh;
					MeshRenderer obj2 = val19.AddComponent<MeshRenderer>();
					((Renderer)obj2).materials = materials;
					((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)1;
					((Renderer)obj2).receiveShadows = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"  {item.file} -> root (static, {objResult.Mesh.vertexCount}v)");
				}
			}
			HideOriginalBody(character);
			_legoApplied = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"LEGO {_characters[_charIndex]} applied! ({list.Count} parts)");
			if (overrideDir == null && _characters[_charIndex] == "Batman")
			{
				TryGiveRescueClaw(character);
			}
		}

		private void TryGiveRescueClaw(Character character)
		{
			try
			{
				Type type = Type.GetType("ItemDatabase, Assembly-CSharp");
				if (type == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"ItemDatabase type not found");
					return;
				}
				Object[] array = Resources.FindObjectsOfTypeAll(type);
				if (array == null || array.Length == 0)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"No ItemDatabase");
					return;
				}
				Object obj = array[0];
				FieldInfo field = type.GetField("Objects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Objects field not found");
					return;
				}
				if (!(field.GetValue(obj) is IList list))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Objects list is null");
					return;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"ItemDatabase: {list.Count} items");
				object obj2 = null;
				int itemIdx = -1;
				for (int i = 0; i < list.Count; i++)
				{
					object obj3 = list[i];
					if (obj3 != null)
					{
						string text = obj3.ToString().ToLower();
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"  Item[{i}]: {obj3} ({obj3.GetType().Name})");
						if (text.Contains("rescue") || text.Contains("hook") || text.Contains("claw"))
						{
							obj2 = obj3;
							itemIdx = i;
							((BaseUnityPlugin)this).Logger.LogInfo((object)$"  >> RESCUE ITEM FOUND at index {i}: {obj3}");
						}
					}
				}
				if (obj2 != null)
				{
					GiveItemToPlayer(character, itemIdx, obj2);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Rescue hook item not found in database");
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"RescueClaw error: {arg}");
			}
		}

		private void GiveItemToPlayer(Character character, int itemIdx, object itemDef)
		{
			try
			{
				Type type = ((object)character).GetType();
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					string text = methodInfo.Name.ToLower();
					if (text.Contains("item") || text.Contains("backpack") || text.Contains("equip"))
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("  Char." + methodInfo.Name + "(" + string.Join(", ", Array.ConvertAll(methodInfo.GetParameters(), (ParameterInfo p) => p.ParameterType.Name + " " + p.Name)) + ")"));
					}
				}
				Type type2 = itemDef.GetType();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("  Item type: " + type2.FullName));
				FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"    Item field: {fieldInfo.Name} = {fieldInfo.GetValue(itemDef)}");
				}
				PropertyInfo[] properties = type2.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					try
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)$"    Item prop: {propertyInfo.Name} = {propertyInfo.GetValue(itemDef)}");
					}
					catch
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("    Item prop: " + propertyInfo.Name + " (error reading)"));
					}
				}
				MethodInfo method = type.GetMethod("PutItemInBackpack", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					ParameterInfo[] parameters = method.GetParameters();
					((BaseUnityPlugin)this).Logger.LogInfo((object)("  PutItemInBackpack(" + string.Join(", ", Array.ConvertAll(parameters, (ParameterInfo p) => p.ParameterType.Name)) + ")"));
					if (parameters.Length == 1)
					{
						method.Invoke(character, new object[1] { itemDef });
						((BaseUnityPlugin)this).Logger.LogInfo((object)"  >> Item given to backpack!");
						ColorItemGold(character);
					}
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"  PutItemInBackpack not found on Character");
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"GiveItem error: {arg}");
			}
		}

		private void ColorItemGold(Character character)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Renderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					if (!((Object)((Component)val).gameObject).name.ToLower().Contains("hook") && !((Object)((Component)val).gameObject).name.ToLower().Contains("rescue") && !((Object)((Component)val).gameObject).name.ToLower().Contains("claw"))
					{
						continue;
					}
					Material[] materials = val.materials;
					foreach (Material val2 in materials)
					{
						val2.color = new Color(1f, 0.84f, 0f, 1f);
						if (val2.HasProperty("_BaseColor"))
						{
							val2.SetColor("_BaseColor", new Color(1f, 0.84f, 0f, 1f));
						}
						val2.SetFloat("_Metallic", 1f);
						val2.SetFloat("_Smoothness", 0.9f);
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)("  Colored gold: " + ((Object)((Component)val).gameObject).name));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("ColorGold error: " + ex.Message));
			}
		}

		private void SwapHead(string sourceDir)
		{
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Expected O, but got Unknown
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_headPivot == (Object)null)
			{
				return;
			}
			Transform val = _headPivot.Find("Lego_head");
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			string path = Path.Combine(sourceDir, "head.obj");
			if (!File.Exists(path))
			{
				return;
			}
			ObjResult objResult = ObjLoader.Load(path);
			if (objResult.Mesh.vertexCount == 0)
			{
				return;
			}
			string path2 = Path.Combine(sourceDir, "noflipz.txt");
			float result = 180f;
			string path3 = Path.Combine(sourceDir, "rotation.txt");
			if (File.Exists(path3))
			{
				float.TryParse(File.ReadAllText(path3).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result);
			}
			if (!(Mathf.Abs(result - 180f) < 1f) && !File.Exists(path2))
			{
				Vector3[] vertices = objResult.Mesh.vertices;
				Vector3[] normals = objResult.Mesh.normals;
				for (int i = 0; i < vertices.Length; i++)
				{
					vertices[i] = new Vector3(vertices[i].x, vertices[i].y, 0f - vertices[i].z);
				}
				for (int j = 0; j < normals.Length; j++)
				{
					normals[j] = new Vector3(normals[j].x, normals[j].y, 0f - normals[j].z);
				}
				objResult.Mesh.vertices = vertices;
				objResult.Mesh.normals = normals;
				for (int k = 0; k < objResult.Mesh.subMeshCount; k++)
				{
					int[] triangles = objResult.Mesh.GetTriangles(k);
					for (int l = 0; l < triangles.Length; l += 3)
					{
						int num = triangles[l];
						triangles[l] = triangles[l + 2];
						triangles[l + 2] = num;
					}
					objResult.Mesh.SetTriangles(triangles, k);
				}
				objResult.Mesh.RecalculateBounds();
			}
			Material val2 = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"));
			Dictionary<string, Texture2D> texCache = new Dictionary<string, Texture2D>();
			Dictionary<string, Material> matCache = new Dictionary<string, Material>();
			Material[] materials = (Material[])((!File.Exists(Path.Combine(sourceDir, "head.mtl"))) ? ((Array)new Material[1]
			{
				new Material(val2)
			}) : ((Array)BuildMaterials(sourceDir, "head", val2, texCache, matCache, objResult)));
			float num2 = 4.06f;
			string path4 = Path.Combine(sourceDir, "head.obj");
			float num3 = 0f;
			string[] array = File.ReadAllLines(path4);
			foreach (string text in array)
			{
				if (text.StartsWith("v "))
				{
					string[] array2 = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
					if (array2.Length >= 3 && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && result2 > num3)
					{
						num3 = result2;
					}
				}
			}
			if (num3 > 1f)
			{
				num2 = num3;
			}
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(0f, num2 * 0.714f, 0f);
			GameObject val4 = new GameObject("Lego_head");
			val4.transform.SetParent(_headPivot, false);
			val4.transform.localPosition = -val3;
			val4.transform.localScale = Vector3.one;
			val4.transform.localRotation = Quaternion.identity;
			val4.AddComponent<MeshFilter>().mesh = objResult.Mesh;
			MeshRenderer obj = val4.AddComponent<MeshRenderer>();
			((Renderer)obj).materials = materials;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)obj).receiveShadows = true;
			val4.AddComponent<LegoHeadFader>();
			_currentHeadMesh = val4;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Head swapped from {Path.GetFileName(sourceDir)} ({objResult.Mesh.vertexCount}v)");
		}

		private void ApplyAccessory(string objPath)
		{
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_00f4: 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)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Expected O, but got Unknown
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			RemoveAccessory();
			if ((Object)(object)_headPivot == (Object)null)
			{
				return;
			}
			string directoryName = Path.GetDirectoryName(objPath);
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(objPath);
			ObjResult objResult = ObjLoader.Load(objPath);
			if (objResult.Mesh.vertexCount == 0)
			{
				return;
			}
			string path = Path.Combine(directoryName, "noflipz.txt");
			float result = 180f;
			string path2 = Path.Combine(directoryName, "rotation.txt");
			if (File.Exists(path2))
			{
				float.TryParse(File.ReadAllText(path2).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result);
			}
			if (!(Mathf.Abs(result - 180f) < 1f) && !File.Exists(path))
			{
				Vector3[] vertices = objResult.Mesh.vertices;
				Vector3[] normals = objResult.Mesh.normals;
				for (int i = 0; i < vertices.Length; i++)
				{
					vertices[i] = new Vector3(vertices[i].x, vertices[i].y, 0f - vertices[i].z);
				}
				for (int j = 0; j < normals.Length; j++)
				{
					normals[j] = new Vector3(normals[j].x, normals[j].y, 0f - normals[j].z);
				}
				objResult.Mesh.vertices = vertices;
				objResult.Mesh.normals = normals;
				for (int k = 0; k < objResult.Mesh.subMeshCount; k++)
				{
					int[] triangles = objResult.Mesh.GetTriangles(k);
					for (int l = 0; l < triangles.Length; l += 3)
					{
						int num = triangles[l];
						triangles[l] = triangles[l + 2];
						triangles[l + 2] = num;
					}
					objResult.Mesh.SetTriangles(triangles, k);
				}
				objResult.Mesh.RecalculateBounds();
			}
			Material val = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"));
			Dictionary<string, Texture2D> texCache = new Dictionary<string, Texture2D>();
			Dictionary<string, Material> matCache = new Dictionary<string, Material>();
			Material[] materials = (Material[])((!File.Exists(Path.Combine(directoryName, fileNameWithoutExtension + ".mtl"))) ? ((Array)new Material[1]
			{
				new Material(val)
			}) : ((Array)BuildMaterials(directoryName, fileNameWithoutExtension, val, texCache, matCache, objResult)));
			float num2 = 4.06f;
			string path3 = Path.Combine(directoryName, "head.obj");
			if (File.Exists(path3))
			{
				float num3 = 0f;
				string[] array = File.ReadAllLines(path3);
				foreach (string text in array)
				{
					if (text.StartsWith("v "))
					{
						string[] array2 = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
						if (array2.Length >= 3 && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && result2 > num3)
						{
							num3 = result2;
						}
					}
				}
				if (num3 > 1f)
				{
					num2 = num3;
				}
			}
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(0f, num2 * 0.714f, 0f);
			GameObject val3 = new GameObject("Lego_accessory_" + fileNameWithoutExtension);
			val3.transform.SetParent(_headPivot, false);
			val3.transform.localPosition = -val2;
			val3.transform.localScale = Vector3.one;
			val3.transform.localRotation = Quaternion.identity;
			val3.AddComponent<MeshFilter>().mesh = objResult.Mesh;
			MeshRenderer obj = val3.AddComponent<MeshRenderer>();
			((Renderer)obj).materials = materials;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)obj).receiveShadows = true;
			val3.AddComponent<LegoHeadFader>();
			_currentAccessory = val3;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Accessory: {fileNameWithoutExtension} from {Path.GetFileName(directoryName)} ({objResult.Mesh.vertexCount}v)");
		}

		private void RemoveAccessory()
		{
			if ((Object)(object)_currentAccessory != (Object)null)
			{
				Object.Destroy((Object)(object)_currentAccessory);
				_currentAccessory = null;
			}
		}

		private void CycleHandColor()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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)
			_handColorIndex = (_handColorIndex + 1) % HandColors.Length;
			Color val = HandColors[_handColorIndex];
			string[] array = new string[9] { "Yellow", "Gold", "Brown", "Dark Brown", "Peach", "Black", "White", "Red", "Green" };
			string text = ((_handColorIndex < array.Length) ? array[_handColorIndex] : $"Color {_handColorIndex}");
			Transform[] array2 = Object.FindObjectsByType<Transform>((FindObjectsSortMode)0);
			foreach (Transform val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null || ((Object)((Component)val2).gameObject).name != "LegoRoot")
				{
					continue;
				}
				Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val3 in componentsInChildren)
				{
					if (!((Object)((Component)val3).gameObject).name.ToLower().Contains("arm"))
					{
						continue;
					}
					Material[] materials = val3.materials;
					foreach (Material val4 in materials)
					{
						val4.mainTexture = null;
						if (val4.HasProperty("_BaseMap"))
						{
							val4.SetTexture("_BaseMap", (Texture)null);
						}
						val4.color = val;
						if (val4.HasProperty("_BaseColor"))
						{
							val4.SetColor("_BaseColor", val);
						}
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Hand color -> " + text));
		}

		private void ExtractClothCape(Mesh torsoMesh, Material[] materials, Transform parent, Vector3 offset)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: 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)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Expected O, but got Unknown
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			if (torsoMesh.subMeshCount < 2)
			{
				return;
			}
			int[] triangles = torsoMesh.GetTriangles(1);
			if (triangles.Length == 0)
			{
				return;
			}
			Vector3[] vertices = torsoMesh.vertices;
			Vector3[] normals = torsoMesh.normals;
			Vector2[] uv = torsoMesh.uv;
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<Vector2> list3 = new List<Vector2>();
			List<int> list4 = new List<int>();
			foreach (int num in triangles)
			{
				if (!dictionary.ContainsKey(num))
				{
					dictionary[num] = list.Count;
					list.Add(vertices[num]);
					list2.Add((num < normals.Length) ? normals[num] : Vector3.up);
					list3.Add((num < uv.Length) ? uv[num] : Vector2.zero);
				}
				list4.Add(dictionary[num]);
			}
			Dictionary<long, int> cache = new Dictionary<long, int>();
			List<int> list5 = new List<int>();
			for (int j = 0; j < list4.Count; j += 3)
			{
				int num2 = list4[j];
				int num3 = list4[j + 1];
				int num4 = list4[j + 2];
				int orCreateMidpoint = GetOrCreateMidpoint(num2, num3, list, list2, list3, cache);
				int orCreateMidpoint2 = GetOrCreateMidpoint(num3, num4, list, list2, list3, cache);
				int orCreateMidpoint3 = GetOrCreateMidpoint(num4, num2, list, list2, list3, cache);
				list5.AddRange(new int[12]
				{
					num2, orCreateMidpoint, orCreateMidpoint3, orCreateMidpoint, num3, orCreateMidpoint2, orCreateMidpoint3, orCreateMidpoint2, num4, orCreateMidpoint,
					orCreateMidpoint2, orCreateMidpoint3
				});
			}
			list4 = list5;
			Mesh val = new Mesh();
			val.vertices = list.ToArray();
			val.normals = list2.ToArray();
			val.uv = list3.ToArray();
			val.triangles = list4.ToArray();
			val.RecalculateBounds();
			val.RecalculateNormals();
			GameObject val2 = new GameObject("Lego_cape_cloth");
			val2.transform.SetParent(parent, false);
			val2.transform.localPosition = offset + new Vector3(0f, -0.15f, -0.02f);
			val2.transform.localScale = new Vector3(1.03f, 1.02f, 1.03f);
			val2.transform.localRotation = Quaternion.identity;
			val2.AddComponent<MeshFilter>().mesh = val;
			Material val3 = ((materials.Length > 1) ? new Material(materials[1]) : new Material(materials[0]));
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.35f, 0.35f, 0.38f, 1f);
			val3.SetTexture("_BumpMap", (Texture)null);
			val3.SetTexture("_DetailAlbedoMap", (Texture)null);
			val3.SetTexture("_DetailNormalMap", (Texture)null);
			val3.DisableKeyword("_NORMALMAP");
			val3.DisableKeyword("_DETAIL_MULX2");
			val3.SetColor("_BaseColor", val4);
			val3.color = val4;
			val3.SetFloat("_Smoothness", 0.15f);
			val3.SetFloat("_Metallic", 0f);
			val3.renderQueue = 2001;
			MeshRenderer obj = val2.AddComponent<MeshRenderer>();
			((Renderer)obj).material = val3;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)obj).receiveShadows = true;
			torsoMesh.SetTriangles(new int[0], 1);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"  Cape: {val.vertexCount}v, static (no physics)");
		}

		private int GetOrCreateMidpoint(int a, int b, List<Vector3> verts, List<Vector3> norms, List<Vector2> uvs, Dictionary<long, int> cache)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			long key = ((a < b) ? (((long)a << 32) | (uint)b) : (((long)b << 32) | (uint)a));
			if (cache.TryGetValue(key, out var value))
			{
				return value;
			}
			value = verts.Count;
			verts.Add((verts[a] + verts[b]) * 0.5f);
			Vector3 val = norms[a] + norms[b];
			norms.Add(((Vector3)(ref val)).normalized);
			uvs.Add((uvs[a] + uvs[b]) * 0.5f);
			cache[key] = value;
			return value;
		}

		private void DumpCharacterMesh(Character character)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_053d: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(_pluginDir, "MeshDump");
			Directory.CreateDirectory(text);
			SkinnedMeshRenderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"=== MESH DUMP: {componentsInChildren.Length} SkinnedMeshRenderers ===");
			HashSet<Transform> hashSet = new HashSet<Transform>();
			int num = 0;
			SkinnedMeshRenderer[] array = componentsInChildren;
			foreach (SkinnedMeshRenderer val in array)
			{
				if ((Object)(object)val.sharedMesh == (Object)null)
				{
					continue;
				}
				Mesh val2 = new Mesh();
				val.BakeMesh(val2);
				string arg = ((Object)((Component)val).gameObject).name.Replace(" ", "_");
				using (StreamWriter streamWriter = new StreamWriter(Path.Combine(text, $"{arg}_{num}.obj")))
				{
					streamWriter.WriteLine("# PEAK Mesh Dump: " + ((Object)((Component)val).gameObject).name);
					streamWriter.WriteLine($"# Vertices: {val2.vertexCount} Triangles: {val2.triangles.Length / 3}");
					Vector3[] vertices = val2.vertices;
					Vector3[] normals = val2.normals;
					Vector2[] uv = val2.uv;
					Matrix4x4 localToWorldMatrix = ((Component)val).transform.localToWorldMatrix;
					for (int j = 0; j < vertices.Length; j++)
					{
						Vector3 val3 = ((Matrix4x4)(ref localToWorldMatrix)).MultiplyPoint3x4(vertices[j]);
						streamWriter.WriteLine($"v {val3.x:F6} {val3.y:F6} {val3.z:F6}");
					}
					for (int k = 0; k < uv.Length; k++)
					{
						streamWriter.WriteLine($"vt {uv[k].x:F6} {uv[k].y:F6}");
					}
					for (int l = 0; l < normals.Length; l++)
					{
						Vector3 val4 = ((Matrix4x4)(ref localToWorldMatrix)).MultiplyVector(normals[l]);
						Vector3 normalized = ((Vector3)(ref val4)).normalized;
						streamWriter.WriteLine($"vn {normalized.x:F6} {normalized.y:F6} {normalized.z:F6}");
					}
					int[] triangles = val2.triangles;
					for (int m = 0; m < triangles.Length; m += 3)
					{
						int num2 = triangles[m] + 1;
						int num3 = triangles[m + 1] + 1;
						int num4 = triangles[m + 2] + 1;
						streamWriter.WriteLine($"f {num2}/{num2}/{num2} {num3}/{num3}/{num3} {num4}/{num4}/{num4}");
					}
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"  Dumped: {arg}_{num}.obj ({val2.vertexCount}v)");
				if (val.bones != null)
				{
					Transform[] bones = val.bones;
					foreach (Transform val5 in bones)
					{
						if ((Object)(object)val5 != (Object)null)
						{
							hashSet.Add(val5);
						}
					}
				}
				Object.Destroy((Object)(object)val2);
				num++;
			}
			using (StreamWriter streamWriter2 = new StreamWriter(Path.Combine(text, "skeleton.json")))
			{
				streamWriter2.WriteLine("{");
				streamWriter2.WriteLine("  \"bones\": [");
				List<Transform> list = new List<Transform>(hashSet);
				List<Transform> list2 = new List<Transform>();
				foreach (Transform item in list)
				{
					Transform val6 = item;
					while ((Object)(object)val6 != (Object)null && !list2.Contains(val6))
					{
						list2.Add(val6);
						if ((Object)(object)val6 == (Object)(object)((Component)character).transform)
						{
							break;
						}
						val6 = val6.parent;
					}
				}
				for (int num5 = 0; num5 < list2.Count; num5++)
				{
					Transform val7 = list2[num5];
					Vector3 position = val7.position;
					Vector3 localScale = val7.localScale;
					Quaternion localRotation = val7.localRotation;
					string text2 = (((Object)(object)val7.parent != (Object)null && list2.Contains(val7.parent)) ? ((Object)val7.parent).name : "");
					string text3 = ((num5 < list2.Count - 1) ? "," : "");
					streamWriter2.WriteLine("    {");
					streamWriter2.WriteLine("      \"name\": \"" + ((Object)val7).name + "\",");
					streamWriter2.WriteLine("      \"parent\": \"" + text2 + "\",");
					streamWriter2.WriteLine($"      \"world_pos\": [{position.x:F6}, {position.y:F6}, {position.z:F6}],");
					streamWriter2.WriteLine($"      \"local_rot\": [{localRotation.x:F6}, {localRotation.y:F6}, {localRotation.z:F6}, {localRotation.w:F6}],");
					streamWriter2.WriteLine($"      \"local_scale\": [{localScale.x:F6}, {localScale.y:F6}, {localScale.z:F6}]");
					streamWriter2.WriteLine("    }" + text3);
				}
				streamWriter2.WriteLine("  ]");
				streamWriter2.WriteLine("}");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Skeleton dumped: {componentsInChildren.Length} meshes, {hashSet.Count} bones -> {text}");
		}

		private void DumpBoneQuaternions(Character character)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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)
			SkinnedMeshRenderer mainRenderer = character.refs.mainRenderer;
			if (((mainRenderer != null) ? mainRenderer.bones : null) == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"No bones found");
				return;
			}
			string text = Path.Combine(_pluginDir, "bone_quaternions.txt");
			using (StreamWriter streamWriter = new StreamWriter(text))
			{
				streamWriter.WriteLine($"PEAK Bone Quaternions - {DateTime.Now}");
				streamWriter.WriteLine("Character: " + ((Object)((Component)character).gameObject).name);
				streamWriter.WriteLine($"Bones: {mainRenderer.bones.Length}");
				streamWriter.WriteLine();
				streamWriter.WriteLine(string.Format("{0,-30} {1,-50} {2,-40} {3,-35}", "Name", "LocalRot (x,y,z,w)", "LocalPos (x,y,z)", "EulerAngles (x,y,z)"));
				streamWriter.WriteLine(new string('-', 155));
				Transform[] bones = mainRenderer.bones;
				foreach (Transform val in bones)
				{
					if (!((Object)(object)val == (Object)null))
					{
						Quaternion localRotation = val.localRotation;
						Vector3 localPosition = val.localPosition;
						Vector3 localEulerAngles = val.localEulerAngles;
						streamWriter.WriteLine($"{((Object)val).name,-30} ({localRotation.x,8:F4}, {localRotation.y,8:F4}, {localRotation.z,8:F4}, {localRotation.w,8:F4})   ({localPosition.x,8:F4}, {localPosition.y,8:F4}, {localPosition.z,8:F4})   ({localEulerAngles.x,8:F2}, {localEulerAngles.y,8:F2}, {localEulerAngles.z,8:F2})");
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Bone quaternions dumped to: " + text));
		}

		private void HideOriginalBody(Character character)
		{
			SkinnedMeshRenderer mainRenderer = character.refs.mainRenderer;
			if ((Object)(object)mainRenderer != (Object)null)
			{
				((Renderer)mainRenderer).shadowCastingMode = (ShadowCastingMode)3;
			}
			Renderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (((Object)((Component)val).gameObject).name.Contains("Lego_") || ((Object)((Component)val).gameObject).name.Contains("LegoMouth"))
				{
					continue;
				}
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
				if (val2 != null)
				{
					((Renderer)val2).shadowCastingMode = (ShadowCastingMode)3;
					continue;
				}
				MeshRenderer val3 = (MeshRenderer)(object)((val is MeshRenderer) ? val : null);
				if (val3 != null)
				{
					((Renderer)val3).shadowCastingMode = (ShadowCastingMode)3;
				}
			}
		}

		private void CleanupLego()
		{
			if ((Object)(object)_lastCharacter != (Object)null)
			{
				RestoreOriginalBody(_lastCharacter);
			}
			Transform[] array = Object.FindObjectsByType<Transform>((FindObjectsSortMode)0);
			foreach (Transform val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "LegoRoot")
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private void OnDestroy()
		{
			CleanupLego();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public class LegoBoneTracker : MonoBehaviour
	{
		public Transform targetBone;

		public Transform handBone;

		public Transform characterTransform;

		public float influence = 1f;

		public bool isHead;

		public bool isArm;

		public bool isLeg;

		public bool isTorso;

		public bool flipModel;

		public float legSide = 1f;

		public float armSide = 1f;

		public float maxAngle = 90f;

		public bool isLeftArm;

		public static float LeftArmBoneMag;

		public static float RightArmBoneMag;

		public static float RightArmReachWeight;

		private static int _emoteFrameCount;

		private static bool _emoteActive;

		private Quaternion _restLocalRotation;

		private Quaternion _restHandRotation;

		private bool _initialized;

		private float _smoothSwing;

		private float _smoothCross;

		private float _smoothTwist;

		private float _smoothCamYaw;

		private Vector3 _lastRootPos;

		private float _lastRootY;

		private float _legTimer;

		private bool _isClimbing;

		private void LateUpdate()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0767: Unknown result type (might be due to invalid IL or missing references)
			//IL_077e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)targetBone == (Object)null)
			{
				return;
			}
			if (!_initialized)
			{
				_restLocalRotation = targetBone.localRotation;
				if ((Object)(object)handBone != (Object)null)
				{
					_restHandRotation = handBone.localRotation;
				}
				_lastRootPos = (((Object)(object)characterTransform != (Object)null) ? characterTransform.position : targetBone.root.position);
				_initialized = true;
			}
			Quaternion val = Quaternion.Inverse(_restLocalRotation) * targetBone.localRotation;
			Quaternion val2 = Quaternion.Inverse(((Component)this).transform.parent.rotation) * targetBone.parent.rotation;
			Quaternion val3 = val2 * val * Quaternion.Inverse(val2);
			if (val3.w < 0f)
			{
				((Quaternion)(ref val3))..ctor(0f - val3.x, 0f - val3.y, 0f - val3.z, 0f - val3.w);
			}
			Vector3 eulerAngles = ((Quaternion)(ref val3)).eulerAngles;
			float num = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			float num2 = ((eulerAngles.y > 180f) ? (eulerAngles.y - 360f) : eulerAngles.y);
			float num3 = ((eulerAngles.z > 180f) ? (eulerAngles.z - 360f) : eulerAngles.z);
			num = Mathf.Clamp(num, -180f, 180f);
			float num4 = 0f;
			float num5 = 0f;
			if (isLeg)
			{
				Vector3 val4 = (((Object)(object)characterTransform != (Object)null) ? characterTransform.position : targetBone.root.position);
				float num6 = Mathf.Max(Time.deltaTime, 0.001f);
				float num7 = Vector3.Distance(val4, _lastRootPos) / num6;
				_lastRootPos = val4;
				float num8 = ((legSide > 0f) ? 0f : ((float)Math.PI));
				if (num7 > 0.15f)
				{
					float num9 = Mathf.Clamp(num7 * 2.6f, 5f, 14f);
					_legTimer += Time.deltaTime * num9;
					float num10 = Mathf.Clamp(num7 * 7.5f, 20f, 50f);
					float num11 = Mathf.Sin(_legTimer + num8);
					float num12 = Mathf.Sign(num11) * Mathf.Pow(Mathf.Abs(num11), 0.55f) * num10;
					_smoothSwing = Mathf.Lerp(_smoothSwing, num12, Time.deltaTime * 20f);
					num4 = Mathf.Sin(_legTimer * 0.5f + num8) * Mathf.Clamp(num7 * 0.8f, 0f, 3f);
					num5 = 0f;
				}
				else
				{
					float num13 = 0f;
					if (legSide > 0f)
					{
						num13 = RightArmReachWeight * 8f;
					}
					_smoothSwing = Mathf.Lerp(_smoothSwing, num13, Time.deltaTime * 14f);
					num4 = Mathf.Lerp(num4, 0f, Time.deltaTime * 10f);
					num5 = 0f;
				}
			}
			else if (isArm)
			{
				Vector3 val5 = (((Object)(object)characterTransform != (Object)null) ? characterTransform.position : targetBone.root.position);
				float num14 = Mathf.Max(Time.deltaTime, 0.001f);
				float num15 = Mathf.Abs((val5.y - _lastRootY) / num14);
				_lastRootPos = val5;
				_lastRootY = val5.y;
				bool flag = num15 > 0.5f;
				_isClimbing = flag || (_isClimbing && num15 > 0.15f);
				float num16 = num;
				float num17 = num2;
				float num18 = num3;
				float num19 = 0f;
				if ((Object)(object)handBone != (Object)null)
				{
					Quaternion val6 = Quaternion.Inverse(_restHandRotation) * handBone.localRotation;
					if (val6.w < 0f)
					{
						((Quaternion)(ref val6))..ctor(0f - val6.x, 0f - val6.y, 0f - val6.z, 0f - val6.w);
					}
					num19 = Mathf.Clamp01(Quaternion.Angle(Quaternion.identity, val6) / 30f);
				}
				float num20 = Mathf.Abs(num16) + Mathf.Abs(num17) + Mathf.Abs(num18);
				if (isLeftArm)
				{
					LeftArmBoneMag = num20;
				}
				else
				{
					RightArmBoneMag = num20;
				}
				if (!isLeftArm)
				{
					if (LeftArmBoneMag > 30f && RightArmBoneMag > 30f)
					{
						_emoteFrameCount = Mathf.Min(_emoteFrameCount + 1, 30);
					}
					else
					{
						_emoteFrameCount = Mathf.Max(_emoteFrameCount - 2, 0);
					}
					_emoteActive = _emoteFrameCount >= 12;
				}
				bool emoteActive = _emoteActive;
				float num21 = 0f;
				float num22 = 0f;
				float num23 = 0f;
				_legTimer += Time.deltaTime * 2.5f;
				if (emoteActive || _isClimbing)
				{
					num21 = num16;
					num22 = num17;
					num23 = num18;
				}
				else if (isLeftArm)
				{
					num21 = 0f;
					num22 = 0f;
					num23 = 0f;
				}
				else
				{
					float num24 = Mathf.Clamp01((num20 - 1f) / 6f);
					num24 = (RightArmReachWeight = Mathf.Max(num24, num19 * 0.5f));
					if (num24 > 0.02f)
					{
						float num25 = Mathf.Clamp(num16, -70f, 70f);
						float num26 = Mathf.Clamp(num17, -50f, 50f);
						float num27 = Mathf.Clamp(num18, -35f, 35f);
						num21 = num25 * num24;
						num22 = num26 * num24;
						num23 = num27 * num24;
					}
				}
				float num28 = (emoteActive ? 12f : (isLeftArm ? 30f : 28f));
				_smoothSwing = Mathf.Lerp(_smoothSwing, num21, Time.deltaTime * num28);
				_smoothTwist = Mathf.Lerp(_smoothTwist, num22, Time.deltaTime * num28);
				_smoothCross = Mathf.Lerp(_smoothCross, num23, Time.deltaTime * num28);
				num4 = _smoothTwist;
				num5 = _smoothCross;
			}
			else
			{
				float num29 = (isHead ? Mathf.Clamp(num, -3f, 3f) : num) * influence;
				_smoothSwing = Mathf.Lerp(_smoothSwing, num29, Time.deltaTime * (isHead ? 18f : 12f));
				if (isTorso && (Object)(object)characterTransform != (Object)null)
				{
					float num30 = RightArmReachWeight * -5f;
					_smoothCamYaw = Mathf.Lerp(_smoothCamYaw, 0f, Time.deltaTime * 8f);
					num4 = _smoothCamYaw;
					_smoothSwing = Mathf.Lerp(_smoothSwing, num30, Time.deltaTime * 8f);
				}
			}
			if (isHead)
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					float y = ((Component)main).transform.eulerAngles.y;
					float num31 = Mathf.DeltaAngle(targetBone.root.eulerAngles.y, y);
					num31 = Mathf.Clamp(num31, -15f, 15f) * 0.25f;
					_smoothCamYaw = Mathf.Lerp(_smoothCamYaw, num31, Time.deltaTime * 4f);
					num4 = _smoothCamYaw;
				}
			}
			((Component)this).transform.localRotation = Quaternion.Euler(_smoothSwing, num4, num5);
		}
	}
	public class LegoStabilizer : MonoBehaviour
	{
		public Transform hipBone;

		public float baseYRotation = 180f;

		public float heightOffset;

		private Vector3 _lastPos;

		private float _smoothLean;

		private bool _initPos;

		private void LateUpdate()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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)
			//IL_00df: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hipBone == (Object)null)
			{
				return;
			}
			float y = hipBone.eulerAngles.y;
			float num = y + baseYRotation;
			Vector3 position = hipBone.position;
			if (!_initPos)
			{
				_lastPos = position;
				_initPos = true;
			}
			float num2 = Mathf.Max(Time.deltaTime, 0.001f);
			Vector3 val = (position - _lastPos) / num2;
			_lastPos = position;
			float num3 = y * ((float)Math.PI / 180f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(Mathf.Cos(num3), 0f, 0f - Mathf.Sin(num3));
			float num4 = Mathf.Clamp(Vector3.Dot(val, val2) * -2f, -6f, 6f);
			_smoothLean = Mathf.Lerp(_smoothLean, num4, Time.deltaTime * 4f);
			Vector3 eulerAngles = ((Component)this).transform.eulerAngles;
			float num5 = Mathf.LerpAngle(eulerAngles.x, 0f, Time.deltaTime * 6f);
			float num6 = Mathf.LerpAngle(eulerAngles.z, _smoothLean, Time.deltaTime * 5f);
			float num7 = Mathf.LerpAngle(eulerAngles.y, num, Time.deltaTime * 10f);
			((Component)this).transform.rotation = Quaternion.Euler(num5, num7, num6);
			Vector3 position2 = ((Component)this).transform.position;
			bool flag = (position.y - _lastPos.y) / num2 > 1.5f || position.y - position2.y > 0.3f;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(hipBone.position, Vector3.down, ref val3, 5f))
			{
				float num8 = ((RaycastHit)(ref val3)).point.y + heightOffset;
				float num9 = position2.y - num8;
				if (!flag)
				{
					if (num9 < 0f)
					{
						position2.y = Mathf.Lerp(position2.y, num8, Time.deltaTime * 20f);
					}
					else if (num9 < 0.2f)
					{
						position2.y = Mathf.Lerp(position2.y, num8, Time.deltaTime * 14f);
					}
				}
			}
			((Component)this).transform.position = position2;
		}
	}
	public class LegoHeadFader : MonoBehaviour
	{
		private Renderer[] _renderers;

		private void Start()
		{
			Transform parent = ((Component)this).transform.parent;
			_renderers = (((Object)(object)parent != (Object)null) ? ((Component)parent).GetComponentsInChildren<Renderer>(true) : ((Component)this).GetComponentsInChildren<Renderer>(true));
		}

		private void LateUpdate()
		{
			//IL_0014: 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)
			if (_renderers == null)
			{
				return;
			}
			ShadowCastingMode shadowCastingMode = (ShadowCastingMode)(LegoSkinPlugin.CameraEnabled ? 1 : 3);
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.shadowCastingMode = shadowCastingMode;
					val.enabled = true;
				}
			}
		}

		private void OnDestroy()
		{
			if (_renderers == null)
			{
				return;
			}
			Renderer[] renderers = _renderers;
			foreach (Renderer val in renderers)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.shadowCastingMode = (ShadowCastingMode)1;
				}
			}
		}
	}
	public class LegoMouthIndicator : MonoBehaviour
	{
		public bool flipModel;

		public Character character;

		private Transform _mouthQuad;

		private float _smoothLevel;

		private Renderer _gameMouthRenderer;

		private Vector3 _gameMouthRestScale;

		private bool _gameMouthFound;

		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005a: 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_0072: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Invalid comparison between Unknown and I4
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("LegoMouth");
			val.transform.SetParent(((Component)this).transform, false);
			float num = (flipModel ? (-0.42f) : 0.42f);
			float num2 = (flipModel ? (-0.01f) : 0.01f);
			val.transform.localPosition = new Vector3(0f, -0.18f, num + num2);
			val.transform.localRotation = (flipModel ? Quaternion.Euler(0f, 180f, 0f) : Quaternion.identity);
			val.transform.localScale = new Vector3(0.1f, 0.04f, 1f);
			_mouthQuad = val.transform;
			Mesh val2 = new Mesh();
			val2.vertices = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f)
			};
			val2.uv = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f, 0f),
				new Vector2(1f, 0f),
				new Vector2(0f, 1f),
				new Vector2(1f, 1f)
			};
			val2.triangles = new int[6] { 0, 2, 1, 2, 3, 1 };
			val2.RecalculateNormals();
			val.AddComponent<MeshFilter>().mesh = val2;
			int num3 = 64;
			Texture2D val3 = new Texture2D(num3, num3, (TextureFormat)4, false);
			float num4 = (float)num3 / 2f;
			float num5 = (float)num3 / 2f;
			float num6 = (float)num3 / 2f - 2f;
			for (int i = 0; i < num3; i++)
			{
				for (int j = 0; j < num3; j++)
				{
					float num7 = Mathf.Sqrt(((float)j - num4) * ((float)j - num4) + ((float)i - num5) * ((float)i - num5));
					float num8 = Mathf.Clamp01(num6 - num7);
					val3.SetPixel(j, i, new Color(0.08f, 0.08f, 0.08f, num8));
				}
			}
			val3.Apply();
			((Texture)val3).filterMode = (FilterMode)1;
			Material val4 = new Material(Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Transparent") ?? Shader.Find("Standard"));
			val4.mainTexture = (Texture)(object)val3;
			val4.SetColor("_BaseColor", Color.white);
			val4.color = Color.white;
			val4.SetFloat("_Surface", 1f);
			val4.SetOverrideTag("RenderType", "Transparent");
			val4.SetInt("_SrcBlend", 5);
			val4.SetInt("_DstBlend", 10);
			val4.SetInt("_ZWrite", 0);
			val4.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val4.renderQueue = 3100;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).material = val4;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			if (!((Object)(object)character != (Object)null))
			{
				return;
			}
			Bodypart[] componentsInChildren = ((Component)character).GetComponentsInChildren<Bodypart>(true);
			foreach (Bodypart val5 in componentsInChildren)
			{
				if ((int)val5.partType == 18)
				{
					_gameMouthRenderer = ((Component)val5).GetComponent<Renderer>();
					if ((Object)(object)_gameMouthRenderer != (Object)null)
					{
						_gameMouthRestScale = ((Component)_gameMouthRenderer).transform.localScale;
						_gameMouthFound = true;
					}
					break;
				}
			}
		}

		private void LateUpdate()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_mouthQuad == (Object)null))
			{
				float num = 0f;
				if (_gameMouthFound && (Object)(object)_gameMouthRenderer != (Object)null)
				{
					Vector3 localScale = ((Component)_gameMouthRenderer).transform.localScale;
					num = Mathf.Abs(((Vector3)(ref localScale)).magnitude / Mathf.Max(((Vector3)(ref _gameMouthRestScale)).magnitude, 0.01f) - 1f);