Decompiled source of PEAK Troll Mod v0.5.0

BepInEx/plugins/PeakTrollMod/PeakTrollMod.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Peak;
using Peak.Network;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using Zorro.Core.Serizalization;

[assembly: ComVisible(false)]
[assembly: Guid("8e2c4942-7667-4f44-a4d8-88d4502a3db9")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyProduct("PEAK Troll Mod")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyTitle("PEAK Troll Mod")]
[assembly: AssemblyDescription("An all-in-one BepInEx 5 mod for PEAK")]
[assembly: AssemblyCompany("PEAK Troll Mod Contributors")]
[assembly: AssemblyVersion("0.5.0.0")]
namespace PeakTrollMod;

[BepInPlugin("com.dougl.peaktrollmod", "PEAK Troll Mod", "0.5.0")]
[BepInProcess("PEAK.exe")]
public sealed class TrollModPlugin : BaseUnityPlugin
{
	public const string Guid = "com.dougl.peaktrollmod";

	public const string Name = "PEAK Troll Mod";

	public const string Version = "0.5.0";

	internal static TrollModPlugin Instance;

	internal ModConfig Settings;

	internal CapabilityRegistry Capabilities;

	internal PlayerManager Players;

	internal TrollNetworkManager Network;

	internal PlayerActions Actions;

	internal NoWaitManager NoWait;

	internal RecoveryManager Recovery;

	internal QuickReconnectManager QuickReconnect;

	internal ModConfigBrowser ModBrowser;

	internal TeamStatusManager TeamStatus;

	internal QuickBackpackManager QuickBackpack;

	internal BetterSpectatingManager BetterSpectating;

	internal PlayerPreferencesManager PlayerPreferences;

	internal LobbyReadinessManager LobbyReadiness;

	internal ActionShortcutManager Shortcuts;

	internal UnlimitedLobbyManager UnlimitedLobby;

	internal StaminaEffectPreviewManager StaminaEffectPreview;

	internal SurvivalAssistManager SurvivalAssist;

	internal LuggageNavigationManager LuggageNavigation;

	internal ClimbForecastManager ClimbForecast;

	internal PartySupplyAdvisorManager PartySupplyAdvisor;

	internal HotkeyConflictDoctor HotkeyDoctor;

	internal InfiniteRescueClawManager InfiniteRescueClaw;

	internal HungerAmplifierManager HungerAmplifier;

	internal InfiniteJetpackFuelManager InfiniteJetpackFuel;

	internal BiggerBackpackManager BiggerBackpack;

	internal BackpackProtectionManager BackpackProtection;

	internal StartAsSkeletonManager StartAsSkeleton;

	internal ScoutEspManager ScoutEsp;

	internal ProfileManager Profiles;

	internal LobbyProfileSyncManager LobbyProfileSync;

	internal AntiSoftlockManager AntiSoftlock;

	internal MindControlManager MindControl;

	internal SpawnManager Spawns;

	internal MirageManager Mirages;

	internal PingPlacementManager PingPlacement;

	internal PhantomPingManager PhantomPings;

	internal AudioManager Audio;

	internal AppearanceManager Appearance;

	internal ProgressionManager Progression;

	internal CampfireTrollManager CampfireTroll;

	internal HelicopterTrollManager HelicopterTroll;

	internal ChaosManager Chaos;

	internal ExpeditionDirectorManager Director;

	internal SummitSaboteurManager SummitSaboteur;

	internal ResetManager Reset;

	internal TrollUIManager Ui;

	internal UiFontManager UiFonts;

	private Harmony _harmony;

	private float _nextDynamicRefresh;

	private float _nextMenuToggle;

	private float _nextMenuInputWarning;

	private bool _menuKeyWasPressed;

	private bool _wasInRoom;

	private bool _shutdown;

	private void Awake()
	{
		//IL_057a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0584: Expected O, but got Unknown
		Instance = this;
		Settings = new ModConfig(((BaseUnityPlugin)this).Config);
		UiFonts = new UiFontManager(((BaseUnityPlugin)this).Logger);
		UiFonts.Load();
		ModBrowser = new ModConfigBrowser();
		ModBrowser.Refresh();
		Capabilities = new CapabilityRegistry(((BaseUnityPlugin)this).Logger);
		Capabilities.Discover();
		Players = new PlayerManager(((BaseUnityPlugin)this).Logger);
		Audio = new AudioManager(((BaseUnityPlugin)this).Logger, (BaseUnityPlugin)(object)this);
		PlayerPreferences = new PlayerPreferencesManager(((BaseUnityPlugin)this).Logger, Players, Audio, Settings);
		LobbyReadiness = new LobbyReadinessManager(Players);
		Mirages = new MirageManager(((BaseUnityPlugin)this).Logger);
		Actions = new PlayerActions(((BaseUnityPlugin)this).Logger, Players, Capabilities, Audio);
		NoWait = new NoWaitManager(((BaseUnityPlugin)this).Logger, Players, Actions, Capabilities, Settings);
		Recovery = new RecoveryManager(((BaseUnityPlugin)this).Logger, Players, Actions);
		Profiles = new ProfileManager(Settings);
		LobbyProfileSync = new LobbyProfileSyncManager(Profiles, Players);
		AntiSoftlock = new AntiSoftlockManager(Players, Recovery, Settings, ((BaseUnityPlugin)this).Logger);
		QuickReconnect = new QuickReconnectManager(((BaseUnityPlugin)this).Logger, Settings, Capabilities);
		TeamStatus = new TeamStatusManager(Players, Settings, ModBrowser, PlayerPreferences);
		QuickBackpack = new QuickBackpackManager(((BaseUnityPlugin)this).Logger, Settings, ModBrowser);
		BetterSpectating = new BetterSpectatingManager(((BaseUnityPlugin)this).Logger, Players, Actions, Settings);
		Spawns = new SpawnManager(((BaseUnityPlugin)this).Logger, Players, Capabilities);
		Shortcuts = new ActionShortcutManager(Settings);
		UnlimitedLobby = new UnlimitedLobbyManager(((BaseUnityPlugin)this).Logger, Settings, Actions, Spawns);
		StaminaEffectPreview = new StaminaEffectPreviewManager(Settings, ((BaseUnityPlugin)this).Logger);
		SurvivalAssist = new SurvivalAssistManager(Settings, ((BaseUnityPlugin)this).Logger);
		LuggageNavigation = new LuggageNavigationManager(Settings, ((BaseUnityPlugin)this).Logger);
		ClimbForecast = new ClimbForecastManager(Settings, ((BaseUnityPlugin)this).Logger);
		PartySupplyAdvisor = new PartySupplyAdvisorManager(Players, Settings, ((BaseUnityPlugin)this).Logger);
		HotkeyDoctor = new HotkeyConflictDoctor(ModBrowser, Settings, ((BaseUnityPlugin)this).Logger);
		InfiniteRescueClaw = new InfiniteRescueClawManager(Settings, ((BaseUnityPlugin)this).Logger);
		HungerAmplifier = new HungerAmplifierManager(((BaseUnityPlugin)this).Logger, Players, Actions);
		InfiniteJetpackFuel = new InfiniteJetpackFuelManager(Settings, ((BaseUnityPlugin)this).Logger);
		BiggerBackpack = new BiggerBackpackManager(Settings, ((BaseUnityPlugin)this).Logger);
		BackpackProtection = new BackpackProtectionManager(Settings, ((BaseUnityPlugin)this).Logger);
		StartAsSkeleton = new StartAsSkeletonManager(Settings, ((BaseUnityPlugin)this).Logger);
		ScoutEsp = new ScoutEspManager(Players, Settings, ((BaseUnityPlugin)this).Logger);
		Network = new TrollNetworkManager(((BaseUnityPlugin)this).Logger, Players, Actions, Mirages, Audio, HungerAmplifier);
		LobbyProfileSync.AttachNetwork(Network);
		MindControl = new MindControlManager(((BaseUnityPlugin)this).Logger, Players, Network, Settings, Capabilities);
		PingPlacement = new PingPlacementManager(((BaseUnityPlugin)this).Logger, Mirages, Players, Network);
		PhantomPings = new PhantomPingManager(((BaseUnityPlugin)this).Logger, Players);
		Appearance = new AppearanceManager(((BaseUnityPlugin)this).Logger);
		Progression = new ProgressionManager(((BaseUnityPlugin)this).Logger, Players, Settings);
		CampfireTroll = new CampfireTrollManager(((BaseUnityPlugin)this).Logger, Players, Actions, Settings);
		HelicopterTroll = new HelicopterTrollManager(((BaseUnityPlugin)this).Logger, Settings);
		Chaos = new ChaosManager(((BaseUnityPlugin)this).Logger, Players, Network, Actions, Mirages, Audio, Spawns);
		Director = new ExpeditionDirectorManager(((BaseUnityPlugin)this).Logger, Players, Actions, Spawns, Chaos, Network, Settings);
		Reset = new ResetManager(((BaseUnityPlugin)this).Logger, Actions, Mirages, Spawns, Audio, Appearance);
		SummitSaboteur = new SummitSaboteurManager(((BaseUnityPlugin)this).Logger, Players, Actions, Network, Spawns, Capabilities);
		Ui = new TrollUIManager(this);
		_harmony = new Harmony("com.dougl.peaktrollmod");
		_harmony.PatchAll(typeof(TrollModPlugin).Assembly);
		SceneManager.sceneLoaded += OnSceneLoaded;
		Players.Refresh();
		_wasInRoom = PhotonNetwork.InRoom;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("PEAK Troll Mod 0.5.0 loaded for PEAK " + Application.version + "."));
	}

	private void Update()
	{
		if (Ui.IsOpen && Input.GetKeyDown((KeyCode)27))
		{
			Ui.ForceClose();
		}
		HandleMenuInput();
		Players.Tick();
		PlayerPreferences.Tick();
		LobbyReadiness.Tick();
		QuickReconnect.Tick();
		Network.Tick();
		LobbyProfileSync.Tick();
		MindControl.Tick();
		Actions.Tick();
		Recovery.Tick();
		AntiSoftlock.Tick();
		NoWait.Tick();
		QuickBackpack.Tick(Ui.IsOpen);
		BetterSpectating.Tick(Ui.IsOpen);
		StaminaEffectPreview.Tick();
		SurvivalAssist.Tick();
		InfiniteJetpackFuel.Tick();
		BiggerBackpack.Tick();
		StartAsSkeleton.Tick();
		HungerAmplifier.Tick();
		LuggageNavigation.Tick();
		ScoutEsp.Tick();
		ClimbForecast.Tick();
		PartySupplyAdvisor.Tick();
		HotkeyDoctor.Tick();
		InfiniteRescueClaw.Tick();
		Audio.Tick();
		Mirages.Tick();
		PhantomPings.Tick();
		Spawns.Tick();
		UnlimitedLobby.Tick();
		Progression.Tick();
		HelicopterTroll.Tick();
		Chaos.Tick();
		Director.Tick();
		SummitSaboteur.Tick();
		Ui.Tick();
		bool inRoom = PhotonNetwork.InRoom;
		if (_wasInRoom && !inRoom)
		{
			Reset.ResetAll();
		}
		_wasInRoom = inRoom;
		if (Time.unscaledTime >= _nextDynamicRefresh)
		{
			_nextDynamicRefresh = Time.unscaledTime + 10f;
			Capabilities.RefreshDynamic();
			Actions.RefreshItemCatalog();
		}
	}

	private void HandleMenuInput()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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)
		KeyboardShortcut value = Settings.MenuKey.Value;
		bool flag = false;
		bool flag2 = false;
		try
		{
			flag = ((KeyboardShortcut)(ref value)).IsDown();
			flag2 = ((KeyboardShortcut)(ref value)).IsPressed();
		}
		catch (Exception ex)
		{
			if (Time.unscaledTime >= _nextMenuInputWarning)
			{
				_nextMenuInputWarning = Time.unscaledTime + 2f;
				Warn("Configured menu shortcut could not be read: " + ex.Message);
			}
		}
		bool flag3 = false;
		try
		{
			if ((int)((KeyboardShortcut)(ref value)).MainKey != 0)
			{
				flag3 = Input.GetKey(((KeyboardShortcut)(ref value)).MainKey);
			}
		}
		catch
		{
		}
		bool flag4 = flag3 && !_menuKeyWasPressed;
		_menuKeyWasPressed = flag3;
		if (Settings.MenuActivation.Value == MenuActivationMode.Toggle)
		{
			if ((flag || flag4) && Time.unscaledTime >= _nextMenuToggle)
			{
				_nextMenuToggle = Time.unscaledTime + 0.15f;
				Ui.Toggle();
			}
		}
		else
		{
			Ui.SetOpen(flag2 || flag3);
		}
	}

	private void OnGUI()
	{
		bool menuOpen = Ui != null && Ui.IsOpen;
		if (TeamStatus != null)
		{
			TeamStatus.Draw(menuOpen);
		}
		if (BetterSpectating != null)
		{
			BetterSpectating.Draw(menuOpen);
		}
		if (StaminaEffectPreview != null)
		{
			StaminaEffectPreview.Draw(menuOpen);
		}
		if (LuggageNavigation != null)
		{
			LuggageNavigation.Draw(menuOpen);
		}
		if (ScoutEsp != null)
		{
			ScoutEsp.Draw(menuOpen);
		}
		if (ClimbForecast != null)
		{
			ClimbForecast.Draw(menuOpen);
		}
		if (MindControl != null)
		{
			MindControl.Draw(menuOpen);
		}
		if (Ui != null)
		{
			Ui.Draw();
		}
	}

	private void FixedUpdate()
	{
		if (Actions != null)
		{
			Actions.FixedTick();
		}
		if (InfiniteRescueClaw != null)
		{
			InfiniteRescueClaw.FixedTick();
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		if (Reset != null)
		{
			Reset.ResetAll();
		}
		if (Players != null)
		{
			Players.Refresh();
		}
		if (Capabilities != null)
		{
			Capabilities.RefreshDynamic();
		}
		if (Actions != null)
		{
			Actions.RefreshItemCatalog();
		}
		if (NoWait != null)
		{
			NoWait.OnSceneLoaded();
		}
		if (Recovery != null)
		{
			Recovery.OnSceneLoaded();
		}
		if (BetterSpectating != null)
		{
			BetterSpectating.OnSceneLoaded();
		}
		if (UnlimitedLobby != null)
		{
			UnlimitedLobby.ResetScene();
		}
		if (StaminaEffectPreview != null)
		{
			StaminaEffectPreview.ResetScene();
		}
		if (SurvivalAssist != null)
		{
			SurvivalAssist.ResetScene();
		}
		if (InfiniteJetpackFuel != null)
		{
			InfiniteJetpackFuel.ResetScene();
		}
		if (BiggerBackpack != null)
		{
			BiggerBackpack.ResetScene();
		}
		if (StartAsSkeleton != null)
		{
			StartAsSkeleton.OnSceneLoaded();
		}
		if (LuggageNavigation != null)
		{
			LuggageNavigation.ResetScene();
		}
		if (ScoutEsp != null)
		{
			ScoutEsp.ResetScene();
		}
		if (AntiSoftlock != null)
		{
			AntiSoftlock.ResetScene();
		}
		if (LobbyProfileSync != null)
		{
			LobbyProfileSync.Reset();
		}
		if (ClimbForecast != null)
		{
			ClimbForecast.ResetScene();
		}
		if (PartySupplyAdvisor != null)
		{
			PartySupplyAdvisor.ResetScene();
		}
		if (InfiniteRescueClaw != null)
		{
			InfiniteRescueClaw.ResetScene();
		}
		if (HungerAmplifier != null)
		{
			HungerAmplifier.Reset();
		}
		if (MindControl != null)
		{
			MindControl.Reset();
		}
		if (Ui != null)
		{
			Ui.ResetVisualAssets();
		}
		if (CampfireTroll != null)
		{
			CampfireTroll.ResetScene();
		}
		if (SummitSaboteur != null)
		{
			SummitSaboteur.Reset();
		}
		if (Director != null)
		{
			Director.OnSceneLoaded();
		}
		if (HelicopterTroll != null)
		{
			HelicopterTroll.ResetScene();
		}
		DebugLog("Scene loaded: " + ((Scene)(ref scene)).name);
	}

	private void OnDisable()
	{
		if (!_shutdown)
		{
			if (Ui != null)
			{
				Ui.ForceClose();
			}
			if (Reset != null)
			{
				Reset.ResetAll();
			}
		}
	}

	private void OnEnable()
	{
		if (!_shutdown && Ui != null)
		{
			Ui.RecoverClosedState();
		}
	}

	private void OnDestroy()
	{
		Shutdown();
	}

	private void OnApplicationQuit()
	{
		Shutdown();
	}

	private void Shutdown()
	{
		if (!_shutdown)
		{
			_shutdown = true;
			SceneManager.sceneLoaded -= OnSceneLoaded;
			if (Ui != null)
			{
				Ui.ForceClose();
			}
			if (LuggageNavigation != null)
			{
				LuggageNavigation.ResetScene();
			}
			if (ScoutEsp != null)
			{
				ScoutEsp.ResetScene();
			}
			if (AntiSoftlock != null)
			{
				AntiSoftlock.ResetScene();
			}
			if (LobbyProfileSync != null)
			{
				LobbyProfileSync.Reset();
			}
			if (ClimbForecast != null)
			{
				ClimbForecast.ResetScene();
			}
			if (PartySupplyAdvisor != null)
			{
				PartySupplyAdvisor.ResetScene();
			}
			if (InfiniteRescueClaw != null)
			{
				InfiniteRescueClaw.RestoreAll();
			}
			if (InfiniteJetpackFuel != null)
			{
				InfiniteJetpackFuel.ResetScene();
			}
			if (BiggerBackpack != null)
			{
				BiggerBackpack.ResetScene();
			}
			if (StartAsSkeleton != null)
			{
				StartAsSkeleton.RestoreOwnedSkeleton();
			}
			if (HungerAmplifier != null)
			{
				HungerAmplifier.Reset();
			}
			if (MindControl != null)
			{
				MindControl.Reset();
			}
			if (SummitSaboteur != null)
			{
				SummitSaboteur.Reset();
			}
			if (Director != null)
			{
				Director.Stop(cleanup: true);
			}
			if (Reset != null)
			{
				Reset.ResetAll();
			}
			if (Audio != null)
			{
				Audio.Dispose();
			}
			if (Network != null)
			{
				Network.Dispose();
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
			if (UiFonts != null)
			{
				UiFonts.Dispose();
			}
			Instance = null;
		}
	}

	internal void DebugLog(string message)
	{
		if (Settings != null && Settings.DebugLogging.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[PTM] " + message));
		}
	}

	internal void Warn(string message)
	{
		((BaseUnityPlugin)this).Logger.LogWarning((object)("[PTM] " + message));
	}
}
[HarmonyPatch]
internal static class ImmortalityPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		string[] names = new string[8] { "Die", "DieInstantly", "DieInstantlyLocal", "RPCA_SetDead", "RPCA_Die", "PassOut", "RPCA_PassOut", "PassOutInstantly" };
		for (int i = 0; i < names.Length; i++)
		{
			MethodInfo method = AccessTools.Method(typeof(Character), names[i], new Type[0], (Type[])null);
			if (method != null)
			{
				yield return method;
			}
		}
	}

	private static bool Prefix(Character __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.SurvivalAssist != null && instance.SurvivalAssist.Immortality && !((Object)(object)__instance == (Object)null))
		{
			return !__instance.IsLocal;
		}
		return true;
	}
}
[HarmonyPatch(typeof(GamefeelHandler), "GetRotation")]
internal static class AccessibleCameraShakePatch
{
	private static void Postfix(ref Vector3 __result)
	{
		//IL_001a: 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)
		TrollModPlugin instance = TrollModPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.Settings != null)
		{
			__result *= Mathf.Clamp01(instance.Settings.CameraShakeScale.Value);
		}
	}
}
[HarmonyPatch(typeof(PointPinger), "get_canPing")]
internal static class SpectatorGhostPingPatch
{
	private static readonly FieldInfo LastPinged = AccessTools.Field(typeof(PointPinger), "_timeLastPinged");

	private static readonly FieldInfo Cooldown = AccessTools.Field(typeof(PointPinger), "coolDown");

	private static void Postfix(PointPinger __instance, ref bool __result)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		Character localCharacter = Character.localCharacter;
		if (!__result && !((Object)(object)instance == (Object)null) && instance.Settings != null && instance.Settings.BetterSpectatingEnabled.Value && instance.Settings.SpectateGhostPings.Value && !((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.data == (Object)null) && localCharacter.data.fullyPassedOut && !((Object)(object)__instance == (Object)null))
		{
			float num = ((LastPinged == null) ? 0f : ((float)LastPinged.GetValue(__instance)));
			float num2 = ((Cooldown == null) ? 0.5f : ((float)Cooldown.GetValue(__instance)));
			if (Time.time - num >= num2)
			{
				__result = true;
			}
		}
	}
}
[HarmonyPatch(typeof(CharacterItems), "DropAllItems")]
internal static class NoWaitInventoryPreservationPatch
{
	private static bool Prefix(CharacterItems __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.NoWait != null)
		{
			return !instance.NoWait.ShouldSuppressDrop(__instance);
		}
		return true;
	}
}
[HarmonyPatch(typeof(Character), "CanDoInput")]
internal static class GameplayInputPatch
{
	private static void Postfix(Character __instance, ref bool __result)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance != (Object)null && instance.Ui != null && instance.Ui.IsTyping && (Object)(object)__instance != (Object)null && __instance.IsLocal)
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(PointPinger), "DoPing")]
internal static class PingPlacementPatch
{
	private static bool Prefix(PointPinger __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance == (Object)null || instance.PingPlacement == null || !instance.PingPlacement.Active)
		{
			return true;
		}
		return !instance.PingPlacement.TryCapture(__instance);
	}
}
[HarmonyPatch(typeof(CursorHandler), "Update")]
internal static class CursorHandlerPatch
{
	private static bool Prefix()
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance == (Object)null || instance.Ui == null || !instance.Ui.IsOpen)
		{
			return true;
		}
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
		return false;
	}
}
[HarmonyPatch(typeof(GUIManager), "UpdateWindowStatus")]
internal static class WindowStatusPatch
{
	private static readonly FieldInfo ShowingCursor = AccessTools.Field(typeof(GUIManager), "<windowShowingCursor>k__BackingField");

	private static readonly FieldInfo BlockingInput = AccessTools.Field(typeof(GUIManager), "<windowBlockingInput>k__BackingField");

	private static readonly FieldInfo LastBlockedInput = AccessTools.Field(typeof(GUIManager), "lastBlockedInput");

	private static void Postfix(GUIManager __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.Ui != null && instance.Ui.IsOpen && !((Object)(object)__instance == (Object)null))
		{
			if (ShowingCursor != null)
			{
				ShowingCursor.SetValue(__instance, true);
			}
			if (BlockingInput != null)
			{
				BlockingInput.SetValue(__instance, instance.Ui.IsTyping);
			}
			if (LastBlockedInput != null && instance.Ui.IsTyping)
			{
				LastBlockedInput.SetValue(__instance, Time.frameCount);
			}
		}
	}
}
[HarmonyPatch(typeof(CharacterInput), "Sample")]
internal static class MindControlInputPatch
{
	private static void Postfix(CharacterInput __instance, bool __0)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance != (Object)null && instance.MindControl != null)
		{
			instance.MindControl.OnInputSampled(__instance, __0);
		}
	}
}
[HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")]
internal static class MindControlCameraPatch
{
	private static void Postfix(MainCameraMovement __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance != (Object)null && instance.MindControl != null)
		{
			instance.MindControl.OverrideCamera(__instance);
		}
	}
}
[HarmonyPatch(typeof(MirageLuggage), "Update")]
internal static class MesaMirageLuggagePatch
{
	private static void Postfix(MirageLuggage __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance != (Object)null && instance.LuggageNavigation != null)
		{
			instance.LuggageNavigation.SuppressNativeMirage((Component)(object)__instance);
		}
	}
}
[HarmonyPatch(typeof(Mirage), "Update")]
internal static class MesaMiragePatch
{
	private static void Postfix(Mirage __instance)
	{
		TrollModPlugin instance = TrollModPlugin.Instance;
		if ((Object)(object)instance != (Object)null && instance.LuggageNavigation != null)
		{
			instance.LuggageNavigation.SuppressNativeMirage((Component)(object)__instance);
		}
	}
}
internal enum FeatureCapability
{
	PlayerDiscovery,
	Ragdoll,
	Launch,
	Speed,
	Flight,
	Visibility,
	Teleport,
	StartEndTeleport,
	Resurrect,
	QuickReconnect,
	EmergencyRecovery,
	Knockout,
	Eliminate,
	StatusEffects,
	HungerAmplifier,
	DropHeldItem,
	GiveItem,
	ScoutmasterSpawn,
	MushroomZombieSpawn,
	LookerSpawn,
	Mandrake,
	PingPlacement,
	MirageLuggage,
	MirageStatue,
	MirageCapybara,
	MirageScout,
	FakeEnemyScoutmaster,
	FakeEnemyZombie,
	FakeEnemyLooker,
	FakeAudio,
	AppearanceSwap,
	VoiceSwap,
	IncomingVoiceMute,
	TalkWhileKnockedOut,
	PoisonCloud,
	SporeCloud,
	ZombieTargeting,
	DynamiteShower,
	ItemStorm,
	SkyLaunch,
	HorizonLaunch,
	WrongMountain,
	CosmeticUnlocks,
	BadgeUnlocks,
	PositionRoulette,
	OneLiveOne,
	ComboBuilder,
	SummitSaboteur,
	MindControl,
	InfiniteJetpackFuel,
	BiggerBackpack,
	BackpackProtection,
	StartAsSkeleton,
	CampfireReset,
	CampfireDeathTrap,
	HelicopterSuppression,
	PhantomPings
}
internal enum PermissionKind
{
	Anyone,
	EveryoneNeedsMod,
	HostOnly,
	Unsupported
}
internal enum NetCommand : byte
{
	Hello = 1,
	Ragdoll,
	Launch,
	Speed,
	Visibility,
	Teleport,
	Knockout,
	Eliminate,
	Status,
	ClearStatuses,
	GiveItem,
	Reset,
	FakeAudio,
	MirageScout,
	FakeEnemy,
	ClearMirages,
	HostSpawnScoutmaster,
	HostSpawnZombie,
	HostClearRequestedSpawns,
	MirageProp,
	SetHelicopterSuppression,
	PhantomPings,
	CancelPhantomPings,
	Flight,
	SetHungerAmplifier,
	SummitSabotageVictim,
	MindControlStart,
	MindControlAck,
	MindControlInput,
	MindControlStop,
	ProfileOffer,
	ProfileResponse,
	DirectorScenarioOffer,
	DirectorScenarioResponse
}
internal enum MirageKind
{
	Luggage,
	AmuletStatue,
	CapybaraPool,
	Scout,
	FakeEnemy
}
internal enum FakeEnemyKind
{
	Scoutmaster,
	MushroomZombie,
	Looker
}
internal enum MirageBehavior
{
	StandStill,
	StandAndStare,
	FollowAtDistance,
	ApproachSlowly,
	ChargeTarget,
	WalkAcross,
	RunAway,
	VanishWhenClose
}
internal enum PhantomPingPattern
{
	BreadcrumbTrail,
	Circle,
	BehindYou
}
internal enum NoWaitDestination
{
	NearestLiving,
	LowestLiving,
	Checkpoint
}
internal enum MenuActivationMode
{
	Toggle,
	Hold
}
internal enum ExpeditionMode
{
	ZombieOutbreak,
	Survival,
	RescueRush,
	Hardcore,
	ChaosClimb,
	Custom
}
internal enum DirectorRoundState
{
	Stopped,
	Running,
	Paused,
	Completed,
	Failed
}
internal sealed class ActionResult
{
	public readonly bool Success;

	public readonly string Message;

	private ActionResult(bool success, string message)
	{
		Success = success;
		Message = message;
	}

	public static ActionResult Ok(string message)
	{
		return new ActionResult(success: true, message);
	}

	public static ActionResult Fail(string message)
	{
		return new ActionResult(success: false, message);
	}
}
internal sealed class PlayerEntry
{
	public int ActorNumber;

	public string Name;

	public ulong SteamUserId;

	public Character Character;

	public bool IsLocal;

	public override string ToString()
	{
		return Name + (IsLocal ? " (You)" : "");
	}
}
internal sealed class MirageRecord
{
	public Guid Id;

	public MirageKind Kind;

	public int CreatorActor;

	public DateTime CreatedUtc;

	public Vector3 Position;

	public Quaternion Rotation;

	public int TargetActor;

	public GameObject Object;
}
internal sealed class ModConfig
{
	public readonly ConfigEntry<KeyboardShortcut> MenuKey;

	public readonly ConfigEntry<float> UiScale;

	public readonly ConfigEntry<float> Transparency;

	public readonly ConfigEntry<bool> ConfirmDestructive;

	public readonly ConfigEntry<bool> ExcludeSelf;

	public readonly ConfigEntry<bool> DebugLogging;

	public readonly ConfigEntry<bool> NetworkDiagnostics;

	public readonly ConfigEntry<bool> MirageDebug;

	public readonly ConfigEntry<bool> FakeEnemyDebug;

	public readonly ConfigEntry<int> MaxSpawnedObjects;

	public readonly ConfigEntry<int> MaxDynamiteObjects;

	public readonly ConfigEntry<int> MaxItemStormObjects;

	public readonly ConfigEntry<float> ChaosMinDelay;

	public readonly ConfigEntry<float> ChaosMaxDelay;

	public readonly ConfigEntry<bool> UnlockAllCosmetics;

	public readonly ConfigEntry<bool> UnlockAllBadges;

	public readonly ConfigEntry<bool> CampfireResetEnabled;

	public readonly ConfigEntry<bool> CampfireDeathTrapEnabled;

	public readonly ConfigEntry<float> CampfireDeathRadius;

	public readonly ConfigEntry<bool> HelicopterSuppressionEnabled;

	public readonly ConfigEntry<bool> NoWaitEnabled;

	public readonly ConfigEntry<NoWaitDestination> NoWaitDestinationMode;

	public readonly ConfigEntry<bool> NoWaitPreserveReconnectState;

	public readonly ConfigEntry<string> LastLobbyId;

	public readonly ConfigEntry<bool> TeamStatusEnabled;

	public readonly ConfigEntry<float> TeamStatusDistance;

	public readonly ConfigEntry<float> TeamStatusScale;

	public readonly ConfigEntry<bool> TeamStatusShowSelf;

	public readonly ConfigEntry<bool> QuickBackpackEnabled;

	public readonly ConfigEntry<KeyboardShortcut> QuickBackpackKey;

	public readonly ConfigEntry<bool> BetterSpectatingEnabled;

	public readonly ConfigEntry<KeyboardShortcut> SpectatePreviousKey;

	public readonly ConfigEntry<KeyboardShortcut> SpectateNextKey;

	public readonly ConfigEntry<KeyboardShortcut> SpectateFreeCameraKey;

	public readonly ConfigEntry<bool> SpectateGhostPings;

	public readonly ConfigEntry<bool> SpectateOverlay;

	public readonly ConfigEntry<bool> PreferExternalQualityOfLifeMods;

	public readonly ConfigEntry<string> PlayerPreferencesData;

	public readonly ConfigEntry<float> TextScale;

	public readonly ConfigEntry<bool> HighContrast;

	public readonly ConfigEntry<float> CameraShakeScale;

	public readonly ConfigEntry<bool> ReduceFlashingEffects;

	public readonly ConfigEntry<MenuActivationMode> MenuActivation;

	public readonly ConfigEntry<bool> ItemSpawnerEnabled;

	public readonly ConfigEntry<bool> EffectPreviewEnabled;

	public readonly ConfigEntry<bool> StaminaEffectPreviewEnabled;

	public readonly ConfigEntry<bool> StaminaEffectPreviewDetails;

	public readonly ConfigEntry<bool> ImmortalityEnabled;

	public readonly ConfigEntry<bool> InfiniteStaminaEnabled;

	public readonly ConfigEntry<bool> RealLuggageDirectionsEnabled;

	public readonly ConfigEntry<float> RealLuggageMaximumDistance;

	public readonly ConfigEntry<bool> MesaAntiMiragesEnabled;

	public readonly ConfigEntry<bool> FavoritesAndRecentsEnabled;

	public readonly ConfigEntry<string> FavoriteItemsData;

	public readonly ConfigEntry<string> RecentItemsData;

	public readonly ConfigEntry<string> FavoriteEffectsData;

	public readonly ConfigEntry<string> RecentEffectsData;

	public readonly ConfigEntry<bool> UnlimitedLobbyEnabled;

	public readonly ConfigEntry<int> UnlimitedLobbyMaxPlayers;

	public readonly ConfigEntry<bool> UnlimitedLobbyScaleSupplies;

	public readonly ConfigEntry<bool> UnlimitedLobbyExtraFood;

	public readonly ConfigEntry<bool> UnlimitedLobbyExtraBackpacks;

	public readonly ConfigEntry<bool> ClimbForecastEnabled;

	public readonly ConfigEntry<float> ClimbForecastMaximumHeight;

	public readonly ConfigEntry<float> ClimbForecastSafetyReserve;

	public readonly ConfigEntry<bool> PartySupplyAdvisorEnabled;

	public readonly ConfigEntry<bool> PartySupplyIncludeBackpacks;

	public readonly ConfigEntry<bool> HotkeyConflictDoctorEnabled;

	public readonly ConfigEntry<bool> InfiniteRescueClawReachEnabled;

	public readonly ConfigEntry<float> MindControlDuration;

	public readonly ConfigEntry<float> MindControlCameraDistance;

	public readonly ConfigEntry<float> MindControlHostPuppetForce;

	public readonly ConfigEntry<KeyboardShortcut> MindControlEscapeKey;

	public readonly ConfigEntry<bool> InfiniteJetpackFuelEnabled;

	public readonly ConfigEntry<bool> BiggerBackpackEnabled;

	public readonly ConfigEntry<bool> BackpackProtectionEnabled;

	public readonly ConfigEntry<bool> StartAsSkeletonEnabled;

	public readonly ConfigEntry<bool> ScoutCompassEnabled;

	public readonly ConfigEntry<bool> ScoutEspEnabled;

	public readonly ConfigEntry<bool> LuggageEspEnabled;

	public readonly ConfigEntry<bool> ZombieEspEnabled;

	public readonly ConfigEntry<bool> ScoutmasterEspEnabled;

	public readonly ConfigEntry<bool> EspLabelsEnabled;

	public readonly ConfigEntry<bool> EspTracersEnabled;

	public readonly ConfigEntry<float> EspMaximumDistance;

	public readonly ConfigEntry<float> EspOutlineWidth;

	public readonly ConfigEntry<string> ScoutEspColor;

	public readonly ConfigEntry<string> LuggageEspColor;

	public readonly ConfigEntry<string> ZombieEspColor;

	public readonly ConfigEntry<string> ScoutmasterEspColor;

	public readonly ConfigEntry<string> ActiveProfileName;

	public readonly ConfigEntry<string> SavedProfileCode;

	public readonly ConfigEntry<bool> AntiSoftlockDoctorEnabled;

	public readonly ConfigEntry<float> AntiSoftlockDetectionDelay;

	public readonly ConfigEntry<string> DirectorScenarioCode;

	public ModConfig(ConfigFile config)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0897: Unknown result type (might be due to invalid IL or missing references)
		MenuKey = config.Bind<KeyboardShortcut>("UI", "MenuKey", new KeyboardShortcut((KeyCode)288, (KeyCode[])(object)new KeyCode[0]), "Open or close the PEAK Troll Mod menu.");
		UiScale = config.Bind<float>("UI", "Scale", 1f, "UI scale (0.75-1.5).");
		Transparency = config.Bind<float>("UI", "Transparency", 0.96f, "Window opacity (0.55-1.0).");
		ConfirmDestructive = config.Bind<bool>("Safety", "ConfirmDestructiveActions", true, "Require a second click for elimination and bulk reset.");
		ExcludeSelf = config.Bind<bool>("Targeting", "ExcludeSelf", true, "Exclude the local player from random targets.");
		DebugLogging = config.Bind<bool>("Diagnostics", "DebugLogging", false, "Enable detailed diagnostics.");
		NetworkDiagnostics = config.Bind<bool>("Diagnostics", "NetworkDiagnostics", false, "Log validated mod messages.");
		MirageDebug = config.Bind<bool>("Diagnostics", "MirageDebugInfo", false, "Log mirage lifecycle.");
		FakeEnemyDebug = config.Bind<bool>("Diagnostics", "FakeEnemyDebugInfo", false, "Log fake-enemy lifecycle.");
		MaxSpawnedObjects = config.Bind<int>("Safety", "MaximumModSpawnedObjects", 24, "Hard cap for tracked spawns and mirages.");
		MaxDynamiteObjects = config.Bind<int>("Safety", "MaximumDynamiteObjects", 64, "Separate hard cap for caller-owned Dynamite Shower items (1-128).");
		MaxItemStormObjects = config.Bind<int>("Safety", "MaximumItemStormObjects", 64, "Separate hard cap for caller-owned Item Storm objects (1-128).");
		ChaosMinDelay = config.Bind<float>("Chaos", "MinimumDelay", 8f, "Minimum chaos event delay.");
		ChaosMaxDelay = config.Bind<float>("Chaos", "MaximumDelay", 18f, "Maximum chaos event delay.");
		UnlockAllCosmetics = config.Bind<bool>("Progression", "UnlockAllCosmetics", false, "Expose all PEAK cosmetics while the mod is enabled without granting platform achievements.");
		UnlockAllBadges = config.Bind<bool>("Progression", "UnlockAllBadges", false, "Expose all PEAK badges and sync the local sash while enabled without granting platform achievements.");
		CampfireResetEnabled = config.Bind<bool>("World", "CampfireTeleportsEveryoneToStart", false, "When this client observes a campfire ignition, teleport all scouts back to the first segment start.");
		CampfireDeathTrapEnabled = config.Bind<bool>("World", "CampfireDeathTrap", false, "When this client observes a campfire ignition, eliminate every living scout within the configured radius. Takes precedence over the reset trap.");
		CampfireDeathRadius = config.Bind<float>("World", "CampfireDeathRadius", 12f, "Radius in metres around an ignited campfire affected by the death trap (3-50).");
		HelicopterSuppressionEnabled = config.Bind<bool>("World", "SuppressSummitHelicopter", false, "Suppress the summit rescue sequence locally and advertise suppression to compatible clients.");
		NoWaitEnabled = config.Bind<bool>("Player", "NoWait", true, "When joining an expedition already in progress, automatically revive the local scout beside the nearest living player.");
		NoWaitDestinationMode = config.Bind<NoWaitDestination>("Player", "NoWaitDestination", NoWaitDestination.NearestLiving, "Where No Wait places a late joiner: nearest living scout, lowest living scout, or the active checkpoint.");
		NoWaitPreserveReconnectState = config.Bind<bool>("Player", "NoWaitPreserveReconnectState", true, "When reconnecting, preserve the local scout's restored inventory, statuses, thorns, extra stamina, and petrification state.");
		LastLobbyId = config.Bind<string>("Reconnect", "LastLobbyId", string.Empty, "Last valid Steam lobby ID observed by Quick Reconnect.");
		TeamStatusEnabled = config.Bind<bool>("Quality of Life", "TeamStatusPanel", true, "Show a compact teammate stamina and condition panel.");
		TeamStatusDistance = config.Bind<float>("Quality of Life", "TeamStatusDistance", 45f, "Maximum world distance for the team panel (10-200 metres).");
		TeamStatusScale = config.Bind<float>("Quality of Life", "TeamStatusScale", 1f, "Team panel scale (0.7-1.4).");
		TeamStatusShowSelf = config.Bind<bool>("Quality of Life", "TeamStatusShowSelf", false, "Include the local scout in the team panel.");
		QuickBackpackEnabled = config.Bind<bool>("Quality of Life", "QuickBackpack", true, "Open the equipped backpack wheel with a hotkey.");
		QuickBackpackKey = config.Bind<KeyboardShortcut>("Quality of Life", "QuickBackpackKey", new KeyboardShortcut((KeyCode)98, (KeyCode[])(object)new KeyCode[0]), "Hold to open the equipped backpack wheel.");
		BetterSpectatingEnabled = config.Bind<bool>("Quality of Life", "BetterSpectating", true, "Add spectator shortcuts, overlay, free camera, ghost pings, and revive-near-target.");
		SpectatePreviousKey = config.Bind<KeyboardShortcut>("Quality of Life", "SpectatePreviousKey", new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[0]), "Cycle to the previous living scout while spectating.");
		SpectateNextKey = config.Bind<KeyboardShortcut>("Quality of Life", "SpectateNextKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[0]), "Cycle to the next living scout while spectating.");
		SpectateFreeCameraKey = config.Bind<KeyboardShortcut>("Quality of Life", "SpectateFreeCameraKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[0]), "Toggle PEAK's free camera while spectating.");
		SpectateGhostPings = config.Bind<bool>("Quality of Life", "SpectateGhostPings", true, "Allow normal point pings while fully passed out.");
		SpectateOverlay = config.Bind<bool>("Quality of Life", "SpectateOverlay", true, "Show the current spectator target, altitude, status, and shortcuts.");
		PreferExternalQualityOfLifeMods = config.Bind<bool>("Compatibility", "PreferExternalQualityOfLifeMods", true, "Yield duplicate built-in features to enabled PeakStatsEx and EasyBackpack components.");
		PlayerPreferencesData = config.Bind<string>("Player Preferences", "SavedPlayers", string.Empty, "Serialized per-Steam-player aliases, colors, voice settings, and random-target exclusions.");
		TextScale = config.Bind<float>("Accessibility", "TextScale", 1f, "Menu text scale (0.85-1.30).");
		HighContrast = config.Bind<bool>("Accessibility", "HighContrastColors", false, "Use brighter text and stronger status contrast.");
		CameraShakeScale = config.Bind<float>("Accessibility", "CameraShakeScale", 1f, "Scale PEAK camera shake from 0 (off) to 1 (normal).");
		ReduceFlashingEffects = config.Bind<bool>("Accessibility", "ReduceFlashingTrollEffects", false, "Slow and cap repeated visual troll effects such as Phantom Pings.");
		MenuActivation = config.Bind<MenuActivationMode>("Accessibility", "MenuActivation", MenuActivationMode.Toggle, "Open F7 as a toggle or only while the shortcut is held.");
		ItemSpawnerEnabled = config.Bind<bool>("Quality of Life", "ItemSpawner", true, "Show the searchable item spawner page in the F7 menu.");
		EffectPreviewEnabled = config.Bind<bool>("Quality of Life", "EffectPreview", true, "Show safe, non-executing effect previews before use.");
		StaminaEffectPreviewEnabled = config.Bind<bool>("Quality of Life", "StaminaEffectPreview", true, "Preview a held consumable's stamina and condition-bar changes before using it. Automatically yields to the standalone Effect Preview mod.");
		StaminaEffectPreviewDetails = config.Bind<bool>("Quality of Life", "StaminaEffectPreviewDetails", true, "Show individual condition changes beneath the held-item stamina forecast.");
		ImmortalityEnabled = config.Bind<bool>("Player", "Immortality", false, "Prevent local death and full pass-out and continuously clear every negative stamina-bar condition, including carried-weight encumbrance, while enabled.");
		InfiniteStaminaEnabled = config.Bind<bool>("Player", "InfiniteStamina", false, "Continuously refill the local scout's available stamina while enabled.");
		RealLuggageDirectionsEnabled = config.Bind<bool>("Quality of Life", "RealLuggageDirections", false, "Show direction and distance to the nearest unopened genuine luggage while ignoring native and mod-created mirages.");
		RealLuggageMaximumDistance = config.Bind<float>("Quality of Life", "RealLuggageMaximumDistance", 750f, "Maximum real-luggage search distance in metres (25-2000).");
		MesaAntiMiragesEnabled = config.Bind<bool>("Quality of Life", "MesaAntiMirages", false, "Locally hide native and PEAK Troll Mod-created mirage visuals wherever they appear. The legacy setting name is retained so existing configs keep working.");
		FavoritesAndRecentsEnabled = config.Bind<bool>("Quality of Life", "FavoritesAndRecentActions", true, "Remember favorite and recently used items/effect previews.");
		FavoriteItemsData = config.Bind<string>("Quick Access", "FavoriteItems", string.Empty, "Newline-separated favorite runtime item names.");
		RecentItemsData = config.Bind<string>("Quick Access", "RecentItems", string.Empty, "Newline-separated recently used runtime item names.");
		FavoriteEffectsData = config.Bind<string>("Quick Access", "FavoriteEffects", string.Empty, "Newline-separated favorite effect preview names.");
		RecentEffectsData = config.Bind<string>("Quick Access", "RecentEffects", string.Empty, "Newline-separated recently previewed effects.");
		UnlimitedLobbyEnabled = config.Bind<bool>("Unlimited Lobby", "Enabled", false, "Raise the next hosted lobby's player cap. Automatically yields to the standalone PEAK Unlimited mod.");
		UnlimitedLobbyMaxPlayers = config.Bind<int>("Unlimited Lobby", "MaxPlayers", 12, "Maximum players for newly hosted rooms (4-30). Change before creating the lobby.");
		UnlimitedLobbyScaleSupplies = config.Bind<bool>("Unlimited Lobby", "ScaleCampfireSupplies", true, "Scale campfire food and backpack spawns for players above the vanilla four-player count.");
		UnlimitedLobbyExtraFood = config.Bind<bool>("Unlimited Lobby", "ExtraCampfireFood", true, "Spawn one additional marshmallow per player above four, including late joiners.");
		UnlimitedLobbyExtraBackpacks = config.Bind<bool>("Unlimited Lobby", "ExtraBackpacks", true, "Spawn roughly one additional backpack per four players above the vanilla cap.");
		ClimbForecastEnabled = config.Bind<bool>("Smart Quality of Life", "ClimbForecast", true, "While reaching toward a steep surface, estimate the climb time, stamina cost, and safety reserve to its next standable ledge.");
		ClimbForecastMaximumHeight = config.Bind<float>("Smart Quality of Life", "ClimbForecastMaximumHeight", 12f, "Maximum vertical height scanned for a standable ledge (3-20 metres).");
		ClimbForecastSafetyReserve = config.Bind<float>("Smart Quality of Life", "ClimbForecastSafetyReserve", 0.2f, "Stamina reserve required for a climb to be rated safe (0-50 percent).");
		PartySupplyAdvisorEnabled = config.Bind<bool>("Smart Quality of Life", "PartySupplyAdvisor", true, "Summarize synchronized party supplies and highlight practical loadout gaps without moving items.");
		PartySupplyIncludeBackpacks = config.Bind<bool>("Smart Quality of Life", "PartySupplyIncludeBackpacks", true, "Include already-synchronized equipped-backpack contents in party supply analysis.");
		HotkeyConflictDoctorEnabled = config.Bind<bool>("Smart Quality of Life", "HotkeyConflictDoctor", true, "Detect exact duplicate BepInEx KeyboardShortcut and KeyCode bindings across enabled plugins.");
		InfiniteRescueClawReachEnabled = config.Bind<bool>("Quality of Life", "InfiniteRescueClawReach", false, "Give the locally held Rescue Claw map-wide targeting and zip the local scout toward distant wall anchors. Yields to a standalone infinite-range rescue-hook mod.");
		MindControlDuration = config.Bind<float>("Mind Control", "MaximumDuration", 60f, "Maximum in-game Mind Control session duration in seconds (10-180).");
		MindControlCameraDistance = config.Bind<float>("Mind Control", "ThirdPersonCameraDistance", 5.5f, "Controller's third-person follow-camera distance in metres (3-10).");
		MindControlHostPuppetForce = config.Bind<float>("Mind Control", "HostPuppetForce", 2.5f, "Bounded native movement force for host-only control of unmodded scouts (1-8).");
		MindControlEscapeKey = config.Bind<KeyboardShortcut>("Mind Control", "ReleaseKey", new KeyboardShortcut((KeyCode)287, (KeyCode[])(object)new KeyCode[0]), "Immediately release or break free from an active Mind Control session.");
		InfiniteJetpackFuelEnabled = config.Bind<bool>("Player", "InfiniteJetpackFuel", false, "Keep the locally equipped Jetpack at its native maximum fuel and restore its original fuel when disabled.");
		BiggerBackpackEnabled = config.Bind<bool>("Quality of Life", "BiggerBackpack", false, "Expand the local Backpack to eight slots and Fanny Pack to four slots. Extra slots require this mod to display on other clients.");
		BackpackProtectionEnabled = config.Bind<bool>("Quality of Life", "BackpackProtection", false, "Prevent other scouts from withdrawing items from your equipped backpack when you or the current host runs a compatible protocol.");
		StartAsSkeletonEnabled = config.Bind<bool>("Player", "StartAsSkeleton", false, "Start each island expedition with PEAK's native Book of Bones skeleton state.");
		ScoutCompassEnabled = config.Bind<bool>("ESP", "ScoutCompass", false, "Show the direction and distance to the nearest other living scout.");
		ScoutEspEnabled = config.Bind<bool>("ESP", "Scouts", false, "Draw local through-wall outlines around other scouts.");
		LuggageEspEnabled = config.Bind<bool>("ESP", "Luggage", false, "Draw local through-wall outlines around unopened genuine luggage.");
		ZombieEspEnabled = config.Bind<bool>("ESP", "Zombies", false, "Draw local through-wall outlines around loaded Mushroom Zombies.");
		ScoutmasterEspEnabled = config.Bind<bool>("ESP", "Scoutmaster", false, "Draw local through-wall outlines around loaded Scoutmasters.");
		EspLabelsEnabled = config.Bind<bool>("ESP", "Labels", true, "Show category/name and distance labels above ESP outlines.");
		EspTracersEnabled = config.Bind<bool>("ESP", "Tracers", false, "Draw colored lines from the bottom-center of the screen to highlighted ESP targets.");
		EspMaximumDistance = config.Bind<float>("ESP", "MaximumDistance", 600f, "Maximum ESP rendering distance in metres (25-2000).");
		EspOutlineWidth = config.Bind<float>("ESP", "OutlineWidth", 2f, "ESP outline and tracer thickness (1-8 pixels).");
		ScoutEspColor = config.Bind<string>("ESP Colors", "Scout", "#40FFC7", "Scout ESP outline color as #RRGGBB.");
		LuggageEspColor = config.Bind<string>("ESP Colors", "Luggage", "#FFC233", "Luggage ESP outline color as #RRGGBB.");
		ZombieEspColor = config.Bind<string>("ESP Colors", "Zombie", "#FF4040", "Zombie ESP outline color as #RRGGBB.");
		ScoutmasterEspColor = config.Bind<string>("ESP Colors", "Scoutmaster", "#B861FF", "Scoutmaster ESP outline color as #RRGGBB.");
		ActiveProfileName = config.Bind<string>("Profiles", "ActiveProfileName", "Custom", "Display name of the last applied or saved PEAK Troll Mod profile.");
		SavedProfileCode = config.Bind<string>("Profiles", "SavedProfileCode", string.Empty, "Portable code for the last saved PEAK Troll Mod profile.");
		AntiSoftlockDoctorEnabled = config.Bind<bool>("Anti-Softlock", "Enabled", true, "Detect likely local softlocks and offer explicit safe recovery actions.");
		AntiSoftlockDetectionDelay = config.Bind<float>("Anti-Softlock", "DetectionDelay", 10f, "Seconds a suspicious state must persist before the doctor recommends a repair (6-30).");
		DirectorScenarioCode = config.Bind<string>("Expedition Director", "LastScenarioCode", string.Empty, "Last validated PTMD1 scenario code exported or imported through Expedition Director.");
	}
}
internal static class ReflectionHelpers
{
	private static readonly Dictionary<string, MethodInfo> Methods = new Dictionary<string, MethodInfo>();

	private static readonly Dictionary<string, FieldInfo> Fields = new Dictionary<string, FieldInfo>();

	public static MethodInfo Method(Type type, string name, Type[] args)
	{
		string key = type.FullName + "::" + name + "/" + args.Length;
		if (!Methods.TryGetValue(key, out var value))
		{
			value = AccessTools.Method(type, name, args, (Type[])null);
			Methods[key] = value;
		}
		return value;
	}

	public static FieldInfo Field(Type type, string name)
	{
		string key = type.FullName + "::" + name;
		if (!Fields.TryGetValue(key, out var value))
		{
			value = AccessTools.Field(type, name);
			Fields[key] = value;
		}
		return value;
	}

	public static object Invoke(object target, MethodInfo method, params object[] args)
	{
		if (target == null || method == null)
		{
			return null;
		}
		return method.Invoke(target, args);
	}

	public static bool HasMethod(Type type, string name, params Type[] args)
	{
		return Method(type, name, args) != null;
	}

	public static bool HasField(Type type, string name)
	{
		return Field(type, name) != null;
	}
}
internal sealed class CapabilityRegistry
{
	private readonly Dictionary<FeatureCapability, string> _unavailable = new Dictionary<FeatureCapability, string>();

	private readonly ManualLogSource _log;

	private bool _discovered;

	public CapabilityRegistry(ManualLogSource log)
	{
		_log = log;
	}

	public void Discover()
	{
		Dictionary<FeatureCapability, string> dictionary = new Dictionary<FeatureCapability, string>(_unavailable);
		_unavailable.Clear();
		Need(FeatureCapability.PlayerDiscovery, typeof(PlayerHandler).GetMethod("GetAllPlayerCharacters") != null, "PlayerHandler.GetAllPlayerCharacters missing");
		Need(FeatureCapability.Ragdoll, ReflectionHelpers.HasMethod(typeof(Character), "AddForceAtPosition", typeof(Vector3), typeof(Vector3), typeof(float)) && ReflectionHelpers.HasMethod(typeof(Character), "Fall", typeof(float), typeof(float)), "native Character.AddForceAtPosition/Fall RPC paths missing");
		Need(FeatureCapability.Launch, ReflectionHelpers.HasMethod(typeof(Character), "AddForceAtPosition", typeof(Vector3), typeof(Vector3), typeof(float)), "native Character.AddForceAtPosition RPC path missing");
		Need(FeatureCapability.Speed, ReflectionHelpers.HasField(typeof(CharacterMovement), "movementModifier"), "CharacterMovement.movementModifier missing");
		Need(FeatureCapability.Flight, ReflectionHelpers.HasField(typeof(CharacterRagdoll), "rigidbodies") && typeof(Rigidbody).GetProperty("linearVelocity") != null && typeof(Rigidbody).GetProperty("useGravity") != null, "character rigidbodies or flight physics properties missing");
		Need(FeatureCapability.Visibility, typeof(Renderer) != null, "Unity Renderer unavailable");
		Need(FeatureCapability.Teleport, typeof(Character).GetMethod("WarpPlayerRPC") != null, "Character.WarpPlayerRPC missing");
		Need(FeatureCapability.StartEndTeleport, typeof(MapHandler).GetField("segments") != null, "MapHandler segment references missing");
		Need(FeatureCapability.Resurrect, ReflectionHelpers.HasMethod(typeof(Character), "RPCA_ReviveAtPosition", typeof(Vector3), typeof(bool), typeof(int)), "Character.RPCA_ReviveAtPosition missing");
		Need(FeatureCapability.QuickReconnect, ReflectionHelpers.HasMethod(typeof(SteamLobbyHandler), "TryJoinLobby", typeof(CSteamID)), "Steam lobby join path missing");
		Need(FeatureCapability.EmergencyRecovery, Available(FeatureCapability.Teleport) && ReflectionHelpers.HasMethod(typeof(CharacterRagdoll), "HaltBodyVelocity", typeof(bool)), "safe warp or rigidbody halt path missing");
		Need(FeatureCapability.Knockout, typeof(Character).GetMethod("PassOutInstantly") != null, "Character.PassOutInstantly missing");
		Need(FeatureCapability.Eliminate, typeof(Character).GetMethod("RPCA_Die") != null, "Character.RPCA_Die missing");
		Need(FeatureCapability.StatusEffects, typeof(CharacterAfflictions).GetMethod("AddStatus") != null, "CharacterAfflictions.AddStatus missing");
		Need(FeatureCapability.HungerAmplifier, ReflectionHelpers.Method(typeof(CharacterAfflictions), "UpdateNormalStatuses", Type.EmptyTypes) != null && ReflectionHelpers.HasField(typeof(CharacterAfflictions), "hungerPerSecond"), "native hunger update or hungerPerSecond field missing");
		Need(FeatureCapability.DropHeldItem, ReflectionHelpers.Method(typeof(CharacterItems), "DropItemFromSlotRPC", new Type[2]
		{
			typeof(byte),
			typeof(Vector3)
		}) != null, "native held-slot drop RPC missing");
		Need(FeatureCapability.GiveItem, ReflectionHelpers.HasMethod(typeof(CharacterItems), "SpawnItemInHand", typeof(string)), "CharacterItems.SpawnItemInHand missing");
		Need(FeatureCapability.SkyLaunch, typeof(Character).GetMethod("WarpPlayerRPC") != null && Available(FeatureCapability.Ragdoll), "native warp/ragdoll RPC paths missing");
		Need(FeatureCapability.HorizonLaunch, typeof(Character).GetMethod("WarpPlayerRPC") != null && Available(FeatureCapability.Ragdoll), "native warp/ragdoll RPC paths missing");
		Need(FeatureCapability.DynamiteShower, HasLoaded(typeof(Dynamite)) && typeof(Dynamite).GetMethod("LightFlare") != null, "no loaded Dynamite item prefab or fuse API");
		Need(FeatureCapability.ItemStorm, HasLoaded(typeof(Item)) && typeof(Item).GetMethod("SetKinematicNetworked") != null, "no loaded network item prefab or physics API");
		Need(FeatureCapability.WrongMountain, Available(FeatureCapability.Teleport) && Available(FeatureCapability.Ragdoll) && Available(FeatureCapability.GiveItem), "native warp, ragdoll, or item RPC path missing");
		Need(FeatureCapability.CosmeticUnlocks, typeof(CustomizationOption).GetProperty("IsLocked") != null, "CustomizationOption.IsLocked missing");
		Need(FeatureCapability.BadgeUnlocks, typeof(BadgeData).GetProperty("IsLocked") != null && typeof(CharacterData).GetMethod("SetBadgeStatus", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null, "badge lock or sash synchronization API missing");
		Need(FeatureCapability.PositionRoulette, Available(FeatureCapability.Teleport), "native warp RPC path missing");
		Need(FeatureCapability.OneLiveOne, Available(FeatureCapability.DynamiteShower), "networked Dynamite spawning or fuse API missing");
		Need(FeatureCapability.ComboBuilder, Available(FeatureCapability.Ragdoll) && Available(FeatureCapability.Knockout) && Available(FeatureCapability.SkyLaunch), "one or more native combo action paths are missing");
		Need(FeatureCapability.SummitSaboteur, Available(FeatureCapability.StartEndTeleport) && Available(FeatureCapability.HorizonLaunch) && Available(FeatureCapability.DropHeldItem) && Available(FeatureCapability.MushroomZombieSpawn) && ReflectionHelpers.Method(typeof(CharacterAfflictions), "RPC_ApplyStatusesFromFloatArray", new Type[2]
		{
			typeof(float[]),
			typeof(PhotonMessageInfo)
		}) != null && typeof(UI_Notifications).GetMethod("AddNotification") != null, "summit reference, native drop/Hunger/launch path, loaded zombie prefab, or notification path missing");
		Need(FeatureCapability.MindControl, ReflectionHelpers.Method(typeof(CharacterInput), "Sample", new Type[1] { typeof(bool) }) != null && ReflectionHelpers.Method(typeof(MainCameraMovement), "LateUpdate", Type.EmptyTypes) != null && ReflectionHelpers.HasField(typeof(CharacterInput), "movementInput") && ReflectionHelpers.HasField(typeof(CharacterInput), "lookInput"), "owned CharacterInput sampling or third-person camera update path missing");
		Need(FeatureCapability.InfiniteJetpackFuel, ReflectionHelpers.HasField(typeof(JetpackItem), "startingFuel") && typeof(ItemSlot).GetProperty("data") != null && ReflectionHelpers.HasField(typeof(FloatItemData), "Value"), "Jetpack starting fuel or backpack instance-data path missing");
		Need(FeatureCapability.BiggerBackpack, ReflectionHelpers.HasField(typeof(BackpackData), "itemSlots") && ReflectionHelpers.Method(typeof(BackpackData), "DeserializeValue", new Type[1] { typeof(BinaryDeserializer) }) != null && ReflectionHelpers.Method(typeof(BackpackWheel), "InitWheel", new Type[3]
		{
			typeof(BackpackReference),
			typeof(int),
			typeof(BackpackType)
		}) != null, "variable backpack data or radial-wheel initialization path missing");
		Need(FeatureCapability.BackpackProtection, ReflectionHelpers.Method(typeof(Item), "RequestPickup", new Type[1] { typeof(PhotonView) }) != null && ReflectionHelpers.HasField(typeof(Item), "backpackReference") && ReflectionHelpers.HasField(typeof(BackpackReference), "view"), "master pickup or equipped-backpack reference path missing");
		Need(FeatureCapability.StartAsSkeleton, ReflectionHelpers.Method(typeof(CharacterData), "SetSkeleton", new Type[1] { typeof(bool) }) != null && typeof(CharacterData).GetProperty("isSkeleton") != null, "native Book of Bones skeleton state path missing");
		Need(FeatureCapability.CampfireReset, ReflectionHelpers.Method(typeof(Campfire), "Light_Rpc", new Type[2]
		{
			typeof(bool),
			typeof(float)
		}) != null && Available(FeatureCapability.StartEndTeleport) && Available(FeatureCapability.Teleport), "campfire ignition or native start-warp path missing");
		Need(FeatureCapability.CampfireDeathTrap, ReflectionHelpers.Method(typeof(Campfire), "Light_Rpc", new Type[2]
		{
			typeof(bool),
			typeof(float)
		}) != null && Available(FeatureCapability.Eliminate), "campfire ignition or native death RPC path missing");
		Need(FeatureCapability.HelicopterSuppression, ReflectionHelpers.Method(typeof(PeakHandler), "SummonHelicopter", Type.EmptyTypes) != null && ReflectionHelpers.HasField(typeof(PeakHandler), "summonedHelicopter"), "summit helicopter summon path missing");
		Need(FeatureCapability.Mandrake, Available(FeatureCapability.ItemStorm) && HasLoadedItem("Mandrake"), "no loaded network Mandrake item prefab");
		Need(FeatureCapability.ScoutmasterSpawn, ReflectionHelpers.HasMethod(typeof(Scoutmaster), "SetCurrentTarget", typeof(Character), typeof(float)), "Scoutmaster.SetCurrentTarget missing");
		Need(FeatureCapability.MushroomZombieSpawn, SpawnManager.TryResolveZombiePrefabName(out var _), "verified Mushroom Zombie resource unavailable");
		Need(FeatureCapability.LookerSpawn, condition: false, "no verified network prefab path in PEAK 2.4.b");
		Need(FeatureCapability.PingPlacement, ReflectionHelpers.HasMethod(typeof(PointPinger), "TryGetPingHit", typeof(RaycastHit).MakeByRefType(), typeof(Vector3)), "PointPinger.TryGetPingHit missing");
		Need(FeatureCapability.PhantomPings, ReflectionHelpers.HasMethod(typeof(PointPinger), "ReceivePoint_Rpc", typeof(Vector3), typeof(Vector3)) && ReflectionHelpers.HasField(typeof(PointPinger), "character"), "PointPinger.ReceivePoint_Rpc or character reference missing");
		Need(FeatureCapability.MirageScout, condition: true, "");
		Need(FeatureCapability.MirageLuggage, HasLoaded(typeof(Luggage)), "no loaded Luggage visual source");
		Need(FeatureCapability.MirageStatue, HasLoaded(typeof(ScoutStatue)), "no loaded ScoutStatue visual source");
		Need(FeatureCapability.MirageCapybara, HasLoaded(typeof(Capybara)), "no loaded Capybara visual source");
		Need(FeatureCapability.FakeEnemyScoutmaster, HasLoaded(typeof(Scoutmaster)), "no loaded Scoutmaster visual source");
		Need(FeatureCapability.FakeEnemyZombie, HasLoaded(typeof(MushroomZombie)), "no loaded MushroomZombie visual source");
		Need(FeatureCapability.FakeEnemyLooker, HasLoaded(typeof(Looker)), "no loaded Looker visual source");
		Need(FeatureCapability.FakeAudio, condition: true, "");
		Need(FeatureCapability.ZombieTargeting, ReflectionHelpers.HasMethod(typeof(MushroomZombie), "SetCurrentTarget", typeof(Character), typeof(float)), "MushroomZombie.SetCurrentTarget missing");
		Need(FeatureCapability.AppearanceSwap, ReflectionHelpers.HasMethod(typeof(CharacterCustomization), "OnPlayerDataChange", typeof(PersistentPlayerData)), "CharacterCustomization.OnPlayerDataChange missing");
		Need(FeatureCapability.VoiceSwap, condition: false, "voice routing ownership and group mutation are not safely exposed");
		Need(FeatureCapability.IncomingVoiceMute, ReflectionHelpers.HasField(typeof(CharacterVoiceHandler), "<audioSource>k__BackingField") || ReflectionHelpers.HasField(typeof(CharacterVoiceHandler), "m_source"), "Character voice AudioSource missing");
		Need(FeatureCapability.TalkWhileKnockedOut, condition: false, "no supported voice privilege hook verified");
		Need(FeatureCapability.PoisonCloud, condition: false, "no verified network hazard prefab path");
		Need(FeatureCapability.SporeCloud, condition: false, "no verified network hazard prefab path");
		if (!_discovered || dictionary.Count != _unavailable.Count)
		{
			_log.LogInfo((object)("Capability discovery complete: " + (Enum.GetValues(typeof(FeatureCapability)).Length - _unavailable.Count) + " available, " + _unavailable.Count + " unavailable."));
		}
		if (!_discovered)
		{
			foreach (KeyValuePair<FeatureCapability, string> item in _unavailable)
			{
				_log.LogWarning((object)string.Concat("Capability ", item.Key, " disabled: ", item.Value));
			}
		}
		_discovered = true;
	}

	private void Need(FeatureCapability feature, bool condition, string reason)
	{
		if (!condition)
		{
			_unavailable[feature] = reason;
		}
	}

	private static bool HasLoaded(Type type)
	{
		return Resources.FindObjectsOfTypeAll(type).Length > 0;
	}

	private static bool HasLoadedItem(string token)
	{
		Item[] array = Resources.FindObjectsOfTypeAll<Item>();
		for (int i = 0; i < array.Length; i++)
		{
			if ((Object)(object)array[i] != (Object)null && (Object)(object)((Component)array[i]).gameObject != (Object)null && ((Object)((Component)array[i]).gameObject).name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	public bool Available(FeatureCapability feature)
	{
		return !_unavailable.ContainsKey(feature);
	}

	public string Reason(FeatureCapability feature)
	{
		if (!_unavailable.TryGetValue(feature, out var value))
		{
			return string.Empty;
		}
		return value;
	}

	public void RefreshDynamic()
	{
		Discover();
	}
}
internal sealed class PlayerManager
{
	private readonly ManualLogSource _log;

	private readonly List<PlayerEntry> _entries = new List<PlayerEntry>();

	private float _nextRefresh;

	public Func<PlayerEntry, bool> ExcludeFromRandom;

	public IList<PlayerEntry> Entries => _entries.AsReadOnly();

	public PlayerEntry Local { get; private set; }

	public bool IsHost
	{
		get
		{
			if (PhotonNetwork.InRoom)
			{
				return PhotonNetwork.IsMasterClient;
			}
			return false;
		}
	}

	public PlayerManager(ManualLogSource log)
	{
		_log = log;
	}

	public void Tick()
	{
		if (!(Time.unscaledTime < _nextRefresh))
		{
			_nextRefresh = Time.unscaledTime + 1f;
			Refresh();
		}
	}

	public void Refresh()
	{
		_entries.Clear();
		Local = null;
		try
		{
			if (!PlayerHandler.Exists)
			{
				return;
			}
			List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
			for (int i = 0; i < allPlayerCharacters.Count; i++)
			{
				Character val = allPlayerCharacters[i];
				if (!((Object)(object)val == (Object)null) && val.refs != null && !((Object)(object)val.refs.view == (Object)null))
				{
					PlayerEntry playerEntry = new PlayerEntry();
					playerEntry.Character = val;
					playerEntry.ActorNumber = val.refs.view.OwnerActorNr;
					playerEntry.Name = (string.IsNullOrEmpty(val.characterName) ? ("Player " + playerEntry.ActorNumber) : val.characterName);
					playerEntry.SteamUserId = (((Object)(object)val.data == (Object)null) ? 0 : val.data.userID);
					playerEntry.IsLocal = val.IsLocal;
					_entries.Add(playerEntry);
					if (playerEntry.IsLocal)
					{
						Local = playerEntry;
					}
				}
			}
		}
		catch (Exception ex)
		{
			_log.LogWarning((object)("Player resolution failed: " + ex.Message));
		}
	}

	public PlayerEntry Find(int actor)
	{
		for (int i = 0; i < _entries.Count; i++)
		{
			if (_entries[i].ActorNumber == actor)
			{
				return _entries[i];
			}
		}
		return null;
	}

	public PlayerEntry Random(bool excludeSelf)
	{
		List<PlayerEntry> list = new List<PlayerEntry>();
		for (int i = 0; i < _entries.Count; i++)
		{
			if ((!excludeSelf || !_entries[i].IsLocal) && (ExcludeFromRandom == null || !ExcludeFromRandom(_entries[i])))
			{
				list.Add(_entries[i]);
			}
		}
		if (list.Count != 0)
		{
			return list[Random.Range(0, list.Count)];
		}
		return null;
	}
}
internal sealed class PlayerActions
{
	private sealed class WrongMountainJob
	{
		public int FirstActor;

		public int SecondActor;

		public Vector3 Direction;

		public float Strength;

		public float ExecuteAt;
	}

	private sealed class CachedState
	{
		public bool HasSpeed;

		public float Speed;

		public bool FlightActive;

		public float FlightSpeed;

		public readonly Dictionary<Rigidbody, FlightBodyState> FlightBodies = new Dictionary<Rigidbody, FlightBodyState>();

		public readonly Dictionary<Renderer, bool> Renderers = new Dictionary<Renderer, bool>();

		public readonly HashSet<STATUSTYPE> Statuses = new HashSet<STATUSTYPE>();

		public readonly Dictionary<STATUSTYPE, float> HostStatusDeltas = new Dictionary<STATUSTYPE, float>();

		public bool SkeletonApplied;

		public float SkeletonApplyGraceUntil;
	}

	private sealed class FlightBodyState
	{
		public bool UseGravity;

		public float MaxLinearVelocity;
	}

	private readonly ManualLogSource _log;

	private readonly PlayerManager _players;

	private readonly CapabilityRegistry _capabilities;

	private readonly AudioManager _audio;

	private readonly Dictionary<int, CachedState> _states = new Dictionary<int, CachedState>();

	private readonly List<Item> _items = new List<Item>();

	private readonly List<WrongMountainJob> _wrongMountainJobs = new List<WrongMountainJob>();

	private readonly MethodInfo _addForceAtPosition;

	private readonly MethodInfo _fall;

	private readonly MethodInfo _die;

	private readonly MethodInfo _spawnItem;

	private readonly MethodInfo _hostApplyStatuses;

	private readonly MethodInfo _dropItemFromSlot;

	private readonly FieldInfo _ragdollRigidbodies;

	public IList<Item> Items => _items.AsReadOnly();

	public PlayerActions(ManualLogSource log, PlayerManager players, CapabilityRegistry capabilities, AudioManager audio)
	{
		_log = log;
		_players = players;
		_capabilities = capabilities;
		_audio = audio;
		_addForceAtPosition = ReflectionHelpers.Method(typeof(Character), "AddForceAtPosition", new Type[3]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(float)
		});
		_fall = ReflectionHelpers.Method(typeof(Character), "Fall", new Type[2]
		{
			typeof(float),
			typeof(float)
		});
		_die = ReflectionHelpers.Method(typeof(Character), "DieInstantly", Type.EmptyTypes);
		_spawnItem = ReflectionHelpers.Method(typeof(CharacterItems), "SpawnItemInHand", new Type[1] { typeof(string) });
		_hostApplyStatuses = ReflectionHelpers.Method(typeof(CharacterAfflictions), "RPC_ApplyStatusesFromFloatArray", new Type[2]
		{
			typeof(float[]),
			typeof(PhotonMessageInfo)
		});
		_dropItemFromSlot = ReflectionHelpers.Method(typeof(CharacterItems), "DropItemFromSlotRPC", new Type[2]
		{
			typeof(byte),
			typeof(Vector3)
		});
		_ragdollRigidbodies = ReflectionHelpers.Field(typeof(CharacterRagdoll), "rigidbodies");
		RefreshItemCatalog();
	}

	private CachedState State(PlayerEntry entry)
	{
		if (!_states.TryGetValue(entry.ActorNumber, out var value))
		{
			value = new CachedState();
			_states.Add(entry.ActorNumber, value);
		}
		return value;
	}

	public void RefreshItemCatalog()
	{
		Item[] array = Resources.FindObjectsOfTypeAll<Item>();
		_items.Clear();
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (Item val in array)
		{
			if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && hashSet.Add(((Object)val).name))
			{
				_items.Add(val);
			}
		}
		_items.Sort((Item a, Item b) => string.Compare(((Object)a).name, ((Object)b).name, StringComparison.OrdinalIgnoreCase));
	}

	public ActionResult RagdollLocal(PlayerEntry target, Vector3 direction, float strength, float seconds)
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: 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_00bd: 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)
		if (!_capabilities.Available(FeatureCapability.Ragdoll))
		{
			return Missing(FeatureCapability.Ragdoll);
		}
		if (target == null || (Object)(object)target.Character == (Object)null)
		{
			return ActionResult.Fail("Target unavailable.");
		}
		strength = Mathf.Clamp(strength, 1f, 75f);
		seconds = Mathf.Clamp(seconds, 0.25f, 5f);
		direction = ((((Vector3)(ref direction)).sqrMagnitude < 0.01f) ? Vector3.up : ((Vector3)(ref direction)).normalized);
		try
		{
			ReflectionHelpers.Invoke(target.Character, _fall, seconds, 0f);
			ReflectionHelpers.Invoke(target.Character, _addForceAtPosition, direction * strength, target.Character.Center, 4f);
			return ActionResult.Ok("Ragdolled " + target.Name + " through PEAK's native RPCs; their mod is not required.");
		}
		catch (Exception ex)
		{
			return Error("Ragdoll", ex);
		}
	}

	public ActionResult RagdollOffMountainLocal(PlayerEntry target, float strength)
	{
		//IL_004b: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.Ragdoll))
		{
			return Missing(FeatureCapability.Ragdoll);
		}
		if (target == null || (Object)(object)target.Character == (Object)null)
		{
			return ActionResult.Fail("Target unavailable.");
		}
		strength = Mathf.Clamp(strength, 1f, 75f);
		bool foundDrop;
		Vector3 val = FindDropDirection(target.Character.Center, out foundDrop);
		try
		{
			ReflectionHelpers.Invoke(target.Character, _fall, 2.5f, 0f);
			ReflectionHelpers.Invoke(target.Character, _addForceAtPosition, val * strength, target.Character.Center, 4f);
			return ActionResult.Ok("Ragdolled " + target.Name + (foundDrop ? " toward the steepest nearby drop." : " away from the climb route (no nearby drop was detected)."));
		}
		catch (Exception ex)
		{
			return Error("Ragdoll off mountain", ex);
		}
	}

	public ActionResult HorizontalRagdollLocal(PlayerEntry target, float strength)
	{
		//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_00da: 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_00e9: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: 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_00b8: 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_0075: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0162: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.Ragdoll))
		{
			return Missing(FeatureCapability.Ragdoll);
		}
		if (target == null || (Object)(object)target.Character == (Object)null)
		{
			return ActionResult.Fail("Target unavailable.");
		}
		strength = Mathf.Clamp(strength, 25f, 150f);
		Vector3 val = Vector3.zero;
		if (_players.Local != null && (Object)(object)_players.Local.Character != (Object)null)
		{
			val = target.Character.Center - _players.Local.Character.Center;
		}
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
		{
			Vector2 insideUnitCircle = Random.insideUnitCircle;
			Vector2 normalized = ((Vector2)(ref insideUnitCircle)).normalized;
			((Vector3)(ref val))..ctor(normalized.x, 0f, normalized.y);
		}
		Vector3 val2 = ((Vector3)(ref val)).normalized + Vector3.up * 0.06f;
		val = ((Vector3)(ref val2)).normalized;
		try
		{
			ReflectionHelpers.Invoke(target.Character, _fall, 5f, 0f);
			ReflectionHelpers.Invoke(target.Character, _addForceAtPosition, val * strength, target.Character.Center, 4f);
			return ActionResult.Ok("Ragdolled " + target.Name + " horizontally at bounded strength " + strength.ToString("0") + ".");
		}
		catch (Exception ex)
		{
			return Error("Horizontal ragdoll", ex);
		}
	}

	public ActionResult WrongMountainLocal(PlayerEntry first, PlayerEntry second, float strength)
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: 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_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.WrongMountain))
		{
			return Missing(FeatureCapability.WrongMountain);
		}
		if (first == null || second == null || (Object)(object)first.Character == (Object)null || (Object)(object)second.Character == (Object)null)
		{
			return ActionResult.Fail("Two available players are required.");
		}
		if (first.ActorNumber == second.ActorNumber)
		{
			return ActionResult.Fail("Wrong Mountain needs two different players.");
		}
		if (first.Character.refs == null || second.Character.refs == null || (Object)(object)first.Character.refs.view == (Object)null || (Object)(object)second.Character.refs.view == (Object)null)
		{
			return ActionResult.Fail("A target Photon view is unavailable.");
		}
		Vector3 center = first.Character.Center;
		Vector3 center2 = second.Character.Center;
		Vector3 direction = center2 - center;
		direction.y = 0f;
		if (((Vector3)(ref direction)).sqrMagnitude < 0.01f)
		{
			Vector2 insideUnitCircle = Random.insideUnitCircle;
			Vector2 normalized = ((Vector2)(ref insideUnitCircle)).normalized;
			((Vector3)(ref direction))..ctor(normalized.x, 0f, normalized.y);
		}
		Vector3 val = ((Vector3)(ref direction)).normalized + Vector3.up * 0.08f;
		direction = ((Vector3)(ref val)).normalized;
		strength = Mathf.Clamp(strength, 25f, 150f);
		try
		{
			first.Character.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { center2, true });
			second.Character.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { center, true });
			GiveRandomItem(first);
			GiveRandomItem(second);
			_wrongMountainJobs.Add(new WrongMountainJob
			{
				FirstActor = first.ActorNumber,
				SecondActor = second.ActorNumber,
				Direction = direction,
				Strength = strength,
				ExecuteAt = Time.unscaledTime + 0.35f
			});
			return ActionResult.Ok("Swapped " + first.Name + " with " + second.Name + "; opposite ragdoll throws and random hand items are queued.");
		}
		catch (Exception ex)
		{
			return Error("Wrong Mountain", ex);
		}
	}

	public ActionResult PositionRouletteLocal(IList<PlayerEntry> entries)
	{
		//IL_0145: 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)
		if (!_capabilities.Available(FeatureCapability.PositionRoulette))
		{
			return Missing(FeatureCapability.PositionRoulette);
		}
		List<PlayerEntry> list = new List<PlayerEntry>();
		Dictionary<int, Vector3> dictionary = new Dictionary<int, Vector3>();
		if (entries != null)
		{
			for (int i = 0; i < entries.Count; i++)
			{
				PlayerEntry playerEntry = entries[i];
				if (playerEntry != null && !((Object)(object)playerEntry.Character == (Object)null) && playerEntry.Character.refs != null && !((Object)(object)playerEntry.Character.refs.view == (Object)null) && !dictionary.ContainsKey(playerEntry.ActorNumber))
				{
					list.Add(playerEntry);
					dictionary.Add(playerEntry.ActorNumber, playerEntry.Character.Center);
				}
			}
		}
		if (list.Count < 2)
		{
			return ActionResult.Fail("Position Roulette needs at least two available scouts.");
		}
		for (int num = list.Count - 1; num > 0; num--)
		{
			int index = Random.Range(0, num + 1);
			PlayerEntry value = list[num];
			list[num] = list[index];
			list[index] = value;
		}
		try
		{
			for (int j = 0; j < list.Count; j++)
			{
				PlayerEntry playerEntry2 = list[(j + 1) % list.Count];
				list[j].Character.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2]
				{
					dictionary[playerEntry2.ActorNumber],
					true
				});
			}
			return ActionResult.Ok("Rotated " + list.Count + " scouts through a randomized no-fixed-point position roulette.");
		}
		catch (Exception ex)
		{
			return Error("Position Roulette", ex);
		}
	}

	private void GiveRandomItem(PlayerEntry target)
	{
		if (_items.Count != 0 && target != null && !((Object)(object)target.Character == (Object)null) && target.Character.refs != null && !((Object)(object)target.Character.refs.items == (Object)null))
		{
			Item val = _items[Random.Range(0, _items.Count)];
			if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name))
			{
				ReflectionHelpers.Invoke(target.Character.refs.items, _spawnItem, ((Object)val).name);
			}
		}
	}

	public void Tick()
	{
		//IL_01c1: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: 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_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyValuePair<int, CachedState> state in _states)
		{
			CachedState value = state.Value;
			if (value.SkeletonApplied && !(Time.unscaledTime < value.SkeletonApplyGraceUntil))
			{
				PlayerEntry playerEntry = _players.Find(state.Key);
				if (playerEntry == null || (Object)(object)playerEntry.Character == (Object)null || (Object)(object)playerEntry.Character.data == (Object)null || !playerEntry.Character.data.isSkeleton)
				{
					value.SkeletonApplied = false;
				}
			}
		}
		for (int num = _wrongMountainJobs.Count - 1; num >= 0; num--)
		{
			WrongMountainJob wrongMountainJob = _wrongMountainJobs[num];
			if (!(Time.unscaledTime < wrongMountainJob.ExecuteAt))
			{
				_wrongMountainJobs.RemoveAt(num);
				PlayerEntry playerEntry2 = _players.Find(wrongMountainJob.FirstActor);
				PlayerEntry playerEntry3 = _players.Find(wrongMountainJob.SecondActor);
				if (playerEntry2 != null && playerEntry3 != null && !((Object)(object)playerEntry2.Character == (Object)null) && !((Object)(object)playerEntry3.Character == (Object)null))
				{
					try
					{
						ReflectionHelpers.Invoke(playerEntry2.Character, _fall, 5f, 0f);
						ReflectionHelpers.Invoke(playerEntry3.Character, _fall, 5f, 0f);
						ReflectionHelpers.Invoke(playerEntry2.Character, _addForceAtPosition, wrongMountainJob.Direction * wrongMountainJob.Strength, playerEntry2.Character.Center, 4f);
						ReflectionHelpers.Invoke(playerEntry3.Character, _addForceAtPosition, -wrongMountainJob.Direction * wrongMountainJob.Strength, playerEntry3.Character.Center, 4f);
					}
					catch (Exception ex)
					{
						_log.LogWarning((object)("Delayed Wrong Mountain throw failed safely: " + ex.Message));
					}
				}
			}
		}
	}

	public void FixedTick()
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: 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_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: 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_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyValuePair<int, CachedState> state in _states)
		{
			CachedState value = state.Value;
			if (!value.FlightActive)
			{
				continue;
			}
			PlayerEntry playerEntry = _players.Find(state.Key);
			if (playerEntry == null || !playerEntry.IsLocal || (Object)(object)playerEntry.Character == (Object)null || (Object)(object)playerEntry.Character.data == (Object)null || playerEntry.Character.data.dead)
			{
				RestoreFlight(value);
				continue;
			}
			Vector3 val = Vector3.zero;
			TrollModPlugin instance = TrollModPlugin.Instance;
			if ((Object)(object)instance == (Object)null || instance.Ui == null || !instance.Ui.IsTyping)
			{
				Vector3 lookDirection_Flat = playerEntry.Character.data.lookDirection_Flat;
				lookDirection_Flat.y = 0f;
				Vector3 lookDirection_Right = playerEntry.Character.data.lookDirection_Right;
				lookDirection_Right.y = 0f;
				if (((Vector3)(ref lookDirection_Flat)).sqrMagnitude > 0.01f)
				{
					((Vector3)(ref lookDirection_Flat)).Normalize();
				}
				if (((Vector3)(ref lookDirection_Right)).sqrMagnitude > 0.01f)
				{
					((Vector3)(ref lookDirection_Right)).Normalize();
				}
				float num = ((Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273)) ? 1f : 0f) - ((Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274)) ? 1f : 0f);
				float num2 = ((Input.GetKey((KeyCode)100) || Input.GetKey((KeyCode)275)) ? 1f : 0f) - ((Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)276)) ? 1f : 0f);
				float num3 = (Input.GetKey((KeyCode)32) ? 1f : 0f) - ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) ? 1f : 0f);
				val = lookDirection_Flat * num + lookDirection_Right * num2 + Vector3.up * num3;
				if (((Vector3)(ref val)).sqrMagnitude > 1f)
				{
					((Vector3)(ref val)).Normalize();
				}
			}
			float num4 = ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) ? 1.75f : 1f);
			Vector3 linearVelocity = val * value.FlightSpeed * num4;
			foreach (KeyValuePair<Rigidbody, FlightBodyState> flightBody in value.FlightBodies)
			{
				if (!((Object)(object)flightBody.Key == (Object)null))
				{
					flightBody.Key.useGravity = false;
					flightBody.Key.maxLinearVelocity = Mathf.Max(flightBody.Key.maxLinearVelocity, value.FlightSpeed * 2f);
					flightBody.Key.linearVelocity = linearVelocity;
				}
			}
		}
	}

	private Vector3 FindDropDirection(Vector3 origin, out bool foundDrop)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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_006c: 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_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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)
		TryGroundHeight(origin, 14f, out var height);
		float num = float.MinValue;
		Vector3 val = Vector3.zero;
		Vector3 val2 = default(Vector3);
		for (int i = 0; i < 24; i++)
		{
			float num2 = (float)i * (float)Math.PI * 2f / 24f;
			((Vector3)(ref val2))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
			float num3 = 0f;
			bool flag = false;
			for (int j = 1; j <= 4; j++)
			{
				float num4 = (float)j * 3f;
				if (!TryGroundHeight(origin + val2 * num4, 28f, out var height2))
				{
					num3 += 80f + (float)(5 - j) * 12f;
					flag = true;
					break;
				}
				float num5 = height - height2;
				num3 = ((!(num5 > 0f)) ? (num3 + num5 * 0.5f) : (num3 + num5 * (6f - (float)j)));
			}
			if (flag)
			{
				num3 += 20f;
			}
			if (num3 > num)
			{
				num = num3;
				val = val2;
			}
		}
		foundDrop = num >= 18f && ((Vector3)(ref val)).sqrMagnitude > 0.01f;
		if (!foundDrop)
		{
			val = DirectionAwayFromRoute(origin);
		}
		Vector3 val3 = ((Vector3)(ref val)).normalized + Vector3.up * 0.22f;
		return ((Vector3)(ref val3)).normalized;
	}

	private static bool TryGroundHeight(Vector3 position, float depth, out float height)
	{
		//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_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(position + Vector3.up * 4f, Vector3.down, ref val, depth, -5, (QueryTriggerInteraction)1))
		{
			height = ((RaycastHit)(ref val)).point.y;
			return true;
		}
		height = position.y - depth;
		return false;
	}

	private Vector3 DirectionAwayFromRoute(Vector3 origin)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_006d: 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_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_00b8: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: 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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Vector3.zero;
		int num = 0;
		MapHandler val2 = Object.FindFirstObjectByType<MapHandler>();
		if ((Object)(object)val2 != (Object)null && val2.segments != null)
		{
			for (int i = 0; i < val2.segments.Length; i++)
			{
				MapSegment val3 = val2.segments[i];
				if (val3 != null && !((Object)(object)val3.reconnectSpawnPos == (Object)null))
				{
					val += val3.reconnectSpawnPos.position;
					num++;
				}
			}
		}
		val = ((num > 0) ? (val / (float)num) : ((_players.Local == null || !((Object)(object)_players.Local.Character != (Object)null)) ? (origin - Vector3.forward) : _players.Local.Character.Center));
		Vector3 val4 = origin - val;
		val4.y = 0f;
		if (!(((Vector3)(ref val4)).sqrMagnitude > 0.01f))
		{
			return Vector3.forward;
		}
		return ((Vector3)(ref val4)).normalized;
	}

	public ActionResult LaunchLocal(PlayerEntry target, Vector3 direction, float strength, bool ragdoll)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.Launch))
		{
			return Missing(FeatureCapability.Launch);
		}
		if (target == null || (Object)(object)target.Character == (Object)null)
		{
			return ActionResult.Fail("Target unavailable.");
		}
		strength = Mathf.Clamp(strength, 5f, 120f);
		direction = ((((Vector3)(ref direction)).sqrMagnitude < 0.01f) ? Vector3.up : ((Vector3)(ref direction)).normalized);
		try
		{
			if (ragdoll)
			{
				ReflectionHelpers.Invoke(target.Character, _fall, 1.5f, 0f);
			}
			ReflectionHelpers.Invoke(target.Character, _addForceAtPosition, direction * strength, target.Character.Center, 4f);
			return ActionResult.Ok("Launched " + target.Name + " through PEAK's native force RPC; no host or target mod required.");
		}
		catch (Exception ex)
		{
			return Error("Launch", ex);
		}
	}

	public ActionResult SkyLaunchLocal(PlayerEntry target, float height)
	{
		//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_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.SkyLaunch))
		{
			return Missing(FeatureCapability.SkyLaunch);
		}
		if (target == null || (Object)(object)target.Character == (Object)null || target.Character.refs == null || (Object)(object)target.Character.refs.view == (Object)null)
		{
			return ActionResult.Fail("Target view unavailable.");
		}
		height = Mathf.Clamp(height, 25f, 300f);
		Vector3 val = target.Character.Center + Vector3.up * height;
		try
		{
			ReflectionHelpers.Invoke(target.Character, _fall, 5f, 0f);
			ReflectionHelpers.Invoke(target.Character, _addForceAtPosition, Vector3.up * 18f, target.Character.Center, 4f);
			target.Character.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, true });
			return ActionResult.Ok("Sent " + target.Name + " " + height.ToString("0") + "m into the sky through PEAK's native RPCs.");
		}
		catch (Exception ex)
		{
			return Error("Sky launch", ex);
		}
	}

	public ActionResult HorizonLaunchLocal(PlayerEntry target, float distance)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: 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_011e: 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_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		if (!_capabilities.Available(FeatureCapability.HorizonLaunch))
		{
			return Missing(FeatureCapability.HorizonLaunch);
		}
		if (target == null || (Object)(object)target.Character == (Object)null || target.Character.refs == null || (Object)(object)target.Character.refs.view == (Object)null)
		{
			return ActionResult.Fail("Target view unavailable.");
		}
		distance = Mathf.Clamp(distance, 25f, 300f);
		Vector3 val = DirectionAwayFromRoute(target.Character.Center);
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
		{
			val = Vector3.forward;
		}
		((Vector3)(ref val)).Normalize();
		if (!TryClearHorizonDestination(target.Character.Center + val * distance, out var destination))
		{
			return ActionResult.Fail("No clear endpoint was found in the outward direction.");
		}
		try
		{
			ReflectionHelpers.Invoke(target.Character, _fall, 6f, 0f);
			Character character = target.Character;
			MethodInfo addForceAtPosition = _addForceAtPosition;
			object[] array = new object[3];
			Vector3 val2 = val + Vector3.up * 0.08f;
			array[0] = ((Vector3)(ref val2)).normalized * 24f;
			array[1] = target.Character.Center;
			array[2] = 4f;
			ReflectionHelpers.Invoke(character, addForceAtPosition, array);
			target.Character.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { destination, true });
			return ActionResult.Ok("Sent " + target.Name + " " + distance.ToString("0") + "m toward the far horizon through PEAK's native RPCs.");
		}
		catch (Exception ex)
		{
			return Error("Far Horizon", ex);
		}
	}

	private static bool TryClearHorizonDestination(Vector3 desired, out Vector3 destination)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: 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)
		//IL_0034: 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)
		for (int i = 0; i < 9; i++)
		{
			Vector3 val = desired + Vector3.up * (8f + (float)i * 5f);
			if (!Physics.CheckSphere(val, 0.8f, -5, (QueryTriggerInteraction)1))
			{
				destination = val;
				return true;
			}
		}
		destination = Vector3.zero;
		return false;
	}

	public ActionResult SetSpeedLocal(PlayerEntry target, float multiplier)
	{
		if (!_capabilities.Available(FeatureCapability.Speed))
		{
			return Missing(FeatureCapability.Speed);
		}
		if (target == null || (Object)(object)target.Character == (Object)null || target.Character.refs == null || (Object)(object)target.Character.refs.movement == (Object)null)
		{
			return ActionResult.Fail("Movement component unavailable.");
		}
		CachedState cachedState = State(target);
		if (!cachedState.HasSpeed)
		{
			cachedState.Speed = target.Character.refs.movement.movementModifier;
			cachedState.HasSpeed = true;
		}
		target.Character.refs.movement.movementModifier = Mathf.Clamp(multiplier, 0.25f, 3f);
		return ActionResult.Ok("Speed set to " + multiplier.ToString("0.00") + "x.");
	}

	public ActionResult SetFlightLocal(PlayerEntry target, bool enabled, float speed)
	{
		if (!_capabilities.Available(FeatureCapability.Flight))
		{
			return Missing(FeatureCapability.Flight);
		}
		if (target == null || !target.IsLocal || (Object)(object)target.Character == (Object)null || target.Character.refs == null || (Object)(object)target.Character.refs.ragdoll == (Object)null || _ragdollRigidbodies == null)
		{
			return ActionResult.Fail("Flight requires the selected player's compatible owner client.");
		}
		CachedState cachedState = State(target);
		if (!enabled)
		{
			RestoreFlight(cachedState);
			return ActionResult.Ok("Flight disabled for " + target.Name + ".");
		}
		speed = Mathf.Clamp(speed, 4f, 20f);
		if (!(_ragdollRigidbodies.GetValue(target.Character.refs.ragdoll) is IList<Rigidbody> list))
		{
			return ActionResult.Fail("No character rigidbody registry was available for flight.");
		}
		for (int i = 0; i < list.Count; i++)
		{
			Rigidbody val = list[i];
			if (!((Object)(object)val == (Object)null))
			{
				if (!cachedState.FlightBodies.ContainsKey(val))
				{
					cachedState.FlightBodies.Add(val, new FlightBodyState
					{
						UseGravity = val.useGravity,
						MaxLinearVelocity = val.maxLinearVeloc