Decompiled source of ScoutTwoSeater v1.0.0

ScoutTwoSeater.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.ScoutTwoSeater
{
	[HarmonyPatch]
	internal static class ScoutTwoSeaterPatches
	{
		private sealed class PassengerInfo
		{
			public PlayerAvatar Player;

			public GameObject Anchor;

			public float MountTime;

			public HashSet<PlayerAvatar> PrevFrameGrabbers = new HashSet<PlayerAvatar>();

			public bool HasReleasedGrabSinceMount;
		}

		private static readonly Dictionary<ItemVehicle, PassengerInfo> Vehicles = new Dictionary<ItemVehicle, PassengerInfo>();

		private static bool IsHostAuthority()
		{
			return SemiFunc.IsMasterClientOrSingleplayer();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemVehicle), "Start")]
		private static void Start_Postfix(ItemVehicle __instance)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0050: 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)
			if (!IsHostAuthority() || !ScoutTwoSeaterPlugin.CfgEnabled.Value || (Object)(object)__instance == (Object)null || Vehicles.ContainsKey(__instance))
			{
				return;
			}
			try
			{
				GameObject val = new GameObject("ScoutTwoSeater_Anchor");
				val.transform.SetParent(((Component)__instance).transform, false);
				val.transform.localPosition = ScoutTwoSeaterPlugin.GetPoseLocalPosition();
				val.transform.localRotation = Quaternion.identity;
				Vehicles[__instance] = new PassengerInfo
				{
					Player = null,
					Anchor = val,
					MountTime = 0f
				};
				if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value)
				{
					ScoutTwoSeaterPlugin.Log.LogInfo((object)$"[ScoutTwoSeater] Registered vehicle {((Object)__instance).GetInstanceID()}");
				}
			}
			catch (Exception ex)
			{
				ScoutTwoSeaterPlugin.Log.LogError((object)("[ScoutTwoSeater] Start postfix failed: " + ex));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemVehicle), "Update")]
		private static void Update_Postfix(ItemVehicle __instance)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHostAuthority() || !ScoutTwoSeaterPlugin.CfgEnabled.Value || (Object)(object)__instance == (Object)null || !Vehicles.TryGetValue(__instance, out var value))
			{
				return;
			}
			if ((Object)(object)value.Anchor == (Object)null)
			{
				Vehicles.Remove(__instance);
				return;
			}
			Vector3 poseLocalPosition = ScoutTwoSeaterPlugin.GetPoseLocalPosition();
			if (value.Anchor.transform.localPosition != poseLocalPosition)
			{
				value.Anchor.transform.localPosition = poseLocalPosition;
			}
			if ((Object)(object)value.Player == (Object)null)
			{
				TryMountNew(__instance, value);
			}
			else
			{
				MaintainPassenger(__instance, value);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemVehicle), "FixedUpdate")]
		private static void FixedUpdate_Postfix(ItemVehicle __instance)
		{
			if (IsHostAuthority() && ScoutTwoSeaterPlugin.CfgEnabled.Value && !((Object)(object)__instance == (Object)null) && Vehicles.TryGetValue(__instance, out var value) && !((Object)(object)value.Player == (Object)null) && !((Object)(object)value.Anchor == (Object)null) && !((Object)(object)value.Player.tumble == (Object)null) && !((Object)(object)value.Player.tumble.physGrabObject == (Object)null) && !((Object)(object)__instance.rb == (Object)null))
			{
				ApplyPullForce(__instance, value.Player, value.Anchor.transform);
			}
		}

		private static void ApplyPullForce(ItemVehicle vehicle, PlayerAvatar player, Transform anchor)
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			PlayerTumble tumble = player.tumble;
			PhysGrabObject physGrabObject = tumble.physGrabObject;
			Rigidbody rb = tumble.rb;
			Rigidbody rb2 = vehicle.rb;
			if (!tumble.isTumbling)
			{
				tumble.TumbleRequest(true, false);
			}
			tumble.TumbleOverrideTime(0.5f);
			physGrabObject.OverrideMaterial(SemiFunc.PhysicMaterialSlippery(), 0.1f);
			physGrabObject.OverrideZeroGravity(0.2f);
			if ((Object)(object)physGrabObject.impactDetector != (Object)null)
			{
				physGrabObject.impactDetector.ImpactDisable(0.2f);
			}
			tumble.OverrideEnemyHurt(0.1f);
			if ((Object)(object)player.physGrabber != (Object)null && player.isLocal)
			{
				player.physGrabber.OverrideDisableSpecialGrabPowers(1f);
				tumble.OverrideTumbleUIDisable(0.2f);
			}
			PullStrength value = ScoutTwoSeaterPlugin.CfgPullStrength.Value;
			float num;
			float num2;
			float num3;
			if (value != 0 && value == PullStrength.Strong)
			{
				num = 1f;
				num2 = 0.5f;
				num3 = 1f;
			}
			else
			{
				num = 0.05f;
				num2 = 0.08f;
				num3 = 0.5f;
			}
			physGrabObject.OverrideMass(num, 0.1f);
			Vector3 pointVelocity = rb2.GetPointVelocity(rb.position);
			rb.velocity = pointVelocity;
			Vector3 val = anchor.position - rb.position;
			rb.velocity += val / Time.fixedDeltaTime * num2;
			rb.angularVelocity = rb2.angularVelocity;
			Quaternion rotation = ((Component)player).transform.rotation;
			Vector3 val2 = SemiFunc.PhysFollowRotation(((Component)tumble).transform, rotation, rb, num3);
			rb.AddTorque(val2, (ForceMode)1);
		}

		private static void TryMountNew(ItemVehicle vehicle, PassengerInfo info)
		{
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Invalid comparison between Unknown and I4
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			PhysGrabObject component = ((Component)vehicle).GetComponent<PhysGrabObject>();
			if ((Object)(object)component == (Object)null || component.playerGrabbing == null)
			{
				info.PrevFrameGrabbers.Clear();
				return;
			}
			PlayerAvatar val = null;
			if (vehicle.seats != null && vehicle.seats.Length != 0 && vehicle.seats[0] != null)
			{
				val = vehicle.seats[0].seatedPlayer;
			}
			float value = ScoutTwoSeaterPlugin.CfgDriverSideThresholdZ.Value;
			HashSet<PlayerAvatar> hashSet = new HashSet<PlayerAvatar>();
			List<PlayerAvatar> list = new List<PlayerAvatar>();
			List<PlayerAvatar> list2 = new List<PlayerAvatar>();
			for (int i = 0; i < component.playerGrabbing.Count; i++)
			{
				PhysGrabber val2 = component.playerGrabbing[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				PlayerAvatar playerAvatar = val2.playerAvatar;
				if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar == (Object)(object)val || playerAvatar.isDisabled || (Object)(object)playerAvatar.tumble == (Object)null)
				{
					continue;
				}
				hashSet.Add(playerAvatar);
				if (info.PrevFrameGrabbers.Contains(playerAvatar))
				{
					continue;
				}
				bool flag = false;
				float num = 0f;
				try
				{
					if ((Object)(object)val2.physGrabPoint != (Object)null)
					{
						Vector3 position = val2.physGrabPoint.position;
						num = ((Component)vehicle).transform.InverseTransformPoint(position).z;
						flag = num > value;
						if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value)
						{
							ScoutTwoSeaterPlugin.Log.LogInfo((object)string.Format("[ScoutTwoSeater] {0} NEW GRAB localZ={1:F2} threshold={2:F2} → {3}", playerAvatar.playerName, num, value, flag ? "FRONT(car-head)" : "REAR(car-tail)"));
						}
					}
					else
					{
						if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value)
						{
							ScoutTwoSeaterPlugin.Log.LogWarning((object)("[ScoutTwoSeater] " + playerAvatar.playerName + " NEW GRAB but physGrabPoint is null - treating as FRONT"));
						}
						flag = true;
					}
				}
				catch (Exception ex)
				{
					ScoutTwoSeaterPlugin.Log.LogWarning((object)("[ScoutTwoSeater] Grab point check error: " + ex.Message));
					flag = true;
				}
				if (flag)
				{
					list.Add(playerAvatar);
				}
				else
				{
					list2.Add(playerAvatar);
				}
			}
			if ((int)vehicle.currentState != 2 && !vehicle.isFullyDestroyed)
			{
				using List<PlayerAvatar>.Enumerator enumerator = list2.GetEnumerator();
				if (enumerator.MoveNext())
				{
					PlayerAvatar current = enumerator.Current;
					Mount(vehicle, info, current);
					info.PrevFrameGrabbers = hashSet;
					return;
				}
			}
			info.PrevFrameGrabbers = hashSet;
		}

		private static void Mount(ItemVehicle vehicle, PassengerInfo info, PlayerAvatar player)
		{
			info.Player = player;
			info.MountTime = Time.time;
			info.HasReleasedGrabSinceMount = false;
			if ((Object)(object)player.tumble != (Object)null)
			{
				player.tumble.TumbleRequest(true, false);
				player.tumble.TumbleOverrideTime(2f);
			}
			if ((Object)(object)player.physGrabber != (Object)null)
			{
				try
				{
					player.physGrabber.OverrideGrabRelease(-1, 0.5f);
				}
				catch
				{
				}
			}
			if (ScoutTwoSeaterPlugin.CfgForceUnequipOnMount.Value && (Object)(object)player.physGrabber != (Object)null && (Object)(object)player.physGrabber.grabbedPhysGrabObject != (Object)null)
			{
				try
				{
					player.physGrabber.OverrideGrabRelease(-1, 0.5f);
				}
				catch
				{
				}
			}
			if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value)
			{
				ScoutTwoSeaterPlugin.Log.LogInfo((object)$"[ScoutTwoSeater] MOUNT: {player.playerName} -> vehicle {((Object)vehicle).GetInstanceID()}");
			}
		}

		private static void MaintainPassenger(ItemVehicle vehicle, PassengerInfo info)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			//IL_010e: 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)
			PlayerAvatar player = info.Player;
			if ((Object)(object)player == (Object)null || player.isDisabled || (Object)(object)player.tumble == (Object)null)
			{
				Dismount(vehicle, info, "passenger disabled");
				return;
			}
			if ((int)vehicle.currentState == 2 || vehicle.isFullyDestroyed)
			{
				Dismount(vehicle, info, "vehicle tumbled or destroyed");
				return;
			}
			if (vehicle.seats != null && vehicle.seats.Length != 0 && vehicle.seats[0] != null && (Object)(object)vehicle.seats[0].seatedPlayer == (Object)(object)player)
			{
				try
				{
					if ((Object)(object)vehicle.photonView != (Object)null)
					{
						vehicle.photonView.RPC("ClearSeatRPC", (RpcTarget)0, new object[1] { 0 });
					}
					if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value)
					{
						ScoutTwoSeaterPlugin.Log.LogInfo((object)("[ScoutTwoSeater] Rescued " + player.playerName + " from driver seat"));
					}
				}
				catch
				{
				}
			}
			if ((Object)(object)info.Anchor != (Object)null && (Object)(object)player.tumble.rb != (Object)null)
			{
				float num = Vector3.Distance(player.tumble.rb.position, info.Anchor.transform.position);
				if (num > ScoutTwoSeaterPlugin.CfgAutoDismountDistance.Value)
				{
					Dismount(vehicle, info, $"distance {num:F1}m");
					return;
				}
			}
			bool flag = false;
			PhysGrabObject component = ((Component)vehicle).GetComponent<PhysGrabObject>();
			if ((Object)(object)component != (Object)null && component.playerGrabbing != null)
			{
				for (int i = 0; i < component.playerGrabbing.Count; i++)
				{
					PhysGrabber val = component.playerGrabbing[i];
					if ((Object)(object)val != (Object)null && (Object)(object)val.playerAvatar == (Object)(object)player)
					{
						flag = true;
						break;
					}
				}
			}
			if (!flag && Time.time - info.MountTime >= 0.3f)
			{
				info.HasReleasedGrabSinceMount = true;
			}
			if (!(info.HasReleasedGrabSinceMount && flag) || !(Time.time - info.MountTime >= ScoutTwoSeaterPlugin.CfgMountDebounceSeconds.Value))
			{
				return;
			}
			if ((Object)(object)player.physGrabber != (Object)null)
			{
				try
				{
					player.physGrabber.OverrideGrabRelease(-1, 0.5f);
				}
				catch
				{
				}
			}
			Dismount(vehicle, info, "re-grab after release");
		}

		private static void Dismount(ItemVehicle vehicle, PassengerInfo info, string reason)
		{
			PlayerAvatar player = info.Player;
			info.Player = null;
			if ((Object)(object)player != (Object)null && (Object)(object)player.tumble != (Object)null && player.tumble.isTumbling)
			{
				try
				{
					player.tumble.TumbleRequest(false, false);
				}
				catch
				{
				}
			}
			if (ScoutTwoSeaterPlugin.CfgVerboseLog.Value && (Object)(object)player != (Object)null)
			{
				ScoutTwoSeaterPlugin.Log.LogInfo((object)("[ScoutTwoSeater] DISMOUNT: " + player.playerName + " (" + reason + ")"));
			}
		}

		internal static void HostSelfMountToggle()
		{
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Invalid comparison between Unknown and I4
			//IL_011a: 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)
			if (!IsHostAuthority() || !ScoutTwoSeaterPlugin.CfgEnabled.Value)
			{
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerGetLocal();
			if ((Object)(object)val == (Object)null)
			{
				ScoutTwoSeaterPlugin.Log.LogInfo((object)"[ScoutTwoSeater] Hotkey: no local player");
				return;
			}
			foreach (KeyValuePair<ItemVehicle, PassengerInfo> vehicle in Vehicles)
			{
				if (vehicle.Value != null && (Object)(object)vehicle.Value.Player == (Object)(object)val)
				{
					Dismount(vehicle.Key, vehicle.Value, "hotkey toggle (dismount)");
					return;
				}
			}
			ItemVehicle val2 = null;
			float num = float.MaxValue;
			float value = ScoutTwoSeaterPlugin.CfgHostSelfMountRange.Value;
			foreach (KeyValuePair<ItemVehicle, PassengerInfo> vehicle2 in Vehicles)
			{
				if (!((Object)(object)vehicle2.Key == (Object)null) && vehicle2.Value != null && !((Object)(object)vehicle2.Value.Player != (Object)null) && (int)vehicle2.Key.currentState != 2 && !vehicle2.Key.isFullyDestroyed)
				{
					float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)vehicle2.Key).transform.position);
					if (num2 < num && num2 <= value)
					{
						num = num2;
						val2 = vehicle2.Key;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				ScoutTwoSeaterPlugin.Log.LogInfo((object)$"[ScoutTwoSeater] Hotkey: no Scout within {value}m");
			}
			else if (val2.seats != null && val2.seats.Length != 0 && val2.seats[0] != null && (Object)(object)val2.seats[0].seatedPlayer == (Object)(object)val)
			{
				ScoutTwoSeaterPlugin.Log.LogInfo((object)"[ScoutTwoSeater] Hotkey: host is driver, cannot self-mount");
			}
			else
			{
				Mount(val2, Vehicles[val2], val);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemVehicle), "OnDestroy")]
		private static void OnDestroy_Postfix(ItemVehicle __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && Vehicles.TryGetValue(__instance, out var value))
			{
				if ((Object)(object)value.Anchor != (Object)null)
				{
					Object.Destroy((Object)(object)value.Anchor);
				}
				Vehicles.Remove(__instance);
			}
		}
	}
	public enum PassengerPose
	{
		Back,
		Front
	}
	public enum PullStrength
	{
		Weak,
		Strong
	}
	public enum Language
	{
		EN,
		CN
	}
	[BepInPlugin("REPOJP.ScoutTwoSeater", "ScoutTwoSeater", "1.0.0")]
	public sealed class ScoutTwoSeaterPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.ScoutTwoSeater";

		public const string PluginName = "ScoutTwoSeater";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ScoutTwoSeaterPlugin Instance;

		private Harmony harmony;

		internal static ConfigEntry<Language> CfgLanguage;

		internal static ConfigEntry<bool> CfgEnabled;

		internal static ConfigEntry<PassengerPose> CfgPose;

		internal static ConfigEntry<bool> CfgForceUnequipOnMount;

		internal static ConfigEntry<float> CfgMountDebounceSeconds;

		internal static ConfigEntry<float> CfgAutoDismountDistance;

		internal static ConfigEntry<bool> CfgVerboseLog;

		internal static ConfigEntry<bool> CfgHostHotkeyEnabled;

		internal static ConfigEntry<KeyCode> CfgHostSelfMountKey;

		internal static ConfigEntry<float> CfgHostSelfMountRange;

		internal static ConfigEntry<float> CfgDriverSideThresholdZ;

		internal static ConfigEntry<PullStrength> CfgPullStrength;

		internal static ConfigEntry<float> CfgBackX;

		internal static ConfigEntry<float> CfgBackY;

		internal static ConfigEntry<float> CfgBackZ;

		internal static ConfigEntry<float> CfgFrontX;

		internal static ConfigEntry<float> CfgFrontY;

		internal static ConfigEntry<float> CfgFrontZ;

		private float cfgReloadAccum;

		private const float CfgReloadInterval = 2f;

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				InitializeConfig();
				harmony = new Harmony("REPOJP.ScoutTwoSeater");
				harmony.PatchAll();
				Log.LogInfo((object)"[ScoutTwoSeater] Loaded v1.0.0");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ScoutTwoSeater] Awake failed: " + ex));
			}
		}

		private void Update()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (CfgEnabled == null || !CfgEnabled.Value)
			{
				return;
			}
			try
			{
				if (CfgHostHotkeyEnabled != null && CfgHostHotkeyEnabled.Value && CfgHostSelfMountKey != null && Input.GetKeyDown(CfgHostSelfMountKey.Value))
				{
					ScoutTwoSeaterPatches.HostSelfMountToggle();
				}
				cfgReloadAccum += Time.deltaTime;
				if (cfgReloadAccum >= 2f)
				{
					cfgReloadAccum = 0f;
					try
					{
						((BaseUnityPlugin)this).Config.Reload();
						return;
					}
					catch
					{
						return;
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ScoutTwoSeater] Update error: " + ex));
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ScoutTwoSeater] OnDestroy failed: " + ex));
			}
		}

		private void InitializeConfig()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Expected O, but got Unknown
			CfgLanguage = ((BaseUnityPlugin)this).Config.Bind<Language>("00_Setup", "Language", Language.EN, "Change interface language. Restart the game after switching.\n切換介面語言。切換後需要重新啟動遊戲才會生效。\nEN = English / CN = 繁體中文");
			LocStrings locStrings = LocStrings.Build(CfgLanguage.Value);
			CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>(locStrings.SecGeneral, locStrings.KeyEnabled, true, locStrings.DescEnabled);
			CfgPose = ((BaseUnityPlugin)this).Config.Bind<PassengerPose>(locStrings.SecGeneral, locStrings.KeyPose, PassengerPose.Back, locStrings.DescPose);
			CfgForceUnequipOnMount = ((BaseUnityPlugin)this).Config.Bind<bool>(locStrings.SecGeneral, locStrings.KeyForceUnequip, false, locStrings.DescForceUnequip);
			CfgMountDebounceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecGeneral, locStrings.KeyDebounce, 1.5f, new ConfigDescription(locStrings.DescDebounce, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			CfgAutoDismountDistance = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecGeneral, locStrings.KeyAutoDismount, 8f, new ConfigDescription(locStrings.DescAutoDismount, (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			CfgVerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>(locStrings.SecGeneral, locStrings.KeyVerboseLog, false, locStrings.DescVerboseLog);
			CfgDriverSideThresholdZ = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecGeneral, locStrings.KeyThresholdZ, -0.2f, new ConfigDescription(locStrings.DescThresholdZ, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
			CfgPullStrength = ((BaseUnityPlugin)this).Config.Bind<PullStrength>(locStrings.SecGeneral, locStrings.KeyPullStrength, PullStrength.Weak, locStrings.DescPullStrength);
			CfgHostHotkeyEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>(locStrings.SecAdvanced, locStrings.KeyHotkeyEnabled, false, locStrings.DescHotkeyEnabled);
			CfgHostSelfMountKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>(locStrings.SecAdvanced, locStrings.KeyHotkeyKey, (KeyCode)118, locStrings.DescHotkeyKey);
			CfgHostSelfMountRange = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecAdvanced, locStrings.KeyHotkeyRange, 6f, new ConfigDescription(locStrings.DescHotkeyRange, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			CfgBackX = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecBackOffset, locStrings.KeyOffsetX, 0f, locStrings.DescOffsetX);
			CfgBackY = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecBackOffset, locStrings.KeyOffsetY, 1f, locStrings.DescOffsetY);
			CfgBackZ = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecBackOffset, locStrings.KeyOffsetZ, -1f, locStrings.DescOffsetZ);
			CfgFrontX = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecFrontOffset, locStrings.KeyOffsetX, 0f, locStrings.DescOffsetX);
			CfgFrontY = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecFrontOffset, locStrings.KeyOffsetY, 1f, locStrings.DescOffsetY);
			CfgFrontZ = ((BaseUnityPlugin)this).Config.Bind<float>(locStrings.SecFrontOffset, locStrings.KeyOffsetZ, 1f, locStrings.DescOffsetZ);
		}

		internal static Vector3 GetPoseLocalPosition()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			PassengerPose value = CfgPose.Value;
			if (value != 0 && value == PassengerPose.Front)
			{
				return new Vector3(CfgFrontX.Value, CfgFrontY.Value, CfgFrontZ.Value);
			}
			return new Vector3(CfgBackX.Value, CfgBackY.Value, CfgBackZ.Value);
		}
	}
	internal sealed class LocStrings
	{
		public string SecGeneral;

		public string SecAdvanced;

		public string SecBackOffset;

		public string SecFrontOffset;

		public string KeyEnabled;

		public string KeyPose;

		public string KeyForceUnequip;

		public string KeyDebounce;

		public string KeyAutoDismount;

		public string KeyVerboseLog;

		public string KeyThresholdZ;

		public string KeyPullStrength;

		public string KeyHotkeyEnabled;

		public string KeyHotkeyKey;

		public string KeyHotkeyRange;

		public string KeyOffsetX;

		public string KeyOffsetY;

		public string KeyOffsetZ;

		public string DescEnabled;

		public string DescPose;

		public string DescForceUnequip;

		public string DescDebounce;

		public string DescAutoDismount;

		public string DescVerboseLog;

		public string DescThresholdZ;

		public string DescPullStrength;

		public string DescHotkeyEnabled;

		public string DescHotkeyKey;

		public string DescHotkeyRange;

		public string DescOffsetX;

		public string DescOffsetY;

		public string DescOffsetZ;

		public static LocStrings Build(Language lang)
		{
			if (lang == Language.EN)
			{
				return new LocStrings
				{
					SecGeneral = "General",
					SecAdvanced = "Advanced",
					SecBackOffset = "BackOffset",
					SecFrontOffset = "FrontOffset",
					KeyEnabled = "Enabled",
					KeyPose = "PassengerSeat",
					KeyForceUnequip = "ForceUnequipOnMount",
					KeyDebounce = "MountDebounceSeconds",
					KeyAutoDismount = "AutoDismountDistance",
					KeyVerboseLog = "VerboseLog",
					KeyThresholdZ = "DriverSideThresholdZ",
					KeyPullStrength = "PullStrength",
					KeyHotkeyEnabled = "EnableHostHotkey",
					KeyHotkeyKey = "HostSelfMountKey",
					KeyHotkeyRange = "HostSelfMountRange",
					KeyOffsetX = "OffsetX",
					KeyOffsetY = "OffsetY",
					KeyOffsetZ = "OffsetZ",
					DescEnabled = "Enable the two-seater Scout. When false, Scout behaves like vanilla.",
					DescPose = "Where the passenger sits. Back = rear of vehicle. Front = front of vehicle.",
					DescForceUnequip = "If true, forces the passenger to unequip their held item when they board.",
					DescDebounce = "Delay (seconds) after mounting before the passenger can press grab again to dismount.",
					DescAutoDismount = "If the passenger's ragdoll drifts more than this distance (meters) from the seat, auto-dismount.",
					DescVerboseLog = "Log mount/dismount details to BepInEx console. Use for debugging.",
					DescThresholdZ = "Threshold for front/back detection (Scout local Z).\nlocalZ > value = car front (vanilla behavior) / localZ <= value = car rear (passenger).\nDefault -0.2 puts the boundary slightly forward of center.\nIf axis is reversed, try a positive value.",
					DescPullStrength = "Weak: Smooth, vehicle does not get pushed. Loose grip.\nStrong: Passenger snaps to seat fast, but vehicle gets pushed around.",
					DescHotkeyEnabled = "Disabled by default. Enable to allow host to force themselves into the passenger seat via a hotkey - useful for solo testing.",
					DescHotkeyKey = "The key the host presses to toggle being a passenger on the nearest Scout. Requires 'EnableHostHotkey' to be true.",
					DescHotkeyRange = "Max distance (meters) the host needs to be within a Scout for the hotkey to take effect.",
					DescOffsetX = "Local X offset relative to Scout (left/right).",
					DescOffsetY = "Local Y offset (up/down). Positive = up.",
					DescOffsetZ = "Local Z offset (front/back). Negative usually = rear, positive = front."
				};
			}
			return new LocStrings
			{
				SecGeneral = "一般",
				SecAdvanced = "進階",
				SecBackOffset = "車尾偏移",
				SecFrontOffset = "車頭偏移",
				KeyEnabled = "啟用雙人座",
				KeyPose = "乘客位置",
				KeyForceUnequip = "上車時強制收起手上道具",
				KeyDebounce = "上下車按鍵間隔(秒)",
				KeyAutoDismount = "自動下車距離",
				KeyVerboseLog = "詳細日誌",
				KeyThresholdZ = "車前後分界線Z",
				KeyPullStrength = "吸力強度",
				KeyHotkeyEnabled = "啟用主機熱鍵",
				KeyHotkeyKey = "主機自我乘客切換鍵",
				KeyHotkeyRange = "主機自我乘客觸發距離",
				KeyOffsetX = "X(左右)",
				KeyOffsetY = "Y(上下)",
				KeyOffsetZ = "Z(前後)",
				DescEnabled = "啟用雙人座 Scout。關閉後 Scout 行為與原版一致。",
				DescPose = "乘客的位置。Back = 車尾後方 / Front = 車頭前方。",
				DescForceUnequip = "若開啟,乘客上車當下會把手上拿的道具收回物品欄。",
				DescDebounce = "乘客上車後,要等這麼久才能再次抓 Scout 觸發下車。避免一按就上車又馬上下車。",
				DescAutoDismount = "乘客的 ragdoll 飄離 Scout 超過這個距離(米)就自動下車。避免乘客被甩飛但仍卡在 tumble 狀態。",
				DescVerboseLog = "開啟後會在 BepInEx 主控台輸出乘客上下車的詳細過程,用於除錯。",
				DescThresholdZ = "玩家抓住 Scout 哪個部位 (用 Scout 本體 local Z 座標判斷):\nlocalZ > 此值 = 車前部 (走原版邏輯) / localZ <= 此值 = 車後部 (變乘客)\n預設 -0.2 = 偏前一點分界 (車中心線稍微往前),這樣大部分後段都是乘客區。\n若軸向反了 (抓車前變乘客、抓車後沒反應) 改成正值試試。",
				DescPullStrength = "Weak (弱):乘客平順上車,車子不會被推開,但拉力較鬆。\nStrong (強):乘客快速貼緊座位,但車子會被乘客推動產生位移。",
				DescHotkeyEnabled = "預設關閉。開啟後主機可以用熱鍵 (預設 V) 強制把自己變乘客 - 給單人測試用。",
				DescHotkeyKey = "主機按下此鍵 -> 把附近最近的 Scout 當成乘客車,自己上車/下車。需要先開啟「啟用主機熱鍵」。",
				DescHotkeyRange = "主機按熱鍵時,要在這距離內找到 Scout 才會生效 (米)。",
				DescOffsetX = "Scout 本體 local 座標 X (左右)。",
				DescOffsetY = "Scout 本體 local 座標 Y (上下,正=上方)。",
				DescOffsetZ = "Scout 本體 local 座標 Z (前後,負通常=後方車尾、正=前方車頭)。"
			};
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}