Decompiled source of EdgeVision v1.0.1

EdgeVision/EdgeVision.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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComputerysModdingUtilities;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: StraftatMod(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EdgeVision
{
	[BepInPlugin("landa.straftat.edgevision", "Edge Vision", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal const string Guid = "landa.straftat.edgevision";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Active;

		internal static ConfigEntry<KeyCode> ToggleKey;

		internal static ConfigEntry<bool> TrainingGroundOnly;

		internal static ConfigEntry<bool> DebugLog;

		internal static ConfigEntry<bool> ShowClimbCorner;

		internal static ConfigEntry<float> ClimbAngleMin;

		internal static ConfigEntry<float> ClimbAngleMax;

		internal static ConfigEntry<float> ClimbEdgeSlopeMin;

		internal static ConfigEntry<bool> ClimbRampCheck;

		internal static ConfigEntry<float> CornerSearch;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<int> Yaws;

		internal static ConfigEntry<float> ProbeHz;

		internal static ConfigEntry<float> PatchSize;

		internal static ConfigEntry<float> OriginDrop;

		internal static ConfigEntry<bool> XRay;

		internal static ConfigEntry<float> Alpha;

		internal static ConfigEntry<float> HiddenAlphaBoost;

		internal static ConfigEntry<Color> ClimbColor;

		private void Awake()
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Expected O, but got Unknown
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Expected O, but got Unknown
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Expected O, but got Unknown
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Expected O, but got Unknown
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Active = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.General", "Active", true, "Master switch. Also toggleable in-game with ToggleKey.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("EdgeVision.General", "ToggleKey", (KeyCode)290, "Hotkey to toggle the overlay.");
			TrainingGroundOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.General", "TrainingGroundOnly", false, "If ON, the overlay only shows in the Training Ground. OFF shows it everywhere (read-only, so no matchmaking impact, but it's a mild aid in live matches).");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.General", "DebugLog", false, "Log a probe summary to the BepInEx console (rays/hits/patches) - leave on while tuning.");
			ShowClimbCorner = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.Surfaces", "ShowClimbCorner", true, "Mark CLIMBABLE WALL CORNERS: the convex vertical edge of a TALL, near-vertical wall (~80-91 deg). On a flat tall wall the vault's head-clearance rays hit and block it, but at a convex corner they miss past the edge so the vault fires - and on a near-vertical corner you stay pinned to the edge and re-trigger it, so you can repeat it (look down + hold forward) to climb the whole structure. These are not obvious by eye, which is the point.");
			ClimbAngleMin = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Surfaces", "ClimbAngleMin", 80f, new ConfigDescription("Lower face-angle bound to even CONSIDER a corner for the climb test (deg from up). 80 = the game's vault minimum. Just a cheap pre-filter - the chained-vault simulation does the real work.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(70f, 90f), Array.Empty<object>()));
			ClimbAngleMax = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Surfaces", "ClimbAngleMax", 91f, new ConfigDescription("Upper face-angle bound (deg from up) - just a loose wall-band pre-filter so floors/ramps don't qualify; the edge-lean does the real work. Allows up to 91 so the vertical-reading FACE of a sloped corner still marks (the two faces share one leaning edge, so both are climbable even if one face's local normal reads ~90).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(80f, 110f), Array.Empty<object>()));
			ClimbEdgeSlopeMin = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Surfaces", "ClimbEdgeSlopeMin", 0.1f, new ConfigDescription("How far the convex EDGE must lean horizontally per metre of height to count as climbable. The climb works because a SLOPED (non-vertical) edge leans out of the vault's head-clearance rays as you rise, so it re-fires up the edge. A smooth vertical corner has a vertical edge (lean ~0) and can't be climbed; a leaning edge (~0.15+/m measured on real climb corners) can. Lower = mark subtler leans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.03f, 1f), Array.Empty<object>()));
			ClimbRampCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.Surfaces", "ClimbRampCheck", true, "Reject a leaning corner if walkable GROUND (a ramp or floor) sits close beside it up the climb zone. The wall-jump/vault that powers the climb both require you to be AIRBORNE (the game needs !isGrounded && !downRay); ground hugging the corner keeps you grounded, so the double jump never arms and the corner doesn't climb despite a perfect-looking edge. Turn OFF if it dims real corners.");
			Range = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Probe", "Range", 12f, new ConfigDescription("How far around you to probe, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 25f), Array.Empty<object>()));
			OriginDrop = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Probe", "OriginDrop", 0.9f, new ConfigDescription("How far below the camera to cast from, in metres. ~0.9 puts the rays at chest height so they strike vaultable ledge faces instead of passing over them.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.8f), Array.Empty<object>()));
			Yaws = ((BaseUnityPlugin)this).Config.Bind<int>("EdgeVision.Probe", "Directions", 72, new ConfigDescription("Number of horizontal probe directions (higher = denser coverage, more cost).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 180), Array.Empty<object>()));
			ProbeHz = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Probe", "RefreshHz", 12f, new ConfigDescription("How many times per second the overlay re-probes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			PatchSize = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Probe", "PatchSize", 0.6f, new ConfigDescription("Size of each marker patch, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f), Array.Empty<object>()));
			CornerSearch = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Probe", "CornerSearch", 1.2f, new ConfigDescription("How far sideways to look for a wall's convex (climbable) edge, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 3f), Array.Empty<object>()));
			XRay = ((BaseUnityPlugin)this).Config.Bind<bool>("EdgeVision.Display", "XRay", false, "Draw the overlay through walls (helps spot hidden walls behind other geometry).");
			Alpha = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Display", "Alpha", 0.5f, new ConfigDescription("Overlay transparency.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			HiddenAlphaBoost = ((BaseUnityPlugin)this).Config.Bind<float>("EdgeVision.Display", "HiddenAlphaBoost", 1.5f, new ConfigDescription("Alpha multiplier for hidden walls so they stand out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()));
			ClimbColor = ((BaseUnityPlugin)this).Config.Bind<Color>("EdgeVision.Display", "ClimbCornerColor", new Color(0.75f, 0.2f, 1f), "Climbable wall-corner colour (the convex edge you can repeat-vault up).");
			GameObject val = new GameObject("EdgeVision");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<EdgeProbe>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Edge Vision loaded (raycast probe).");
		}
	}
	internal class EdgeProbe : MonoBehaviour
	{
		private enum Cat
		{
			None,
			Vault,
			WallJump,
			Climb
		}

		private const float VaultMin = 80f;

		private const float VaultMax = 130f;

		private const float WjMin = 88f;

		private const float WjMax = 100f;

		private const float Offset = 0.03f;

		private Material _mat;

		private GameObject _overlay;

		private Mesh _mesh;

		private bool _lastXRay;

		private float _nextProbe;

		private float _nextLog;

		private float _nextCross;

		private int _dRays;

		private int _dHits;

		private int _dWall;

		private int _dVault;

		private int _dClimb;

		private int _dSkipVert;

		private Type _smType;

		private FieldInfo _smInstance;

		private FieldInfo _smTestMap;

		private Type _weaponType;

		private Type _itemType;

		private Type _fpcType;

		private Type _phType;

		private Type _spawnerType;

		private readonly List<Vector3> _verts = new List<Vector3>();

		private readonly List<Color> _colors = new List<Color>();

		private readonly List<int> _tris = new List<int>();

		private readonly HashSet<long> _cells = new HashSet<long>();

		private readonly RaycastHit[] _hitBuf = (RaycastHit[])(object)new RaycastHit[24];

		private bool _errLogged;

		private static readonly float[] EdgeSampleHeights = new float[5] { 0f, 0.4f, 0.8f, 1.2f, 1.6f };

		private readonly List<float> _slopeBuf = new List<float>();

		private void Awake()
		{
			BuildMaterial();
			EnsureOverlay();
			_smType = Type.GetType("SceneMotor, Assembly-CSharp");
			_smInstance = _smType?.GetField("Instance", BindingFlags.Static | BindingFlags.Public);
			_smTestMap = _smType?.GetField("testMap");
			_weaponType = Type.GetType("Weapon, Assembly-CSharp");
			_itemType = Type.GetType("ItemBehaviour, Assembly-CSharp");
			_fpcType = Type.GetType("FirstPersonController, Assembly-CSharp");
			_phType = Type.GetType("PlayerHealth, Assembly-CSharp");
			_spawnerType = Type.GetType("Spawner, Assembly-CSharp");
			Plugin.Log.LogInfo((object)"Edge probe alive.");
		}

		private void EnsureOverlay()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//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_0066: Expected O, but got Unknown
			if ((Object)(object)_mat == (Object)null)
			{
				BuildMaterial();
			}
			if ((Object)(object)_mesh == (Object)null)
			{
				_mesh = new Mesh
				{
					indexFormat = (IndexFormat)1
				};
				_mesh.MarkDynamic();
			}
			if (!((Object)(object)_overlay != (Object)null))
			{
				_overlay = new GameObject("EdgeVision_Overlay")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)_overlay);
				_overlay.AddComponent<MeshFilter>().sharedMesh = _mesh;
				MeshRenderer obj = _overlay.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = _mat;
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
				((Renderer)obj).lightProbeUsage = (LightProbeUsage)0;
				((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0;
				_overlay.SetActive(false);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_mesh != (Object)null)
			{
				Object.Destroy((Object)(object)_mesh);
			}
			if ((Object)(object)_mat != (Object)null)
			{
				Object.Destroy((Object)(object)_mat);
			}
			if ((Object)(object)_overlay != (Object)null)
			{
				Object.Destroy((Object)(object)_overlay);
			}
		}

		private void BuildMaterial()
		{
			//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_002d: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Sprites/Default");
			_mat = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			if (_mat.HasProperty("_Color"))
			{
				_mat.SetColor("_Color", Color.white);
			}
			if (_mat.HasProperty("_SrcBlend"))
			{
				_mat.SetInt("_SrcBlend", 5);
			}
			if (_mat.HasProperty("_DstBlend"))
			{
				_mat.SetInt("_DstBlend", 10);
			}
			if (_mat.HasProperty("_ZWrite"))
			{
				_mat.SetInt("_ZWrite", 0);
			}
			if (_mat.HasProperty("_Cull"))
			{
				_mat.SetInt("_Cull", 0);
			}
			ApplyZTest();
			_mat.renderQueue = 3000;
		}

		private void ApplyZTest()
		{
			_lastXRay = Plugin.XRay.Value;
			if (_mat.HasProperty("_ZTest"))
			{
				_mat.SetInt("_ZTest", _lastXRay ? 8 : 4);
			}
		}

		private void Update()
		{
			try
			{
				UpdateBody();
			}
			catch (Exception ex)
			{
				if (!_errLogged)
				{
					_errLogged = true;
					Plugin.Log.LogError((object)("EdgeVision Update exception (suppressing further occurrences): " + ex));
				}
			}
		}

		private void UpdateBody()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			EnsureOverlay();
			if (Input.GetKeyDown(Plugin.ToggleKey.Value))
			{
				Plugin.Active.Value = !Plugin.Active.Value;
			}
			if (Plugin.XRay.Value != _lastXRay)
			{
				ApplyZTest();
			}
			bool value = Plugin.Active.Value;
			bool flag = InGame();
			bool flag2 = !Plugin.TrainingGroundOnly.Value || IsTrainingGround();
			if (!(value && flag && flag2))
			{
				if (_overlay.activeSelf)
				{
					_overlay.SetActive(false);
				}
				if (Plugin.DebugLog.Value && Time.unscaledTime >= _nextLog)
				{
					_nextLog = Time.unscaledTime + 2f;
					Plugin.Log.LogInfo((object)$"EdgeVision idle: active={value} inGame={flag} trainingGate={flag2}");
				}
			}
			else
			{
				if (!_overlay.activeSelf)
				{
					_overlay.SetActive(true);
				}
				if (!(Time.unscaledTime < _nextProbe))
				{
					_nextProbe = Time.unscaledTime + 1f / Mathf.Max(2f, Plugin.ProbeHz.Value);
					Probe();
				}
			}
		}

		private void LogCrosshair(Camera cam)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00b1: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)cam).transform.position;
			Vector3 forward = ((Component)cam).transform.forward;
			int num = Physics.RaycastNonAlloc(position, forward, _hitBuf, Plugin.Range.Value, -1, (QueryTriggerInteraction)1);
			float num2 = float.MaxValue;
			int num3 = -1;
			for (int i = 0; i < num; i++)
			{
				if (!IsExcluded(((RaycastHit)(ref _hitBuf[i])).collider) && ((RaycastHit)(ref _hitBuf[i])).distance < num2)
				{
					num2 = ((RaycastHit)(ref _hitBuf[i])).distance;
					num3 = i;
				}
			}
			if (num3 < 0)
			{
				Plugin.Log.LogInfo((object)"EdgeVision crosshair: (nothing in range)");
				return;
			}
			RaycastHit val = _hitBuf[num3];
			float num4 = Vector3.Angle(((RaycastHit)(ref val)).normal, Vector3.up);
			int layer = ((Component)((RaycastHit)(ref val)).collider).gameObject.layer;
			bool flag = !HasVisibleMesh(((RaycastHit)(ref val)).collider);
			bool flag2 = false;
			bool flag3 = false;
			float num5 = 0f;
			Vector3 ch = default(Vector3);
			((Vector3)(ref ch))..ctor(((RaycastHit)(ref val)).normal.x, 0f, ((RaycastHit)(ref val)).normal.z);
			if (((Vector3)(ref ch)).sqrMagnitude >= 0.0001f)
			{
				((Vector3)(ref ch)).Normalize();
				flag2 = FindEdgeAtHeight(((RaycastHit)(ref val)).point, ch, ((RaycastHit)(ref val)).point.y, out var edge);
				num5 = EdgeLean(((RaycastHit)(ref val)).point, ch, out var edge2, out edge);
				flag3 = GroundNearCorner(edge2, ((RaycastHit)(ref val)).point, ch);
			}
			Plugin.Log.LogInfo((object)($"EdgeVision crosshair: angle={num4:F1} layer={layer} hidden={flag} " + $"edge={flag2} edgeLean={num5:F2} groundNear={flag3} " + $"climbBand={num4 >= Plugin.ClimbAngleMin.Value && num4 <= Plugin.ClimbAngleMax.Value} dist={num2:F1}"));
		}

		private bool InGame()
		{
			if (_fpcType == null)
			{
				return true;
			}
			return Object.FindObjectOfType(_fpcType) != (Object)null;
		}

		private void Probe()
		{
			//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_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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			Camera val = Camera.main;
			if ((Object)(object)val == (Object)null)
			{
				val = Object.FindObjectOfType<Camera>();
			}
			if ((Object)(object)val == (Object)null)
			{
				if (Plugin.DebugLog.Value && Time.unscaledTime >= _nextLog)
				{
					_nextLog = Time.unscaledTime + 2f;
					Plugin.Log.LogInfo((object)"EdgeVision probe: no camera found.");
				}
				return;
			}
			Vector3 val2 = ((Component)val).transform.position - Vector3.up * Plugin.OriginDrop.Value;
			if (Plugin.DebugLog.Value && Time.unscaledTime >= _nextCross)
			{
				_nextCross = Time.unscaledTime + 0.35f;
				LogCrosshair(val);
			}
			_verts.Clear();
			_colors.Clear();
			_tris.Clear();
			_cells.Clear();
			_dRays = (_dHits = (_dWall = (_dVault = (_dClimb = (_dSkipVert = 0)))));
			int value = Plugin.Yaws.Value;
			float value2 = Plugin.Range.Value;
			float[] array = new float[8] { 42f, 28f, 16f, 6f, -4f, -16f, -30f, -45f };
			for (int i = 0; i < value; i++)
			{
				float num = (float)i / (float)value * 360f;
				for (int j = 0; j < array.Length; j++)
				{
					Vector3 val3 = Quaternion.Euler(0f - array[j], num, 0f) * Vector3.forward;
					_dRays++;
					int num2 = Physics.RaycastNonAlloc(val2, val3, _hitBuf, value2, -1, (QueryTriggerInteraction)1);
					float num3 = float.MaxValue;
					int num4 = -1;
					for (int k = 0; k < num2; k++)
					{
						if (!IsExcluded(((RaycastHit)(ref _hitBuf[k])).collider) && ((RaycastHit)(ref _hitBuf[k])).distance < num3)
						{
							num3 = ((RaycastHit)(ref _hitBuf[k])).distance;
							num4 = k;
						}
					}
					if (num4 >= 0)
					{
						HandleHit(_hitBuf[num4]);
					}
				}
			}
			_mesh.Clear();
			if (_verts.Count > 0)
			{
				_mesh.SetVertices(_verts);
				_mesh.SetColors(_colors);
				_mesh.SetTriangles(_tris, 0);
				_mesh.RecalculateBounds();
			}
			if (Plugin.DebugLog.Value && Time.unscaledTime >= _nextLog)
			{
				_nextLog = Time.unscaledTime + 2f;
				Plugin.Log.LogInfo((object)($"EdgeVision probe: rays={_dRays} hits={_dHits} wall={_dWall} " + $"vaultLips={_dVault} climbCorners={_dClimb} skipVert={_dSkipVert} " + $"patches={_verts.Count / 4} @ {val2}"));
			}
		}

		private void HandleHit(RaycastHit hit)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_0102: 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_00ef: 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_00f8: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Collider collider = ((RaycastHit)(ref hit)).collider;
			if ((Object)(object)collider == (Object)null)
			{
				return;
			}
			bool flag = !HasVisibleMesh(collider);
			_dHits++;
			Vector3 normal = ((RaycastHit)(ref hit)).normal;
			float num = Vector3.Angle(normal, Vector3.up);
			float a = Mathf.Clamp01(Plugin.Alpha.Value * (flag ? Plugin.HiddenAlphaBoost.Value : 1f));
			if (!Plugin.ShowClimbCorner.Value || !(num >= Plugin.ClimbAngleMin.Value) || !(num <= Plugin.ClimbAngleMax.Value))
			{
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(normal.x, 0f, normal.z);
			if (((Vector3)(ref val)).sqrMagnitude >= 0.0001f)
			{
				((Vector3)(ref val)).Normalize();
				if (EdgeLean(((RaycastHit)(ref hit)).point, val, out var edge, out var _) >= Plugin.ClimbEdgeSlopeMin.Value && (!Plugin.ClimbRampCheck.Value || !GroundNearCorner(edge, ((RaycastHit)(ref hit)).point, val)) && DedupDir(edge, Cat.Climb, val))
				{
					Color value = Plugin.ClimbColor.Value;
					value.a = a;
					AddPatch(edge, normal, value);
					_dClimb++;
				}
			}
		}

		private bool IsExcluded(Collider col)
		{
			if ((Object)(object)col == (Object)null)
			{
				return true;
			}
			if (col is CharacterController)
			{
				return true;
			}
			if ((Object)(object)col.attachedRigidbody != (Object)null)
			{
				return true;
			}
			if (_fpcType != null && (Object)(object)((Component)col).GetComponentInParent(_fpcType) != (Object)null)
			{
				return true;
			}
			if (_phType != null && (Object)(object)((Component)col).GetComponentInParent(_phType) != (Object)null)
			{
				return true;
			}
			if (_spawnerType != null && (Object)(object)((Component)col).GetComponentInParent(_spawnerType) != (Object)null)
			{
				return true;
			}
			if (IsWeaponOrItem(col))
			{
				return true;
			}
			return false;
		}

		private bool IsWeaponOrItem(Collider col)
		{
			if (_weaponType != null && (Object)(object)((Component)col).GetComponentInParent(_weaponType) != (Object)null)
			{
				return true;
			}
			if (_itemType != null && (Object)(object)((Component)col).GetComponentInParent(_itemType) != (Object)null)
			{
				return true;
			}
			return false;
		}

		private bool GroundNearCorner(Vector3 edge, Vector3 hit, Vector3 ch)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(edge.x - hit.x, 0f, edge.z - hit.z);
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				return false;
			}
			((Vector3)(ref val)).Normalize();
			RaycastHit val2 = default(RaycastHit);
			for (float num = 1f; num <= 3f; num += 0.5f)
			{
				if (Physics.Raycast(edge + Vector3.up * num + val * 0.7f, Vector3.down, ref val2, 1.3f, -1, (QueryTriggerInteraction)1) && Vector3.Angle(((RaycastHit)(ref val2)).normal, Vector3.up) < 60f)
				{
					return true;
				}
			}
			return false;
		}

		private float EdgeLean(Vector3 hitPoint, Vector3 ch, out Vector3 edge, out Vector3 netDisp)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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)
			//IL_000e: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			edge = hitPoint;
			netDisp = Vector3.zero;
			_slopeBuf.Clear();
			Vector3 val = default(Vector3);
			Vector3 val2 = default(Vector3);
			Vector3 val3 = default(Vector3);
			float num = 0f;
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < EdgeSampleHeights.Length; i++)
			{
				float num2 = hitPoint.y + EdgeSampleHeights[i];
				if (!FindEdgeAtHeight(hitPoint, ch, num2, out var edge2))
				{
					flag = false;
					continue;
				}
				if (!flag2)
				{
					edge = edge2;
					val2 = edge2;
					flag2 = true;
				}
				val3 = edge2;
				if (flag)
				{
					float num3 = edge2.x - val.x;
					float num4 = edge2.z - val.z;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4) / (num2 - num);
					if (num5 <= 0.8f)
					{
						_slopeBuf.Add(num5);
					}
				}
				val = edge2;
				num = num2;
				flag = true;
			}
			if (_slopeBuf.Count < 2)
			{
				return -1f;
			}
			netDisp = new Vector3(val3.x - val2.x, 0f, val3.z - val2.z);
			_slopeBuf.Sort();
			return _slopeBuf[_slopeBuf.Count / 2];
		}

		private bool FindEdgeAtHeight(Vector3 hitPoint, Vector3 ch, float worldY, out Vector3 edge)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_005b: 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_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_00b4: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			edge = default(Vector3);
			Vector3 val = Vector3.Cross(Vector3.up, ch);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = new Vector3(hitPoint.x, worldY, hitPoint.z) + ch * 1.6f;
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(val2, -ch, ref val3, 3.2f, -1, (QueryTriggerInteraction)1))
			{
				return false;
			}
			if (Vector3.Dot(((RaycastHit)(ref val3)).normal, ch) < 0.5f)
			{
				return false;
			}
			float distance = ((RaycastHit)(ref val3)).distance;
			Vector3 point = ((RaycastHit)(ref val3)).point;
			float value = Plugin.CornerSearch.Value;
			float num = float.MaxValue;
			Vector3 val4 = default(Vector3);
			bool flag = false;
			for (int i = -1; i <= 1; i += 2)
			{
				for (float num2 = 0.1f; num2 <= value; num2 += 0.1f)
				{
					if (!Physics.Raycast(val2 + normalized * ((float)i * num2), -ch, distance + 0.5f, -1, (QueryTriggerInteraction)1))
					{
						if (num2 < num)
						{
							num = num2;
							val4 = point + normalized * ((float)i * (num2 - 0.1f));
							flag = true;
						}
						break;
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			edge = val4;
			return true;
		}

		private bool DedupDir(Vector3 p, Cat cat, Vector3 horiz)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			float cell = Mathf.Max(0.25f, Plugin.PatchSize.Value * 0.8f);
			int num = (int)Mathf.Round(Mathf.Atan2(horiz.z, horiz.x) / ((float)Math.PI / 8f)) & 0xF;
			return _cells.Add(CellKey(p, cell, cat) * 16 + num);
		}

		private static bool HasVisibleMesh(Collider col)
		{
			MeshRenderer component = ((Component)col).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && ((Renderer)component).enabled)
			{
				return true;
			}
			MeshRenderer componentInChildren = ((Component)col).GetComponentInChildren<MeshRenderer>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return ((Renderer)componentInChildren).enabled;
			}
			return false;
		}

		private void AddPatch(Vector3 center, Vector3 normal, Color col)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_000b: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0077: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e6: 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_00ef: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0025: 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)
			Vector3 val = Vector3.Cross(normal, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = Vector3.Cross(normal, Vector3.forward);
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = Vector3.Cross(normal, val);
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			float num = Plugin.PatchSize.Value * 0.5f;
			Vector3 val3 = normal * 0.03f;
			Vector3 val4 = center + val3;
			int count = _verts.Count;
			_verts.Add(val4 - val * num - normalized * num);
			_verts.Add(val4 + val * num - normalized * num);
			_verts.Add(val4 + val * num + normalized * num);
			_verts.Add(val4 - val * num + normalized * num);
			for (int i = 0; i < 4; i++)
			{
				_colors.Add(col);
			}
			_tris.Add(count);
			_tris.Add(count + 1);
			_tris.Add(count + 2);
			_tris.Add(count);
			_tris.Add(count + 2);
			_tris.Add(count + 3);
		}

		private static long CellKey(Vector3 p, float cell, Cat cat)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			long num = (long)Mathf.Floor(p.x / cell);
			long num2 = (long)Mathf.Floor(p.y / cell);
			long num3 = (long)Mathf.Floor(p.z / cell);
			return ((num * 73856093) ^ (num2 * 19349663) ^ (num3 * 83492791)) * 4 + (long)cat;
		}

		private bool IsTrainingGround()
		{
			try
			{
				if (_smTestMap == null)
				{
					return false;
				}
				object obj = _smInstance?.GetValue(null);
				return obj != null && (bool)_smTestMap.GetValue(obj);
			}
			catch
			{
				return false;
			}
		}
	}
}