Decompiled source of Clone And Pose Yourself v2.0.0

Mods/CloneMod.dll

Decompiled 2 days 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 System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(CloneMod), "CloneMod", "9.5.10", "Int_Void", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("CloneMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CloneMod")]
[assembly: AssemblyTitle("CloneMod")]
[assembly: AssemblyVersion("1.0.0.0")]
public class CloneMod : MelonMod
{
	public enum ReturnMode
	{
		Keep,
		Spring
	}

	private class Handle
	{
		public int type;

		public int role;

		public int kind;

		public float side;

		public Transform a;

		public Transform b;

		public Transform c;

		public float rad;

		public float ext;

		public float limit = 180f;

		public float maxBend = 150f;

		public Vector3 anat = Vector3.forward;

		public Vector3 pole = Vector3.forward;

		public Behaviour phys;

		public SkinnedMeshRenderer jawBlendRenderer;

		public int jawBlendIndex = -1;

		public bool virtualJaw;

		public bool jawBlendEdited;

		public bool jawBlendHeld;

		public float jawBlendRestWeight;

		public Vector3 scaleA = Vector3.one;

		public Vector3 scaleB = Vector3.one;

		public Vector3 gPos;

		public Vector3 gVel;

		public bool gInit;

		public Vector3 anchor;

		public bool anchorSet;

		public Transform sh;

		public Transform[] chain;

		public Vector3 restDirP;

		public Vector3 restPoleP;

		public Vector3 hingeA;

		public bool restValid;
	}

	private class Grab
	{
		public bool prev;

		public bool attached;

		public Handle limb;

		public Vector3 offset;

		public Vector3 worldOff;

		public Quaternion handStartRot;

		public Quaternion pivotStartRot;

		public List<Collider> handCols = new List<Collider>();

		public List<Collider> ignoredCols = new List<Collider>();

		public Behaviour disabledPhys;

		public bool physWasEnabled;

		public Quaternion boneStartRot;

		public Quaternion boneStartLocalRot = Quaternion.identity;

		public Quaternion parentStartLocalRot = Quaternion.identity;

		public Quaternion headStartWorldRot = Quaternion.identity;

		public Quaternion rotStartPv = Quaternion.identity;

		public Vector3 handStartPosition;

		public Vector3 headStartWorldPosition;

		public Vector3 neckStartWorldPosition;

		public Quaternion neckStartPv = Quaternion.identity;

		public Quaternion headStartPv = Quaternion.identity;

		public float jawBlendStartWeight;

		public float twistDone;

		public RagBone ragBone;

		public Vector3 ragOffset;

		public Quaternion ragHandRot0 = Quaternion.identity;

		public Quaternion ragBoneRot0 = Quaternion.identity;
	}

	private class ColPart
	{
		public GameObject go;

		public Rigidbody rb;

		public CapsuleCollider cap;

		public Transform a;

		public Transform b;

		public float rad;

		public float ext;

		public bool useFwd;

		public Vector3 tp;

		public Quaternion tr = Quaternion.identity;
	}

	private sealed class PhysicsRestPose
	{
		public Transform transform;

		public Transform sourceTransform;

		public Vector3 localPosition;

		public Quaternion localRotation;
	}

	private sealed class PhysicsLivePair
	{
		public Transform source;

		public Transform clone;
	}

	private class RagBone
	{
		public HumanBodyBones hb;

		public Transform t;

		public GameObject go;

		public Transform px;

		public Rigidbody rb;

		public Collider col;

		public RagBone parent;

		public RagBone hingeChild;

		public ConfigurableJoint cj;

		public bool hinge;

		public Matrix4x4 rel;

		public bool frozen;
	}

	private class RagPin
	{
		public RagBone b;

		public Vector3 pos;

		public Quaternion rot;
	}

	private const int POSE_SLOTS = 30;

	private static readonly HumanBodyBones[] RAG_BONES;

	private static readonly HumanBodyBones[] LEFT_FINGER_BONES;

	private static readonly HumanBodyBones[] RIGHT_FINGER_BONES;

	private static MelonPreferences_Category _cat;

	private static MelonPreferences_Entry<float> PrefAngle;

	private static MelonPreferences_Entry<float> PrefDist;

	private static MelonPreferences_Entry<float> PrefFreezeDelay;

	private static MelonPreferences_Entry<float> PrefSpringSpeed;

	private static MelonPreferences_Entry<float> PrefReach;

	private static MelonPreferences_Entry<float> PrefGrabStrength;

	private static MelonPreferences_Entry<float> PrefJawAngle;

	private static MelonPreferences_Entry<float> PrefFingerGestureDelay;

	private static MelonPreferences_Entry<bool> PrefMirror;

	private static MelonPreferences_Entry<bool> PrefBeeps;

	private static MelonPreferences_Entry<bool> PrefPelvisRot;

	private static MelonPreferences_Entry<bool> PrefPullBody;

	private static MelonPreferences_Entry<bool> PrefLoadFreeze;

	private static MelonPreferences_Entry<bool> PrefLoadGround;

	private static MelonPreferences_Entry<int> PrefSlot;

	private static MelonPreferences_Entry<bool> PrefColliders;

	private static MelonPreferences_Entry<bool> PrefHeadFix;

	private static MelonPreferences_Entry<bool> PrefCleanModel;

	private static MelonPreferences_Entry<bool> PrefTrackHead;

	private static MelonPreferences_Entry<bool> PrefGrabBones;

	private static MelonPreferences_Entry<bool> PrefStickyGrab;

	private static MelonPreferences_Entry<float> PrefHandSpeed;

	private static MelonPreferences_Entry<float> PrefHandStretch;

	private static MelonPreferences_Entry<ReturnMode> PrefReturn;

	private static MelonPreferences_Entry<bool> PrefGroundLegs;

	private static MelonPreferences_Entry<bool> PrefGroundArms;

	private static MelonPreferences_Entry<float> PrefGroundStrength;

	private static MelonPreferences_Entry<float> PrefMaxSpeed;

	private static MelonPreferences_Entry<float> PrefMaxAccel;

	private static MelonPreferences_Entry<float> PrefStretchLimit;

	private static MelonPreferences_Entry<bool> PrefLoadPlacement;

	private static MelonPreferences_Entry<bool> PrefRigid;

	private static MelonPreferences_Entry<bool> PrefRotateHand;

	private static MelonPreferences_Entry<bool> PrefTwistFix;

	private static MelonPreferences_Entry<bool> PrefShoulder;

	private static MelonPreferences_Entry<bool> PrefTouch;

	private static MelonPreferences_Entry<float> PrefTouchMargin;

	private static MelonPreferences_Entry<bool> PrefRagdollGrab;

	private static MelonPreferences_Entry<float> PrefRagGrabStrength;

	private static MelonPreferences_Entry<bool> PrefTouchUnragdoll;

	private static MelonPreferences_Entry<bool> PrefRagPinOnRelease;

	private static MelonPreferences_Entry<bool> PrefRagPinAllOnStart;

	private static MelonPreferences_Entry<bool> PrefRagTouchPush;

	private static MelonPreferences_Entry<bool> PrefRagRigidGrab;

	private static MelonPreferences_Entry<float> PrefRagPinStiff;

	private GameObject _clone;

	private GameObject _pivot;

	private GameObject _srcGO;

	private Transform[] _srcT;

	private Transform[] _cloneT;

	private Transform[] _bones;

	private Transform[] _spine;

	private bool[] _skip;

	private bool[] _noPos;

	private Transform _hips;

	private Transform _head;

	private Transform _jawBone;

	private Quaternion _jawRestLocalRotation = Quaternion.identity;

	private float _jawRestBlendWeight;

	private bool _jawRestCaptured;

	private bool _jawRestSynced;

	private bool _jawCommandActive;

	private bool _jawCommandOpen;

	private float _height = 1.8f;

	private bool _frozen;

	private Vector3 _anchorPos;

	private Vector3 _anchorHeading = Vector3.forward;

	private readonly List<SkinnedMeshRenderer> _bsSrc = new List<SkinnedMeshRenderer>();

	private readonly List<SkinnedMeshRenderer> _bsDst = new List<SkinnedMeshRenderer>();

	private readonly List<Handle> _handles = new List<Handle>();

	private readonly Grab[] _grab = new Grab[2]
	{
		new Grab(),
		new Grab()
	};

	private readonly List<Behaviour> _dbones = new List<Behaviour>();

	private readonly Dictionary<int, PhysicsRestPose> _physicsRestPose = new Dictionary<int, PhysicsRestPose>();

	private readonly List<PhysicsLivePair> _physicsLivePairs = new List<PhysicsLivePair>();

	private readonly List<ColPart> _parts = new List<ColPart>();

	private readonly List<(object el, Func<object> get)> _menuEls = new List<(object, Func<object>)>();

	private Quaternion[] _baseLr;

	private bool[] _edited;

	private bool[] _held;

	private Vector3[] _vel;

	private Dictionary<int, int> _idx;

	private Vector3 _restPos;

	private Vector3 _restHips;

	private Vector3 _pivVel;

	private Quaternion _restRot = Quaternion.identity;

	private Vector3 _fwdAnat = Vector3.forward;

	private float _rUA;

	private float _rFA;

	private float _rTh;

	private float _rCa;

	private float _rPel;

	private float _rChest;

	private float _rHead;

	private float _rFoot;

	private bool _pulled;

	private bool _colOn;

	private bool _colGrace;

	private float _colGraceUntil;

	private GameObject _prefab;

	private IntPtr _prefabCratePtr = IntPtr.Zero;

	private bool _ragdolled;

	private readonly List<RagBone> _rag = new List<RagBone>();

	private readonly List<Collider> _ragCols = new List<Collider>();

	private bool _ragGrace;

	private float _ragGraceUntil;

	private Vector3[] _ragLp;

	private Quaternion[] _ragLr;

	private float _ragTotalMass = 75f;

	private readonly List<RagPin> _pins = new List<RagPin>();

	private const float RAG_GRAB_GAIN = 14f;

	private const float RAG_GRAB_SPEED = 10f;

	private const float RAG_TOUCH_MARGIN = 0.06f;

	private const float RAG_TOUCH_ACCEL = 35f;

	private const float ATTACH_DROP_DIST = 2f;

	private const float LEAN_TOTAL = 40f;

	private const float SHOULDER_LIMIT = 35f;

	private const float NECK_DOWN = 22f;

	private const float NECK_UP = 35f;

	private const float NECK_YAW = 45f;

	private const float NECK_ROLL = 40f;

	private const float HEAD_DOWN = 20f;

	private const float HEAD_UP = 30f;

	private const float HEAD_YAW = 50f;

	private const float HEAD_ROLL = 45f;

	private Action _cdAction;

	private bool _cdActive;

	private int _cdLeft;

	private float _cdNext;

	private bool _cdBeeps;

	private static AudioClip _beepClip;

	private static CloneMod _physicsMirrorPatchOwner;

	private Harmony _physicsMirrorHarmony;

	private readonly HashSet<MethodBase> _patchedMirrorPhysicsMethods = new HashSet<MethodBase>();

	private static readonly string[] BLACKLIST;

	private static MethodInfo _gripM;

	private static bool _gripFloat;

	private static bool _gripSearched;

	private static Vector3 V3(Vector4 v)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(v.x, v.y, v.z);
	}

	public override void OnInitializeMelon()
	{
		_cat = MelonPreferences.CreateCategory("CloneMod", "Clone Mod");
		PrefAngle = _cat.CreateEntry<float>("SideAngle", 90f, "Side Angle", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefDist = _cat.CreateEntry<float>("Distance", 1.2f, "Distance", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefMirror = _cat.CreateEntry<bool>("MirrorImage", true, "Mirror Image", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefFreezeDelay = _cat.CreateEntry<float>("FreezeDelay", 3f, "Freeze Countdown", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefBeeps = _cat.CreateEntry<bool>("Beeps", true, "Countdown Beeps", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefReturn = _cat.CreateEntry<ReturnMode>("ReturnMode_v8", ReturnMode.Spring, "Return Mode", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefSpringSpeed = _cat.CreateEntry<float>("SpringSpeed_v8", 8f, "Spring Speed", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefReach = _cat.CreateEntry<float>("GrabReach_v8", 0.06f, "Grab Reach", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefGrabStrength = _cat.CreateEntry<float>("GrabStrength_v8", 1f, "Grab Strength", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefJawAngle = _cat.CreateEntry<float>("JawOpenAngle_v952", 35f, "Jaw Open Angle (degrees; negative reverses)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefFingerGestureDelay = _cat.CreateEntry<float>("FingerGestureDelay_v9510", 3f, "Finger Gesture Countdown (seconds)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefPelvisRot = _cat.CreateEntry<bool>("PelvisRotate_v8", true, "Pelvis Rotate", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefPullBody = _cat.CreateEntry<bool>("PullBody_v8", true, "Pull Body", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefColliders = _cat.CreateEntry<bool>("CloneColliders_v8", false, "Clone Colliders", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefHeadFix = _cat.CreateEntry<bool>("HeadNeckFix", true, "Fix Head/Neck Offset", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefCleanModel = _cat.CreateEntry<bool>("CleanModel", false, "Clean Model (use prefab)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefTrackHead = _cat.CreateEntry<bool>("TrackHead", true, "Track Head Rotation", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefGrabBones = _cat.CreateEntry<bool>("GrabPhysBones_v82", true, "Grab Physics Bones", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefStickyGrab = _cat.CreateEntry<bool>("StickyGrab_v9", true, "Sticky Grab", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefHandSpeed = _cat.CreateEntry<float>("HandFollowSpeed_v83", 20f, "Hand Follow Speed", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefHandStretch = _cat.CreateEntry<float>("HandStretch_v83", 1f, "Hand Stretch", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefGroundLegs = _cat.CreateEntry<bool>("GroundLegs_v9", false, "Legs Ground Lock", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefGroundArms = _cat.CreateEntry<bool>("GroundArms_v9", false, "Arms Ground Lock", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefGroundStrength = _cat.CreateEntry<float>("GroundStrength_v9", 10f, "Ground Pull Strength", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefMaxSpeed = _cat.CreateEntry<float>("BodyMaxSpeed_v9", 2.5f, "Body Max Speed", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefMaxAccel = _cat.CreateEntry<float>("BodyAccel_v9", 10f, "Body Accel", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefStretchLimit = _cat.CreateEntry<float>("PullLimit_v9", 0.35f, "Pull Limit (x height)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefLoadPlacement = _cat.CreateEntry<bool>("PoseLoadPlacement_v9", false, "Pose Load Placement", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefLoadFreeze = _cat.CreateEntry<bool>("PoseLoadFreeze_v91", true, "Auto-Freeze On Load", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefLoadGround = _cat.CreateEntry<bool>("PoseLoadGround_v91", true, "Feet To Ground On Load", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefSlot = _cat.CreateEntry<int>("PoseSlot_v91", 1, "Pose Slot", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRigid = _cat.CreateEntry<bool>("RigidAttach_v92", true, "Rigid Attach", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRotateHand = _cat.CreateEntry<bool>("RotateWithHand_v92", true, "Rotate Part With Hand", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefTwistFix = _cat.CreateEntry<bool>("TwistFix_v92", true, "Elbow/Twist Fix", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefShoulder = _cat.CreateEntry<bool>("ShoulderAssist_v92", true, "Shoulder Assist", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefTouch = _cat.CreateEntry<bool>("TouchPose_v93", false, "Touch Pose (push parts)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefTouchMargin = _cat.CreateEntry<float>("TouchMargin_v93", 0.06f, "Touch Margin (m)", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagdollGrab = _cat.CreateEntry<bool>("RagdollGrab_v94", false, "Ragdoll Grab Mode", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagGrabStrength = _cat.CreateEntry<float>("RagGrabStrength_v94", 1f, "Ragdoll Grab Strength", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefTouchUnragdoll = _cat.CreateEntry<bool>("TouchUnragdoll_v941", false, "Touch to Un-Ragdoll", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagPinOnRelease = _cat.CreateEntry<bool>("RagPinOnRelease_v95", false, "Ragdoll: Pin On Release", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagPinAllOnStart = _cat.CreateEntry<bool>("RagPinAllOnStart_v95", false, "Ragdoll: Pin All On Start", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagTouchPush = _cat.CreateEntry<bool>("RagTouchPush_v95", false, "Ragdoll: Touch Push", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagPinStiff = _cat.CreateEntry<float>("RagPinStiff_v95", 200f, "Ragdoll: Pin Stiffness", (string)null, false, false, (ValueValidator)null, (string)null);
		PrefRagRigidGrab = _cat.CreateEntry<bool>("RagRigidGrab_v95", true, "Ragdoll: Rigid Grab", (string)null, false, false, (ValueValidator)null, (string)null);
		BuildMenu();
		_physicsMirrorPatchOwner = this;
		Hooking.OnLevelLoaded += OnLevelLoaded;
		MelonLogger.Msg("CloneMod v9.5.10 loaded!");
	}

	public override void OnDeinitializeMelon()
	{
		Hooking.OnLevelLoaded -= OnLevelLoaded;
		Despawn();
		try
		{
			if (_physicsMirrorHarmony != null)
			{
				_physicsMirrorHarmony.UnpatchSelf();
			}
		}
		catch
		{
		}
		if (_physicsMirrorPatchOwner == this)
		{
			_physicsMirrorPatchOwner = null;
		}
	}

	private void OnLevelLoaded(LevelInfo info)
	{
		_cdActive = false;
		_prefab = null;
		_prefabCratePtr = IntPtr.Zero;
		Despawn();
	}

	private void AddBool(Page p, string name, Color col, MelonPreferences_Entry<bool> e, Action<bool> extra = null)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		BoolElement item = p.CreateBool(name, col, e.Value, (Action<bool>)delegate(bool v)
		{
			e.Value = v;
			_cat.SaveToFile(false);
			if (extra != null)
			{
				extra(v);
			}
		});
		_menuEls.Add((item, () => e.Value));
	}

	private void AddFloat(Page p, string name, Color col, MelonPreferences_Entry<float> e, float inc, float min, float max)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		FloatElement item = p.CreateFloat(name, col, e.Value, inc, min, max, (Action<float>)delegate(float v)
		{
			e.Value = v;
			_cat.SaveToFile(false);
		});
		_menuEls.Add((item, () => e.Value));
	}

	private void AddReturnEnum(Page p, string name, Color col)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		EnumElement item = p.CreateEnum(name, col, (Enum)PrefReturn.Value, (Action<Enum>)delegate(Enum v)
		{
			PrefReturn.Value = (ReturnMode)(object)v;
			_cat.SaveToFile(false);
			if (PrefReturn.Value == ReturnMode.Spring)
			{
				CommitPose();
			}
		});
		_menuEls.Add((item, () => PrefReturn.Value));
	}

	private void RefreshMenuValues()
	{
		for (int i = 0; i < _menuEls.Count; i++)
		{
			try
			{
				PropertyInfo property = _menuEls[i].el.GetType().GetProperty("Value");
				if (property != null && property.CanWrite)
				{
					property.SetValue(_menuEls[i].el, _menuEls[i].get());
				}
			}
			catch
			{
			}
		}
	}

	private void BuildMenu()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: 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_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_032e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_0351: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0404: Unknown result type (might be due to invalid IL or missing references)
		//IL_0419: Unknown result type (might be due to invalid IL or missing references)
		//IL_042e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0443: Unknown result type (might be due to invalid IL or missing references)
		//IL_0458: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0481: Unknown result type (might be due to invalid IL or missing references)
		//IL_0493: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fc: 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_0542: Unknown result type (might be due to invalid IL or missing references)
		//IL_0565: Unknown result type (might be due to invalid IL or missing references)
		//IL_0588: Unknown result type (might be due to invalid IL or missing references)
		//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_061e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0638: Unknown result type (might be due to invalid IL or missing references)
		//IL_0649: Unknown result type (might be due to invalid IL or missing references)
		//IL_0664: Unknown result type (might be due to invalid IL or missing references)
		//IL_0679: Unknown result type (might be due to invalid IL or missing references)
		//IL_0699: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_070e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0724: Unknown result type (might be due to invalid IL or missing references)
		//IL_0747: Unknown result type (might be due to invalid IL or missing references)
		//IL_0762: Unknown result type (might be due to invalid IL or missing references)
		//IL_077d: Unknown result type (might be due to invalid IL or missing references)
		//IL_079b: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0809: Unknown result type (might be due to invalid IL or missing references)
		//IL_0824: Unknown result type (might be due to invalid IL or missing references)
		//IL_083f: Unknown result type (might be due to invalid IL or missing references)
		//IL_085a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0875: Unknown result type (might be due to invalid IL or missing references)
		//IL_0894: Unknown result type (might be due to invalid IL or missing references)
		//IL_08aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0903: Unknown result type (might be due to invalid IL or missing references)
		//IL_0919: Unknown result type (might be due to invalid IL or missing references)
		//IL_093d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0960: Unknown result type (might be due to invalid IL or missing references)
		//IL_0973: 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_099f: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a19: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a2e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a4c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a5d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ad3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b10: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b2d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b72: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bb0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0be5: Unknown result type (might be due to invalid IL or missing references)
		Color yellow = Color.yellow;
		Color magenta = Color.magenta;
		Color green = Color.green;
		Color val = default(Color);
		((Color)(ref val))..ctor(1f, 0.55f, 0.2f);
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(1f, 0.8f, 0.4f);
		Color cyan = Color.cyan;
		Color val3 = default(Color);
		((Color)(ref val3))..ctor(0.45f, 0.65f, 1f);
		Color val4 = default(Color);
		((Color)(ref val4))..ctor(0.6f, 1f, 0.4f);
		Color gray = Color.gray;
		Page val5 = Page.Root.CreatePage("CloneMod", Color.white, 0, true);
		val5.CreateFunction("1) Spawn Clone", Color.green, (Action)Spawn);
		val5.CreateFunction("2) Freeze (countdown)", Color.cyan, (Action)FreezeCountdown);
		val5.CreateFunction("Freeze Now (no countdown)", Color.cyan, (Action)FreezeNow);
		val5.CreateFunction("3) Unfreeze (back to mirror)", Color.yellow, (Action)Unfreeze);
		val5.CreateFunction("Despawn", Color.red, (Action)Despawn);
		val5.CreateFunction("Quick Save Pose", Color.green, (Action)delegate
		{
			SavePose(0, notify: true);
		});
		val5.CreateFunction("Quick Load Pose", Color.cyan, (Action)delegate
		{
			LoadPose(0, makeUndo: true);
		});
		Page val6 = val5.CreatePage("Jaw", new Color(1f, 0.75f, 0.2f), 0, true);
		AddFloat(val6, "Open Angle (degrees; negative reverses)", new Color(1f, 0.75f, 0.2f), PrefJawAngle, 5f, -90f, 90f);
		val6.CreateFunction("Open Jaw", new Color(1f, 0.75f, 0.2f), (Action)OpenJaw);
		val6.CreateFunction("Close Jaw", new Color(1f, 0.75f, 0.2f), (Action)CloseJaw);
		val6.CreateFunction("Toggle Jaw", new Color(1f, 0.75f, 0.2f), (Action)ToggleJaw);
		val6.CreateFunction("Stop Override / Follow Avatar", Color.white, (Action)ResumeAvatarJaw);
		Color val7 = default(Color);
		((Color)(ref val7))..ctor(0.25f, 0.85f, 1f);
		Page val8 = val5.CreatePage("Finger Gestures", val7, 0, true);
		AddFloat(val8, "Capture Countdown (seconds)", val7, PrefFingerGestureDelay, 1f, 1f, 10f);
		val8.CreateFunction("Capture LEFT Hand (timer)", val7, (Action)delegate
		{
			StartFingerGestureCountdown(left: true);
		});
		val8.CreateFunction("Capture RIGHT Hand (timer)", val7, (Action)delegate
		{
			StartFingerGestureCountdown(left: false);
		});
		val8.CreateFunction("Help: hold finger pose until beeps end", Color.white, (Action)delegate
		{
			MelonLogger.Msg("[Clone] Freeze the clone, press a hand button, then hold your desired finger pose until the countdown ends.");
		});
		Page val9 = val5.CreatePage("Pose Edit", yellow, 0, true);
		AddBool(val9, "Touch Pose (push parts by hand)", yellow, PrefTouch);
		AddReturnEnum(val9, "Return: Keep / Spring", yellow);
		val9.CreateFunction("Save Current Pose (as rest)", yellow, (Action)CommitPose);
		val9.CreateFunction("Body to Ground (feet)", yellow, (Action)FeetToGround);
		AddBool(val9, "Pull Body (torso, then pelvis)", yellow, PrefPullBody);
		AddFloat(val9, "Spring Speed", yellow, PrefSpringSpeed, 1f, 2f, 20f);
		AddBool(val9, "Clone Colliders (pose + ragdoll)", yellow, PrefColliders, delegate
		{
			if (_ragdolled)
			{
				RefreshPlayerIgnore();
			}
		});
		Page val10 = val5.CreatePage("Grab", magenta, 0, true);
		AddBool(val10, "Rigid Attach (OFF = free manipulation)", magenta, PrefRigid);
		AddBool(val10, "Rotate Part With Hand", magenta, PrefRotateHand);
		AddBool(val10, "Elbow/Twist Fix", magenta, PrefTwistFix);
		AddBool(val10, "Shoulder Assist", magenta, PrefShoulder);
		AddBool(val10, "Pelvis Rotate", magenta, PrefPelvisRot);
		AddBool(val10, "Grab Physics Bones", magenta, PrefGrabBones);
		AddBool(val10, "Sticky Grab (no auto-release)", magenta, PrefStickyGrab);
		Page p = val10.CreatePage("Grab Tuning", magenta, 0, true);
		AddFloat(p, "Grab Reach", magenta, PrefReach, 0.02f, 0.02f, 0.3f);
		AddFloat(p, "Touch Margin (m)", magenta, PrefTouchMargin, 0.01f, 0f, 0.2f);
		AddFloat(p, "Grab Strength", magenta, PrefGrabStrength, 0.25f, 0.25f, 5f);
		AddFloat(p, "Hand Follow Speed", magenta, PrefHandSpeed, 2f, 5f, 40f);
		AddFloat(p, "Hand Stretch (1 = off)", magenta, PrefHandStretch, 0.05f, 1f, 1.6f);
		AddFloat(p, "Body Max Speed", magenta, PrefMaxSpeed, 0.25f, 0.5f, 8f);
		AddFloat(p, "Body Accel", magenta, PrefMaxAccel, 1f, 2f, 40f);
		AddFloat(p, "Pull Limit (Spring, x height)", magenta, PrefStretchLimit, 0.05f, 0.1f, 1.5f);
		Page val11 = val5.CreatePage("Ground", green, 0, true);
		AddBool(val11, "Legs Ground Lock", green, PrefGroundLegs, delegate(bool v)
		{
			if (v)
			{
				CaptureGroundAnchors();
			}
		});
		AddBool(val11, "Arms Ground Lock", green, PrefGroundArms, delegate(bool v)
		{
			if (v)
			{
				CaptureGroundAnchors();
			}
		});
		AddFloat(val11, "Ground Pull Strength", green, PrefGroundStrength, 1f, 2f, 25f);
		val11.CreateFunction("Re-capture Ground Anchors", green, (Action)CaptureGroundAnchors);
		Page val12 = val5.CreatePage("Ragdoll", val, 0, true);
		val12.CreateFunction("Toggle Ragdoll (full body)", val, (Action)ToggleRagdoll);
		AddBool(val12, "Rigid Grab (part sticks to hand)", val, PrefRagRigidGrab);
		AddBool(val12, "Ragdoll Grab Mode (grab = toggle part)", val, PrefRagdollGrab, OnRagdollModeChanged);
		AddBool(val12, "Touch to Un-Ragdoll", val, PrefTouchUnragdoll);
		AddBool(val12, "Touch Push (hand pushes parts)", val, PrefRagTouchPush);
		AddFloat(val12, "Ragdoll Grab Strength", val, PrefRagGrabStrength, 0.25f, 0.25f, 5f);
		Page val13 = val12.CreatePage("Pins (hold pose / spring)", val2, 0, true);
		AddBool(val13, "Pin On Release (freeze where dropped)", val2, PrefRagPinOnRelease);
		AddBool(val13, "Pin All On Ragdoll Start", val2, PrefRagPinAllOnStart);
		AddFloat(val13, "Pin Stiffness (spring)", val2, PrefRagPinStiff, 25f, 25f, 600f);
		val13.CreateFunction("Pin All Parts Now", val2, (Action)PinAll);
		val13.CreateFunction("Pin Held Parts", val2, (Action)PinHeldParts);
		val13.CreateFunction("Unpin All", Color.red, (Action)UnpinAll);
		Page val14 = val5.CreatePage("Poses (save/load)", cyan, 0, true);
		IntElement item = val14.CreateInt("Slot", cyan, PrefSlot.Value, 1, 1, 30, (Action<int>)delegate(int v)
		{
			PrefSlot.Value = v;
			_cat.SaveToFile(false);
			PoseInfo(v);
		});
		_menuEls.Add((item, () => PrefSlot.Value));
		val14.CreateFunction("Save To Slot", cyan, (Action)delegate
		{
			SavePose(PrefSlot.Value, notify: true);
		});
		val14.CreateFunction("Load Slot", cyan, (Action)delegate
		{
			LoadPose(PrefSlot.Value, makeUndo: true);
		});
		val14.CreateFunction("Save To Next Free Slot", cyan, (Action)SaveNextFree);
		val14.CreateFunction("Undo Last Load", cyan, (Action)UndoLoad);
		val14.CreateFunction("Delete Slot", Color.red, (Action)delegate
		{
			DeletePose(PrefSlot.Value);
		});
		AddBool(val14, "Auto-Freeze On Load", cyan, PrefLoadFreeze);
		AddBool(val14, "Feet To Ground On Load", cyan, PrefLoadGround);
		AddBool(val14, "Load Placement (pos/rot)", cyan, PrefLoadPlacement);
		Page val15 = val5.CreatePage("Placement", val3, 0, true);
		val15.CreateFunction("Re-anchor Here", val3, (Action)PlaceHere);
		AddBool(val15, "Mirror Image", val3, PrefMirror);
		AddFloat(val15, "Side Angle", val3, PrefAngle, 15f, 0f, 360f);
		AddFloat(val15, "Distance", val3, PrefDist, 0.1f, 0.2f, 6f);
		Page val16 = val5.CreatePage("Avatar", val4, 0, true);
		AddBool(val16, "Fix Head/Neck Offset", val4, PrefHeadFix);
		AddBool(val16, "Track Head Rotation", val4, PrefTrackHead);
		AddBool(val16, "Clean Model (use prefab)", val4, PrefCleanModel);
		val16.CreateFunction("(applies on next Spawn)", val4, (Action)delegate
		{
		});
		Page val17 = val5.CreatePage("Misc", gray, 0, true);
		AddFloat(val17, "Freeze Countdown (sec)", gray, PrefFreezeDelay, 1f, 1f, 15f);
		AddBool(val17, "Countdown Beeps", gray, PrefBeeps);
		val17.CreateFunction("RESET ALL SETTINGS", Color.red, (Action)ResetAll);
		Page p2 = val5.CreatePage("Help", Color.white, 0, true);
		AddHelp(p2, Color.white, "BASICS", "Spawn: clone mirrors you live", "Freeze: locks the pose, then edit it", "Unfreeze: back to live mirror");
		AddHelp(p2, yellow, "POSE EDIT", "Grip a limb/head/torso/pelvis to move it", "Touch Pose: hand pushes parts away", "Keep: pose stays after release", "Spring: part returns to saved pose", "Save Current Pose: new rest pose", "Clone Colliders: clone + ragdoll solid");
		AddHelp(p2, magenta, "GRAB", "Rigid Attach: part sticks to hand", "Rigid OFF: free manipulation", "Rotate With Hand: part follows rotation", "Head turns first, neck after limit", "Twist Fix: no elbow/knee flip");
		AddHelp(p2, green, "GROUND", "Legs/Arms Ground Lock: stick to floor");
		AddHelp(p2, val, "RAGDOLL", "Toggle Ragdoll: full body physics", "Rigid Grab: part sticks to your hand", "Grab Mode: grip toggles part ON/OFF", "Grab Mode OFF: parts keep ragdoll", "Touch Push: hand pushes loose parts", "Touch to Un-Ragdoll: touch = part OFF");
		AddHelp(p2, val2, "PINS", "Pin On Release: dropped part freezes", "Pinned part acts like Spring", "Pin Stiffness: spring strength", "Pin All Parts Now: hold whole body", "Unpin All: release all pins");
		AddHelp(p2, cyan, "POSES", "Slot -> Save / Load / Undo / Delete", "Quick Save/Load: slot on main page");
		AddHelp(val6, new Color(1f, 0.75f, 0.2f), "JAW", "Set Open Angle in degrees; negative reverses direction", "Open/Close/Toggle Jaw work with a jaw bone or detected jaw blendshape", "Follow Avatar Jaw disables the override");
	}

	private void AddHelp(Page p, Color col, string title, params string[] lines)
	{
		//IL_0012: 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)
		p.CreateFunction("== " + title + " ==", col, (Action)delegate
		{
		});
		foreach (string t in lines)
		{
			p.CreateFunction(t, col, (Action)delegate
			{
				MelonLogger.Msg("[Help] " + t);
			});
		}
	}

	private void ResetAll()
	{
		((MelonPreferences_Entry)PrefAngle).ResetToDefault();
		((MelonPreferences_Entry)PrefDist).ResetToDefault();
		((MelonPreferences_Entry)PrefMirror).ResetToDefault();
		((MelonPreferences_Entry)PrefFreezeDelay).ResetToDefault();
		((MelonPreferences_Entry)PrefBeeps).ResetToDefault();
		((MelonPreferences_Entry)PrefReturn).ResetToDefault();
		((MelonPreferences_Entry)PrefSpringSpeed).ResetToDefault();
		((MelonPreferences_Entry)PrefReach).ResetToDefault();
		((MelonPreferences_Entry)PrefGrabStrength).ResetToDefault();
		((MelonPreferences_Entry)PrefJawAngle).ResetToDefault();
		((MelonPreferences_Entry)PrefFingerGestureDelay).ResetToDefault();
		_jawCommandActive = false;
		_jawCommandOpen = false;
		((MelonPreferences_Entry)PrefPelvisRot).ResetToDefault();
		((MelonPreferences_Entry)PrefPullBody).ResetToDefault();
		((MelonPreferences_Entry)PrefColliders).ResetToDefault();
		((MelonPreferences_Entry)PrefHeadFix).ResetToDefault();
		((MelonPreferences_Entry)PrefCleanModel).ResetToDefault();
		((MelonPreferences_Entry)PrefTrackHead).ResetToDefault();
		((MelonPreferences_Entry)PrefGrabBones).ResetToDefault();
		((MelonPreferences_Entry)PrefStickyGrab).ResetToDefault();
		((MelonPreferences_Entry)PrefHandSpeed).ResetToDefault();
		((MelonPreferences_Entry)PrefHandStretch).ResetToDefault();
		((MelonPreferences_Entry)PrefGroundLegs).ResetToDefault();
		((MelonPreferences_Entry)PrefGroundArms).ResetToDefault();
		((MelonPreferences_Entry)PrefGroundStrength).ResetToDefault();
		((MelonPreferences_Entry)PrefMaxSpeed).ResetToDefault();
		((MelonPreferences_Entry)PrefMaxAccel).ResetToDefault();
		((MelonPreferences_Entry)PrefStretchLimit).ResetToDefault();
		((MelonPreferences_Entry)PrefLoadPlacement).ResetToDefault();
		((MelonPreferences_Entry)PrefLoadFreeze).ResetToDefault();
		((MelonPreferences_Entry)PrefLoadGround).ResetToDefault();
		((MelonPreferences_Entry)PrefRigid).ResetToDefault();
		((MelonPreferences_Entry)PrefRotateHand).ResetToDefault();
		((MelonPreferences_Entry)PrefTwistFix).ResetToDefault();
		((MelonPreferences_Entry)PrefShoulder).ResetToDefault();
		((MelonPreferences_Entry)PrefTouch).ResetToDefault();
		((MelonPreferences_Entry)PrefTouchMargin).ResetToDefault();
		((MelonPreferences_Entry)PrefRagdollGrab).ResetToDefault();
		((MelonPreferences_Entry)PrefRagGrabStrength).ResetToDefault();
		((MelonPreferences_Entry)PrefTouchUnragdoll).ResetToDefault();
		((MelonPreferences_Entry)PrefRagPinOnRelease).ResetToDefault();
		((MelonPreferences_Entry)PrefRagPinAllOnStart).ResetToDefault();
		((MelonPreferences_Entry)PrefRagTouchPush).ResetToDefault();
		((MelonPreferences_Entry)PrefRagPinStiff).ResetToDefault();
		((MelonPreferences_Entry)PrefRagRigidGrab).ResetToDefault();
		_cat.SaveToFile(false);
		RefreshMenuValues();
		ApplyPhysState();
		MelonLogger.Msg("All settings reset to default.");
	}

	private void FreezeCountdown()
	{
		if ((Object)(object)_clone == (Object)null)
		{
			MelonLogger.Warning("No clone.");
		}
		else if (!_frozen && !_cdActive)
		{
			_cdAction = FreezeNow;
			_cdLeft = Mathf.Max(1, Mathf.RoundToInt(PrefFreezeDelay.Value));
			_cdBeeps = PrefBeeps.Value;
			_cdNext = Time.unscaledTime;
			_cdActive = true;
		}
	}

	public override void OnUpdate()
	{
		if (!_cdActive || Time.unscaledTime < _cdNext)
		{
			return;
		}
		if (_cdLeft > 0)
		{
			if (_cdBeeps)
			{
				PlayBeep();
			}
			_cdLeft--;
			_cdNext += 1f;
		}
		else
		{
			_cdActive = false;
			Action cdAction = _cdAction;
			_cdAction = null;
			cdAction?.Invoke();
		}
	}

	private void StartFingerGestureCountdown(bool left)
	{
		if ((Object)(object)_clone == (Object)null)
		{
			MelonLogger.Warning("[Clone] Spawn a clone first.");
			return;
		}
		if (!_frozen)
		{
			MelonLogger.Warning("[Clone] Freeze the clone before capturing a finger gesture.");
			return;
		}
		if (_cdActive)
		{
			MelonLogger.Warning("[Clone] Another countdown is already active. Wait for it to finish first.");
			return;
		}
		if ((Object)(object)_srcGO == (Object)null || _srcT == null || _cloneT == null || _bones == null)
		{
			MelonLogger.Warning("[Clone] Source/clone skeleton is not ready.");
			return;
		}
		HumanBodyBones[] fingerBones = (left ? LEFT_FINGER_BONES : RIGHT_FINGER_BONES);
		if (CountMappedFingerBones(fingerBones) == 0)
		{
			MelonLogger.Warning("[Clone] No mapped humanoid finger bones were found on this avatar. The avatar needs a Humanoid finger rig.");
			return;
		}
		int num = Mathf.Clamp(Mathf.RoundToInt(PrefFingerGestureDelay.Value), 1, 10);
		_cdAction = delegate
		{
			CaptureFingerGesture(left);
		};
		_cdLeft = num;
		_cdBeeps = PrefBeeps.Value;
		_cdNext = Time.unscaledTime;
		_cdActive = true;
		MelonLogger.Msg($"[Clone] {(left ? "Left" : "Right")} hand gesture capture in {num} second(s). Hold the desired finger pose until the countdown ends.");
	}

	private int CountMappedFingerBones(HumanBodyBones[] fingerBones)
	{
		if (fingerBones == null)
		{
			return 0;
		}
		int num = 0;
		for (int i = 0; i < fingerBones.Length; i++)
		{
			if ((Object)(object)Bone(fingerBones[i]) != (Object)null && (Object)(object)SourceBone(fingerBones[i]) != (Object)null)
			{
				num++;
			}
		}
		return num;
	}

	private Transform SourceBone(HumanBodyBones bone)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		Transform val = Bone(bone);
		if ((Object)(object)val == (Object)null || _cloneT == null || _srcT == null)
		{
			return null;
		}
		int num = Mathf.Min(_cloneT.Length, _srcT.Length);
		for (int i = 0; i < num; i++)
		{
			if ((Object)(object)_cloneT[i] == (Object)(object)val)
			{
				return _srcT[i];
			}
		}
		return null;
	}

	private void CaptureFingerGesture(bool left)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_clone == (Object)null || !_frozen || _cloneT == null || _idx == null)
		{
			MelonLogger.Warning("[Clone] Finger capture cancelled: the clone no longer exists or is not frozen.");
			return;
		}
		HumanBodyBones[] array = (left ? LEFT_FINGER_BONES : RIGHT_FINGER_BONES);
		int num = 0;
		foreach (HumanBodyBones val in array)
		{
			Transform val2 = SourceBone(val);
			Transform val3 = Bone(val);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				Quaternion val4 = (val3.localRotation = val2.localRotation);
				if (_idx.TryGetValue(((Object)val3).GetInstanceID(), out var value) && value >= 0 && value < _baseLr.Length)
				{
					_baseLr[value] = val4;
					_edited[value] = false;
					_held[value] = false;
					_vel[value] = Vector3.zero;
				}
				num++;
			}
		}
		if (num == 0)
		{
			MelonLogger.Warning("[Clone] Could not capture the " + (left ? "left" : "right") + " hand: no matching finger bones.");
			return;
		}
		MelonLogger.Msg($"[Clone] Captured {(left ? "left" : "right")} hand gesture ({num} finger joints). It is applied to the frozen clone.");
	}

	private static void PlayBeep()
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)Player.RigManager == (Object)null)
			{
				return;
			}
			if ((Object)(object)_beepClip == (Object)null)
			{
				_beepClip = AudioClip.Create("beep", 4410, 1, 44100, false);
				float[] array = new float[4410];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = Mathf.Sin((float)Math.PI * 1760f * (float)i / 44100f);
				}
				_beepClip.SetData(Il2CppStructArray<float>.op_Implicit(array), 0);
			}
			AudioSource.PlayClipAtPoint(_beepClip, ((Rig)Player.RigManager.physicsRig).m_head.position, 0.5f);
		}
		catch
		{
		}
	}

	private void ApplyPhysState()
	{
		if (_dbones == null)
		{
			return;
		}
		ClearDynamicBoneMirrorLinks();
		int num = 0;
		for (int i = 0; i < _dbones.Count; i++)
		{
			Behaviour val = _dbones[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				if (!val.enabled)
				{
					val.enabled = true;
				}
				num++;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Could not enable clone physics component " + ((Object)val).name + ": " + ex.Message);
			}
		}
		if (num > 0)
		{
			MelonLogger.Msg($"[Clone] Independent physics active on {num} clone components.");
		}
	}

	private void SetupDynamicBoneMirrorCopy()
	{
		ClearDynamicBoneMirrorLinks();
		if (_dbones == null)
		{
			return;
		}
		for (int i = 0; i < _dbones.Count; i++)
		{
			Behaviour val = _dbones[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				if (val.enabled)
				{
					val.enabled = false;
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Could not prepare clone physics component " + ((Object)val).name + ": " + ex.Message);
			}
		}
		if (_dbones.Count > 0)
		{
			MelonLogger.Msg("[Clone] Clone-side physics initialized independently; mirror links are cleared.");
		}
		InstallMirrorPhysicsPatches();
	}

	private void InstallMirrorPhysicsPatches()
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		if (_dbones == null || _dbones.Count == 0)
		{
			return;
		}
		_physicsMirrorPatchOwner = this;
		try
		{
			if (_physicsMirrorHarmony == null)
			{
				_physicsMirrorHarmony = new Harmony("IntVoid.CloneMod.MirrorPhysicsCorrection");
			}
			MethodInfo method = typeof(CloneMod).GetMethod("MirrorAwarePhysicsApplyPrefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (method == null)
			{
				return;
			}
			HarmonyMethod val = new HarmonyMethod(method);
			int num = 0;
			for (int i = 0; i < _dbones.Count; i++)
			{
				Behaviour val2 = _dbones[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				MethodInfo methodInfo = FindParameterlessInstanceMethod(((object)val2).GetType(), "ApplyParticlesToTransforms");
				if (!(methodInfo == null) && !_patchedMirrorPhysicsMethods.Contains(methodInfo))
				{
					try
					{
						_physicsMirrorHarmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						_patchedMirrorPhysicsMethods.Add(methodInfo);
						num++;
					}
					catch (Exception ex)
					{
						MelonLogger.Warning("[Clone] Could not patch mirrored physics on " + ((object)val2).GetType().Name + ": " + ex.Message);
					}
				}
			}
			if (num > 0)
			{
				MelonLogger.Msg($"[Clone] Mirror-safe particle transform correction installed on {num} physics method(s).");
			}
		}
		catch (Exception ex2)
		{
			MelonLogger.Warning("[Clone] Mirror physics correction setup failed: " + ex2.Message);
		}
	}

	private static MethodInfo FindParameterlessInstanceMethod(Type type, string methodName)
	{
		Type type2 = type;
		while (type2 != null)
		{
			try
			{
				MethodInfo method = type2.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null && !method.IsStatic)
				{
					return method;
				}
			}
			catch
			{
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static bool MirrorAwarePhysicsApplyPrefix(object __instance)
	{
		CloneMod physicsMirrorPatchOwner = _physicsMirrorPatchOwner;
		if (physicsMirrorPatchOwner == null || !physicsMirrorPatchOwner.ShouldCorrectMirroredPhysics(__instance))
		{
			return true;
		}
		try
		{
			return !physicsMirrorPatchOwner.ApplyMirroredPhysicsParticles(__instance);
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("[Clone] Mirror particle correction failed; using original solver: " + ex.Message);
			return true;
		}
	}

	private bool ShouldCorrectMirroredPhysics(object instance)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		if (!PrefMirror.Value || (Object)(object)_pivot == (Object)null || (Object)(object)_clone == (Object)null)
		{
			return false;
		}
		if (_pivot.transform.localScale.x > -0.5f)
		{
			return false;
		}
		Behaviour val = (Behaviour)((instance is Behaviour) ? instance : null);
		if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null)
		{
			return false;
		}
		Transform transform = ((Component)val).transform;
		return (Object)(object)transform == (Object)(object)_clone.transform || transform.IsChildOf(_clone.transform);
	}

	private static object ReadPhysicsMember(object owner, params string[] names)
	{
		if (owner == null)
		{
			return null;
		}
		Type type = owner.GetType();
		while (type != null)
		{
			for (int i = 0; i < names.Length; i++)
			{
				try
				{
					FieldInfo field = type.GetField(names[i], BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						return field.GetValue(owner);
					}
				}
				catch
				{
				}
				try
				{
					PropertyInfo property = type.GetProperty(names[i], BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null && property.CanRead)
					{
						return property.GetValue(owner, null);
					}
				}
				catch
				{
				}
			}
			type = type.BaseType;
		}
		return null;
	}

	private static int ReadPhysicsInt(object owner, params string[] names)
	{
		object obj = ReadPhysicsMember(owner, names);
		if (!(obj is int result))
		{
			try
			{
				if (obj != null)
				{
					return Convert.ToInt32(obj, CultureInfo.InvariantCulture);
				}
			}
			catch
			{
			}
			return -1;
		}
		return result;
	}

	private static bool ReadPhysicsVector3(object owner, out Vector3 vector, params string[] names)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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)
		object obj = ReadPhysicsMember(owner, names);
		if (obj is Vector3)
		{
			vector = (Vector3)obj;
			return true;
		}
		vector = Vector3.zero;
		return false;
	}

	private bool ApplyMirroredPhysicsParticles(object instance)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0347: Unknown result type (might be due to invalid IL or missing references)
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		object obj = ReadPhysicsMember(instance, "m_ParticleTrees", "_particleTrees", "particleTrees");
		if (!(obj is IEnumerable enumerable) || (Object)(object)_pivot == (Object)null)
		{
			return false;
		}
		Vector3 val = _pivot.transform.rotation * Vector3.right;
		if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
		{
			return false;
		}
		((Vector3)(ref val)).Normalize();
		int num = 0;
		foreach (object item in enumerable)
		{
			object obj2 = ReadPhysicsMember(item, "m_Particles", "_particles", "particles");
			if (!(obj2 is IEnumerable enumerable2))
			{
				continue;
			}
			List<object> list = new List<object>();
			foreach (object item2 in enumerable2)
			{
				list.Add(item2);
			}
			for (int i = 1; i < list.Count; i++)
			{
				object owner = list[i];
				int num2 = ReadPhysicsInt(owner, "m_ParentIndex", "_parentIndex", "parentIndex");
				if (num2 < 0 || num2 >= list.Count)
				{
					continue;
				}
				object owner2 = list[num2];
				Transform val2 = ReadTransformMember(owner, "m_Transform", "transform", "m_TransformRef");
				Transform val3 = ReadTransformMember(owner2, "m_Transform", "transform", "m_TransformRef");
				if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
				{
					int num3 = ReadPhysicsInt(owner2, "m_ChildCount", "_childCount", "childCount");
					if (num3 <= 1)
					{
						Vector3 vector;
						bool flag = ReadPhysicsVector3(owner, out vector, "m_Position", "_position", "position");
						Vector3 vector2;
						bool flag2 = ReadPhysicsVector3(owner2, out vector2, "m_Position", "_position", "position");
						if (flag && flag2)
						{
							Vector3 val4 = val3.TransformDirection(val2.localPosition);
							Vector3 val5 = Vector3.Reflect(val4, val);
							Vector3 val6 = vector - vector2;
							if (((Vector3)(ref val5)).sqrMagnitude > 1E-06f && ((Vector3)(ref val6)).sqrMagnitude > 1E-06f)
							{
								Quaternion val7 = Quaternion.FromToRotation(val5, val6);
								val3.rotation = val7 * val3.rotation;
							}
						}
					}
				}
				if ((Object)(object)val2 != (Object)null && ReadPhysicsVector3(owner, out var vector3, "m_Position", "_position", "position"))
				{
					val2.position = vector3;
					num++;
				}
			}
		}
		return num > 0;
	}

	private void ResetClonePhysicsParticles()
	{
		if (_dbones == null)
		{
			return;
		}
		string[] array = new string[3] { "ResetParticlesPosition", "ResetParticles", "ResetParticlePositions" };
		string[] array2 = new string[2] { "SetupParticles", "InitializeRig" };
		for (int i = 0; i < _dbones.Count; i++)
		{
			Behaviour val = _dbones[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				Type type = ((object)val).GetType();
				MethodInfo methodInfo = null;
				for (int j = 0; j < array.Length; j++)
				{
					if (!(methodInfo == null))
					{
						break;
					}
					methodInfo = type.GetMethod(array[j], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				}
				if (methodInfo != null)
				{
					methodInfo.Invoke(val, null);
					continue;
				}
				MethodInfo methodInfo2 = null;
				for (int k = 0; k < array2.Length; k++)
				{
					if (!(methodInfo2 == null))
					{
						break;
					}
					methodInfo2 = type.GetMethod(array2[k], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				}
				if (methodInfo2 != null)
				{
					methodInfo2.Invoke(val, null);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Could not reset clone physics history on " + ((Object)val).name + ": " + ex.Message);
			}
		}
	}

	private void ClearDynamicBoneMirrorLinks()
	{
		if (_dbones == null)
		{
			return;
		}
		string[] names = new string[3] { "m_MirrorReflectionBone", "_mirrorReflectionBone", "mirrorReflectionBone" };
		string[] names2 = new string[3] { "m_IsMirrorClone", "_isMirrorClone", "isMirrorClone" };
		for (int i = 0; i < _dbones.Count; i++)
		{
			Behaviour val = _dbones[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				Type type = ((object)val).GetType();
				FieldInfo fieldInfo = FindField(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, names);
				FieldInfo fieldInfo2 = FindField(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, names2);
				if (fieldInfo != null && !fieldInfo.FieldType.IsValueType)
				{
					fieldInfo.SetValue(val, null);
				}
				if (fieldInfo2 != null && fieldInfo2.FieldType == typeof(bool))
				{
					fieldInfo2.SetValue(val, false);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Clear physics mirror failed for " + ((Object)val).name + ": " + ex.Message);
			}
		}
	}

	private static bool IsPhysicsBoneComponent(Behaviour component)
	{
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		string text = ((object)component).GetType().Name.ToLowerInvariant();
		return text.Contains("dynamicbone") || text.Contains("smartbone") || text.Contains("mapdbone") || text == "dbone";
	}

	private static FieldInfo FindField(Type t, BindingFlags flags, params string[] names)
	{
		for (int i = 0; i < names.Length; i++)
		{
			FieldInfo field = t.GetField(names[i], flags);
			if (field != null)
			{
				return field;
			}
		}
		return null;
	}

	private int CapturePhysicsRestPoseFromSource(GameObject source, GameObject clone)
	{
		//IL_040a: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Unknown result type (might be due to invalid IL or missing references)
		//IL_0418: Unknown result type (might be due to invalid IL or missing references)
		//IL_0438: 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_0440: Unknown result type (might be due to invalid IL or missing references)
		//IL_0442: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0459: Unknown result type (might be due to invalid IL or missing references)
		_physicsRestPose.Clear();
		_physicsLivePairs.Clear();
		if ((Object)(object)source == (Object)null || (Object)(object)clone == (Object)null)
		{
			return 0;
		}
		Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
		Il2CppArrayBase<Transform> componentsInChildren = clone.GetComponentsInChildren<Transform>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Transform val = componentsInChildren[i];
			if (!((Object)(object)val == (Object)null))
			{
				string key = PathOf(val, clone.transform);
				if (!dictionary.ContainsKey(key))
				{
					dictionary[key] = val;
				}
			}
		}
		int num = 0;
		int num2 = 0;
		Il2CppArrayBase<MonoBehaviour> componentsInChildren2 = source.GetComponentsInChildren<MonoBehaviour>(true);
		HashSet<int> hashSet = new HashSet<int>();
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			Behaviour val2 = (Behaviour)(object)componentsInChildren2[j];
			if ((Object)(object)val2 == (Object)null || !IsPhysicsBoneComponent(val2))
			{
				continue;
			}
			try
			{
				FieldInfo fieldInfo = FindField(((object)val2).GetType(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, "m_ParticleTrees", "_particleTrees", "particleTrees");
				if (fieldInfo == null || !(fieldInfo.GetValue(val2) is IEnumerable enumerable))
				{
					continue;
				}
				foreach (object item in enumerable)
				{
					if (item == null)
					{
						continue;
					}
					FieldInfo fieldInfo2 = FindField(item.GetType(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, "m_Particles", "_particles", "particles");
					if (fieldInfo2 == null || !(fieldInfo2.GetValue(item) is IEnumerable enumerable2))
					{
						continue;
					}
					foreach (object item2 in enumerable2)
					{
						if (item2 == null)
						{
							continue;
						}
						Transform val3 = ReadTransformMember(item2, "m_Transform", "transform", "m_TransformRef");
						if ((Object)(object)val3 == (Object)null)
						{
							continue;
						}
						if (!dictionary.TryGetValue(PathOf(val3, source.transform), out var value) || (Object)(object)value == (Object)null)
						{
							value = null;
							if (_srcT != null && _cloneT != null)
							{
								int num3 = Mathf.Min(_srcT.Length, _cloneT.Length);
								for (int k = 0; k < num3; k++)
								{
									if ((Object)(object)_srcT[k] == (Object)(object)val3)
									{
										value = _cloneT[k];
										break;
									}
								}
							}
							if ((Object)(object)value == (Object)null)
							{
								continue;
							}
						}
						if (IsHumanoidTransform(value) || IsJawTransform(value))
						{
							continue;
						}
						int instanceID = ((Object)value).GetInstanceID();
						if (hashSet.Add(instanceID))
						{
							_physicsLivePairs.Add(new PhysicsLivePair
							{
								source = val3,
								clone = value
							});
							num++;
						}
						FieldInfo fieldInfo3 = FindField(item2.GetType(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, "m_InitLocalPosition", "_initLocalPosition", "initLocalPosition");
						FieldInfo fieldInfo4 = FindField(item2.GetType(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, "m_InitLocalRotation", "_initLocalRotation", "initLocalRotation");
						if (!(fieldInfo3 == null) && !(fieldInfo4 == null))
						{
							object value2 = fieldInfo3.GetValue(item2);
							object value3 = fieldInfo4.GetValue(item2);
							if (value2 is Vector3 && value3 is Quaternion)
							{
								Vector3 localPosition = (Vector3)value2;
								Quaternion localRotation = (Quaternion)value3;
								_physicsRestPose[instanceID] = new PhysicsRestPose
								{
									transform = value,
									sourceTransform = val3,
									localPosition = localPosition,
									localRotation = localRotation
								};
								value.localPosition = localPosition;
								value.localRotation = localRotation;
								num2++;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Could not read physics particle data from " + ((Object)val2).name + ": " + ex.Message);
			}
		}
		if (num2 > 0)
		{
			MelonLogger.Msg($"[Clone] Captured {num2} authored DynamicBone rest transforms from source metadata.");
		}
		if (num > 0)
		{
			MelonLogger.Msg($"[Clone] Mapped {num} live physics transforms to their exact source avatar transforms.");
		}
		if (num == 0 && componentsInChildren2.Length > 0)
		{
			MelonLogger.Warning("[Clone] No source physics particle transforms mapped; check whether the avatar's physics components had initialized before Spawn.");
		}
		return num2;
	}

	private void CopyLivePhysicsPoseToClone()
	{
	}

	private void RestorePhysicsAuthoredRest()
	{
		//IL_005c: 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)
		if ((Object)(object)_clone == (Object)null || _physicsRestPose.Count == 0)
		{
			return;
		}
		foreach (PhysicsRestPose value in _physicsRestPose.Values)
		{
			if (!((Object)(object)value.transform == (Object)null))
			{
				value.transform.localPosition = value.localPosition;
				value.transform.localRotation = value.localRotation;
			}
		}
	}

	private static Transform[] PrepareDummy(GameObject go, out List<Behaviour> dbones)
	{
		dbones = new List<Behaviour>();
		foreach (MonoBehaviour componentsInChild in go.GetComponentsInChildren<MonoBehaviour>(true))
		{
			if ((Object)(object)componentsInChild == (Object)null)
			{
				continue;
			}
			string text = ((object)componentsInChild).GetType().Name.ToLowerInvariant();
			if (text.Contains("dynamicbone") || text.Contains("smartbone") || text.Contains("mapdbone") || text == "dbone")
			{
				dbones.Add((Behaviour)(object)componentsInChild);
				try
				{
					((Behaviour)componentsInChild).enabled = false;
				}
				catch
				{
				}
				continue;
			}
			bool flag = false;
			for (int i = 0; i < BLACKLIST.Length; i++)
			{
				if (flag)
				{
					break;
				}
				if (text.Contains(BLACKLIST[i]))
				{
					flag = true;
				}
			}
			if (flag)
			{
				((Behaviour)componentsInChild).enabled = false;
			}
		}
		Transform[] array = null;
		foreach (Animator componentsInChild2 in go.GetComponentsInChildren<Animator>(true))
		{
			if ((Object)(object)componentsInChild2 == (Object)null)
			{
				continue;
			}
			if (array == null)
			{
				try
				{
					Transform[] array2 = (Transform[])(object)new Transform[55];
					for (int j = 0; j < array2.Length; j++)
					{
						array2[j] = componentsInChild2.GetBoneTransform((HumanBodyBones)j);
					}
					if ((Object)(object)array2[0] != (Object)null)
					{
						array = array2;
					}
				}
				catch
				{
				}
			}
			((Behaviour)componentsInChild2).enabled = false;
		}
		foreach (Rigidbody componentsInChild3 in go.GetComponentsInChildren<Rigidbody>(true))
		{
			if ((Object)(object)componentsInChild3 != (Object)null)
			{
				componentsInChild3.isKinematic = true;
				componentsInChild3.useGravity = false;
			}
		}
		foreach (Collider componentsInChild4 in go.GetComponentsInChildren<Collider>(true))
		{
			if ((Object)(object)componentsInChild4 != (Object)null)
			{
				componentsInChild4.enabled = false;
			}
		}
		return array;
	}

	private void Spawn()
	{
		try
		{
			if ((Object)(object)_clone != (Object)null)
			{
				MelonLogger.Warning("Clone exists.");
				return;
			}
			if ((Object)(object)Player.Avatar == (Object)null || (Object)(object)Player.RigManager == (Object)null)
			{
				MelonLogger.Warning("Avatar not ready.");
				return;
			}
			GameObject src = ((Component)Player.Avatar).gameObject;
			if (!PrefCleanModel.Value && !PrefHeadFix.Value)
			{
				FinishSpawn(src, null);
				return;
			}
			AvatarCrate val = null;
			try
			{
				val = ((CrateReferenceT<AvatarCrate>)(object)Player.RigManager.AvatarCrate).Crate;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				FinishSpawn(src, null);
				return;
			}
			IntPtr ptr = ((Il2CppObjectBase)val).Pointer;
			if ((Object)(object)_prefab != (Object)null && _prefabCratePtr == ptr)
			{
				FinishSpawn(src, _prefab);
				return;
			}
			((CrateT<GameObject>)(object)val).LoadAsset(Action<GameObject>.op_Implicit((Action<GameObject>)delegate(GameObject prefab)
			{
				try
				{
					if ((Object)(object)prefab == (Object)null)
					{
						FinishSpawn(src, null);
					}
					else
					{
						_prefab = prefab;
						_prefabCratePtr = ptr;
						FinishSpawn(src, prefab);
					}
				}
				catch (Exception ex2)
				{
					MelonLogger.Warning("LoadAsset:" + ex2.Message);
				}
			}));
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("Spawn:" + ex.Message);
		}
	}

	private void FinishSpawn(GameObject src, GameObject prefab)
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Expected O, but got Unknown
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)src == (Object)null || (Object)(object)Player.Avatar == (Object)null || (Object)(object)Player.RigManager == (Object)null || (Object)(object)((Component)Player.Avatar).gameObject != (Object)(object)src)
			{
				return;
			}
			Despawn();
			Transform transform = src.transform;
			GameObject val = null;
			Transform[] array = null;
			Transform[] srcOut = null;
			Transform[] cloneOut = null;
			bool flag = false;
			List<Behaviour> dbones = null;
			if ((Object)(object)prefab != (Object)null)
			{
				val = Object.Instantiate<GameObject>(prefab, transform.position, transform.rotation);
				array = PrepareDummy(val, out dbones);
				if (array != null && MatchBones(src, val, 0.7f, out srcOut, out cloneOut))
				{
					flag = true;
				}
				else
				{
					Object.Destroy((Object)(object)val);
					val = null;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Object.Instantiate<GameObject>(src, transform.position, transform.rotation);
				array = PrepareDummy(val, out dbones);
				if (array == null || !MatchBones(src, val, 0f, out srcOut, out cloneOut) || srcOut.Length < 2)
				{
					Object.Destroy((Object)(object)val);
					MelonLogger.Warning("Spawn failed (humanoid bones not found).");
					return;
				}
			}
			((Object)val).name = "AvatarPoseReplica";
			val.transform.localScale = transform.lossyScale;
			_pivot = new GameObject("PoseAnchorPivot");
			_pivot.transform.SetPositionAndRotation(transform.position, Quaternion.identity);
			val.transform.SetParent(_pivot.transform, false);
			_srcGO = src;
			_srcT = srcOut;
			_cloneT = cloneOut;
			_bones = array;
			_clone = val;
			_hips = array[0];
			_head = array[10];
			int num = _cloneT.Length;
			_skip = new bool[num];
			_noPos = new bool[num];
			_baseLr = (Quaternion[])(object)new Quaternion[num];
			_edited = new bool[num];
			_held = new bool[num];
			_vel = (Vector3[])(object)new Vector3[num];
			_idx = new Dictionary<int, int>();
			for (int i = 0; i < num; i++)
			{
				_baseLr[i] = Quaternion.identity;
				_idx[((Object)_cloneT[i]).GetInstanceID()] = i;
			}
			if (flag && PrefHeadFix.Value)
			{
				Transform val2 = array[9];
				for (int j = 1; j < num; j++)
				{
					Transform val3 = _cloneT[j];
					if ((Object)(object)val3 == (Object)(object)_head || ((Object)(object)val2 != (Object)null && (Object)(object)val3 == (Object)(object)val2))
					{
						_noPos[j] = true;
					}
				}
			}
			if (flag && (Object)(object)_head != (Object)null && !PrefTrackHead.Value)
			{
				for (int k = 1; k < num; k++)
				{
					if ((Object)(object)_cloneT[k] == (Object)(object)_head)
					{
						_skip[k] = true;
					}
				}
			}
			_dbones.Clear();
			try
			{
				HashSet<string> hashSet = new HashSet<string>();
				foreach (Behaviour item in dbones)
				{
					if ((Object)(object)item != (Object)null)
					{
						hashSet.Add(((object)item).GetType().Name);
					}
				}
				MelonLogger.Msg("Physics components on clone: " + ((hashSet.Count == 0) ? "none" : string.Join(", ", hashSet)));
			}
			catch
			{
			}
			CapturePhysicsRestPoseFromSource(src, val);
			foreach (Behaviour item2 in dbones)
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					_dbones.Add(item2);
					Transform val4 = ReadTransformMember(item2, "m_Root", "root", "rootBone", "m_RootBone", "rootTransform", "m_RootTransform", "_root", "_rootBone");
					if ((Object)(object)val4 != (Object)null)
					{
						MarkPhysicsSubtreeSkipped(val4);
					}
				}
			}
			MarkPhysicsParticleTransformsSkipped();
			if (dbones.Count > 0)
			{
				SetupDynamicBoneMirrorCopy();
			}
			Il2CppArrayBase<Renderer> componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			for (int l = 0; l < componentsInChildren.Length; l++)
			{
				SkinnedMeshRenderer val5 = ((Il2CppObjectBase)componentsInChildren[l]).TryCast<SkinnedMeshRenderer>();
				if ((Object)(object)val5 != (Object)null)
				{
					val5.updateWhenOffscreen = true;
				}
			}
			SetupBlendShapes(src, val);
			_jawCommandActive = false;
			_jawCommandOpen = false;
			_jawBone = null;
			_jawRestCaptured = false;
			_jawRestSynced = false;
			_jawRestBlendWeight = 0f;
			float height = 1.8f;
			try
			{
				Avatar avatar = Player.RigManager.avatar;
				if ((Object)(object)avatar != (Object)null && avatar.height > 0.1f)
				{
					height = avatar.height;
				}
			}
			catch
			{
			}
			_height = height;
			_frozen = false;
			_ragdolled = false;
			ProtectPhysicsRestTransformsFromLivePose();
			ClearAllGrabs();
			PlaceHere();
			ComputeRadii();
			BuildHandles();
			BuildParts();
			RefreshPlayerIgnore();
			ApplyPhysState();
			MelonLogger.Msg($"Clone spawned ({num} bones, {_dbones.Count} physics comps, clean={flag}).");
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("FinishSpawn:" + ex.Message);
		}
	}

	private static bool IsUnder(Transform t, Transform ancestor)
	{
		Transform parent = t.parent;
		while ((Object)(object)parent != (Object)null)
		{
			if ((Object)(object)parent == (Object)(object)ancestor)
			{
				return true;
			}
			parent = parent.parent;
		}
		return false;
	}

	private static Transform ReadTransformMember(object owner, params string[] names)
	{
		if (owner == null)
		{
			return null;
		}
		Type type = owner.GetType();
		for (int i = 0; i < names.Length; i++)
		{
			try
			{
				FieldInfo field = type.GetField(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object? value = field.GetValue(owner);
					Transform val = (Transform)((value is Transform) ? value : null);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			try
			{
				PropertyInfo property = type.GetProperty(names[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					object? value2 = property.GetValue(owner, null);
					Transform val2 = (Transform)((value2 is Transform) ? value2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			catch
			{
			}
		}
		return null;
	}

	private bool IsHumanoidTransform(Transform t)
	{
		if ((Object)(object)t == (Object)null || _bones == null)
		{
			return false;
		}
		for (int i = 0; i < _bones.Length; i++)
		{
			if ((Object)(object)_bones[i] == (Object)(object)t)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsJawTransform(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return false;
		}
		string text = ((Object)t).name.ToLowerInvariant().Replace("_", "").Replace("-", "")
			.Replace(" ", "");
		if (text.Contains("mandible"))
		{
			return true;
		}
		if (!text.Contains("jaw"))
		{
			return false;
		}
		return !text.Contains("upper") && !text.Contains("teeth") && !text.Contains("mesh") && !text.Contains("blend") && !text.Contains("target") && !text.Contains("socket");
	}

	private void MarkPhysicsSubtreeSkipped(Transform root)
	{
		if ((Object)(object)root == (Object)null || _cloneT == null || _skip == null)
		{
			return;
		}
		for (int i = 1; i < _cloneT.Length; i++)
		{
			Transform val = _cloneT[i];
			if (!((Object)(object)val == (Object)null) && (!((Object)(object)val != (Object)(object)root) || IsUnder(val, root)) && !IsHumanoidTransform(val) && !IsJawTransform(val))
			{
				_skip[i] = true;
			}
		}
	}

	private void MarkPhysicsParticleTransformsSkipped()
	{
		if (_dbones == null || _cloneT == null || _skip == null)
		{
			return;
		}
		int num = 0;
		for (int i = 0; i < _dbones.Count; i++)
		{
			Behaviour val = _dbones[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				FieldInfo field = ((object)val).GetType().GetField("m_ParticleTrees", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null || !(field.GetValue(val) is IEnumerable enumerable))
				{
					continue;
				}
				foreach (object item in enumerable)
				{
					if (item == null)
					{
						continue;
					}
					FieldInfo field2 = item.GetType().GetField("m_Particles", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 == null || !(field2.GetValue(item) is IEnumerable enumerable2))
					{
						continue;
					}
					foreach (object item2 in enumerable2)
					{
						if (item2 == null)
						{
							continue;
						}
						Transform val2 = ReadTransformMember(item2, "m_Transform", "transform", "m_TransformRef");
						if ((Object)(object)val2 == (Object)null || IsHumanoidTransform(val2) || IsJawTransform(val2))
						{
							continue;
						}
						for (int j = 1; j < _cloneT.Length; j++)
						{
							if (!((Object)(object)_cloneT[j] != (Object)(object)val2) && !_skip[j])
							{
								_skip[j] = true;
								num++;
								break;
							}
						}
					}
				}
			}
			catch
			{
			}
		}
		if (num > 0)
		{
			MelonLogger.Msg($"[Clone] Protected {num} SmartBone/DynamicBone particle transforms from live-pose overwrites.");
		}
	}

	private void ProtectPhysicsRestTransformsFromLivePose()
	{
		if (_cloneT == null || _skip == null)
		{
			return;
		}
		for (int i = 1; i < _cloneT.Length; i++)
		{
			Transform tr = _cloneT[i];
			if (!((Object)(object)tr == (Object)null) && !IsHumanoidTransform(tr) && !IsJawTransform(tr))
			{
				int instanceID = ((Object)tr).GetInstanceID();
				if (_physicsRestPose.ContainsKey(instanceID) || _physicsLivePairs.Exists((PhysicsLivePair p) => p != null && (Object)(object)p.clone == (Object)(object)tr))
				{
					_skip[i] = true;
				}
			}
		}
	}

	private void SetupBlendShapes(GameObject src, GameObject go)
	{
		_bsSrc.Clear();
		_bsDst.Clear();
		try
		{
			Transform transform = src.transform;
			Dictionary<string, SkinnedMeshRenderer> dictionary = new Dictionary<string, SkinnedMeshRenderer>();
			Dictionary<string, List<SkinnedMeshRenderer>> dictionary2 = new Dictionary<string, List<SkinnedMeshRenderer>>();
			foreach (SkinnedMeshRenderer componentsInChild in src.GetComponentsInChildren<SkinnedMeshRenderer>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && !((Object)(object)componentsInChild.sharedMesh == (Object)null))
				{
					dictionary[PathOf(((Component)componentsInChild).transform, transform)] = componentsInChild;
					if (!dictionary2.ContainsKey(((Object)componentsInChild).name))
					{
						dictionary2[((Object)componentsInChild).name] = new List<SkinnedMeshRenderer>();
					}
					dictionary2[((Object)componentsInChild).name].Add(componentsInChild);
				}
			}
			HashSet<SkinnedMeshRenderer> hashSet = new HashSet<SkinnedMeshRenderer>();
			foreach (SkinnedMeshRenderer componentsInChild2 in go.GetComponentsInChildren<SkinnedMeshRenderer>(true))
			{
				if ((Object)(object)componentsInChild2 == (Object)null || (Object)(object)componentsInChild2.sharedMesh == (Object)null || componentsInChild2.sharedMesh.blendShapeCount == 0)
				{
					continue;
				}
				if (dictionary.TryGetValue(PathOf(((Component)componentsInChild2).transform, go.transform), out var value) && (Object)(object)value.sharedMesh != (Object)null && value.sharedMesh.blendShapeCount == componentsInChild2.sharedMesh.blendShapeCount)
				{
					_bsSrc.Add(value);
					_bsDst.Add(componentsInChild2);
					hashSet.Add(value);
				}
				else
				{
					if (!dictionary2.TryGetValue(((Object)componentsInChild2).name, out var value2))
					{
						continue;
					}
					foreach (SkinnedMeshRenderer item in value2)
					{
						if (hashSet.Contains(item) || (Object)(object)item.sharedMesh == (Object)null || item.sharedMesh.blendShapeCount != componentsInChild2.sharedMesh.blendShapeCount)
						{
							continue;
						}
						_bsSrc.Add(item);
						_bsDst.Add(componentsInChild2);
						hashSet.Add(item);
						break;
					}
				}
			}
		}
		catch
		{
		}
	}

	private static string PathOf(Transform t, Transform root)
	{
		if ((Object)(object)t == (Object)(object)root)
		{
			return "";
		}
		List<string> list = new List<string>();
		Transform val = t;
		while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
		{
			int num = 0;
			Transform parent = val.parent;
			if ((Object)(object)parent != (Object)null)
			{
				for (int i = 0; i < parent.childCount; i++)
				{
					Transform child = parent.GetChild(i);
					if ((Object)(object)child == (Object)(object)val)
					{
						break;
					}
					if (((Object)child).name == ((Object)val).name)
					{
						num++;
					}
				}
			}
			list.Add(((Object)val).name + "#" + num);
			val = val.parent;
		}
		list.Reverse();
		return string.Join("/", list);
	}

	private static bool MatchBones(GameObject src, GameObject clone, float minRatio, out Transform[] srcOut, out Transform[] cloneOut)
	{
		Transform transform = src.transform;
		Transform transform2 = clone.transform;
		Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
		Dictionary<string, Transform> dictionary2 = new Dictionary<string, Transform>();
		HashSet<string> hashSet = new HashSet<string>();
		foreach (Transform componentsInChild in ((Component)transform).GetComponentsInChildren<Transform>(true))
		{
			string key = PathOf(componentsInChild, transform);
			if (!dictionary.ContainsKey(key))
			{
				dictionary[key] = componentsInChild;
			}
			if (dictionary2.ContainsKey(((Object)componentsInChild).name))
			{
				hashSet.Add(((Object)componentsInChild).name);
			}
			else
			{
				dictionary2[((Object)componentsInChild).name] = componentsInChild;
			}
		}
		Dictionary<int, Transform> dictionary3 = new Dictionary<int, Transform>();
		try
		{
			Animator componentInChildren = src.GetComponentInChildren<Animator>(true);
			Animator componentInChildren2 = clone.GetComponentInChildren<Animator>(true);
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren2 != (Object)null)
			{
				for (int i = 0; i < 55; i++)
				{
					Transform boneTransform = componentInChildren.GetBoneTransform((HumanBodyBones)i);
					Transform boneTransform2 = componentInChildren2.GetBoneTransform((HumanBodyBones)i);
					if ((Object)(object)boneTransform != (Object)null && (Object)(object)boneTransform2 != (Object)null)
					{
						dictionary3[((Object)boneTransform2).GetInstanceID()] = boneTransform;
					}
				}
			}
		}
		catch
		{
		}
		List<Transform> list = new List<Transform>();
		List<Transform> list2 = new List<Transform>();
		Il2CppArrayBase<Transform> componentsInChildren = ((Component)transform2).GetComponentsInChildren<Transform>(true);
		Dictionary<string, int> dictionary4 = new Dictionary<string, int>();
		for (int j = 0; j < componentsInChildren.Length; j++)
		{
			string name = ((Object)componentsInChildren[j]).name;
			dictionary4.TryGetValue(name, out var value);
			dictionary4[name] = value + 1;
		}
		for (int k = 0; k < componentsInChildren.Length; k++)
		{
			if (k == 0)
			{
				list.Add(transform);
				list2.Add(componentsInChildren[0]);
				continue;
			}
			Transform value2 = null;
			bool flag = dictionary3.TryGetValue(((Object)componentsInChildren[k]).GetInstanceID(), out value2) || dictionary.TryGetValue(PathOf(componentsInChildren[k], transform2), out value2);
			if (!flag)
			{
				string name2 = ((Object)componentsInChildren[k]).name;
				if (!hashSet.Contains(name2) && dictionary4[name2] == 1)
				{
					flag = dictionary2.TryGetValue(name2, out value2);
				}
			}
			if (flag && (Object)(object)value2 != (Object)null)
			{
				list.Add(value2);
				list2.Add(componentsInChildren[k]);
			}
		}
		srcOut = list.ToArray();
		cloneOut = list2.ToArray();
		int num = componentsInChildren.Length - 1;
		int num2 = list.Count - 1;
		float num3 = ((num > 0) ? ((float)num2 / (float)num) : 0f);
		return num > 0 && num2 > 0 && num3 >= minRatio;
	}

	private void Despawn()
	{
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: 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)
		_cdActive = false;
		_cdAction = null;
		try
		{
			if ((Object)(object)_clone != (Object)null)
			{
				Object.Destroy((Object)(object)_clone);
			}
			if ((Object)(object)_pivot != (Object)null)
			{
				Object.Destroy((Object)(object)_pivot);
			}
			for (int i = 0; i < _parts.Count; i++)
			{
				if ((Object)(object)_parts[i].go != (Object)null)
				{
					Object.Destroy((Object)(object)_parts[i].go);
				}
			}
			DestroyRag();
		}
		catch
		{
		}
		_parts.Clear();
		_handles.Clear();
		_bsSrc.Clear();
		_bsDst.Clear();
		_dbones.Clear();
		_physicsRestPose.Clear();
		_physicsLivePairs.Clear();
		_ragCols.Clear();
		_pins.Clear();
		ClearAllGrabs();
		_clone = null;
		_pivot = null;
		_srcGO = null;
		_srcT = null;
		_cloneT = null;
		_bones = null;
		_spine = null;
		_hips = null;
		_head = null;
		_baseLr = null;
		_edited = null;
		_held = null;
		_vel = null;
		_idx = null;
		_skip = null;
		_noPos = null;
		_frozen = false;
		_colOn = false;
		_colGrace = false;
		_pulled = false;
		_pivVel = Vector3.zero;
		_ragdolled = false;
		_ragLp = null;
		_ragLr = null;
		_jawBone = null;
		_jawRestLocalRotation = Quaternion.identity;
		_jawRestBlendWeight = 0f;
		_jawRestCaptured = false;
		_jawRestSynced = false;
		_jawCommandActive = false;
		_jawCommandOpen = false;
	}

	private static Vector3 FlatHeading(Vector3 v, Vector3 fb)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		v.y = 0f;
		if (((Vector3)(ref v)).sqrMagnitude < 0.0001f)
		{
			return fb;
		}
		return ((Vector3)(ref v)).normalized;
	}

	private static Vector3 HeadForward()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)Player.RigManager != (Object)null)
			{
				return ((Rig)Player.RigManager.physicsRig).m_head.forward;
			}
		}
		catch
		{
		}
		return Vector3.forward;
	}

	private void PlaceHere()
	{
		//IL_002a: 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_0035: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_clone == (Object)null) && _srcT != null)
		{
			_anchorPos = _srcT[0].position;
			_anchorHeading = FlatHeading(HeadForward(), FlatHeading(_srcT[0].forward, Vector3.forward));
		}
	}

	private void SetPivot(Vector3 pos, Quaternion rot, bool flip)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		if (!_frozen)
		{
			Transform transform = _pivot.transform;
			Vector3 val = (Vector3)(flip ? new Vector3(-1f, 1f, 1f) : Vector3.one);
			if (!(transform.localScale == val) || !(transform.localPosition == pos) || !(transform.localRotation == rot))
			{
				transform.SetPositionAndRotation(pos, rot);
				transform.localScale = val;
			}
		}
	}

	private void ApplyLive()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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_00cb: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		Transform val = _srcT[0];
		Transform val2 = _cloneT[0];
		Vector3 position = val.position;
		Quaternion rotation = val.rotation;
		float num = Mathf.Max(0.1f, PrefDist.Value);
		Vector3 val3 = Quaternion.AngleAxis(PrefAngle.Value, Vector3.up) * _anchorHeading;
		Vector3 localPosition;
		Quaternion localRotation;
		if (PrefMirror.Value)
		{
			Vector3 val4 = _anchorPos + val3 * (num * 0.5f);
			Quaternion val5 = Quaternion.LookRotation(Vector3.Cross(val3, Vector3.up), Vector3.up);
			Quaternion val6 = Quaternion.Inverse(val5);
			SetPivot(val4, val5, flip: true);
			localPosition = val6 * (position - val4);
			localRotation = val6 * rotation;
		}
		else
		{
			SetPivot(val3 * num, Quaternion.identity, flip: false);
			localPosition = position;
			localRotation = rotation;
		}
		val2.localPosition = localPosition;
		val2.localRotation = localRotation;
		val2.localScale = val.lossyScale;
		for (int i = 1; i < _cloneT.Length; i++)
		{
			if (!_skip[i])
			{
				Transform val7 = _cloneT[i];
				if (!_noPos[i])
				{
					val7.localPosition = _srcT[i].localPosition;
				}
				val7.localRotation = _srcT[i].localRotation;
			}
		}
		for (int j = 0; j < _bsSrc.Count; j++)
		{
			SkinnedMeshRenderer val8 = _bsSrc[j];
			SkinnedMeshRenderer val9 = _bsDst[j];
			if (!((Object)(object)val8 == (Object)null) && !((Object)(object)val9 == (Object)null))
			{
				int blendShapeCount = val9.sharedMesh.blendShapeCount;
				for (int k = 0; k < blendShapeCount; k++)
				{
					val9.SetBlendShapeWeight(k, val8.GetBlendShapeWeight(k));
				}
			}
		}
		if (!_jawCommandActive)
		{
			CaptureJawCommandRestFromCurrentPose();
		}
	}

	public override void OnLateUpdate()
	{
		if ((Object)(object)_clone == (Object)null)
		{
			return;
		}
		try
		{
			if (_dbones != null && _dbones.Count > 0)
			{
				MarkPhysicsParticleTransformsSkipped();
				ProtectPhysicsRestTransformsFromLivePose();
			}
			if (_ragdolled)
			{
				if (_ragGrace && Time.time >= _ragGraceUntil)
				{
					_ragGrace = false;
					RefreshPlayerIgnore();
				}
				DriveRagdoll();
				if (PrefRagdollGrab.Value)
				{
					UpdateRagdollGrabToggle();
				}
				else
				{
					UpdateRagdollGrab();
				}
				if (PrefTouchUnragdoll.Value)
				{
					UpdateTouchUnragdoll();
				}
				return;
			}
			if (!_frozen)
			{
				if ((Object)(object)_srcGO == (Object)null || (Object)(object)Player.Avatar == (Object)null || (Object)(object)((Component)Player.Avatar).gameObject != (Object)(object)_srcGO)
				{
					Despawn();
					return;
				}
				ApplyLive();
			}
			else
			{
				UpdatePoseEdit();
			}
			ApplyJawCommand();
			UpdateColliders();
			RestoreUnusedArmScales();
		}
		catch (Exception ex)
		{
			MelonLogger.Warning("OnLateUpdate:" + ex.Message);
		}
	}

	private void FreezeNow()
	{
		//IL_0054: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_clone == (Object)null) && !_frozen)
		{
			if (_ragdolled)
			{
				UnragdollClone();
			}
			RestorePhysicsAuthoredRest();
			ResetClonePhysicsParticles();
			for (int i = 0; i < _cloneT.Length; i++)
			{
				_baseLr[i] = _cloneT[i].localRotation;
				_edited[i] = false;
				_held[i] = false;
				_vel[i] = Vector3.zero;
			}
			SyncRest();
			_pivVel = Vector3.zero;
			InitAnatomy();
			ClearAllGrabs();
			CaptureJawCommandRestFromCurrentPose();
			_frozen = true;
			CaptureJawBlendshapeRest();
			CaptureGroundAnchors();
			ApplyPhysState();
			MelonLogger.Msg("Clone frozen.");
		}
	}

	private void Unfreeze()
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if ((Object)(object)_clone == (Object)null || !_frozen)
		{
			return;
		}
		if (_ragdolled)
		{
			UnragdollClone();
		}
		if ((Object)(object)_srcGO == (Object)null || (Object)(object)Player.Avatar == (Object)null || (Object)(object)((Component)Player.Avatar).gameObject != (Object)(object)_srcGO