Decompiled source of PeakAutoPathfind v0.1.0

plugins/Local.PeakAutoPathfind.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PeakAutoPathfind.Loot;
using PeakAutoPathfind.Planning;
using PeakAutoPathfind.Player;
using PeakAutoPathfind.UI;
using UnityEngine;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Local.PeakAutoPathfind")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("Local.PeakAutoPathfind")]
[assembly: AssemblyTitle("PeakAutoPathfind")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace PeakAutoPathfind
{
	internal sealed class GoalInfo
	{
		public GoalKind Kind;

		public Vector3 Position;

		public string Label = "";
	}
	internal static class PingTracker
	{
		public static bool HasPing;

		public static Vector3 LastPing;

		public static float LastPingTime;

		public static void Record(Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			HasPing = true;
			LastPing = point;
			LastPingTime = Time.time;
		}
	}
	internal static class CustomWaypointStore
	{
		public static bool HasWaypoint;

		public static Vector3 Position;

		public static void Set(Vector3 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			HasWaypoint = true;
			Position = pos;
		}

		public static void Clear()
		{
			HasWaypoint = false;
		}
	}
	internal sealed class GoalSelector
	{
		public GoalInfo Select(Character? local)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0069: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (PingTracker.HasPing)
			{
				return new GoalInfo
				{
					Kind = GoalKind.Ping,
					Position = PingTracker.LastPing,
					Label = "Ping"
				};
			}
			if (TryNearestUsefulCampfire(local, out var pos))
			{
				return new GoalInfo
				{
					Kind = GoalKind.Campfire,
					Position = pos,
					Label = "Campfire"
				};
			}
			if (TryPeak(out var pos2))
			{
				return new GoalInfo
				{
					Kind = GoalKind.Peak,
					Position = pos2,
					Label = "Peak"
				};
			}
			if (CustomWaypointStore.HasWaypoint)
			{
				return new GoalInfo
				{
					Kind = GoalKind.Custom,
					Position = CustomWaypointStore.Position,
					Label = "Custom"
				};
			}
			return new GoalInfo
			{
				Kind = GoalKind.None,
				Label = "None"
			};
		}

		private static bool TryNearestUsefulCampfire(Character? local, out Vector3 pos)
		{
			//IL_0001: 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_0025: 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_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_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)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			pos = default(Vector3);
			if (Campfire.ALL_CAMPFIRES == null || Campfire.ALL_CAMPFIRES.Count == 0)
			{
				return false;
			}
			Vector3 val = (((Object)(object)local != (Object)null) ? local.Center : Vector3.zero);
			float num = float.MaxValue;
			Campfire val2 = null;
			foreach (Campfire aLL_CAMPFIRE in Campfire.ALL_CAMPFIRES)
			{
				if (!((Object)(object)aLL_CAMPFIRE == (Object)null))
				{
					Vector3 val3 = aLL_CAMPFIRE.Center();
					float num2 = Vector3.Distance(val, val3);
					float num3 = num2;
					if (aLL_CAMPFIRE.Lit)
					{
						num3 += 25f;
					}
					if (num3 < num)
					{
						num = num3;
						val2 = aLL_CAMPFIRE;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			pos = val2.Center();
			return true;
		}

		private static bool TryPeak(out Vector3 pos)
		{
			//IL_0001: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			pos = default(Vector3);
			try
			{
				PeakHandler instance = Singleton<PeakHandler>.Instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.peakSequence != (Object)null)
				{
					pos = instance.peakSequence.transform.position;
					return true;
				}
			}
			catch
			{
			}
			if (Campfire.ALL_CAMPFIRES == null || Campfire.ALL_CAMPFIRES.Count == 0)
			{
				return false;
			}
			float num = float.MinValue;
			Campfire val = null;
			foreach (Campfire aLL_CAMPFIRE in Campfire.ALL_CAMPFIRES)
			{
				if (!((Object)(object)aLL_CAMPFIRE == (Object)null))
				{
					Vector3 val2 = aLL_CAMPFIRE.Center();
					if (val2.y > num)
					{
						num = val2.y;
						val = aLL_CAMPFIRE;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			pos = val.Center();
			return true;
		}
	}
	internal static class ModConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyCode> TakeoverKey;

		internal static ConfigEntry<KeyCode> CustomWaypointKey;

		internal static ConfigEntry<KeyCode> ConfirmKey;

		internal static ConfigEntry<KeyCode> DenyKey;

		internal static ConfigEntry<bool> ShowPathWhenManual;

		internal static ConfigEntry<float> ArriveDistance;

		internal static ConfigEntry<float> WaypointReachDistance;

		internal static ConfigEntry<float> ProbeDistance;

		internal static ConfigEntry<float> StuckTimeoutSeconds;

		internal static ConfigEntry<float> SafeDropHeight;

		internal static ConfigEntry<float> ConservativeLootSaveRatio;

		internal static ConfigEntry<float> GraphSampleSpacing;

		internal static ConfigEntry<float> GraphMaxRadius;

		internal static ConfigEntry<bool> AllowAutoJump;

		internal static ConfigEntry<bool> AllowAutoClimb;

		internal static ConfigEntry<bool> EnableLootOptimization;

		internal static ConfigEntry<float> ReplanIntervalSeconds;

		internal static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch for PeakAutoPathfind.");
			TakeoverKey = config.Bind<KeyCode>("Controls", "TakeoverKey", (KeyCode)289, "Toggle guided takeover.");
			CustomWaypointKey = config.Bind<KeyCode>("Controls", "CustomWaypointKey", (KeyCode)290, "Set custom waypoint at look-hit or player position.");
			ConfirmKey = config.Bind<KeyCode>("Controls", "ConfirmKey", (KeyCode)121, "Confirm pending risky action.");
			DenyKey = config.Bind<KeyCode>("Controls", "DenyKey", (KeyCode)110, "Deny pending risky action.");
			ShowPathWhenManual = config.Bind<bool>("Visual", "ShowPathWhenManual", false, "Keep drawing last path while in manual control.");
			ArriveDistance = config.Bind<float>("Pathfinding", "ArriveDistance", 2.5f, "Distance to mark goal as arrived.");
			WaypointReachDistance = config.Bind<float>("Pathfinding", "WaypointReachDistance", 1.75f, "Distance to advance to next waypoint.");
			ProbeDistance = config.Bind<float>("Pathfinding", "ProbeDistance", 3.5f, "Local obstacle probe distance.");
			StuckTimeoutSeconds = config.Bind<float>("Pathfinding", "StuckTimeoutSeconds", 4f, "Seconds without progress before replanning.");
			SafeDropHeight = config.Bind<float>("Safety", "SafeDropHeight", 4f, "Drops taller than this require confirmation.");
			ConservativeLootSaveRatio = config.Bind<float>("Loot", "ConservativeLootSaveRatio", 0.3f, "Minimum relative cost save to detour for loot.");
			GraphSampleSpacing = config.Bind<float>("Pathfinding", "GraphSampleSpacing", 4f, "World-space spacing for global graph samples.");
			GraphMaxRadius = config.Bind<float>("Pathfinding", "GraphMaxRadius", 180f, "Max radius around player/goal for graph build.");
			AllowAutoJump = config.Bind<bool>("Actions", "AllowAutoJump", true, "Allow automatic short jumps.");
			AllowAutoClimb = config.Bind<bool>("Actions", "AllowAutoClimb", true, "Allow climb attempts (still may Hold).");
			EnableLootOptimization = config.Bind<bool>("Loot", "EnableLootOptimization", true, "Evaluate closed luggage as optional waypoints.");
			ReplanIntervalSeconds = config.Bind<float>("Pathfinding", "ReplanIntervalSeconds", 1.25f, "Minimum seconds between automatic replans.");
		}
	}
	internal sealed class PathfindController : MonoBehaviour
	{
		private readonly GoalSelector _goals = new GoalSelector();

		private readonly MapGraphBuilder _graphBuilder = new MapGraphBuilder();

		private readonly GlobalPathfinder _pathfinder = new GlobalPathfinder();

		private readonly LootAwareOptimizer _lootOptimizer = new LootAwareOptimizer();

		private readonly LocalProbePlanner _localPlanner = new LocalProbePlanner();

		private readonly ConfirmPromptUI _confirmUi = new ConfirmPromptUI();

		private readonly StatusHud _hud = new StatusHud();

		private PathVisualizer? _visualizer;

		private ControlMode _mode;

		private PathStatus _status;

		private GoalInfo _goal = new GoalInfo
		{
			Kind = GoalKind.None
		};

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

		private int _wpIndex;

		private LocalAction _lastAction;

		private float _lastReplanTime = -999f;

		private float _lastProgressTime;

		private Vector3 _lastProgressPos;

		private PendingActionKind _pendingKind;

		private Vector3 _pendingDropDir;

		private GoalKind _lastGoalKind;

		private Vector3 _lastGoalPos;

		private PlayerLoadout _lastLoadout = new PlayerLoadout();

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("PeakAutoPathfind_PathViz");
			Object.DontDestroyOnLoad((Object)(object)val);
			_visualizer = val.AddComponent<PathVisualizer>();
		}

		private void Update()
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: 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_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value)
			{
				ForceManual("disabled");
				return;
			}
			HandleHotkeys();
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal)
			{
				ActionExecutor.Clear();
				return;
			}
			if (_mode == ControlMode.ConfirmWait)
			{
				HandleConfirmInput(localCharacter);
				RefreshHud(localCharacter);
				return;
			}
			if (_mode == ControlMode.Manual)
			{
				ActionExecutor.Clear();
				if (ModConfig.ShowPathWhenManual.Value)
				{
					_visualizer?.SetPath(_waypoints);
				}
				else
				{
					_visualizer?.Clear();
				}
				_status = PathStatus.Idle;
				RefreshHud(localCharacter);
				return;
			}
			if (PlayerInterruptedMovement())
			{
				ForceManual("player interrupt");
				RefreshHud(localCharacter);
				return;
			}
			_goal = _goals.Select(localCharacter);
			if (_goal.Kind == GoalKind.None)
			{
				_status = PathStatus.Seeking;
				ActionExecutor.Clear();
				_visualizer?.Clear();
				RefreshHud(localCharacter);
				return;
			}
			float num = Vector3.Distance(localCharacter.Center, _goal.Position);
			if (num <= ModConfig.ArriveDistance.Value)
			{
				_status = PathStatus.Arrived;
				ActionExecutor.Clear();
				RefreshHud(localCharacter);
				return;
			}
			if ((_waypoints.Count == 0 || _goal.Kind != _lastGoalKind || Vector3.Distance(_goal.Position, _lastGoalPos) > 1.5f || LoadoutChanged(localCharacter) || Time.time - _lastReplanTime >= ModConfig.ReplanIntervalSeconds.Value * 4f) && Time.time - _lastReplanTime >= ModConfig.ReplanIntervalSeconds.Value)
			{
				Replan(localCharacter);
			}
			if (_waypoints.Count == 0)
			{
				_status = PathStatus.Planning;
				ActionExecutor.Clear();
				RefreshHud(localCharacter);
				return;
			}
			while (_wpIndex < _waypoints.Count && Vector3.Distance(localCharacter.Center, _waypoints[_wpIndex]) <= ModConfig.WaypointReachDistance.Value)
			{
				_wpIndex++;
			}
			if (_wpIndex >= _waypoints.Count)
			{
				Replan(localCharacter);
				RefreshHud(localCharacter);
				return;
			}
			Vector3 val = _waypoints[_wpIndex];
			LocalProbeDecision localProbeDecision = _localPlanner.Decide(localCharacter, val, _goal.Position);
			_lastAction = localProbeDecision.Action;
			if (localProbeDecision.NeedsConfirm)
			{
				EnterConfirm(localProbeDecision);
				RefreshHud(localCharacter);
				return;
			}
			if (TryDetectIntentionalChest(localCharacter, out Luggage lug) && (Object)(object)lug != (Object)null)
			{
				EnterConfirmChest(lug);
				RefreshHud(localCharacter);
				return;
			}
			bool sprint = Vector3.Distance(localCharacter.Center, val) > 6f && localCharacter.data.currentStamina > localCharacter.GetMaxStamina() * 0.25f;
			ActionExecutor.ApplyDecision(localCharacter, localProbeDecision, sprint);
			_status = ((localProbeDecision.Action == LocalAction.Climb) ? PathStatus.Climb : PathStatus.Moving);
			_visualizer?.SetPath(_waypoints);
			UpdateStuck(localCharacter);
			RefreshHud(localCharacter);
		}

		private void OnGUI()
		{
			_hud.Draw();
			_confirmUi.Draw();
		}

		private void HandleHotkeys()
		{
			//IL_0005: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_00ba: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (Input.GetKeyDown(ModConfig.TakeoverKey.Value))
			{
				if (_mode == ControlMode.Manual)
				{
					_mode = ControlMode.Guided;
					_status = PathStatus.Planning;
					_lastReplanTime = -999f;
					Plugin.Log.LogInfo((object)"Guided mode ON");
				}
				else
				{
					ForceManual("hotkey toggle");
				}
			}
			if (Input.GetKeyDown(ModConfig.CustomWaypointKey.Value))
			{
				Character localCharacter = Character.localCharacter;
				Vector3 val = (((Object)(object)localCharacter != (Object)null) ? localCharacter.Center : Vector3.zero);
				Camera main = Camera.main;
				RaycastHit val2 = default(RaycastHit);
				if ((Object)(object)main != (Object)null && Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val2, 200f))
				{
					val = ((RaycastHit)(ref val2)).point;
				}
				CustomWaypointStore.Set(val);
				Plugin.Log.LogInfo((object)$"Custom waypoint set at {val}");
				_lastReplanTime = -999f;
			}
		}

		private void HandleConfirmInput(Character local)
		{
			//IL_0018: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			ActionExecutor.Clear();
			_status = PathStatus.WaitingConfirm;
			if (PlayerInterruptedMovement() || Input.GetKeyDown(ModConfig.TakeoverKey.Value))
			{
				_confirmUi.Hide();
				ForceManual("interrupt during confirm");
			}
			else if (Input.GetKeyDown(ModConfig.ConfirmKey.Value))
			{
				if (_pendingKind == PendingActionKind.CliffDrop)
				{
					LocalProbeDecision decision = new LocalProbeDecision
					{
						Action = LocalAction.DropDown,
						MoveDirection = _pendingDropDir
					};
					ActionExecutor.ApplyDecision(local, decision, sprint: false);
				}
				else
				{
					PendingActionKind pendingKind = _pendingKind;
					if ((uint)(pendingKind - 2) <= 1u)
					{
						ActionExecutor.RequestInteractOnce();
					}
				}
				_confirmUi.Hide();
				_pendingKind = PendingActionKind.None;
				_mode = ControlMode.Guided;
				_lastReplanTime = -999f;
			}
			else if (Input.GetKeyDown(ModConfig.DenyKey.Value))
			{
				_confirmUi.Hide();
				_pendingKind = PendingActionKind.None;
				_mode = ControlMode.Guided;
				_wpIndex++;
				_lastReplanTime = -999f;
				_status = PathStatus.Replanning;
			}
		}

		private void EnterConfirm(LocalProbeDecision decision)
		{
			//IL_0015: 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)
			_mode = ControlMode.ConfirmWait;
			_pendingKind = decision.ConfirmKind;
			_pendingDropDir = decision.MoveDirection;
			ActionExecutor.Clear();
			string message = decision.ConfirmKind switch
			{
				PendingActionKind.CliffDrop => "即将执行较高落差移动(自动跳崖)。是否继续?", 
				PendingActionKind.OpenChest => "路线建议开箱。是否手动确认开箱?", 
				PendingActionKind.UseConsumable => "路线建议消耗道具。是否确认使用?", 
				_ => "需要确认危险动作。", 
			};
			_confirmUi.Show(decision.ConfirmKind, message, decision.DropHeight);
		}

		private void EnterConfirmChest(Luggage lug)
		{
			_mode = ControlMode.ConfirmWait;
			_pendingKind = PendingActionKind.OpenChest;
			ActionExecutor.Clear();
			string text = (string.IsNullOrEmpty(lug.displayName) ? "Luggage" : lug.displayName);
			_confirmUi.Show(PendingActionKind.OpenChest, "靠近箱子「" + text + "」。Mod 不会自动开箱,确认后按一次交互。");
		}

		private bool TryDetectIntentionalChest(Character local, out Luggage? lug)
		{
			//IL_0033: 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_0069: 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)
			lug = null;
			if (Luggage.ALL_LUGGAGE == null)
			{
				return false;
			}
			foreach (Luggage item in Luggage.ALL_LUGGAGE)
			{
				if (!((Object)(object)item == (Object)null) && !item.IsOpen && Vector3.Distance(local.Center, item.Center()) < 1.8f && _wpIndex < _waypoints.Count && Vector3.Distance(_waypoints[_wpIndex], item.Center()) < 3f)
				{
					lug = item;
					return true;
				}
			}
			return false;
		}

		private void Replan(Character local)
		{
			//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_0041: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: 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_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)
			_status = PathStatus.Planning;
			_lastReplanTime = Time.time;
			_lastGoalKind = _goal.Kind;
			_lastGoalPos = _goal.Position;
			_lastLoadout = InventoryReader.Read(local);
			List<LootPoint> list = LootScanner.ScanNear(local.Center, ModConfig.GraphMaxRadius.Value);
			List<Vector3> list2 = new List<Vector3>();
			foreach (LootPoint item in list)
			{
				list2.Add(item.Position);
			}
			MapGraph mapGraph = _graphBuilder.Build(local.Center, _goal.Position, list2);
			if (mapGraph.Nodes.Count < 2)
			{
				_waypoints.Clear();
				return;
			}
			int startId = 0;
			int goalId = 1;
			PathResult direct = _pathfinder.Find(mapGraph, startId, goalId, _lastLoadout);
			PathResult pathResult = _lootOptimizer.Optimize(mapGraph, startId, goalId, _lastLoadout, list, direct);
			_waypoints.Clear();
			if (pathResult.Success && pathResult.Waypoints.Count > 0)
			{
				_waypoints.AddRange(pathResult.Waypoints);
				_wpIndex = 0;
				_status = PathStatus.Moving;
				_lastProgressPos = local.Center;
				_lastProgressTime = Time.time;
				_visualizer?.SetPath(_waypoints);
				Plugin.Log.LogInfo((object)$"Replanned: {_waypoints.Count} waypoints, cost={pathResult.TotalCost:0.0}, goal={_goal.Label}");
			}
			else
			{
				_waypoints.Add(local.Center);
				_waypoints.Add(_goal.Position);
				_wpIndex = 0;
				_status = PathStatus.Moving;
				_visualizer?.SetPath(_waypoints);
			}
		}

		private bool LoadoutChanged(Character local)
		{
			PlayerLoadout playerLoadout = InventoryReader.Read(local);
			if (playerLoadout.HasRope == _lastLoadout.HasRope && playerLoadout.HasClimbSpike == _lastLoadout.HasClimbSpike)
			{
				return Mathf.Abs(playerLoadout.Stamina - _lastLoadout.Stamina) > playerLoadout.MaxStamina * 0.25f;
			}
			return true;
		}

		private void UpdateStuck(Character local)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Distance(local.Center, _lastProgressPos) > 0.75f)
			{
				_lastProgressPos = local.Center;
				_lastProgressTime = Time.time;
			}
			else if (Time.time - _lastProgressTime > ModConfig.StuckTimeoutSeconds.Value)
			{
				_status = PathStatus.Stuck;
				_status = PathStatus.Replanning;
				_lastReplanTime = -999f;
				_lastProgressTime = Time.time;
			}
		}

		private static bool PlayerInterruptedMovement()
		{
			if (!Input.GetKey((KeyCode)119) && !Input.GetKey((KeyCode)97) && !Input.GetKey((KeyCode)115) && !Input.GetKey((KeyCode)100))
			{
				return Input.GetKey((KeyCode)32);
			}
			return true;
		}

		private void ForceManual(string reason)
		{
			if (_mode != ControlMode.Manual)
			{
				Plugin.Log.LogInfo((object)("Manual mode (" + reason + ")"));
			}
			_mode = ControlMode.Manual;
			_confirmUi.Hide();
			_pendingKind = PendingActionKind.None;
			ActionExecutor.Clear();
			if (!ModConfig.ShowPathWhenManual.Value)
			{
				_visualizer?.Clear();
			}
		}

		private void RefreshHud(Character local)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			_hud.Mode = _mode;
			_hud.Status = _status;
			_hud.GoalKind = _goal.Kind;
			_hud.GoalLabel = _goal.Label;
			_hud.Distance = ((_goal.Kind == GoalKind.None) ? 0f : Vector3.Distance(local.Center, _goal.Position));
			_hud.Action = _lastAction;
			_hud.Stamina = local.data.currentStamina;
			_hud.MaxStamina = local.GetMaxStamina();
			_hud.Extra = ((_waypoints.Count > 0) ? $"路点 {_wpIndex}/{_waypoints.Count}" : "");
		}
	}
	[BepInPlugin("Local.PeakAutoPathfind", "PeakAutoPathfind", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony? _harmony;

		private GameObject? _controllerGo;

		public const string Id = "Local.PeakAutoPathfind";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "PeakAutoPathfind";

		public static string Version => "0.1.0";

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("Local.PeakAutoPathfind");
			_harmony.PatchAll();
			_controllerGo = new GameObject("PeakAutoPathfind_Controller");
			Object.DontDestroyOnLoad((Object)(object)_controllerGo);
			_controllerGo.AddComponent<PathfindController>();
			Log.LogInfo((object)$"{Name} v{Version} loaded. Takeover={ModConfig.TakeoverKey.Value}");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)_controllerGo != (Object)null)
			{
				Object.Destroy((Object)(object)_controllerGo);
			}
		}
	}
	internal enum ControlMode
	{
		Manual,
		Guided,
		ConfirmWait
	}
	internal enum PathStatus
	{
		Idle,
		Seeking,
		Planning,
		Moving,
		Climb,
		Replanning,
		Stuck,
		Arrived,
		WaitingConfirm
	}
	internal enum GoalKind
	{
		None,
		Ping,
		Campfire,
		Peak,
		Custom
	}
	internal enum PendingActionKind
	{
		None,
		CliffDrop,
		OpenChest,
		UseConsumable
	}
	internal enum LocalAction
	{
		Hold,
		FollowWaypoint,
		Direct,
		Detour,
		Climb,
		JumpGrab,
		GapJump,
		DropDown
	}
}
namespace PeakAutoPathfind.UI
{
	internal sealed class ConfirmPromptUI
	{
		public bool Visible;

		public PendingActionKind Kind;

		public string Message = "";

		public float DetailValue;

		public void Show(PendingActionKind kind, string message, float detail = 0f)
		{
			Visible = true;
			Kind = kind;
			Message = message;
			DetailValue = detail;
		}

		public void Hide()
		{
			Visible = false;
			Kind = PendingActionKind.None;
			Message = "";
		}

		public void Draw()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (Visible)
			{
				float num = 520f;
				float num2 = 160f;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.22f, num, num2);
				GUI.Box(val, "PeakAutoPathfind — 需要确认");
				GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 16f, ((Rect)(ref val)).y + 28f, num - 32f, num2 - 36f));
				GUILayout.Label(Message, Array.Empty<GUILayoutOption>());
				if (Kind == PendingActionKind.CliffDrop)
				{
					GUILayout.Label($"预计落差: {DetailValue:0.0} m(安全阈值 {ModConfig.SafeDropHeight.Value:0.0} m)", Array.Empty<GUILayoutOption>());
				}
				GUILayout.Space(10f);
				GUILayout.Label($"[{ModConfig.ConfirmKey.Value}] 接受    [{ModConfig.DenyKey.Value}] 拒绝并重规划    [WASD/空格/{ModConfig.TakeoverKey.Value}] 中断接管", Array.Empty<GUILayoutOption>());
				GUILayout.EndArea();
			}
		}
	}
	internal sealed class StatusHud
	{
		public ControlMode Mode;

		public PathStatus Status;

		public GoalKind GoalKind;

		public string GoalLabel = "";

		public float Distance;

		public LocalAction Action;

		public float Stamina;

		public float MaxStamina;

		public string Extra = "";

		public void Draw()
		{
			//IL_0021: 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_0104: 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)
			if (ModConfig.Enabled.Value)
			{
				GUI.Box(new Rect(12f, 12f, 360f, 118f), "PeakAutoPathfind");
				GUILayout.BeginArea(new Rect(20f, 34f, 340f, 90f));
				GUILayout.Label($"模式: {Mode}   状态: {Status}", Array.Empty<GUILayoutOption>());
				GUILayout.Label($"目标: {GoalLabel} ({GoalKind})  距离: {Distance:0.0}m", Array.Empty<GUILayoutOption>());
				GUILayout.Label($"动作: {Action}   体力: {Stamina:0}/{MaxStamina:0}", Array.Empty<GUILayoutOption>());
				if (!string.IsNullOrEmpty(Extra))
				{
					GUILayout.Label(Extra, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Label($"热键: {ModConfig.TakeoverKey.Value}=接管  {ModConfig.CustomWaypointKey.Value}=路标", Array.Empty<GUILayoutOption>());
				GUILayout.EndArea();
			}
		}
	}
	internal sealed class PathVisualizer : MonoBehaviour
	{
		private LineRenderer? _line;

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

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			_line = ((Component)this).gameObject.AddComponent<LineRenderer>();
			((Renderer)_line).material = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Hidden/Internal-Colored"));
			_line.startWidth = 0.12f;
			_line.endWidth = 0.06f;
			_line.startColor = new Color(0.2f, 0.85f, 1f, 0.9f);
			_line.endColor = new Color(0.2f, 1f, 0.45f, 0.55f);
			_line.positionCount = 0;
			_line.useWorldSpace = true;
			_line.numCapVertices = 2;
			_line.numCornerVertices = 2;
		}

		public void SetPath(IReadOnlyList<Vector3> waypoints)
		{
			_points.Clear();
			if (waypoints != null)
			{
				_points.AddRange(waypoints);
			}
			Refresh();
		}

		public void Clear()
		{
			_points.Clear();
			Refresh();
		}

		private void Refresh()
		{
			//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_0046: 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))
			{
				_line.positionCount = _points.Count;
				for (int i = 0; i < _points.Count; i++)
				{
					_line.SetPosition(i, _points[i] + Vector3.up * 0.35f);
				}
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_line != (Object)null && (Object)(object)((Renderer)_line).material != (Object)null)
			{
				Object.Destroy((Object)(object)((Renderer)_line).material);
			}
		}
	}
}
namespace PeakAutoPathfind.Player
{
	internal sealed class DesiredInput
	{
		public Vector2 Move;

		public bool Jump;

		public bool Sprint;

		public bool Interact;

		public bool Active;
	}
	internal static class ActionExecutor
	{
		public static DesiredInput Current { get; } = new DesiredInput();

		public static void Clear()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Current.Active = false;
			Current.Move = Vector2.zero;
			Current.Jump = false;
			Current.Sprint = false;
			Current.Interact = false;
		}

		public static void ApplyDecision(Character character, LocalProbeDecision decision, bool sprint)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0078: 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_007f: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			Current.Active = true;
			Current.Sprint = sprint;
			Current.Jump = false;
			Current.Interact = false;
			Vector3 val = character.data.lookDirection_Flat;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = ((Component)character).transform.forward;
			}
			val.y = 0f;
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = Vector3.Cross(Vector3.up, val);
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 moveDirection = decision.MoveDirection;
			moveDirection.y = 0f;
			if (((Vector3)(ref moveDirection)).sqrMagnitude < 0.01f)
			{
				Current.Move = Vector2.zero;
			}
			else
			{
				((Vector3)(ref moveDirection)).Normalize();
				float num = Vector3.Dot(moveDirection, val);
				float num2 = Vector3.Dot(moveDirection, normalized);
				DesiredInput current = Current;
				Vector2 val3 = new Vector2(num2, num);
				current.Move = ((Vector2)(ref val3)).normalized;
			}
			switch (decision.Action)
			{
			case LocalAction.JumpGrab:
			case LocalAction.GapJump:
				Current.Jump = ModConfig.AllowAutoJump.Value;
				break;
			case LocalAction.Hold:
				Current.Move = Vector2.zero;
				break;
			case LocalAction.FollowWaypoint:
			case LocalAction.Direct:
			case LocalAction.Detour:
			case LocalAction.Climb:
				break;
			}
		}

		public static void RequestInteractOnce()
		{
			Current.Active = true;
			Current.Interact = true;
		}
	}
}
namespace PeakAutoPathfind.Planning
{
	internal sealed class PlayerLoadout
	{
		public float Stamina;

		public float MaxStamina;

		public bool HasRope;

		public bool HasClimbSpike;

		public bool HasConsumable;

		public readonly List<string> ItemNames = new List<string>();
	}
	internal static class InventoryReader
	{
		public static PlayerLoadout Read(Character? character)
		{
			PlayerLoadout playerLoadout = new PlayerLoadout();
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return playerLoadout;
			}
			playerLoadout.Stamina = character.data.currentStamina;
			playerLoadout.MaxStamina = Mathf.Max(0.01f, character.GetMaxStamina());
			try
			{
				CharacterItems val = ((character.refs != null) ? character.refs.items : null);
				if ((Object)(object)val == (Object)null)
				{
					return playerLoadout;
				}
				Item currentItem = character.data.currentItem;
				if ((Object)(object)currentItem != (Object)null)
				{
					ConsiderItem(currentItem, playerLoadout);
				}
			}
			catch
			{
			}
			return playerLoadout;
		}

		private static void ConsiderItem(Item item, PlayerLoadout loadout)
		{
			string text = ((Object)item).name ?? "";
			loadout.ItemNames.Add(text);
			string text2 = text.ToLowerInvariant();
			if (text2.Contains("rope") || text2.Contains("ascender"))
			{
				loadout.HasRope = true;
			}
			if (text2.Contains("spike") || text2.Contains("piton") || text2.Contains("chalk"))
			{
				loadout.HasClimbSpike = true;
			}
			if (text2.Contains("food") || text2.Contains("heal") || text2.Contains("energy") || text2.Contains("scout"))
			{
				loadout.HasConsumable = true;
			}
		}
	}
	internal sealed class RouteCostEvaluator
	{
		public float EvaluateEdge(GraphEdge edge, PlayerLoadout loadout)
		{
			float num = edge.BaseCost + edge.ClimbCost;
			if (edge.DropHeight > ModConfig.SafeDropHeight.Value)
			{
				num += edge.DropHeight * 8f;
			}
			if (edge.RequiresTool && !loadout.HasRope && !loadout.HasClimbSpike)
			{
				num += 500f;
			}
			float num2 = loadout.Stamina / Mathf.Max(0.01f, loadout.MaxStamina);
			if (num2 < 0.35f)
			{
				num += edge.ClimbCost * 3f;
			}
			else if (num2 < 0.6f)
			{
				num += edge.ClimbCost * 1.2f;
			}
			return num;
		}

		public bool IsEdgeFeasible(GraphEdge edge, PlayerLoadout loadout)
		{
			if (edge.RequiresTool && !loadout.HasRope && !loadout.HasClimbSpike)
			{
				return false;
			}
			float num = edge.ClimbCost * 0.15f;
			if (loadout.Stamina < num && edge.ClimbCost > 2f)
			{
				return false;
			}
			return true;
		}
	}
	internal sealed class PathResult
	{
		public readonly List<Vector3> Waypoints = new List<Vector3>();

		public float TotalCost;

		public bool Success;
	}
	internal sealed class GlobalPathfinder
	{
		private readonly RouteCostEvaluator _cost = new RouteCostEvaluator();

		public PathResult Find(MapGraph graph, int startId, int goalId, PlayerLoadout loadout)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			PathResult pathResult = new PathResult();
			if (graph.Nodes.Count == 0 || startId < 0 || goalId < 0)
			{
				return pathResult;
			}
			int count = graph.Nodes.Count;
			float[] array = new float[count];
			float[] array2 = new float[count];
			int[] array3 = new int[count];
			bool[] array4 = new bool[count];
			for (int i = 0; i < count; i++)
			{
				array[i] = float.PositiveInfinity;
				array2[i] = float.PositiveInfinity;
				array3[i] = -1;
			}
			array[startId] = 0f;
			array2[startId] = Heuristic(graph.Nodes[startId].Position, graph.Nodes[goalId].Position);
			SortedSet<(float, int)> sortedSet = new SortedSet<(float, int)>(Comparer<(float, int)>.Create(delegate((float f, int id) a, (float f, int id) b)
			{
				int num2 = a.f.CompareTo(b.f);
				return (num2 == 0) ? a.id.CompareTo(b.id) : num2;
			}));
			sortedSet.Add((array2[startId], startId));
			while (sortedSet.Count > 0)
			{
				int item = sortedSet.Min.Item2;
				sortedSet.Remove(sortedSet.Min);
				if (item == goalId)
				{
					Reconstruct(graph, array3, item, pathResult);
					pathResult.Success = true;
					pathResult.TotalCost = array[goalId];
					return pathResult;
				}
				if (array4[item])
				{
					continue;
				}
				array4[item] = true;
				if (!graph.Adjacency.TryGetValue(item, out List<int> value))
				{
					continue;
				}
				foreach (int item2 in value)
				{
					GraphEdge graphEdge = graph.Edges[item2];
					int to = graphEdge.To;
					if (!array4[to] && (_cost.IsEdgeFeasible(graphEdge, loadout) || !graphEdge.RequiresTool || !(loadout.Stamina < 5f)))
					{
						float num = array[item] + _cost.EvaluateEdge(graphEdge, loadout);
						if (!(num >= array[to]))
						{
							array3[to] = item;
							array[to] = num;
							array2[to] = num + Heuristic(graph.Nodes[to].Position, graph.Nodes[goalId].Position);
							sortedSet.Add((array2[to], to));
						}
					}
				}
			}
			return pathResult;
		}

		private static float Heuristic(Vector3 a, Vector3 b)
		{
			//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)
			return Vector3.Distance(a, b);
		}

		private static void Reconstruct(MapGraph graph, int[] cameFrom, int current, PathResult result)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Stack<Vector3> stack = new Stack<Vector3>();
			while (current >= 0)
			{
				stack.Push(graph.Nodes[current].Position);
				current = cameFrom[current];
			}
			result.Waypoints.AddRange(stack);
		}
	}
	internal sealed class LocalProbeDecision
	{
		public LocalAction Action;

		public Vector3 MoveDirection;

		public float DropHeight;

		public bool NeedsConfirm;

		public PendingActionKind ConfirmKind;
	}
	internal sealed class LocalProbePlanner
	{
		private readonly LayerMask _mask = LayerMask.op_Implicit(-1);

		public LocalProbeDecision Decide(Character character, Vector3 waypoint, Vector3 goal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_003d: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_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_0063: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_008a: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_012b: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: 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_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			Vector3 center = character.Center;
			Vector3 val = waypoint - center;
			val.y = 0f;
			Vector3 val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : ((Vector3)(ref character.data.lookDirection_Flat)).normalized);
			float value = ModConfig.ProbeDistance.Value;
			Vector3 val3 = center + Vector3.up * 0.5f;
			Vector3 val4 = center + val2 * 1.2f + Vector3.up * 0.5f;
			float num = 0f;
			RaycastHit val5 = default(RaycastHit);
			num = ((!Physics.Raycast(val4, Vector3.down, ref val5, 30f, LayerMask.op_Implicit(_mask), (QueryTriggerInteraction)1)) ? 30f : (val4.y - ((RaycastHit)(ref val5)).point.y));
			if (num > ModConfig.SafeDropHeight.Value && waypoint.y < center.y - 1f)
			{
				return new LocalProbeDecision
				{
					Action = LocalAction.DropDown,
					MoveDirection = val2,
					DropHeight = num,
					NeedsConfirm = true,
					ConfirmKind = PendingActionKind.CliffDrop
				};
			}
			RaycastHit val6 = default(RaycastHit);
			if (Physics.SphereCast(val3, 0.3f, val2, ref val6, value, LayerMask.op_Implicit(_mask), (QueryTriggerInteraction)1))
			{
				float num2 = ((RaycastHit)(ref val6)).point.y - center.y;
				if (num2 > 0.4f && num2 < 1.3f && ModConfig.AllowAutoJump.Value)
				{
					return new LocalProbeDecision
					{
						Action = LocalAction.GapJump,
						MoveDirection = val2
					};
				}
				if (num2 >= 1.3f && ModConfig.AllowAutoClimb.Value)
				{
					return new LocalProbeDecision
					{
						Action = LocalAction.Climb,
						MoveDirection = val2
					};
				}
				Vector3 val7 = Vector3.Cross(Vector3.up, val2);
				Vector3 normalized = ((Vector3)(ref val7)).normalized;
				val7 = val2 + normalized;
				RaycastHit val8 = default(RaycastHit);
				if (!Physics.SphereCast(val3, 0.3f, ((Vector3)(ref val7)).normalized, ref val8, value * 0.8f, LayerMask.op_Implicit(_mask), (QueryTriggerInteraction)1))
				{
					LocalProbeDecision obj = new LocalProbeDecision
					{
						Action = LocalAction.Detour
					};
					val7 = val2 + normalized;
					obj.MoveDirection = ((Vector3)(ref val7)).normalized;
					return obj;
				}
				val7 = val2 - normalized;
				if (!Physics.SphereCast(val3, 0.3f, ((Vector3)(ref val7)).normalized, ref val8, value * 0.8f, LayerMask.op_Implicit(_mask), (QueryTriggerInteraction)1))
				{
					LocalProbeDecision obj2 = new LocalProbeDecision
					{
						Action = LocalAction.Detour
					};
					val7 = val2 - normalized;
					obj2.MoveDirection = ((Vector3)(ref val7)).normalized;
					return obj2;
				}
				return new LocalProbeDecision
				{
					Action = LocalAction.Hold,
					MoveDirection = Vector3.zero
				};
			}
			return new LocalProbeDecision
			{
				Action = LocalAction.FollowWaypoint,
				MoveDirection = val2
			};
		}
	}
	internal sealed class GraphNode
	{
		public int Id;

		public Vector3 Position;

		public bool IsLoot;

		public bool RequiresClimb;
	}
	internal sealed class GraphEdge
	{
		public int From;

		public int To;

		public float BaseCost;

		public float ClimbCost;

		public float DropHeight;

		public bool RequiresTool;

		public string ToolHint = "";
	}
	internal sealed class MapGraph
	{
		public readonly List<GraphNode> Nodes = new List<GraphNode>();

		public readonly List<GraphEdge> Edges = new List<GraphEdge>();

		public readonly Dictionary<int, List<int>> Adjacency = new Dictionary<int, List<int>>();

		public void Clear()
		{
			Nodes.Clear();
			Edges.Clear();
			Adjacency.Clear();
		}

		public int AddNode(Vector3 pos, bool isLoot = false, bool requiresClimb = false)
		{
			//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)
			int count = Nodes.Count;
			Nodes.Add(new GraphNode
			{
				Id = count,
				Position = pos,
				IsLoot = isLoot,
				RequiresClimb = requiresClimb
			});
			Adjacency[count] = new List<int>();
			return count;
		}

		public void AddEdge(GraphEdge edge)
		{
			Edges.Add(edge);
			Adjacency[edge.From].Add(Edges.Count - 1);
		}
	}
	internal sealed class MapGraphBuilder
	{
		private readonly LayerMask _groundMask = LayerMask.op_Implicit(-1);

		public MapGraph Build(Vector3 start, Vector3 goal, IReadOnlyList<Vector3> lootPoints)
		{
			//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_001e: 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_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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			MapGraph mapGraph = new MapGraph();
			float value = ModConfig.GraphSampleSpacing.Value;
			float value2 = ModConfig.GraphMaxRadius.Value;
			Vector3 val = (start + goal) * 0.5f;
			float num = Mathf.Max(Vector3.Distance(start, goal) * 0.75f + 40f, 60f);
			num = Mathf.Min(num, value2);
			int item = mapGraph.AddNode(SnapToGround(start));
			int item2 = mapGraph.AddNode(SnapToGround(goal));
			List<int> list = new List<int> { item, item2 };
			int num2 = Mathf.Clamp(Mathf.CeilToInt(num * 2f / value), 8, 48);
			for (int i = -num2; i <= num2; i++)
			{
				for (int j = -num2; j <= num2; j++)
				{
					Vector3 val2 = val + new Vector3((float)i * value, 40f, (float)j * value);
					if (TryFindGround(val2, out var ground) && !(Vector3.Distance(new Vector3(ground.x, 0f, ground.z), new Vector3(val.x, 0f, val.z)) > num))
					{
						list.Add(mapGraph.AddNode(ground));
					}
				}
			}
			foreach (Vector3 lootPoint in lootPoints)
			{
				list.Add(mapGraph.AddNode(SnapToGround(lootPoint), isLoot: true));
			}
			float num3 = value * 1.75f;
			for (int k = 0; k < mapGraph.Nodes.Count; k++)
			{
				for (int l = k + 1; l < mapGraph.Nodes.Count; l++)
				{
					Vector3 position = mapGraph.Nodes[k].Position;
					Vector3 position2 = mapGraph.Nodes[l].Position;
					float num4 = Vector2.Distance(new Vector2(position.x, position.z), new Vector2(position2.x, position2.z));
					if ((!(num4 > num3) || !(Vector3.Distance(position, position2) > num3 * 1.4f)) && HasClearance(position, position2))
					{
						float num5 = position.y - position2.y;
						float num6 = Mathf.Max(0f, position2.y - position.y);
						bool flag = num6 > 1.6f;
						bool flag2 = num6 > 4.5f;
						float baseCost = Vector3.Distance(position, position2);
						mapGraph.AddEdge(new GraphEdge
						{
							From = k,
							To = l,
							BaseCost = baseCost,
							ClimbCost = num6 * 2.2f,
							DropHeight = Mathf.Max(0f, num5),
							RequiresTool = flag2,
							ToolHint = (flag2 ? "rope_or_spike" : "")
						});
						mapGraph.AddEdge(new GraphEdge
						{
							From = l,
							To = k,
							BaseCost = baseCost,
							ClimbCost = Mathf.Max(0f, position.y - position2.y) * 2.2f,
							DropHeight = Mathf.Max(0f, position2.y - position.y),
							RequiresTool = (Mathf.Max(0f, position.y - position2.y) > 4.5f),
							ToolHint = ""
						});
					}
				}
			}
			return mapGraph;
		}

		private Vector3 SnapToGround(Vector3 p)
		{
			//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_000c: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!TryFindGround(p + Vector3.up * 30f, out var ground))
			{
				return p;
			}
			return ground;
		}

		private bool TryFindGround(Vector3 from, out Vector3 ground)
		{
			//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_0007: 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_0015: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			ground = from;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(from, Vector3.down, ref val, 80f, LayerMask.op_Implicit(_groundMask), (QueryTriggerInteraction)1))
			{
				ground = ((RaycastHit)(ref val)).point + Vector3.up * 0.15f;
				return Vector3.Angle(((RaycastHit)(ref val)).normal, Vector3.up) < 55f;
			}
			return false;
		}

		private bool HasClearance(Vector3 a, Vector3 b)
		{
			//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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.01f)
			{
				return true;
			}
			val /= magnitude;
			Vector3 val2 = a + Vector3.up * 0.9f;
			RaycastHit val3 = default(RaycastHit);
			if (Physics.SphereCast(val2, 0.25f, val, ref val3, magnitude, LayerMask.op_Implicit(_groundMask), (QueryTriggerInteraction)1))
			{
				return ((RaycastHit)(ref val3)).distance > magnitude - 0.6f;
			}
			return true;
		}
	}
}
namespace PeakAutoPathfind.Patches
{
	[HarmonyPatch(typeof(PointPinger), "ReceivePoint_Rpc")]
	internal static class PointPingerPatch
	{
		private static void Postfix(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			PingTracker.Record(point);
			Plugin.Log.LogInfo((object)$"[PeakAutoPathfind] Ping recorded at {point}");
		}
	}
	[HarmonyPatch(typeof(CharacterInput), "Sample")]
	internal static class CharacterInputPatch
	{
		private static void Postfix(CharacterInput __instance)
		{
			//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)
			DesiredInput current = ActionExecutor.Current;
			if (!current.Active)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.input != (Object)(object)__instance))
			{
				__instance.movementInput = current.Move;
				if (current.Jump)
				{
					__instance.jumpWasPressed = true;
					__instance.jumpIsPressed = true;
				}
				if (current.Sprint)
				{
					__instance.sprintIsPressed = true;
				}
				if (current.Interact)
				{
					__instance.interactWasPressed = true;
					__instance.interactIsPressed = true;
					current.Interact = false;
				}
			}
		}
	}
}
namespace PeakAutoPathfind.Loot
{
	internal sealed class LootPoint
	{
		public Vector3 Position;

		public string Name = "";

		public Luggage? Source;
	}
	internal static class LootScanner
	{
		public static List<LootPoint> ScanNear(Vector3 origin, float radius)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			List<LootPoint> list = new List<LootPoint>();
			if (Luggage.ALL_LUGGAGE == null)
			{
				return list;
			}
			foreach (Luggage item in Luggage.ALL_LUGGAGE)
			{
				if (!((Object)(object)item == (Object)null) && !item.IsOpen)
				{
					Vector3 val = item.Center();
					if (!(Vector3.Distance(origin, val) > radius))
					{
						list.Add(new LootPoint
						{
							Position = val,
							Name = (string.IsNullOrEmpty(item.displayName) ? ((Object)item).name : item.displayName),
							Source = item
						});
					}
				}
			}
			return list;
		}
	}
	internal sealed class LootAwareOptimizer
	{
		private readonly GlobalPathfinder _pathfinder = new GlobalPathfinder();

		public PathResult Optimize(MapGraph graph, int startId, int goalId, PlayerLoadout loadout, IReadOnlyList<LootPoint> loot, PathResult direct)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableLootOptimization.Value || loot.Count == 0 || !direct.Success)
			{
				return direct;
			}
			float value = ModConfig.ConservativeLootSaveRatio.Value;
			PathResult pathResult = direct;
			float num = direct.TotalCost;
			foreach (LootPoint item in loot)
			{
				int num2 = FindNearestNode(graph, item.Position);
				if (num2 < 0)
				{
					continue;
				}
				PlayerLoadout playerLoadout = CloneLoadout(loadout);
				playerLoadout.HasRope = true;
				playerLoadout.HasClimbSpike = true;
				PathResult pathResult2 = _pathfinder.Find(graph, startId, num2, loadout);
				PathResult pathResult3 = _pathfinder.Find(graph, num2, goalId, playerLoadout);
				if (pathResult2.Success && pathResult3.Success)
				{
					float num3 = pathResult2.TotalCost + pathResult3.TotalCost + 8f;
					float num4 = (direct.TotalCost - num3) / Mathf.Max(1f, direct.TotalCost);
					bool flag = !loadout.HasRope && !loadout.HasClimbSpike && pathResult3.TotalCost + 50f < _pathfinder.Find(graph, num2, goalId, loadout).TotalCost;
					if ((num4 >= value || flag) && num3 < num)
					{
						num = num3;
						pathResult = Merge(pathResult2, pathResult3);
						pathResult.TotalCost = num3;
					}
				}
			}
			return pathResult;
		}

		private static int FindNearestNode(MapGraph graph, Vector3 pos)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			int result = -1;
			float num = float.MaxValue;
			for (int i = 0; i < graph.Nodes.Count; i++)
			{
				float num2 = Vector3.Distance(graph.Nodes[i].Position, pos);
				if (num2 < num)
				{
					num = num2;
					result = i;
				}
			}
			return result;
		}

		private static PlayerLoadout CloneLoadout(PlayerLoadout src)
		{
			PlayerLoadout playerLoadout = new PlayerLoadout
			{
				Stamina = src.Stamina,
				MaxStamina = src.MaxStamina,
				HasRope = src.HasRope,
				HasClimbSpike = src.HasClimbSpike,
				HasConsumable = src.HasConsumable
			};
			playerLoadout.ItemNames.AddRange(src.ItemNames);
			return playerLoadout;
		}

		private static PathResult Merge(PathResult a, PathResult b)
		{
			//IL_004f: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			PathResult pathResult = new PathResult
			{
				Success = true
			};
			pathResult.Waypoints.AddRange(a.Waypoints);
			if (b.Waypoints.Count > 0)
			{
				int num = 0;
				if (pathResult.Waypoints.Count > 0 && Vector3.Distance(pathResult.Waypoints[pathResult.Waypoints.Count - 1], b.Waypoints[0]) < 0.5f)
				{
					num = 1;
				}
				for (int i = num; i < b.Waypoints.Count; i++)
				{
					pathResult.Waypoints.Add(b.Waypoints[i]);
				}
			}
			return pathResult;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}