Decompiled source of Waypoint Movement v0.1.15

WaypointMovementPlugin.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CyberpunkPink.WaypointMovement;

[BepInPlugin("org.cyberpunkpink.plugins.WaypointMovement", "Waypoint Movement Plugin", "0.1.14.0")]
[DefaultExecutionOrder(32000)]
public sealed class WaypointMovementPlugin : BaseUnityPlugin
{
	private sealed class PinkMovementBudget
	{
		public string TurnId;

		public float UsedMeters;

		public float AllowanceMeters;

		public float MetersPerWorldUnit;

		public DateTime UpdatedUtc;
	}

	private struct NativeDistanceCandidate
	{
		public float Scale;

		public string Unit;

		public float Score;

		public string SourceText;

		public Component SourceComponent;
	}

	public const string PluginName = "Waypoint Movement Plugin";

	public const string Guid = "org.cyberpunkpink.plugins.WaypointMovement";

	public const string Version = "0.1.14.0";

	private ConfigEntry<float> _waypointEpsilon;

	private ConfigEntry<float> _lineWidth;

	private ConfigEntry<bool> _diagnosticLogging;

	private ConfigEntry<string> _displayDistanceUnit;

	private bool _settingsOpen;

	private Rect _settingsRect = new Rect(80f, 80f, 360f, 180f);

	private bool _dragActive;

	private bool _waypointMode;

	private CreatureBoardAsset _activeAsset;

	private Vector3 _origin;

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

	private GameObject _routeRoot;

	private LineRenderer _routeLine;

	private LineRenderer _overageLine;

	private Material _routeMaterial;

	private Material _overageMaterial;

	private readonly List<GameObject> _markers = new List<GameObject>();

	private string _activeCreatureId = string.Empty;

	private Vector3 _lastLivePosition;

	private bool _pinkBudgetActive;

	private string _pinkTurnId = string.Empty;

	private float _pinkUsedMeters;

	private float _pinkAllowanceMeters;

	private float _pinkMetersPerWorldUnit = 2f;

	private bool _haveFacingYawOffset;

	private float _facingYawOffset;

	private bool _haveLastWaypointFacing;

	private Quaternion _lastWaypointFacing;

	private CreatureBoardAsset _pendingFacingAsset;

	private Quaternion _pendingFacingRotation;

	private int _pendingFacingFrames;

	private float _nextFacingOverrideLog;

	private static readonly object PinkSync = new object();

	private static readonly Dictionary<string, PinkMovementBudget> PinkBudgets = new Dictionary<string, PinkMovementBudget>(StringComparer.Ordinal);

	private static readonly Queue<string> PinkMovementEvents = new Queue<string>();

	private readonly Dictionary<Renderer, bool> _hiddenRenderers = new Dictionary<Renderer, bool>();

	private readonly Dictionary<TMP_Text, bool> _hiddenTexts = new Dictionary<TMP_Text, bool>();

	private readonly Dictionary<Text, bool> _hiddenLegacyTexts = new Dictionary<Text, bool>();

	private Component _nativeDistanceComponent;

	private float _nextNativeHideScan;

	private float _nextCalibrationScan;

	private float _distanceScale = 1f;

	private string _distanceUnit = string.Empty;

	private bool _distanceCalibrated;

	private float _cachedDistanceScale = 1f;

	private string _cachedDistanceUnit = string.Empty;

	private bool _haveCachedDistance;

	private GUIStyle _distanceStyle;

	private GUIStyle _distanceShadowStyle;

	private static readonly Regex DistanceRegex = new Regex("^\\s*(-?\\d+(?:[\\.,]\\d+)?)\\s*([^\\d\\s]+)\\s*$", RegexOptions.Compiled);

	public static bool SetPinkMovementState(string creatureId, string turnId, float usedMeters, float allowanceMeters, float metersPerWorldUnit)
	{
		string text = NormalizeCreatureId(creatureId);
		if (text.Length == 0 || string.IsNullOrEmpty(turnId))
		{
			return false;
		}
		if (float.IsNaN(usedMeters) || float.IsInfinity(usedMeters))
		{
			usedMeters = 0f;
		}
		if (float.IsNaN(allowanceMeters) || float.IsInfinity(allowanceMeters))
		{
			allowanceMeters = 0f;
		}
		if (float.IsNaN(metersPerWorldUnit) || float.IsInfinity(metersPerWorldUnit) || metersPerWorldUnit <= 0f)
		{
			metersPerWorldUnit = 2f;
		}
		lock (PinkSync)
		{
			PinkBudgets[text] = new PinkMovementBudget
			{
				TurnId = turnId,
				UsedMeters = Math.Max(0f, usedMeters),
				AllowanceMeters = Math.Max(0f, allowanceMeters),
				MetersPerWorldUnit = metersPerWorldUnit,
				UpdatedUtc = DateTime.UtcNow
			};
		}
		return true;
	}

	public static void ClearPinkMovementState(string creatureId)
	{
		string text = NormalizeCreatureId(creatureId);
		if (text.Length == 0)
		{
			return;
		}
		lock (PinkSync)
		{
			PinkBudgets.Remove(text);
		}
	}

	public static string PopPinkMovementEvent()
	{
		lock (PinkSync)
		{
			return (PinkMovementEvents.Count > 0) ? PinkMovementEvents.Dequeue() : null;
		}
	}

	private void Awake()
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Expected O, but got Unknown
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Expected O, but got Unknown
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Expected O, but got Unknown
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Expected O, but got Unknown
		_waypointEpsilon = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WaypointEpsilon", 0.05f, "Minimum world-space distance between consecutive route points.");
		_lineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RouteLineWidth", 0.08f, "Width of the persistent waypoint route line.");
		_diagnosticLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DiagnosticLogging", true, "Logs drag, waypoint, native-ruler suppression, and distance calibration events.");
		_displayDistanceUnit = ((BaseUnityPlugin)this).Config.Bind<string>("General", "DistanceUnit", "Meters", "Waypoint movement display unit. Supported values: Feet or Meters. Change in game with Ctrl+U.");
		Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
		Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnCameraPreRender));
		Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender));
		Application.onBeforeRender += new UnityAction(OnBeforeRender);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Waypoint Movement Plugin 0.1.14.0 loaded.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Controls: HOLD LMB to carry normally; RMB while held = waypoint; release LMB = native drop; Backspace = remove last waypoint; Ctrl+U = settings.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Waypoint facing: after the first waypoint, the held token faces away from the most recent waypoint instead of the original pickup point.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Waypoint facing enforcement runs at render boundaries so TaleSpire's native origin-facing cannot win later in the frame.");
	}

	private void OnDestroy()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Expected O, but got Unknown
		Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
		Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnCameraPreRender));
		Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender));
		Application.onBeforeRender -= new UnityAction(OnBeforeRender);
		_pendingFacingAsset = null;
		_pendingFacingFrames = 0;
		ResetRoute("plugin unload");
	}

	private void Update()
	{
		try
		{
			if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown((KeyCode)117))
			{
				_settingsOpen = !_settingsOpen;
				LogDiagnostic("Waypoint settings " + (_settingsOpen ? "opened" : "closed") + ".");
			}
			Tick();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Waypoint movement update failed: " + ex));
			ResetRoute("update exception");
		}
	}

	private void LateUpdate()
	{
		try
		{
			EnforceWaypointFacing("late-update", logOverwrite: false);
			MaintainPendingDropFacing(consumeFrame: true);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Waypoint facing update failed: " + ex));
			_pendingFacingAsset = null;
			_pendingFacingFrames = 0;
		}
	}

	private void OnBeforeRender()
	{
		EnforceWaypointFacing("before-render", logOverwrite: true);
		MaintainPendingDropFacing(consumeFrame: false);
	}

	private void OnCameraPreCull(Camera cam)
	{
		EnforceWaypointFacing("pre-cull", logOverwrite: true);
		MaintainPendingDropFacing(consumeFrame: false);
	}

	private void OnCameraPreRender(Camera cam)
	{
		EnforceWaypointFacing("pre-render", logOverwrite: true);
		MaintainPendingDropFacing(consumeFrame: false);
	}

	private void OnCameraPostRender(Camera cam)
	{
		EnforceWaypointFacing("post-render", logOverwrite: false);
		MaintainPendingDropFacing(consumeFrame: false);
	}

	private void EnforceWaypointFacing(string phase, bool logOverwrite)
	{
		//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_0049: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if (_dragActive && !((Object)(object)_activeAsset == (Object)null) && _waypoints.Count != 0 && Input.GetMouseButton(0))
		{
			Quaternion rotation = ((Component)_activeAsset).transform.rotation;
			UpdateWaypointFacing(((Component)_activeAsset).transform.position);
			Quaternion rotation2 = ((Component)_activeAsset).transform.rotation;
			float num = Quaternion.Angle(rotation, rotation2);
			if (logOverwrite && num > 0.5f && Time.unscaledTime >= _nextFacingOverrideLog)
			{
				_nextFacingOverrideLog = Time.unscaledTime + 0.5f;
				LogDiagnostic("Waypoint facing re-applied during " + phase + " after native drag changed yaw by " + num.ToString("0.###", CultureInfo.InvariantCulture) + " deg.");
			}
		}
	}

	private void MaintainPendingDropFacing(bool consumeFrame)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (_pendingFacingFrames <= 0)
		{
			return;
		}
		if ((Object)(object)_pendingFacingAsset != (Object)null)
		{
			((Component)_pendingFacingAsset).transform.rotation = _pendingFacingRotation;
		}
		if (consumeFrame)
		{
			_pendingFacingFrames--;
			if (_pendingFacingFrames <= 0)
			{
				_pendingFacingAsset = null;
			}
		}
	}

	private void Tick()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: 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)
		//IL_02f0: 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_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
		bool mouseButton = Input.GetMouseButton(0);
		if (!_dragActive)
		{
			CreatureBoardAsset val = default(CreatureBoardAsset);
			if (mouseButton && CreaturePresenter.TryGetAsset(LocalClient.SelectedCreatureId, ref val) && !((Object)(object)val == (Object)null))
			{
				_dragActive = true;
				_waypointMode = false;
				_activeAsset = val;
				_activeCreatureId = NormalizeCreatureId(LocalClient.SelectedCreatureId);
				_origin = ToVector3(val.LastPlacedPosition);
				_lastLivePosition = ((Component)val).transform.position;
				_waypoints.Clear();
				_haveFacingYawOffset = false;
				_facingYawOffset = 0f;
				_haveLastWaypointFacing = false;
				_pendingFacingAsset = null;
				_pendingFacingFrames = 0;
				_nextFacingOverrideLog = 0f;
				_distanceCalibrated = _haveCachedDistance;
				_distanceScale = (_haveCachedDistance ? _cachedDistanceScale : 1f);
				_distanceUnit = (_haveCachedDistance ? _cachedDistanceUnit : string.Empty);
				_nativeDistanceComponent = null;
				_nextNativeHideScan = 0f;
				_nextCalibrationScan = 0f;
				RefreshPinkBudget();
				if (_pinkBudgetActive)
				{
					_waypointMode = true;
					EnsureRouteVisual();
					LogDiagnostic("PINK movement budget active: used=" + _pinkUsedMeters.ToString("0.###", CultureInfo.InvariantCulture) + " allowance=" + _pinkAllowanceMeters.ToString("0.###", CultureInfo.InvariantCulture) + " turn=" + _pinkTurnId);
				}
				LogDiagnostic("Held-token tracking started. Origin=" + Format(_origin) + " Live=" + Format(((Component)val).transform.position));
			}
			return;
		}
		if (!mouseButton)
		{
			if ((Object)(object)_activeAsset != (Object)null)
			{
				_lastLivePosition = ((Component)_activeAsset).transform.position;
				if (_waypoints.Count > 0)
				{
					UpdateWaypointFacing(_lastLivePosition);
					if (_haveLastWaypointFacing)
					{
						_pendingFacingAsset = _activeAsset;
						_pendingFacingRotation = _lastWaypointFacing;
						_pendingFacingFrames = 30;
					}
				}
			}
			CommitPinkMovement();
			LogDiagnostic("LMB released; TaleSpire performs its normal drop.");
			ResetRoute("left mouse released");
			return;
		}
		if ((Object)(object)_activeAsset == (Object)null)
		{
			ResetRoute("active asset disappeared");
			return;
		}
		Vector3 val2 = (_lastLivePosition = ((Component)_activeAsset).transform.position);
		RefreshPinkBudget();
		if (_pinkBudgetActive && !_waypointMode)
		{
			_waypointMode = true;
			EnsureRouteVisual();
		}
		if ((!_waypointMode || (_pinkBudgetActive && (Object)(object)_nativeDistanceComponent == (Object)null)) && Time.unscaledTime >= _nextCalibrationScan)
		{
			_nextCalibrationScan = Time.unscaledTime + 0.1f;
			TryCalibrateDistance(val2);
		}
		if (Input.GetMouseButtonDown(1))
		{
			TryCalibrateDistance(val2);
			LogDiagnostic("RMB observed while LMB held at " + Format(val2));
			AddWaypoint(val2);
		}
		if (Input.GetKeyDown((KeyCode)8))
		{
			RemoveLastWaypoint();
		}
		if (_waypointMode)
		{
			UpdateRouteVisual(val2);
			if (Time.unscaledTime >= _nextNativeHideScan)
			{
				_nextNativeHideScan = Time.unscaledTime + 0.1f;
				HideNativeRulerVisuals();
			}
		}
	}

	private void AddWaypoint(Vector3 livePosition)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: 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_0098: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = ((_waypoints.Count > 0) ? _waypoints[_waypoints.Count - 1] : _origin);
		float num = Math.Max(0.001f, _waypointEpsilon.Value);
		if (Vector3.Distance(val, livePosition) < num)
		{
			LogDiagnostic("RMB received, but waypoint is too close to previous point.");
			return;
		}
		bool flag = _waypoints.Count == 0;
		_waypoints.Add(livePosition);
		if (flag && (Object)(object)_activeAsset != (Object)null)
		{
			_lastWaypointFacing = ((Component)_activeAsset).transform.rotation;
			_haveLastWaypointFacing = true;
			_haveFacingYawOffset = false;
		}
		LogDiagnostic("Waypoint " + _waypoints.Count + " added at " + Format(livePosition));
		if (!_waypointMode)
		{
			_waypointMode = true;
			EnsureRouteVisual();
			HideNativeRulerVisuals();
			LogDiagnostic("Waypoint mode activated; vanilla straight movement ruler hidden until drop.");
		}
		RebuildMarkers();
		UpdateRouteVisual(livePosition);
	}

	private void RemoveLastWaypoint()
	{
		//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_0050: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		if (_waypoints.Count == 0)
		{
			LogDiagnostic("Backspace pressed with no waypoint to remove.");
			return;
		}
		Vector3 value = _waypoints[_waypoints.Count - 1];
		_waypoints.RemoveAt(_waypoints.Count - 1);
		LogDiagnostic("Removed waypoint at " + Format(value));
		if (_waypoints.Count == 0)
		{
			_haveFacingYawOffset = false;
			_facingYawOffset = 0f;
			_haveLastWaypointFacing = false;
			if (_pinkBudgetActive)
			{
				RebuildMarkers();
				if ((Object)(object)_activeAsset != (Object)null)
				{
					UpdateRouteVisual(((Component)_activeAsset).transform.position);
				}
				LogDiagnostic("No waypoints remain; PINK budget keeps the custom movement ruler active.");
			}
			else
			{
				_waypointMode = false;
				DestroyRouteVisual();
				RestoreNativeRulerVisuals();
				LogDiagnostic("No waypoints remain; returned to vanilla drag ruler.");
			}
		}
		else
		{
			RebuildMarkers();
			if ((Object)(object)_activeAsset != (Object)null)
			{
				UpdateRouteVisual(((Component)_activeAsset).transform.position);
			}
		}
	}

	private void UpdateWaypointFacing(Vector3 livePosition)
	{
		//IL_00d9: 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_00e1: 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)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: 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_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: 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_0189: 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)
		if ((Object)(object)_activeAsset == (Object)null || _waypoints.Count == 0)
		{
			return;
		}
		float num = Math.Max(0.001f, _waypointEpsilon.Value);
		if (!_haveFacingYawOffset)
		{
			Vector3 direction = livePosition - _origin;
			direction.y = 0f;
			if (((Vector3)(ref direction)).sqrMagnitude >= num * num)
			{
				float num2 = HeadingDegrees(direction);
				Quaternion rotation = ((Component)_activeAsset).transform.rotation;
				float y = ((Quaternion)(ref rotation)).eulerAngles.y;
				_facingYawOffset = Mathf.DeltaAngle(num2, y);
				_haveFacingYawOffset = true;
				LogDiagnostic("Waypoint facing calibrated: yaw offset=" + _facingYawOffset.ToString("0.###", CultureInfo.InvariantCulture) + " deg.");
			}
		}
		Vector3 val = _waypoints[_waypoints.Count - 1];
		Vector3 direction2 = livePosition - val;
		direction2.y = 0f;
		if (((Vector3)(ref direction2)).sqrMagnitude < num * num)
		{
			if (_haveLastWaypointFacing)
			{
				((Component)_activeAsset).transform.rotation = _lastWaypointFacing;
			}
			return;
		}
		float num3 = HeadingDegrees(direction2);
		float num4 = num3 + (_haveFacingYawOffset ? _facingYawOffset : 0f);
		Quaternion rotation2 = ((Component)_activeAsset).transform.rotation;
		Vector3 eulerAngles = ((Quaternion)(ref rotation2)).eulerAngles;
		Quaternion val2 = Quaternion.Euler(eulerAngles.x, num4, eulerAngles.z);
		((Component)_activeAsset).transform.rotation = val2;
		_lastWaypointFacing = val2;
		_haveLastWaypointFacing = true;
	}

	private static float HeadingDegrees(Vector3 direction)
	{
		return Mathf.Atan2(direction.x, direction.z) * 57.29578f;
	}

	private void EnsureRouteVisual()
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		//IL_00a1: 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_00c8: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_routeRoot != (Object)null) || !((Object)(object)_routeLine != (Object)null) || !((Object)(object)_overageLine != (Object)null))
		{
			_routeRoot = new GameObject("CyberpunkPINK_WaypointRoute");
			_routeLine = CreateRouteLine("CyberpunkPINK_WaypointLegal", Color.white);
			_overageLine = CreateRouteLine("CyberpunkPINK_WaypointOverage", Color.red);
			Shader val = Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Unlit/Color");
			}
			if ((Object)(object)val != (Object)null)
			{
				_routeMaterial = new Material(val);
				_routeMaterial.color = Color.white;
				((Renderer)_routeLine).material = _routeMaterial;
				_overageMaterial = new Material(val);
				_overageMaterial.color = Color.red;
				((Renderer)_overageLine).material = _overageMaterial;
			}
		}
	}

	private LineRenderer CreateRouteLine(string name, Color color)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0071: 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)
		GameObject val = new GameObject(name);
		val.transform.SetParent(_routeRoot.transform, false);
		LineRenderer val2 = val.AddComponent<LineRenderer>();
		val2.useWorldSpace = true;
		val2.startWidth = Math.Max(0.01f, _lineWidth.Value);
		val2.endWidth = Math.Max(0.01f, _lineWidth.Value);
		val2.numCornerVertices = 8;
		val2.numCapVertices = 8;
		val2.startColor = color;
		val2.endColor = color;
		((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)val2).receiveShadows = false;
		return val2;
	}

	private void UpdateRouteVisual(Vector3 livePosition)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		EnsureRouteVisual();
		if (!((Object)(object)_routeLine == (Object)null) && !((Object)(object)_overageLine == (Object)null))
		{
			List<Vector3> points = BuildRoutePoints(livePosition);
			if (!_pinkBudgetActive)
			{
				SetLinePoints(_routeLine, points);
				_overageLine.positionCount = 0;
				return;
			}
			float num = (UseFeetDisplay() ? GetFeetPerWorldUnit() : Math.Max(0.0001f, _pinkMetersPerWorldUnit));
			float splitDistance = Math.Max(0f, (_pinkAllowanceMeters - _pinkUsedMeters) / num);
			SplitRouteAtDistance(points, splitDistance, out var legal, out var over);
			SetLinePoints(_routeLine, legal);
			SetLinePoints(_overageLine, over);
		}
	}

	private static void SplitRouteAtDistance(List<Vector3> points, float splitDistance, out List<Vector3> legal, out List<Vector3> over)
	{
		//IL_002f: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		legal = new List<Vector3>();
		over = new List<Vector3>();
		if (points == null || points.Count == 0)
		{
			return;
		}
		if (splitDistance <= 0f)
		{
			over.AddRange(points);
			return;
		}
		legal.Add(points[0]);
		float num = 0f;
		for (int i = 1; i < points.Count; i++)
		{
			Vector3 val = points[i - 1];
			Vector3 val2 = points[i];
			float num2 = Vector3.Distance(val, val2);
			if (num2 <= 0.0001f)
			{
				continue;
			}
			if (num + num2 <= splitDistance + 0.0001f)
			{
				legal.Add(val2);
				num += num2;
				continue;
			}
			float num3 = Math.Max(0f, splitDistance - num);
			float num4 = Math.Max(0f, Math.Min(1f, num3 / num2));
			Vector3 val3 = Vector3.Lerp(val, val2, num4);
			if (legal.Count == 0 || Vector3.Distance(legal[legal.Count - 1], val3) > 0.0001f)
			{
				legal.Add(val3);
			}
			over.Add(val3);
			over.Add(val2);
			for (int j = i + 1; j < points.Count; j++)
			{
				over.Add(points[j]);
			}
			break;
		}
	}

	private static void SetLinePoints(LineRenderer line, List<Vector3> points)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)line == (Object)null)
		{
			return;
		}
		if (points == null || points.Count < 2)
		{
			line.positionCount = 0;
			return;
		}
		line.positionCount = points.Count;
		for (int i = 0; i < points.Count; i++)
		{
			Vector3 val = points[i];
			val.y += 0.035f;
			line.SetPosition(i, val);
		}
	}

	private List<Vector3> BuildRoutePoints(Vector3 livePosition)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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)
		List<Vector3> list = new List<Vector3>(_waypoints.Count + 2);
		list.Add(_origin);
		for (int i = 0; i < _waypoints.Count; i++)
		{
			AddPointIfDistinct(list, _waypoints[i]);
		}
		AddPointIfDistinct(list, livePosition);
		return list;
	}

	private void AddPointIfDistinct(List<Vector3> points, Vector3 candidate)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		float num = Math.Max(0.001f, _waypointEpsilon.Value);
		if (points.Count == 0 || Vector3.Distance(points[points.Count - 1], candidate) >= num)
		{
			points.Add(candidate);
		}
	}

	private void RebuildMarkers()
	{
		//IL_0059: 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_0078: 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)
		DestroyMarkers();
		if ((Object)(object)_routeRoot == (Object)null)
		{
			return;
		}
		for (int i = 0; i < _waypoints.Count; i++)
		{
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val).name = "CyberpunkPINK_Waypoint_" + (i + 1);
			val.transform.SetParent(_routeRoot.transform, true);
			Vector3 position = _waypoints[i];
			position.y += 0.035f;
			val.transform.position = position;
			val.transform.localScale = new Vector3(0.18f, 0.055f, 0.18f);
			Collider component = val.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Renderer component2 = val.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)_routeMaterial != (Object)null)
			{
				component2.material = _routeMaterial;
			}
			_markers.Add(val);
		}
	}

	private void DestroyMarkers()
	{
		for (int i = 0; i < _markers.Count; i++)
		{
			if ((Object)(object)_markers[i] != (Object)null)
			{
				Object.Destroy((Object)(object)_markers[i]);
			}
		}
		_markers.Clear();
	}

	private void HideNativeRulerVisuals()
	{
		Renderer[] array = Object.FindObjectsOfType<Renderer>();
		int num = 0;
		foreach (Renderer val in array)
		{
			if (!((Object)(object)val == (Object)null) && !IsOurObject(((Component)val).transform) && LooksLikeRuler(((Component)val).transform))
			{
				if (!_hiddenRenderers.ContainsKey(val))
				{
					_hiddenRenderers.Add(val, val.enabled);
					num++;
				}
				val.enabled = false;
			}
		}
		TMP_Text[] array2 = Object.FindObjectsOfType<TMP_Text>();
		foreach (TMP_Text val2 in array2)
		{
			if (!((Object)(object)val2 == (Object)null) && !IsOurObject(val2.transform) && ((Object)(object)_nativeDistanceComponent == (Object)(object)val2 || LooksLikeRuler(val2.transform)))
			{
				if (!_hiddenTexts.ContainsKey(val2))
				{
					_hiddenTexts.Add(val2, ((Behaviour)val2).enabled);
					num++;
				}
				((Behaviour)val2).enabled = false;
			}
		}
		Text[] array3 = Object.FindObjectsOfType<Text>();
		foreach (Text val3 in array3)
		{
			if (!((Object)(object)val3 == (Object)null) && !IsOurObject(((Component)val3).transform) && ((Object)(object)_nativeDistanceComponent == (Object)(object)val3 || LooksLikeRuler(((Component)val3).transform)))
			{
				if (!_hiddenLegacyTexts.ContainsKey(val3))
				{
					_hiddenLegacyTexts.Add(val3, ((Behaviour)val3).enabled);
					num++;
				}
				((Behaviour)val3).enabled = false;
			}
		}
		if (num > 0)
		{
			LogDiagnostic("Suppressed " + num + " vanilla ruler visual component(s), including the native distance readout when identified.");
		}
	}

	private void RestoreNativeRulerVisuals()
	{
		foreach (KeyValuePair<Renderer, bool> hiddenRenderer in _hiddenRenderers)
		{
			if ((Object)(object)hiddenRenderer.Key != (Object)null)
			{
				hiddenRenderer.Key.enabled = hiddenRenderer.Value;
			}
		}
		_hiddenRenderers.Clear();
		foreach (KeyValuePair<TMP_Text, bool> hiddenText in _hiddenTexts)
		{
			if ((Object)(object)hiddenText.Key != (Object)null)
			{
				((Behaviour)hiddenText.Key).enabled = hiddenText.Value;
			}
		}
		_hiddenTexts.Clear();
		foreach (KeyValuePair<Text, bool> hiddenLegacyText in _hiddenLegacyTexts)
		{
			if ((Object)(object)hiddenLegacyText.Key != (Object)null)
			{
				((Behaviour)hiddenLegacyText.Key).enabled = hiddenLegacyText.Value;
			}
		}
		_hiddenLegacyTexts.Clear();
	}

	private bool IsOurObject(Transform transform)
	{
		Transform val = transform;
		while ((Object)(object)val != (Object)null)
		{
			if ((Object)(object)((Component)val).gameObject == (Object)(object)_routeRoot || ((Object)val).name.StartsWith("CyberpunkPINK_Waypoint", StringComparison.Ordinal))
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	private static bool LooksLikeRuler(Transform transform)
	{
		Transform val = transform;
		while ((Object)(object)val != (Object)null)
		{
			string text = ((((Object)val).name == null) ? string.Empty : ((Object)val).name.ToLowerInvariant());
			if (text.Contains("ruler") || text.Contains("measure"))
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	private void TryCalibrateDistance(Vector3 livePosition)
	{
		//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_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		float num = Vector3.Distance(_origin, livePosition);
		if (num < 0.1f)
		{
			return;
		}
		NativeDistanceCandidate nativeDistanceCandidate = default(NativeDistanceCandidate);
		bool flag = false;
		TMP_Text[] array = Object.FindObjectsOfType<TMP_Text>();
		foreach (TMP_Text val in array)
		{
			if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && !string.IsNullOrEmpty(val.text) && !IsOurObject(val.transform) && TryMakeDistanceCandidate(val.text, val.transform, (Component)(object)val, num, out var candidate))
			{
				candidate.Score += (LooksLikeRuler(val.transform) ? 1000f : 0f);
				candidate.Score += ScoreCandidateNearHeldToken(val.transform, livePosition);
				if (!flag || candidate.Score > nativeDistanceCandidate.Score)
				{
					nativeDistanceCandidate = candidate;
					flag = true;
				}
			}
		}
		Text[] array2 = Object.FindObjectsOfType<Text>();
		foreach (Text val2 in array2)
		{
			if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).enabled && !string.IsNullOrEmpty(val2.text) && !IsOurObject(((Component)val2).transform) && TryMakeDistanceCandidate(val2.text, ((Component)val2).transform, (Component)(object)val2, num, out var candidate2))
			{
				candidate2.Score += (LooksLikeRuler(((Component)val2).transform) ? 1000f : 0f);
				candidate2.Score += ScoreCandidateNearHeldToken(((Component)val2).transform, livePosition);
				if (!flag || candidate2.Score > nativeDistanceCandidate.Score)
				{
					nativeDistanceCandidate = candidate2;
					flag = true;
				}
			}
		}
		if (flag)
		{
			_distanceScale = nativeDistanceCandidate.Scale;
			_distanceUnit = nativeDistanceCandidate.Unit;
			_distanceCalibrated = true;
			_cachedDistanceScale = nativeDistanceCandidate.Scale;
			_cachedDistanceUnit = nativeDistanceCandidate.Unit;
			_haveCachedDistance = true;
			_nativeDistanceComponent = nativeDistanceCandidate.SourceComponent;
			LogDiagnostic("Campaign distance calibrated from native ruler: " + _distanceScale.ToString("0.###", CultureInfo.InvariantCulture) + " " + _distanceUnit + "/world-unit (source='" + nativeDistanceCandidate.SourceText + "').");
		}
	}

	private bool TryMakeDistanceCandidate(string sourceText, Transform transform, Component sourceComponent, float straightWorldDistance, out NativeDistanceCandidate candidate)
	{
		candidate = default(NativeDistanceCandidate);
		if (string.IsNullOrEmpty(sourceText))
		{
			return false;
		}
		Match match = DistanceRegex.Match(sourceText.Trim());
		if (!match.Success)
		{
			return false;
		}
		string s = match.Groups[1].Value.Replace(',', '.');
		string text = match.Groups[2].Value.Trim();
		if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || result <= 0f)
		{
			return false;
		}
		if (string.IsNullOrEmpty(text) || text.Length > 12)
		{
			return false;
		}
		float num = result / straightWorldDistance;
		if (num < 0.01f || num > 1000f)
		{
			return false;
		}
		candidate.Scale = num;
		candidate.Unit = text;
		candidate.SourceText = sourceText.Trim();
		candidate.SourceComponent = sourceComponent;
		candidate.Score = 10f;
		return true;
	}

	private float ScoreCandidateNearHeldToken(Transform transform, Vector3 livePosition)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null || (Object)(object)transform == (Object)null)
		{
			return 0f;
		}
		try
		{
			Vector3 val = main.WorldToScreenPoint(livePosition + Vector3.up * 0.25f);
			Vector3 val2 = main.WorldToScreenPoint(transform.position);
			if (val.z <= 0f || val2.z <= 0f)
			{
				return 0f;
			}
			float num = Vector2.Distance(new Vector2(val.x, val.y), new Vector2(val2.x, val2.y));
			return Math.Max(0f, 500f - num);
		}
		catch
		{
			return 0f;
		}
	}

	private float GetRouteWorldDistance(Vector3 livePosition)
	{
		//IL_0001: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = BuildRoutePoints(livePosition);
		float num = 0f;
		for (int i = 1; i < list.Count; i++)
		{
			num += Vector3.Distance(list[i - 1], list[i]);
		}
		return num;
	}

	private void OnGUI()
	{
		//IL_000f: 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_002a: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		if (_settingsOpen)
		{
			_settingsRect = GUI.Window(48117, _settingsRect, new WindowFunction(DrawSettingsWindow), "Waypoint Movement Settings");
		}
		if (!_dragActive || !_waypointMode || (Object)(object)_activeAsset == (Object)null)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		Vector3 val = main.WorldToScreenPoint(((Component)_activeAsset).transform.position + Vector3.up * 0.3f);
		if (val.z <= 0f)
		{
			return;
		}
		EnsureGuiStyles();
		bool flag = false;
		string text;
		if (_pinkBudgetActive)
		{
			float routeWorldDistance = GetRouteWorldDistance(((Component)_activeAsset).transform.position);
			if (UseFeetDisplay())
			{
				float feetPerWorldUnit = GetFeetPerWorldUnit();
				float num = _pinkUsedMeters + routeWorldDistance * feetPerWorldUnit;
				float pinkAllowanceMeters = _pinkAllowanceMeters;
				flag = num > pinkAllowanceMeters + 0.001f;
				text = FormatDistance(num) + " / " + FormatDistance(pinkAllowanceMeters) + " ft";
			}
			else
			{
				float num2 = Math.Max(0.0001f, _pinkMetersPerWorldUnit);
				float num3 = _pinkUsedMeters + routeWorldDistance * num2;
				flag = num3 > _pinkAllowanceMeters + 0.001f;
				text = FormatDistance(num3) + " / " + FormatDistance(_pinkAllowanceMeters) + " m";
			}
		}
		else
		{
			if (!_distanceCalibrated || string.IsNullOrEmpty(_distanceUnit))
			{
				return;
			}
			text = (GetRouteWorldDistance(((Component)_activeAsset).transform.position) * _distanceScale).ToString("0.0", CultureInfo.InvariantCulture) + " " + _distanceUnit;
		}
		_distanceStyle.normal.textColor = (flag ? Color.red : Color.white);
		float num4 = val.x + 18f;
		float num5 = (float)Screen.height - val.y - 18f;
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(num4 + 2f, num5 + 2f, 130f, 30f);
		Rect val3 = default(Rect);
		((Rect)(ref val3))..ctor(num4, num5, 130f, 30f);
		GUI.Label(val2, text, _distanceShadowStyle);
		GUI.Label(val3, text, _distanceStyle);
	}

	private bool UseFeetDisplay()
	{
		return string.Equals((_displayDistanceUnit != null) ? _displayDistanceUnit.Value : "Meters", "Feet", StringComparison.OrdinalIgnoreCase);
	}

	private float GetFeetPerWorldUnit()
	{
		if (_distanceCalibrated && !string.IsNullOrEmpty(_distanceUnit))
		{
			switch (_distanceUnit.Trim().ToLowerInvariant())
			{
			case "ft":
			case "feet":
			case "foot":
				return Math.Max(0.0001f, _distanceScale);
			case "m":
			case "meter":
			case "meters":
			case "metre":
			case "metres":
				return Math.Max(0.0001f, _distanceScale * 3.28084f);
			}
		}
		if (_haveCachedDistance && !string.IsNullOrEmpty(_cachedDistanceUnit))
		{
			switch (_cachedDistanceUnit.Trim().ToLowerInvariant())
			{
			case "ft":
			case "feet":
			case "foot":
				return Math.Max(0.0001f, _cachedDistanceScale);
			case "m":
			case "meter":
			case "meters":
			case "metre":
			case "metres":
				return Math.Max(0.0001f, _cachedDistanceScale * 3.28084f);
			}
		}
		return 5f;
	}

	private void DrawSettingsWindow(int windowId)
	{
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label("Distance Unit", (GUILayoutOption[])(object)new GUILayoutOption[0]);
		string text = (UseFeetDisplay() ? "Feet" : "Meters");
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		if (GUILayout.Toggle(text == "Feet", "Feet", GUI.skin.button, (GUILayoutOption[])(object)new GUILayoutOption[0]) && text != "Feet")
		{
			_displayDistanceUnit.Value = "Feet";
			((BaseUnityPlugin)this).Config.Save();
		}
		if (GUILayout.Toggle(text == "Meters", "Meters", GUI.skin.button, (GUILayoutOption[])(object)new GUILayoutOption[0]) && text != "Meters")
		{
			_displayDistanceUnit.Value = "Meters";
			((BaseUnityPlugin)this).Config.Save();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(8f);
		GUILayout.Label("Controls: Ctrl+U toggles this window.", (GUILayoutOption[])(object)new GUILayoutOption[0]);
		if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[0]))
		{
			_settingsOpen = false;
		}
		GUILayout.EndVertical();
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
	}

	private void EnsureGuiStyles()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		if (_distanceStyle == null)
		{
			_distanceStyle = new GUIStyle(GUI.skin.label);
			_distanceStyle.fontSize = 18;
			_distanceStyle.fontStyle = (FontStyle)1;
			_distanceStyle.normal.textColor = Color.white;
			_distanceShadowStyle = new GUIStyle(_distanceStyle);
			_distanceShadowStyle.normal.textColor = Color.black;
		}
	}

	private void ResetRoute(string reason)
	{
		if (_dragActive || (Object)(object)_routeRoot != (Object)null)
		{
			LogDiagnostic("Route reset: " + reason);
		}
		RestoreNativeRulerVisuals();
		DestroyRouteVisual();
		_waypoints.Clear();
		_dragActive = false;
		_waypointMode = false;
		_activeAsset = null;
		_activeCreatureId = string.Empty;
		_pinkBudgetActive = false;
		_pinkTurnId = string.Empty;
		_pinkUsedMeters = 0f;
		_pinkAllowanceMeters = 0f;
		_pinkMetersPerWorldUnit = 2f;
		_haveFacingYawOffset = false;
		_facingYawOffset = 0f;
		_haveLastWaypointFacing = false;
		_distanceCalibrated = false;
		_nativeDistanceComponent = null;
	}

	private void DestroyRouteVisual()
	{
		DestroyMarkers();
		if ((Object)(object)_routeRoot != (Object)null)
		{
			Object.Destroy((Object)(object)_routeRoot);
		}
		_routeRoot = null;
		_routeLine = null;
		_overageLine = null;
		if ((Object)(object)_routeMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_routeMaterial);
		}
		if ((Object)(object)_overageMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)_overageMaterial);
		}
		_routeMaterial = null;
		_overageMaterial = null;
	}

	private void RefreshPinkBudget()
	{
		_pinkBudgetActive = false;
		if (string.IsNullOrEmpty(_activeCreatureId))
		{
			return;
		}
		lock (PinkSync)
		{
			if (PinkBudgets.TryGetValue(_activeCreatureId, out var value) && value != null)
			{
				if ((DateTime.UtcNow - value.UpdatedUtc).TotalSeconds > 5.0)
				{
					PinkBudgets.Remove(_activeCreatureId);
					return;
				}
				_pinkBudgetActive = true;
				_pinkTurnId = value.TurnId ?? string.Empty;
				_pinkUsedMeters = Math.Max(0f, value.UsedMeters);
				_pinkAllowanceMeters = Math.Max(0f, value.AllowanceMeters);
				_pinkMetersPerWorldUnit = Math.Max(0.0001f, value.MetersPerWorldUnit);
			}
		}
	}

	private void CommitPinkMovement()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		RefreshPinkBudget();
		if (!_pinkBudgetActive || string.IsNullOrEmpty(_pinkTurnId) || string.IsNullOrEmpty(_activeCreatureId))
		{
			return;
		}
		float routeWorldDistance = GetRouteWorldDistance(_lastLivePosition);
		float num = Math.Max(0.001f, _waypointEpsilon.Value);
		if (routeWorldDistance < num)
		{
			return;
		}
		string item = _activeCreatureId + "\t" + _pinkTurnId + "\t" + routeWorldDistance.ToString("R", CultureInfo.InvariantCulture);
		lock (PinkSync)
		{
			PinkMovementEvents.Enqueue(item);
			while (PinkMovementEvents.Count > 64)
			{
				PinkMovementEvents.Dequeue();
			}
		}
		if (UseFeetDisplay())
		{
			LogDiagnostic("Movement committed: " + (routeWorldDistance * GetFeetPerWorldUnit()).ToString("0.###", CultureInfo.InvariantCulture) + " ft for turn " + _pinkTurnId);
		}
		else
		{
			LogDiagnostic("PINK movement committed: " + (routeWorldDistance * _pinkMetersPerWorldUnit).ToString("0.###", CultureInfo.InvariantCulture) + "m for turn " + _pinkTurnId);
		}
	}

	private static string FormatDistance(float value)
	{
		return value.ToString("0.#", CultureInfo.InvariantCulture);
	}

	private static string NormalizeCreatureId(object value)
	{
		string text = ((value == null) ? string.Empty : value.ToString());
		StringBuilder stringBuilder = new StringBuilder();
		foreach (char c in text)
		{
			if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
			{
				stringBuilder.Append(char.ToLowerInvariant(c));
			}
		}
		string text2 = stringBuilder.ToString();
		if (text2.Length < 32)
		{
			return text2;
		}
		return text2.Substring(text2.Length - 32);
	}

	private void LogDiagnostic(string message)
	{
		if (_diagnosticLogging != null && _diagnosticLogging.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Waypoint] " + message));
		}
	}

	private static Vector3 ToVector3(float3 value)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(value.x, value.y, value.z);
	}

	private static string Format(Vector3 value)
	{
		return $"({value.x:0.###}, {value.y:0.###}, {value.z:0.###})";
	}
}