Decompiled source of WallClimb v1.0.1

WallClimb.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Il2CppHexabodyVR.PlayerController;
using Il2CppHurricaneVR.Framework.Components;
using Il2CppHurricaneVR.Framework.Core;
using Il2CppHurricaneVR.Framework.Core.Grabbers;
using Il2CppHurricaneVR.Framework.Shared;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using WallClimb;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(WallClimbMod), "WallClimb", "1.45.0", "", null)]
[assembly: MelonGame("Kubunautilus", "BrutalistickVR")]
[assembly: MelonPriority(-45)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("WallClimb")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WallClimb")]
[assembly: AssemblyTitle("WallClimb")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WallClimb
{
	public static class Cfg
	{
		public const string Category = "WallClimb";

		private const int Schema = 18;

		private const bool DefEnabled = true;

		private const float DefGrabUpRange = 0.1f;

		private const float DefGrabDownRange = 0.1f;

		private const bool DefGrabWithGrip = true;

		private const bool DefGrabWithTrigger = false;

		private const bool DefShowIndicator = true;

		private const bool DefKeepComponent = true;

		private const bool DefAutoMark = true;

		private const float DefAutoMarkRadius = 2.5f;

		private const bool DefUseClosestPoint = true;

		private const bool DefRequireClearance = false;

		private const float DefBreakDistance = 1f;

		private const bool DefAllowCeiling = true;

		private const bool DefAllowFloor = true;

		private const float DefTopSurfaceMinHeight = 0.5f;

		private const float DefMinWallSize = 0.1f;

		private const bool DefHoldManyHands = true;

		private const float DefCeilingProbeUp = 3f;

		private const float DefCeilingMinSpan = 0.35f;

		private const bool DefUseClimbableMarker = false;

		private const bool DefWallJumpEnabled = true;

		private const float DefWallJumpApex = 0.7f;

		private const float DefWallJumpAway = 2.6f;

		private const float DefMaxUpness = 0.55f;

		private const bool DefRequireStatic = false;

		private const float DefMinWallHeight = 0.25f;

		private const bool DefAddKinematicRigidbody = true;

		private const bool DefAutoApplyLayer = false;

		private const bool DefDisableHandCollision = false;

		private const float DefMaxHangTime = 30f;

		private const float DefStuckReleaseDistance = 1.5f;

		private const bool DefVerbose = true;

		private const bool DefStrictFilters = false;

		private const bool DefAllowDynamicBodies = false;

		private const bool DefEnableTelekinesis = false;

		private const bool DefAllowOverlapGrab = false;

		private const float DefGrabMaxDistance = 0.1f;

		private const float DefGrabRadius = 0.1f;

		private const string DefTerrainLayer = "Terrain";

		private const bool DefSkipGameLayers = true;

		private static readonly string[] SkipLayers = new string[7] { "PlayerBody", "PlayerHead", "Hand", "Cosmetic", "Menu", "UI", "Trigger" };

		private const bool DefIncludeTriggers = false;

		private const bool DefSkipForeignWeapons = true;

		private const string DefForeignPrefixes = "Mahito";

		public static MelonPreferences_Category Prefs;

		public static MelonPreferences_Entry<bool> Enabled;

		public static MelonPreferences_Entry<float> GrabRadius;

		public static MelonPreferences_Entry<float> GrabUpRange;

		public static MelonPreferences_Entry<float> GrabDownRange;

		public static MelonPreferences_Entry<bool> GrabWithGrip;

		public static MelonPreferences_Entry<bool> GrabWithTrigger;

		public static MelonPreferences_Entry<bool> ShowIndicator;

		public static MelonPreferences_Entry<bool> KeepComponent;

		public static MelonPreferences_Entry<bool> UseClimbableMarker;

		public static MelonPreferences_Entry<bool> AddKinematicRigidbody;

		public static MelonPreferences_Entry<bool> AutoMark;

		public static MelonPreferences_Entry<float> AutoMarkRadius;

		public static MelonPreferences_Entry<bool> UseClosestPoint;

		public static MelonPreferences_Entry<bool> RequireClearance;

		public static MelonPreferences_Entry<float> BreakDistance;

		public static MelonPreferences_Entry<bool> AllowCeiling;

		public static MelonPreferences_Entry<bool> AllowFloor;

		public static MelonPreferences_Entry<float> TopSurfaceMinHeight;

		public static MelonPreferences_Entry<float> MinWallSize;

		public static MelonPreferences_Entry<bool> HoldManyHands;

		public static MelonPreferences_Entry<float> CeilingProbeUp;

		public static MelonPreferences_Entry<float> GrabMaxDistance;

		public static MelonPreferences_Entry<float> CeilingMinSpan;

		public static MelonPreferences_Entry<bool> AutoApplyLayer;

		public static MelonPreferences_Entry<bool> DisableHandCollision;

		public static MelonPreferences_Entry<float> MaxHangTime;

		public static MelonPreferences_Entry<float> StuckReleaseDistance;

		public static MelonPreferences_Entry<bool> WallJumpEnabled;

		public static MelonPreferences_Entry<float> WallJumpApex;

		public static MelonPreferences_Entry<float> WallJumpAway;

		public static MelonPreferences_Entry<float> MaxUpness;

		public static MelonPreferences_Entry<bool> RequireStatic;

		public static MelonPreferences_Entry<float> MinWallHeight;

		public static MelonPreferences_Entry<bool> Verbose;

		public static MelonPreferences_Entry<bool> StrictFilters;

		public static MelonPreferences_Entry<bool> AllowDynamicBodies;

		public static MelonPreferences_Entry<bool> EnableTelekinesis;

		public static MelonPreferences_Entry<bool> AllowOverlapGrab;

		public static MelonPreferences_Entry<bool> IncludeTriggers;

		public static MelonPreferences_Entry<string> TerrainLayer;

		public static MelonPreferences_Entry<bool> SkipGameLayers;

		public static MelonPreferences_Entry<bool> HitBackFaces;

		public static MelonPreferences_Entry<bool> SkipForeignWeapons;

		public static MelonPreferences_Entry<string> ForeignPrefixes;

		public static void Register()
		{
			Prefs = MelonPreferences.CreateCategory("WallClimb", "WallClimb");
			MelonPreferences_Entry<int> val = Prefs.CreateEntry<int>("CfgSchema", 0, "схема настроек", (string)null, false, false, (ValueValidator)null, (string)null);
			Enabled = Prefs.CreateEntry<bool>("Enabled", true, "Мод включён", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabRadius = Prefs.CreateEntry<float>("GrabRadius", 0.1f, "Радиус поиска стены рукой, м", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabUpRange = Prefs.CreateEntry<float>("GrabUpRange", 0.1f, "Насколько вверх ищем от кисти, м", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabDownRange = Prefs.CreateEntry<float>("GrabDownRange", 0.1f, "Насколько вниз ищем от кисти, м", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabWithGrip = Prefs.CreateEntry<bool>("GrabWithGrip", true, "Хватать стену за Grip", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabWithTrigger = Prefs.CreateEntry<bool>("GrabWithTrigger", false, "Хватать стену за триггер", (string)null, false, false, (ValueValidator)null, (string)null);
			ShowIndicator = Prefs.CreateEntry<bool>("ShowIndicator", true, "Показывать игровую точку захвата", (string)null, false, false, (ValueValidator)null, (string)null);
			KeepComponent = Prefs.CreateEntry<bool>("KeepComponent", true, "Оставлять компоненты на стене после отпускания (иначе пропадают точки захвата)", (string)null, false, false, (ValueValidator)null, (string)null);
			UseClimbableMarker = Prefs.CreateEntry<bool>("UseClimbableMarker", false, "Вешать HVRClimbable (в игре их 0, обычно не нужно)", (string)null, false, false, (ValueValidator)null, (string)null);
			AddKinematicRigidbody = Prefs.CreateEntry<bool>("AddKinematicRigidbody", true, "Добавить кинематический Rigidbody на стену (иначе сустав без тела и NPC ломаются)", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoApplyLayer = Prefs.CreateEntry<bool>("AutoApplyLayer", false, "Разрешить игре менять слой геометрии (небезопасно для NPC)", (string)null, false, false, (ValueValidator)null, (string)null);
			DisableHandCollision = Prefs.CreateEntry<bool>("DisableHandCollision", false, "Выключать коллайдер руки на время хвата (рука проходит сквозь стену)", (string)null, false, false, (ValueValidator)null, (string)null);
			MaxHangTime = Prefs.CreateEntry<float>("MaxHangTime", 30f, "Сколько максимум висеть на стене, с (страховка от застревания)", (string)null, false, false, (ValueValidator)null, (string)null);
			StuckReleaseDistance = Prefs.CreateEntry<float>("StuckReleaseDistance", 1.5f, "Отпустить, если рука дальше точки хвата, м", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoMark = Prefs.CreateEntry<bool>("AutoMark", true, "Заранее помечать стены рядом, чтобы были точки захвата", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoMarkRadius = Prefs.CreateEntry<float>("AutoMarkRadius", 2.5f, "Радиск автоматической разметки стен, м", (string)null, false, false, (ValueValidator)null, (string)null);
			UseClosestPoint = Prefs.CreateEntry<bool>("UseClosestPoint", true, "Цеплять за ближайшую точку коллайдера (иначе рука уходит в стену)", (string)null, false, false, (ValueValidator)null, (string)null);
			RequireClearance = Prefs.CreateEntry<bool>("RequireClearance", false, "Не хватать, если перед хватом что-то мешает", (string)null, false, false, (ValueValidator)null, (string)null);
			BreakDistance = Prefs.CreateEntry<float>("BreakDistance", 1f, "На каком расстоянии хват рвётся сам, м (0 = не рвётся)", (string)null, false, false, (ValueValidator)null, (string)null);
			AllowCeiling = Prefs.CreateEntry<bool>("AllowCeiling", true, "Цепляться за потолок", (string)null, false, false, (ValueValidator)null, (string)null);
			AllowFloor = Prefs.CreateEntry<bool>("AllowFloor", true, "Цепляться за верх плиты (берётся только если он выше ног)", (string)null, false, false, (ValueValidator)null, (string)null);
			TopSurfaceMinHeight = Prefs.CreateEntry<float>("TopSurfaceMinHeight", 0.5f, "Насколько верх плиты должен быть выше шара, м", (string)null, false, false, (ValueValidator)null, (string)null);
			MinWallSize = Prefs.CreateEntry<float>("MinWallSize", 0.1f, "Мин. толщина коллайдера, м: вырезает ступеньки и перекладины лестниц", (string)null, false, false, (ValueValidator)null, (string)null);
			HoldManyHands = Prefs.CreateEntry<bool>("HoldManyHands", true, "Две руки на одной поверхности (иначе на потолке не схватить обеими)", (string)null, false, false, (ValueValidator)null, (string)null);
			CeilingProbeUp = Prefs.CreateEntry<float>("CeilingProbeUp", 3f, "Насколько вверх искать потолок при разметке, м", (string)null, false, false, (ValueValidator)null, (string)null);
			GrabMaxDistance = Prefs.CreateEntry<float>("GrabMaxDistance", 0.1f, "Предел дистанции захвата, м (на офисе стены начинаются с 1 м)", (string)null, false, false, (ValueValidator)null, (string)null);
			CeilingMinSpan = Prefs.CreateEntry<float>("CeilingMinSpan", 0.35f, "Мин. размах потолка по горизонтали, м", (string)null, false, false, (ValueValidator)null, (string)null);
			WallJumpEnabled = Prefs.CreateEntry<bool>("WallJumpEnabled", true, "Прыжок со стены кнопкой A", (string)null, false, false, (ValueValidator)null, (string)null);
			WallJumpApex = Prefs.CreateEntry<float>("WallJumpApex", 0.7f, "Высота прыжка со стены, м", (string)null, false, false, (ValueValidator)null, (string)null);
			WallJumpAway = Prefs.CreateEntry<float>("WallJumpAway", 2.6f, "Толчок от стены, м/с", (string)null, false, false, (ValueValidator)null, (string)null);
			MaxUpness = Prefs.CreateEntry<float>("MaxUpness", 0.55f, "Стена, если |n.y| меньше этого", (string)null, false, false, (ValueValidator)null, (string)null);
			RequireStatic = Prefs.CreateEntry<bool>("RequireStatic", false, "Только статичная геометрия", (string)null, false, false, (ValueValidator)null, (string)null);
			MinWallHeight = Prefs.CreateEntry<float>("MinWallHeight", 0.25f, "Мин. высота коллайдера, м", (string)null, false, false, (ValueValidator)null, (string)null);
			Verbose = Prefs.CreateEntry<bool>("Verbose", true, "Подробный лог", (string)null, false, false, (ValueValidator)null, (string)null);
			StrictFilters = Prefs.CreateEntry<bool>("StrictFilters", false, "Жёсткие фильтры размера (для незнакомых карт лучше false)", (string)null, false, false, (ValueValidator)null, (string)null);
			AllowDynamicBodies = Prefs.CreateEntry<bool>("AllowDynamicBodies", false, "Цепляться за подвижные предметы (они ломаются, лучше false)", (string)null, false, false, (ValueValidator)null, (string)null);
			EnableTelekinesis = Prefs.CreateEntry<bool>("EnableTelekinesis", false, "Разрешить телекинез на помеченной геометрии (лучше false)", (string)null, false, false, (ValueValidator)null, (string)null);
			AllowOverlapGrab = Prefs.CreateEntry<bool>("AllowOverlapGrab", false, "Запасной поиск сферой (даёт хват за воздух перед стеной)", (string)null, false, false, (ValueValidator)null, (string)null);
			IncludeTriggers = Prefs.CreateEntry<bool>("IncludeTriggers", false, "Считать триггеры поверхностями (на части карт стены сделаны триггерами)", (string)null, false, false, (ValueValidator)null, (string)null);
			TerrainLayer = Prefs.CreateEntry<string>("TerrainLayer", "Terrain", "Слой геометрии уровня (для подсказки в логе)", (string)null, false, false, (ValueValidator)null, (string)null);
			SkipGameLayers = Prefs.CreateEntry<bool>("SkipGameLayers", true, "Пропускать слои игровых сущностей (PlayerBody, PlayerHead, Hand, Cosmetic)", (string)null, false, false, (ValueValidator)null, (string)null);
			HitBackFaces = Prefs.CreateEntry<bool>("HitBackFaces", true, "Искать обратные грани: без этого внутренние стены помещения невидимы изнутри", (string)null, false, false, (ValueValidator)null, (string)null);
			SkipForeignWeapons = Prefs.CreateEntry<bool>("SkipForeignWeapons", true, "Не хватать оружие других модов (ArmWeaponMod и т.п.)", (string)null, false, false, (ValueValidator)null, (string)null);
			ForeignPrefixes = Prefs.CreateEntry<string>("ForeignPrefixes", "Mahito", "Префиксы имён чужих оружей через запятую", (string)null, false, false, (ValueValidator)null, (string)null);
			if (val.Value != 18)
			{
				int value = val.Value;
				Enabled.Value = true;
				GrabRadius.Value = 0.1f;
				GrabUpRange.Value = 0.1f;
				GrabDownRange.Value = 0.1f;
				GrabWithGrip.Value = true;
				GrabWithTrigger.Value = false;
				ShowIndicator.Value = true;
				KeepComponent.Value = true;
				UseClimbableMarker.Value = false;
				AddKinematicRigidbody.Value = true;
				AutoMark.Value = true;
				AutoMarkRadius.Value = 2.5f;
				UseClosestPoint.Value = true;
				RequireClearance.Value = false;
				BreakDistance.Value = 1f;
				AllowCeiling.Value = true;
				AllowFloor.Value = true;
				TopSurfaceMinHeight.Value = 0.5f;
				MinWallSize.Value = 0.1f;
				HoldManyHands.Value = true;
				CeilingProbeUp.Value = 3f;
				GrabMaxDistance.Value = 0.1f;
				CeilingMinSpan.Value = 0.35f;
				AutoApplyLayer.Value = false;
				DisableHandCollision.Value = false;
				MaxHangTime.Value = 30f;
				StuckReleaseDistance.Value = 1.5f;
				WallJumpEnabled.Value = true;
				WallJumpApex.Value = 0.7f;
				WallJumpAway.Value = 2.6f;
				MaxUpness.Value = 0.55f;
				RequireStatic.Value = false;
				MinWallHeight.Value = 0.25f;
				Verbose.Value = true;
				StrictFilters.Value = false;
				AllowDynamicBodies.Value = false;
				EnableTelekinesis.Value = false;
				AllowOverlapGrab.Value = false;
				IncludeTriggers.Value = false;
				TerrainLayer.Value = "Terrain";
				SkipGameLayers.Value = true;
				HitBackFaces.Value = true;
				SkipForeignWeapons.Value = true;
				ForeignPrefixes.Value = "Mahito";
				val.Value = 18;
				MelonLogger.Msg("[WallClimb] СХЕМА {0} -> {1}: значения сброшены к дефолтам кода.", new object[2] { value, 18 });
			}
			MelonLogger.Msg("[WallClimb] захват: радиус={0:F2}м вверх={1:F2} вниз={2:F2} grip={3} триггер={4} индикатор={5} оставлятьКомпонент={6} маркерClimbable={7} кинемRigidbody={8}", new object[9] { GrabRadius.Value, GrabUpRange.Value, GrabDownRange.Value, GrabWithGrip.Value, GrabWithTrigger.Value, ShowIndicator.Value, KeepComponent.Value, UseClimbableMarker.Value, AddKinematicRigidbody.Value });
			MelonLogger.Msg("[WallClimb] хват: ближайшаяТочка={0} проверкаЗазора={1} рвётсяНа={2:F2}м", new object[3] { UseClosestPoint.Value, RequireClearance.Value, BreakDistance.Value });
			MelonLogger.Msg("[WallClimb] поверхности: стены upness<{0:F2}; потолок (нормаль вниз)={1}; верх плиты (нормаль вверх)={2} от {3:F2}м над шаром", new object[4] { MaxUpness.Value, AllowCeiling.Value, AllowFloor.Value, TopSurfaceMinHeight.Value });
			MelonLogger.Msg("[WallClimb] прыжок со стены: включён={0} апекс={1:F2}м (v={2:F2}м/с) толчок={3:F2}м/с", new object[4]
			{
				WallJumpEnabled.Value,
				WallJumpApex.Value,
				SpeedForApex(),
				WallJumpAway.Value
			});
			MelonLogger.Msg("[WallClimb] стена: upness<{0:F2} статика={1} минВысота={2:F2}м схема={3}", new object[4] { MaxUpness.Value, RequireStatic.Value, MinWallHeight.Value, val.Value });
		}

		public static float SpeedForApex()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Abs(Physics.gravity.y);
			if (num < 0.01f)
			{
				num = 9.81f;
			}
			return Mathf.Sqrt(2f * num * Mathf.Max(0f, WallJumpApex.Value));
		}
	}
	public class WallClimbMod : MelonMod
	{
		private sealed class Hand
		{
			public HVRHandGrabber Grabber;

			public HVRHandSide Side;

			public bool WasDown;

			public float GrabTime;

			public Vector3 GrabPoint;

			public float GrabDistance;
		}

		private const string Tag = "[WallClimb]";

		private static HexaBodyPlayer4 _body;

		private static bool _found;

		private static readonly List<HVRHandGrabber> Grabbers = new List<HVRHandGrabber>();

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

		private static Transform _own;

		private static Transform _root;

		private static readonly HashSet<string> BodyParts = new HashSet<string>
		{
			"Neck", "Head", "Jaw", "UpperChest", "MiddleChest", "Pelvis", "Shoulder_R", "Shoulder_L", "Elbow_R", "Elbow_L",
			"Hip_R", "Hip_L", "Knee_R", "Knee_L", "Foot_R", "Foot_L", "Hand_R", "Hand_L"
		};

		private static readonly Vector3[] ProbeDirs;

		private static readonly List<GameObject> Touched;

		private static Vector3 _wallNormal;

		private static float _wallTimer;

		private static float _ownRefresh;

		private static int _addedTotal;

		private static readonly List<Hand> Hands;

		private static readonly List<HVRHandGrabber> Held;

		private static readonly List<HVRController> Ctls;

		private static float _registerAt;

		private static int _unregistered;

		private static bool _backFacesSet;

		private const float ContactBack = 0.08f;

		private const float ContactAhead = 0.06f;

		private static readonly float[] AutoMarkHeights;

		private static readonly Vector3[] AutoMarkDirs;

		private static readonly HashSet<int> Marked;

		private static float _autoTimer;

		private static bool _warnedTerrain;

		private static readonly string[] SkipLayers;

		private static bool _dumpedPositions;

		private static float _nearDist;

		private static string _nearName;

		private static Vector3 _nearNormal;

		private static string _nearLayer;

		private static Rigidbody _nearRb;

		private static readonly Dictionary<string, int> Skips;

		private static readonly Dictionary<string, string> SkipSamples;

		public override void OnInitializeMelon()
		{
			Cfg.Register();
			MelonLogger.Msg("[WallClimb] v1.45.0 - ArmWeaponMod: ne khvataem chuzhoe oruzhie.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Cleanup();
			_body = null;
			_found = false;
			Grabbers.Clear();
		}

		public override void OnDeinitializeMelon()
		{
			Cleanup();
		}

		private static void Cleanup()
		{
			for (int i = 0; i < Touched.Count; i++)
			{
				GameObject val = Touched[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					HVRClimbable component = val.GetComponent<HVRClimbable>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					HVRGrabbable component2 = val.GetComponent<HVRGrabbable>();
					if ((Object)(object)component2 != (Object)null)
					{
						Object.Destroy((Object)(object)component2);
					}
				}
				catch
				{
				}
			}
			Touched.Clear();
		}

		public override void OnUpdate()
		{
			//IL_0095: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.Enabled.Value || !EnsureBody())
			{
				return;
			}
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (_wallTimer > 0f)
			{
				_wallTimer -= unscaledDeltaTime;
			}
			ApplyBackFaces();
			_ownRefresh -= unscaledDeltaTime;
			if (_ownRefresh <= 0f)
			{
				_ownRefresh = 1f;
				RefreshOwnColliders();
			}
			int num = -1;
			for (int i = 0; i < Hands.Count; i++)
			{
				Hand hand = Hands[i];
				if (hand != null && !((Object)(object)hand.Grabber == (Object)null))
				{
					bool flag = false;
					if (Cfg.GrabWithGrip.Value && HVRController.GetButtonState(hand.Side, (HVRButtons)0).Active)
					{
						flag = true;
					}
					if (Cfg.GrabWithTrigger.Value && HVRController.GetButtonState(hand.Side, (HVRButtons)1).Active)
					{
						flag = true;
					}
					bool num2 = flag && !hand.WasDown;
					hand.WasDown = flag;
					if (num2 && num < 0)
					{
						num = i;
					}
				}
			}
			for (int num3 = Held.Count - 1; num3 >= 0; num3--)
			{
				if ((Object)(object)Held[num3] == (Object)null || !((HVRGrabberBase)Held[num3]).IsGrabbing)
				{
					Held.RemoveAt(num3);
				}
			}
			if (num >= 0)
			{
				HVRHandGrabber grabber = Hands[num].Grabber;
				HVRHandGrabber val = (((Object)(object)grabber != (Object)null && !((HVRGrabberBase)grabber).IsGrabbing) ? grabber : FindFreeGrabber());
				if ((Object)(object)val != (Object)null)
				{
					TryGrab(val);
				}
				else
				{
					ReleaseAll("отпускание");
				}
			}
			bool num4 = Held.Count > 0;
			AutoMarkWalls(unscaledDeltaTime);
			StuckWatchdog();
			if (num4 && Cfg.WallJumpEnabled.Value)
			{
				HexaBodyInputsBase inputs = HexaBodyPlayer4.Inputs;
				if ((Object)(object)inputs != (Object)null && inputs.JumpState.Active)
				{
					WallJump();
					return;
				}
			}
			if (Cfg.Verbose.Value && _wallTimer <= 0f)
			{
				_wallTimer = 2f;
				MelonLogger.Msg("[WallClimb] состояние: висим руками={0}/{1} навешено={2} n={3} | {4}", new object[5]
				{
					Held.Count,
					Hands.Count,
					_addedTotal,
					_wallNormal,
					GrabberNames()
				});
			}
		}

		private static bool AnyHanging()
		{
			return Held.Count > 0;
		}

		private static HVRHandGrabber FindFreeGrabber()
		{
			for (int i = 0; i < Grabbers.Count; i++)
			{
				HVRHandGrabber val = Grabbers[i];
				if (!((Object)(object)val == (Object)null) && !((HVRGrabberBase)val).IsGrabbing)
				{
					return val;
				}
			}
			return null;
		}

		private static string GrabberNames()
		{
			string text = "грабберов=" + Grabbers.Count;
			for (int i = 0; i < Grabbers.Count; i++)
			{
				HVRHandGrabber val = Grabbers[i];
				text = ((!((Object)(object)val == (Object)null)) ? (text + " " + (val.IsLeftHand ? "Л" : (val.IsRightHand ? "П" : "?")) + "=" + ((!((HVRGrabberBase)val).IsGrabbing) ? "-" : (val.IsClimbing ? "climb" : "grab"))) : (text + " [null]"));
			}
			return text;
		}

		private static void TryGrab(HVRHandGrabber free)
		{
			//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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)free == (Object)null)
			{
				return;
			}
			Vector3 alt;
			Vector3 val = HandPosition(free, out alt);
			if (!_dumpedPositions)
			{
				_dumpedPositions = true;
				Rigidbody val2 = ((!((Object)(object)_body != (Object)null)) ? null : (free.IsLeftHand ? _body.LeftHandRigidBody : _body.RightHandRigidBody));
				MelonLogger.Msg("[WallClimb] ПОЗИЦИИ: телоРуки={0} HandWorldPosition={1} transformГраббера={2} риг={3}", new object[4]
				{
					((Object)(object)val2 != (Object)null) ? V3(((Component)val2).transform.position) : "НЕТ",
					V3(alt),
					V3(((Component)free).transform.position),
					((Object)(object)_root != (Object)null) ? V3(_root.position) : "нет"
				});
			}
			Vector3 normal;
			float gap;
			string name;
			Collider val3 = FindWall(val, out normal, out gap, out name);
			string text = "лучи";
			if ((Object)(object)val3 == (Object)null)
			{
				MelonLogger.Msg("[WallClimb] захват не состоялся: " + NearInfo());
				return;
			}
			bool made;
			HVRGrabbable val4 = MakeGrabbable(val3, out made);
			if ((Object)(object)val4 == (Object)null)
			{
				MelonLogger.Msg("[WallClimb] захват не начат: не удалось создать HVRGrabbable.");
				return;
			}
			bool flag;
			try
			{
				flag = ((HVRGrabberBase)free).TryGrab(val4, true);
			}
			catch (Exception ex)
			{
				MelonLogger.Msg("[WallClimb] TryGrab бросил: {0}", new object[1] { ex.GetType().Name });
				flag = false;
			}
			ResetSkips();
			_wallNormal = normal;
			if (flag && !Held.Contains(free))
			{
				Held.Add(free);
				RememberGrabPoint(free, normal, val3);
			}
			MelonLogger.Msg("[WallClimb] ЗАХВАТ ({0}): {1} рука=({2:F2},{3:F2},{4:F2}) стена=[{5}] d={6:F2} поверхность={7} триггер={8} n={9} новыйКомпонент={10} итог={11} | {12}", new object[13]
			{
				text,
				free.IsLeftHand ? "левая" : "правая",
				val.x,
				val.y,
				val.z,
				name,
				gap,
				SurfaceKind(normal),
				(Object)(object)val3 != (Object)null && val3.isTrigger,
				normal,
				made,
				flag ? "да" : "нет",
				GrabberNames()
			});
		}

		private static HVRGrabbable MakeGrabbable(Collider wall, out bool made)
		{
			made = false;
			GameObject gameObject = ((Component)wall).gameObject;
			HVRGrabbable component = gameObject.GetComponent<HVRGrabbable>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			try
			{
				if (Cfg.AddKinematicRigidbody.Value && (Object)(object)gameObject.GetComponent<Rigidbody>() == (Object)null)
				{
					Rigidbody obj = gameObject.AddComponent<Rigidbody>();
					obj.isKinematic = true;
					obj.useGravity = false;
				}
				component = gameObject.AddComponent<HVRGrabbable>();
				if (Cfg.UseClimbableMarker.Value)
				{
					gameObject.AddComponent<HVRClimbable>();
				}
				component.Stationary = true;
				component.ForceGrabbable = Cfg.EnableTelekinesis.Value;
				component.ShowGrabIndicator = Cfg.ShowIndicator.Value;
				component.ShowTriggerGrabIndicator = Cfg.ShowIndicator.Value;
				component.ShowForceGrabIndicator = Cfg.EnableTelekinesis.Value;
				component.AutoApplyLayer = Cfg.AutoApplyLayer.Value;
				component.DisableHandCollision = Cfg.DisableHandCollision.Value;
				component.TrackingType = (HVRGrabTracking)0;
				component.HoldType = (HVRHoldType)(Cfg.HoldManyHands.Value ? 3 : 0);
				component.GrabControl = (HVRGrabControls)0;
				component.UseColliderClosestPoint = Cfg.UseClosestPoint.Value;
				component.RequireOverlapClearance = Cfg.RequireClearance.Value;
				component.BreakDistance = Mathf.Max(0f, Cfg.BreakDistance.Value);
				Touched.Add(gameObject);
				_addedTotal++;
				made = true;
				return component;
			}
			catch (Exception ex)
			{
				MelonLogger.Msg("[WallClimb] AddComponent упал: {0}", new object[1] { ex.Message });
				return null;
			}
		}

		private static void AutoMarkWalls(float dt)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.AutoMark.Value || (Object)(object)_body == (Object)null || (Object)(object)_body.LocoBall == (Object)null)
			{
				return;
			}
			_autoTimer -= dt;
			if (_autoTimer > 0f)
			{
				return;
			}
			_autoTimer = 0.5f;
			Vector3 position = ((Component)_body.LocoBall).transform.position;
			float num = Mathf.Max(0.5f, Cfg.AutoMarkRadius.Value);
			int num2 = 0;
			for (int i = 0; i < AutoMarkHeights.Length; i++)
			{
				Vector3 val = position + Vector3.up * AutoMarkHeights[i];
				for (int j = 0; j < AutoMarkDirs.Length; j++)
				{
					Vector3 val2 = AutoMarkDirs[j];
					Vector3 val3 = val + val2 * 0.03f;
					float num3 = num;
					for (int k = 0; k < 6; k++)
					{
						if (!(num3 > 0.01f))
						{
							break;
						}
						RaycastHit val4 = default(RaycastHit);
						if (!Physics.Raycast(val3, val2, ref val4, num3, -1, (QueryTriggerInteraction)1))
						{
							break;
						}
						Collider collider = ((RaycastHit)(ref val4)).collider;
						if ((Object)(object)collider == (Object)null)
						{
							break;
						}
						bool num4 = OwnCollider(collider);
						val3 = ((RaycastHit)(ref val4)).point + val2 * 0.02f;
						num3 -= ((RaycastHit)(ref val4)).distance + 0.02f;
						if (!num4 && !GameLayer(collider) && Passes(collider, ((RaycastHit)(ref val4)).normal) && SurfaceAllowed(((RaycastHit)(ref val4)).normal, ((RaycastHit)(ref val4)).point.y))
						{
							if (Marked.Add(((Object)collider).GetInstanceID()))
							{
								num2++;
							}
							MakeGrabbable(collider, out var _);
							break;
						}
					}
				}
			}
			float num5 = Mathf.Max(0.5f, Cfg.CeilingProbeUp.Value);
			for (int l = 0; l < AutoMarkHeights.Length; l++)
			{
				Vector3 val5 = position + Vector3.up * AutoMarkHeights[l];
				float num6 = num5;
				for (int m = 0; m < 6; m++)
				{
					if (!(num6 > 0.01f))
					{
						break;
					}
					RaycastHit val6 = default(RaycastHit);
					if (!Physics.Raycast(val5, Vector3.up, ref val6, num6, -1, (QueryTriggerInteraction)1))
					{
						break;
					}
					Collider collider2 = ((RaycastHit)(ref val6)).collider;
					if ((Object)(object)collider2 == (Object)null)
					{
						break;
					}
					bool num7 = OwnCollider(collider2);
					val5 = ((RaycastHit)(ref val6)).point + Vector3.up * 0.02f;
					num6 -= ((RaycastHit)(ref val6)).distance + 0.02f;
					if (!num7 && !GameLayer(collider2) && Passes(collider2, ((RaycastHit)(ref val6)).normal) && SurfaceAllowed(((RaycastHit)(ref val6)).normal, ((RaycastHit)(ref val6)).point.y))
					{
						if (Marked.Add(((Object)collider2).GetInstanceID()))
						{
							num2++;
						}
						MakeGrabbable(collider2, out var _);
						break;
					}
				}
			}
			if (num2 > 0 && Cfg.Verbose.Value)
			{
				MelonLogger.Msg("[WallClimb] разметка: новых стен рядом={0} всего={1}", new object[2] { num2, Marked.Count });
			}
			RegisterUnseenColliders(position);
			ResetSkips();
		}

		private static bool IsInPhysics(Collider c)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = c.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			int num = 1 << ((Component)c).gameObject.layer;
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit((Il2CppArrayBase<Collider>)(object)Physics.OverlapSphere(center, 0.05f, num, (QueryTriggerInteraction)2));
			if (array == null)
			{
				return false;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)(object)c)
				{
					return true;
				}
			}
			return false;
		}

		private static void RegisterUnseenColliders(Vector3 center)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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)
			if (Time.time - _registerAt < 3f)
			{
				return;
			}
			_registerAt = Time.time;
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(Object.FindObjectsOfType<Collider>());
			if (array == null)
			{
				return;
			}
			float num = Mathf.Max(3f, Cfg.AutoMarkRadius.Value);
			foreach (Collider val in array)
			{
				if ((Object)(object)val == (Object)null || !val.enabled || !((Component)val).gameObject.activeInHierarchy || val.isTrigger || (Object)(object)val.attachedRigidbody != (Object)null || OwnCollider(val) || GameLayer(val))
				{
					continue;
				}
				Bounds bounds = val.bounds;
				Vector3 val2 = ((Bounds)(ref bounds)).ClosestPoint(center);
				if (Vector3.Distance(center, val2) > num || IsInPhysics(val))
				{
					continue;
				}
				string name = ((Object)((Component)val).gameObject).name;
				if (!name.StartsWith("Terrain") && !name.StartsWith("terrain"))
				{
					try
					{
						Rigidbody obj = ((Component)val).gameObject.AddComponent<Rigidbody>();
						obj.isKinematic = true;
						obj.useGravity = false;
						_unregistered++;
					}
					catch (Exception)
					{
					}
				}
			}
			if (_unregistered > 0)
			{
				MelonLogger.Msg("[WallClimb] ВОЗВРАЩЕНО В ФИЗИКУ: " + _unregistered + " коллайдеров (их видел глаз, а физика - нет)");
			}
		}

		private static void ApplyBackFaces()
		{
			if (_backFacesSet)
			{
				return;
			}
			_backFacesSet = true;
			try
			{
				bool value = Cfg.HitBackFaces.Value;
				if (Physics.queriesHitBackfaces != value)
				{
					Physics.queriesHitBackfaces = value;
					MelonLogger.Msg("[WallClimb] queriesHitBackfaces: было=" + Physics.queriesHitBackfaces + " стало=" + Physics.queriesHitBackfaces + " (без этого внутренние стены помещения невидимы для физики)");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Msg("[WallClimb] не удалось включить queriesHitBackfaces: " + ex.Message);
			}
		}

		private static string SurfaceKind(Vector3 n)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0.01f, Cfg.MaxUpness.Value);
			if (Mathf.Abs(n.y) <= num)
			{
				return "стена";
			}
			if (n.y < 0f - Mathf.Max(0.5f, num))
			{
				return "потолок";
			}
			if (n.y > Mathf.Max(0.5f, num))
			{
				return "верх плиты";
			}
			return "непонятно";
		}

		private static bool GameLayer(Collider col)
		{
			if (!Cfg.SkipGameLayers.Value || (Object)(object)col == (Object)null)
			{
				return false;
			}
			string text = LayerMask.LayerToName(((Component)col).gameObject.layer);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			for (int i = 0; i < SkipLayers.Length; i++)
			{
				if (text == SkipLayers[i])
				{
					return true;
				}
			}
			if (text == Cfg.TerrainLayer.Value && !_warnedTerrain)
			{
				_warnedTerrain = true;
				MelonLogger.Msg("[WallClimb] ВНИМАНИЕ: геометрия уровня на слое [{0}], а в SkipGameLayers его нет - скорректируй список слоёв.", new object[1] { text });
			}
			return false;
		}

		private static Vector3 HandPosition(HVRHandGrabber g, out Vector3 alt)
		{
			//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_0014: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00cb: 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)
			alt = Vector3.zero;
			if ((Object)(object)g == (Object)null)
			{
				return Vector3.zero;
			}
			try
			{
				alt = g.HandWorldPosition;
			}
			catch
			{
			}
			if ((Object)(object)_body != (Object)null)
			{
				Rigidbody val = (g.IsLeftHand ? _body.LeftHandRigidBody : _body.RightHandRigidBody);
				if ((Object)(object)val != (Object)null)
				{
					return ((Component)val).transform.position;
				}
			}
			try
			{
				Transform controllerHandTarget = g.ControllerHandTarget;
				if ((Object)(object)controllerHandTarget != (Object)null)
				{
					return controllerHandTarget.position;
				}
			}
			catch
			{
			}
			if (((Vector3)(ref alt)).sqrMagnitude > 0.0001f)
			{
				return alt;
			}
			try
			{
				Vector3 handAnchorWorld = g.HandAnchorWorld;
				if (((Vector3)(ref handAnchorWorld)).sqrMagnitude > 0.0001f)
				{
					return handAnchorWorld;
				}
			}
			catch
			{
			}
			return ((Component)g).transform.position;
		}

		private static string V3(Vector3 v)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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 $"({v.x:F2},{v.y:F2},{v.z:F2})";
		}

		private static bool OwnCollider(Collider col)
		{
			if ((Object)(object)col == (Object)null)
			{
				return true;
			}
			if (OwnIds.Contains(((Object)col).GetInstanceID()))
			{
				return true;
			}
			Transform transform = ((Component)col).transform;
			if ((Object)(object)_own != (Object)null && ((Object)(object)transform == (Object)(object)_own || transform.IsChildOf(_own)))
			{
				return true;
			}
			if ((Object)(object)_root != (Object)null && ((Object)(object)transform == (Object)(object)_root || transform.IsChildOf(_root)))
			{
				return true;
			}
			if (LayerMask.LayerToName(((Component)col).gameObject.layer) == "Hand")
			{
				return true;
			}
			for (int i = 0; i < Grabbers.Count; i++)
			{
				Transform val = (((Object)(object)Grabbers[i] != (Object)null) ? ((Component)Grabbers[i]).transform : null);
				if ((Object)(object)val != (Object)null && ((Object)(object)transform == (Object)(object)val || transform.IsChildOf(val)))
				{
					return true;
				}
			}
			return false;
		}

		private static bool OwnObject(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return true;
			}
			Transform transform = go.transform;
			if ((Object)(object)_own != (Object)null && ((Object)(object)transform == (Object)(object)_own || transform.IsChildOf(_own)))
			{
				return true;
			}
			if ((Object)(object)_root != (Object)null && ((Object)(object)transform == (Object)(object)_root || transform.IsChildOf(_root)))
			{
				return true;
			}
			if (LayerMask.LayerToName(go.layer) == "Hand")
			{
				return true;
			}
			for (int i = 0; i < Grabbers.Count; i++)
			{
				Transform val = (((Object)(object)Grabbers[i] != (Object)null) ? ((Component)Grabbers[i]).transform : null);
				if ((Object)(object)val != (Object)null && ((Object)(object)transform == (Object)(object)val || transform.IsChildOf(val)))
				{
					return true;
				}
			}
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(go.GetComponents<Collider>());
			for (int j = 0; j < array.Length; j++)
			{
				if ((Object)(object)array[j] != (Object)null && OwnIds.Contains(((Object)array[j]).GetInstanceID()))
				{
					return true;
				}
			}
			return false;
		}

		private static void RefreshOwnColliders()
		{
			if ((Object)(object)_root == (Object)null)
			{
				return;
			}
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit(((Component)_root).GetComponentsInChildren<Collider>(true));
			if (array == null)
			{
				return;
			}
			OwnIds.Clear();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					OwnIds.Add(((Object)array[i]).GetInstanceID());
				}
			}
		}

		private static void RememberGrabPoint(HVRHandGrabber g, Vector3 normal, Collider wall)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < Hands.Count; i++)
			{
				if (Hands[i] != null && !((Object)(object)Hands[i].Grabber != (Object)(object)g))
				{
					Vector3 position = ((Component)g).transform.position;
					Vector3 val = ClosestPointOn(wall, position);
					Hands[i].GrabTime = Time.time;
					Hands[i].GrabPoint = val;
					Hands[i].GrabDistance = Vector3.Distance(position, val);
					break;
				}
			}
		}

		private static Vector3 ClosestPointOn(Collider col, Vector3 p)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)col != (Object)null))
			{
				return p;
			}
			return col.ClosestPoint(p);
		}

		private static void StuckWatchdog()
		{
			//IL_00ba: 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)
			if (Held.Count == 0)
			{
				return;
			}
			float num = Mathf.Max(1f, Cfg.MaxHangTime.Value);
			float num2 = Mathf.Max(0.5f, Cfg.StuckReleaseDistance.Value);
			for (int num3 = Held.Count - 1; num3 >= 0; num3--)
			{
				HVRHandGrabber val = Held[num3];
				if ((Object)(object)val == (Object)null || !((HVRGrabberBase)val).IsGrabbing)
				{
					Held.RemoveAt(num3);
				}
				else
				{
					for (int i = 0; i < Hands.Count; i++)
					{
						Hand hand = Hands[i];
						if (hand == null || (Object)(object)hand.Grabber != (Object)(object)val)
						{
							continue;
						}
						float num4 = Time.time - hand.GrabTime;
						float num5 = Vector3.Distance(((Component)val).transform.position, hand.GrabPoint);
						if (num4 > num)
						{
							MelonLogger.Msg("[WallClimb] СТОРОЖ: висеть {0:F0}с, отпускаю принудительно", new object[1] { num4 });
							Held.RemoveAt(num3);
							try
							{
								((HVRGrabberBase)val).ForceRelease();
							}
							catch
							{
							}
							break;
						}
						if (num5 > num2)
						{
							MelonLogger.Msg("[WallClimb] СТОРОЖ: рука ушла на {0:F2}м от точки хвата (в начале было {1:F2}м), отпускаю", new object[2] { num5, hand.GrabDistance });
							Held.RemoveAt(num3);
							try
							{
								((HVRGrabberBase)val).ForceRelease();
							}
							catch
							{
							}
							break;
						}
					}
				}
			}
		}

		private static void ReleaseAll(string reason)
		{
			if (Held.Count == 0)
			{
				return;
			}
			int count = Held.Count;
			for (int i = 0; i < count; i++)
			{
				HVRHandGrabber val = Held[i];
				if (!((Object)(object)val == (Object)null))
				{
					try
					{
						((HVRGrabberBase)val).ForceRelease();
					}
					catch
					{
					}
				}
			}
			Held.Clear();
			MelonLogger.Msg("[WallClimb] ОТПУЩЕНО ({0}): рук={1}", new object[2] { reason, count });
			if (!Cfg.KeepComponent.Value)
			{
				Cleanup();
			}
		}

		private static void WallJump()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007b: 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_00a8: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			ReleaseAll("прыжок");
			if (!((Object)(object)_body == (Object)null))
			{
				Vector3 wallNormal = _wallNormal;
				float num = Cfg.SpeedForApex();
				if (wallNormal.y > 0.5f)
				{
					num = 0f - num;
				}
				Vector3 zero = default(Vector3);
				((Vector3)(ref zero))..ctor(wallNormal.x, 0f, wallNormal.z);
				if (((Vector3)(ref zero)).sqrMagnitude > 1E-06f)
				{
					((Vector3)(ref zero)).Normalize();
				}
				else
				{
					zero = Vector3.zero;
				}
				Vector3 val = (((Object)(object)_body.LocoBall != (Object)null) ? _body.LocoBall.velocity : Vector3.zero);
				float num2 = Mathf.Max(0f, Cfg.WallJumpAway.Value);
				PushVector(new Vector3(zero.x * num2, num - val.y, zero.z * num2));
				MelonLogger.Msg("[WallClimb] ПРЫЖОК ({0}): n=({1:F2},{2:F2},{3:F2}) верт={4:F2}м/с вбок={5:F2}м/с vYвход={6:F2}", new object[7]
				{
					(wallNormal.y > 0.5f) ? "с потолка" : "со стены",
					wallNormal.x,
					wallNormal.y,
					wallNormal.z,
					num,
					num2,
					val.y
				});
			}
		}

		private static void PushVector(Vector3 delta)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Vector3)(ref delta)).sqrMagnitude < 1E-08f))
			{
				Add(_body.Head);
				Add(_body.Pelvis);
				Add(_body.Knee);
				Add(_body.LocoBall);
			}
			void Add(Rigidbody rb)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)rb == (Object)null))
				{
					rb.velocity += delta;
				}
			}
		}

		private static bool SurfaceAllowed(Vector3 normal, float hitY)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0.01f, Cfg.MaxUpness.Value);
			float y = normal.y;
			float num2 = Mathf.Max(0.5f, num);
			if (Mathf.Abs(y) <= num)
			{
				return true;
			}
			if (y < 0f - num2)
			{
				return Cfg.AllowCeiling.Value;
			}
			if (y > num2)
			{
				if (!Cfg.AllowFloor.Value)
				{
					return false;
				}
				float num3 = (((Object)(object)_body != (Object)null && (Object)(object)_body.LocoBall != (Object)null) ? ((Component)_body.LocoBall).transform.position.y : hitY);
				return hitY > num3 + Mathf.Max(0.05f, Cfg.TopSurfaceMinHeight.Value);
			}
			return false;
		}

		private static Collider FindWall(Vector3 hand, out Vector3 normal, out float gap, out string name)
		{
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: 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_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_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: 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_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			normal = Vector3.zero;
			gap = -1f;
			name = "";
			float num = float.MaxValue;
			float num2 = -1f;
			string nearName = "";
			string nearLayer = "";
			Vector3 nearNormal = Vector3.zero;
			Rigidbody nearRb = null;
			Collider val = null;
			float num3 = Mathf.Max(0.1f, Cfg.GrabRadius.Value);
			float num4 = Mathf.Max(0f, Cfg.GrabUpRange.Value);
			float num5 = Mathf.Max(0f, Cfg.GrabDownRange.Value);
			for (int i = 0; i < ProbeDirs.Length; i++)
			{
				Vector3 val2 = ProbeDirs[i];
				float num6 = ((val2.y > 0.5f) ? num4 : ((val2.y < -0.5f) ? num5 : num3));
				if (num6 <= 0.01f)
				{
					continue;
				}
				num6 = Mathf.Min(num6, Mathf.Max(0.15f, Cfg.GrabMaxDistance.Value));
				if (num6 <= 0.01f)
				{
					continue;
				}
				Vector3 val3 = hand + val2 * 0.03f;
				float num7 = num6;
				RaycastHit[] array = Il2CppArrayBase<RaycastHit>.op_Implicit((Il2CppArrayBase<RaycastHit>)(object)Physics.RaycastAll(hand - val2 * 0.08f, val2, 0.14f, -1, (QueryTriggerInteraction)1));
				for (int j = 0; j < array.Length; j++)
				{
					RaycastHit val4 = array[j];
					Collider collider = ((RaycastHit)(ref val4)).collider;
					if (((RaycastHit)(ref val4)).distance >= 0.06f && ((RaycastHit)(ref val4)).distance <= 0.14f && !((Object)(object)collider == (Object)null) && !OwnCollider(collider) && !GameLayer(collider) && Passes(collider, ((RaycastHit)(ref val4)).normal) && SurfaceAllowed(((RaycastHit)(ref val4)).normal, ((RaycastHit)(ref val4)).point.y) && !(((RaycastHit)(ref val4)).distance >= num))
					{
						num = ((RaycastHit)(ref val4)).distance;
						val = collider;
						normal = ((RaycastHit)(ref val4)).normal;
						name = ((Object)((Component)collider).gameObject).name;
					}
				}
				for (int k = 0; k < 6; k++)
				{
					if (!(num7 > 0.01f))
					{
						break;
					}
					RaycastHit val5 = default(RaycastHit);
					if (!Physics.Raycast(val3, val2, ref val5, num7, -1, (QueryTriggerInteraction)1))
					{
						break;
					}
					Collider collider2 = ((RaycastHit)(ref val5)).collider;
					if ((Object)(object)collider2 == (Object)null)
					{
						break;
					}
					bool num8 = OwnCollider(collider2);
					val3 = ((RaycastHit)(ref val5)).point + val2 * 0.02f;
					num7 -= ((RaycastHit)(ref val5)).distance + 0.02f;
					if (num8 || GameLayer(collider2))
					{
						continue;
					}
					if (num2 < 0f)
					{
						num2 = ((RaycastHit)(ref val5)).distance;
						nearName = ((Object)((Component)collider2).gameObject).name;
						nearNormal = ((RaycastHit)(ref val5)).normal;
						nearLayer = LayerMask.LayerToName(((Component)collider2).gameObject.layer);
						nearRb = collider2.attachedRigidbody;
					}
					if (Passes(collider2, ((RaycastHit)(ref val5)).normal) && SurfaceAllowed(((RaycastHit)(ref val5)).normal, ((RaycastHit)(ref val5)).point.y))
					{
						if (((RaycastHit)(ref val5)).distance < num)
						{
							num = ((RaycastHit)(ref val5)).distance;
							val = collider2;
							normal = ((RaycastHit)(ref val5)).normal;
							name = ((Object)((Component)collider2).gameObject).name;
						}
						break;
					}
				}
			}
			_nearDist = num2;
			_nearName = nearName;
			_nearNormal = nearNormal;
			_nearLayer = nearLayer;
			_nearRb = nearRb;
			if ((Object)(object)val == (Object)null)
			{
				val = FindInsideShell(hand, out var normal2, out var gap2, out var name2, num3);
				if ((Object)(object)val != (Object)null)
				{
					normal = normal2;
					gap = gap2;
					name = name2;
				}
			}
			else
			{
				gap = num;
			}
			return val;
		}

		private static Collider FindInsideShell(Vector3 hand, out Vector3 normal, out float gap, out string name, float radius)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0090: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			normal = Vector3.zero;
			gap = -1f;
			name = "";
			Collider[] array = Il2CppArrayBase<Collider>.op_Implicit((Il2CppArrayBase<Collider>)(object)Physics.OverlapSphere(hand, radius, -1, (QueryTriggerInteraction)1));
			if (array == null)
			{
				return null;
			}
			Collider val = null;
			float num = float.MaxValue;
			RaycastHit val4 = default(RaycastHit);
			foreach (Collider val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || OwnCollider(val2) || GameLayer(val2) || !Passes(val2, Vector3.up))
				{
					continue;
				}
				for (int j = 0; j < ProbeDirs.Length; j++)
				{
					Vector3 val3 = ProbeDirs[j];
					if (val2.Raycast(new Ray(hand, val3), ref val4, radius) && !(((RaycastHit)(ref val4)).distance < 0.02f) && SurfaceAllowed(((RaycastHit)(ref val4)).normal, ((RaycastHit)(ref val4)).point.y) && !(((RaycastHit)(ref val4)).distance >= num))
					{
						num = ((RaycastHit)(ref val4)).distance;
						val = val2;
						normal = ((RaycastHit)(ref val4)).normal;
						gap = ((RaycastHit)(ref val4)).distance;
						name = ((Object)((Component)val2).gameObject).name;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				gap = num;
			}
			return val;
		}

		private static string NearInfo()
		{
			if (_nearDist < 0f)
			{
				return "лучи вообще ничего не нашли рядом с рукой";
			}
			return "ближайшая поверхность [" + _nearName + "] d=" + _nearDist.ToString("F2") + " слой=" + _nearLayer + " n=(" + _nearNormal.x.ToString("F2") + "," + _nearNormal.y.ToString("F2") + "," + _nearNormal.z.ToString("F2") + ")" + (((Object)(object)_nearRb != (Object)null) ? (" rb=" + (_nearRb.isKinematic ? "кинематическое" : "ДИНАМИЧЕСКОЕ")) : " rb=нет") + "; причины отказа: " + SkipSummary();
		}

		private static bool IsForeign(Collider col)
		{
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			string value = Cfg.ForeignPrefixes.Value;
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			Transform val = ((Component)col).transform;
			int num = 0;
			while ((Object)(object)val != (Object)null && num++ < 12)
			{
				string name = ((Object)val).name;
				if (!string.IsNullOrEmpty(name))
				{
					string[] array = value.Split(',');
					for (int i = 0; i < array.Length; i++)
					{
						string text = array[i].Trim();
						if (text.Length != 0 && name.StartsWith(text, StringComparison.OrdinalIgnoreCase))
						{
							return true;
						}
					}
				}
				val = val.parent;
			}
			return false;
		}

		private static bool Passes(Collider col, Vector3 normal)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			if (OwnIds.Contains(((Object)col).GetInstanceID()))
			{
				return false;
			}
			Transform transform = ((Component)col).transform;
			if ((Object)(object)_own != (Object)null && ((Object)(object)transform == (Object)(object)_own || transform.IsChildOf(_own)))
			{
				return false;
			}
			if ((Object)(object)_root != (Object)null && ((Object)(object)transform == (Object)(object)_root || transform.IsChildOf(_root)))
			{
				return false;
			}
			if (BodyParts.Contains(((Object)((Component)col).gameObject).name))
			{
				return false;
			}
			if (Cfg.SkipForeignWeapons.Value && IsForeign(col))
			{
				NoteSkip("чужое оружие", col);
				return false;
			}
			if (Cfg.RequireStatic.Value && (Object)(object)col.attachedRigidbody != (Object)null)
			{
				NoteSkip("есть Rigidbody", col);
				return false;
			}
			if (!Cfg.AllowDynamicBodies.Value)
			{
				Rigidbody attachedRigidbody = col.attachedRigidbody;
				if ((Object)(object)attachedRigidbody != (Object)null && !attachedRigidbody.isKinematic)
				{
					NoteSkip("подвижный проп", col);
					return false;
				}
			}
			if (!Cfg.StrictFilters.Value)
			{
				return true;
			}
			Bounds bounds = col.bounds;
			float num = Mathf.Max(0.01f, Cfg.MaxUpness.Value);
			if (Mathf.Abs(normal.y) > num)
			{
				if (Mathf.Max(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.z) < Mathf.Max(0.1f, Cfg.CeilingMinSpan.Value))
				{
					NoteSkip("потолок узкий", col);
					return false;
				}
				if (((Bounds)(ref bounds)).size.y < 0.05f)
				{
					NoteSkip("потолок без толщины", col);
					return false;
				}
				return true;
			}
			if (Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)) < Mathf.Max(0.05f, Cfg.MinWallSize.Value))
			{
				NoteSkip("мелкий", col);
				return false;
			}
			if (((Bounds)(ref bounds)).size.y < Mathf.Max(0.05f, Cfg.MinWallHeight.Value))
			{
				NoteSkip("низкий", col);
				return false;
			}
			return true;
		}

		private static void NoteSkip(string reason, Collider col)
		{
			Skips.TryGetValue(reason, out var value);
			Skips[reason] = value + 1;
			if (!SkipSamples.ContainsKey(reason) && (Object)(object)col != (Object)null)
			{
				SkipSamples[reason] = ((Object)((Component)col).gameObject).name;
			}
		}

		private static string SkipSummary()
		{
			if (Skips.Count == 0)
			{
				return "причин отказа не зафиксировано";
			}
			string text = "";
			foreach (KeyValuePair<string, int> skip in Skips)
			{
				if (text.Length > 0)
				{
					text += "; ";
				}
				text = text + skip.Key + "=" + skip.Value;
				if (SkipSamples.ContainsKey(skip.Key))
				{
					text = text + " (например " + SkipSamples[skip.Key] + ")";
				}
			}
			return text;
		}

		private static void ResetSkips()
		{
			Skips.Clear();
			SkipSamples.Clear();
		}

		private static void DumpExistingGrabbables()
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			HVRGrabbable[] array = Il2CppArrayBase<HVRGrabbable>.op_Implicit(Object.FindObjectsOfType<HVRGrabbable>(true));
			HVRClimbable[] array2 = Il2CppArrayBase<HVRClimbable>.op_Implicit(Object.FindObjectsOfType<HVRClimbable>(true));
			MelonLogger.Msg("[WallClimb] РАЗВЕДКА: в сцене HVRGrabbable={0}, HVRClimbable={1}", new object[2]
			{
				(array != null) ? array.Length : 0,
				(array2 != null) ? array2.Length : 0
			});
			if (array == null)
			{
				return;
			}
			int num = Mathf.Min(array.Length, 8);
			for (int i = 0; i < num; i++)
			{
				HVRGrabbable val = array[i];
				if (!((Object)(object)val == (Object)null))
				{
					Rigidbody val2 = (((Object)(object)val.Rigidbody != (Object)null) ? val.Rigidbody : ((Component)val).GetComponent<Rigidbody>());
					MelonLogger.Msg("[WallClimb]  образец[{0}] {1}: stationary={2} rb={3} слой={4} трекинг={5} хват={6} кнопка={7} индикатор={8}", new object[9]
					{
						i,
						((Object)val).name,
						val.Stationary,
						(Object)(object)val2 != (Object)null,
						LayerMask.LayerToName(((Component)val).gameObject.layer),
						val.TrackingType,
						val.HoldType,
						val.GrabControl,
						val.ShowGrabIndicator
					});
					MelonLogger.Msg("[WallClimb]      ближайшаяТочка={0} зазор={1} рвётсяНа={2:F2} joint1={3} joint2={4}", new object[5]
					{
						val.UseColliderClosestPoint,
						val.RequireOverlapClearance,
						val.BreakDistance,
						((Object)(object)val.OneHandJointSettings != (Object)null) ? "есть" : "НЕТ",
						((Object)(object)val.TwoHandJointSettings != (Object)null) ? "есть" : "НЕТ"
					});
				}
			}
		}

		private static bool EnsureBody()
		{
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_body != (Object)null)
			{
				return true;
			}
			HexaBodyPlayer4[] array = Il2CppArrayBase<HexaBodyPlayer4>.op_Implicit(Object.FindObjectsOfType<HexaBodyPlayer4>(false));
			foreach (HexaBodyPlayer4 val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.LocoBall == (Object)null)
				{
					continue;
				}
				_body = val;
				OwnIds.Clear();
				_own = ((Component)val).transform;
				_root = (((Object)(object)_own != (Object)null) ? _own.root : null);
				if ((Object)(object)_root != (Object)null)
				{
					Collider[] array2 = Il2CppArrayBase<Collider>.op_Implicit(((Component)_root).GetComponentsInChildren<Collider>(true));
					if (array2 != null)
					{
						for (int j = 0; j < array2.Length; j++)
						{
							if ((Object)(object)array2[j] != (Object)null)
							{
								OwnIds.Add(((Object)array2[j]).GetInstanceID());
							}
						}
					}
				}
				Grabbers.Clear();
				Transform root = ((Component)val).transform.root;
				if ((Object)(object)root != (Object)null)
				{
					HVRHandGrabber[] array3 = Il2CppArrayBase<HVRHandGrabber>.op_Implicit(((Component)root).GetComponentsInChildren<HVRHandGrabber>(true));
					if (array3 != null)
					{
						Grabbers.AddRange(array3);
					}
				}
				if (Grabbers.Count == 0)
				{
					HVRHandGrabber[] array4 = Il2CppArrayBase<HVRHandGrabber>.op_Implicit(Object.FindObjectsOfType<HVRHandGrabber>(false));
					if (array4 != null)
					{
						Grabbers.AddRange(array4);
					}
				}
				MelonLogger.Msg("[WallClimb] найден игрок: {0}; своих коллайдеров={1}; {2}", new object[3]
				{
					((Object)val).name,
					OwnIds.Count,
					GrabberNames()
				});
				Ctls.Clear();
				if ((Object)(object)root != (Object)null)
				{
					HVRController[] array5 = Il2CppArrayBase<HVRController>.op_Implicit(((Component)root).GetComponentsInChildren<HVRController>(true));
					if (array5 != null)
					{
						Ctls.AddRange(array5);
					}
				}
				if (Ctls.Count == 0)
				{
					HVRController[] array6 = Il2CppArrayBase<HVRController>.op_Implicit(Object.FindObjectsOfType<HVRController>(false));
					if (array6 != null)
					{
						Ctls.AddRange(array6);
					}
				}
				MelonLogger.Msg("[WallClimb] контроллеров для кнопок: {0}", new object[1] { Ctls.Count });
				if (Ctls.Count == 0)
				{
					MelonLogger.Msg("[WallClimb] ВНИМАНИЕ: HVRController не найдены, кнопку захвата не прочитать.");
				}
				if (Grabbers.Count == 0)
				{
					MelonLogger.Msg("[WallClimb] ВНИМАНИЕ: HVRHandGrabber не найдены, хватать нечем.");
				}
				Hands.Clear();
				for (int k = 0; k < Grabbers.Count; k++)
				{
					HVRHandGrabber val2 = Grabbers[k];
					if (!((Object)(object)val2 == (Object)null))
					{
						Hands.Add(new Hand
						{
							Grabber = val2,
							Side = (HVRHandSide)(!val2.IsLeftHand),
							WasDown = false
						});
						MelonLogger.Msg("[WallClimb]  рука[{0}] граббер={1} сторона={2}", new object[3]
						{
							k,
							val2.IsLeftHand ? "левая" : "правая",
							(object)(HVRHandSide)(!val2.IsLeftHand)
						});
					}
				}
				MelonLogger.Msg("[WallClimb] кнопки: Л.Grip={0} П.Grip={1} Л.Trigger={2} П.Trigger={3}", new object[4]
				{
					HVRController.GetButtonState((HVRHandSide)0, (HVRButtons)0).Active,
					HVRController.GetButtonState((HVRHandSide)1, (HVRButtons)0).Active,
					HVRController.GetButtonState((HVRHandSide)0, (HVRButtons)1).Active,
					HVRController.GetButtonState((HVRHandSide)1, (HVRButtons)1).Active
				});
				DumpExistingGrabbables();
				return true;
			}
			if (!_found)
			{
				_found = true;
				MelonLogger.Msg("[WallClimb] ждём появления игрока в сцене...");
			}
			return false;
		}

		static WallClimbMod()
		{
			//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)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: 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_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] obj = new Vector3[10]
			{
				Vector3.forward,
				Vector3.back,
				Vector3.left,
				Vector3.right,
				Vector3.up,
				Vector3.down,
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3)
			};
			Vector3 val = new Vector3(1f, 1f, 0f);
			obj[6] = ((Vector3)(ref val)).normalized;
			val = new Vector3(-1f, 1f, 0f);
			obj[7] = ((Vector3)(ref val)).normalized;
			val = new Vector3(1f, -1f, 0f);
			obj[8] = ((Vector3)(ref val)).normalized;
			val = new Vector3(-1f, -1f, 0f);
			obj[9] = ((Vector3)(ref val)).normalized;
			ProbeDirs = (Vector3[])(object)obj;
			Touched = new List<GameObject>();
			Hands = new List<Hand>();
			Held = new List<HVRHandGrabber>();
			Ctls = new List<HVRController>();
			_registerAt = -99f;
			AutoMarkHeights = new float[3] { 0f, 0.9f, 1.8f };
			Vector3[] obj2 = new Vector3[8]
			{
				Vector3.forward,
				Vector3.back,
				Vector3.left,
				Vector3.right,
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3)
			};
			val = new Vector3(1f, 0f, 1f);
			obj2[4] = ((Vector3)(ref val)).normalized;
			val = new Vector3(-1f, 0f, 1f);
			obj2[5] = ((Vector3)(ref val)).normalized;
			val = new Vector3(1f, 0f, -1f);
			obj2[6] = ((Vector3)(ref val)).normalized;
			val = new Vector3(-1f, 0f, -1f);
			obj2[7] = ((Vector3)(ref val)).normalized;
			AutoMarkDirs = (Vector3[])(object)obj2;
			Marked = new HashSet<int>();
			SkipLayers = new string[9] { "Player", "PlayerBody", "PlayerHead", "Hand", "Hands", "Cosmetic", "Menu", "UI", "Trigger" };
			_nearDist = -1f;
			_nearName = "";
			_nearLayer = "";
			Skips = new Dictionary<string, int>();
			SkipSamples = new Dictionary<string, string>();
		}
	}
}