Decompiled source of SoulFly v1.0.1

SoulFly.dll

Decompiled 12 hours ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

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

internal class SoulFlyController : MonoBehaviour
{
	internal static SoulFlyController Instance;

	internal static bool SoulActive;

	private static readonly FieldInfo FieldAnimator = AccessTools.Field(typeof(PlayerAvatarVisuals), "animator");

	private static readonly MethodInfo MethodApplyLocalVisibility = AccessTools.Method(typeof(PlayerAvatarVisuals), "ApplyLocalVisibility", new Type[1] { typeof(ShadowCastingMode) }, (Type[])null);

	private static readonly FieldInfo FieldDeadSet = AccessTools.Field(typeof(PlayerAvatar), "deadSet");

	private static readonly FieldInfo FieldSpectating = AccessTools.Field(typeof(PlayerAvatar), "spectating");

	private PlayerController playerController;

	private PlayerAvatar playerAvatar;

	private PlayerAvatarVisuals visuals;

	private PlayerLocalCamera localCamera;

	private Camera mainCamera;

	private Transform cameraParent;

	private Transform aimTransform;

	private Animator animator;

	private float animatorSpeed = 1f;

	private bool animatorSpeedCaptured;

	private Vector3 flyPosition;

	private float flyYaw;

	private float flyPitch;

	private Quaternion frozenBodyRotation = Quaternion.identity;

	private Quaternion frozenAimRotation = Quaternion.identity;

	private void Awake()
	{
		Instance = this;
	}

	private void Update()
	{
		if ((Object)(object)GameDirector.instance == (Object)null)
		{
			return;
		}
		bool flag = CanToggle();
		if (flag && SoulFlyHotkey.HotkeyDown())
		{
			if (SoulActive)
			{
				Exit();
			}
			else
			{
				Enter();
			}
		}
		if (!SoulActive)
		{
			return;
		}
		if (!Validate())
		{
			Exit();
			return;
		}
		HoldPlayer();
		if (flag && SemiFunc.NoTextInputsActive())
		{
			UpdateLook();
			UpdateMovement();
		}
	}

	private void LateUpdate()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		if (SoulActive && !((Object)(object)mainCamera == (Object)null))
		{
			((Component)mainCamera).transform.SetPositionAndRotation(flyPosition, Quaternion.Euler(flyPitch, flyYaw, 0f));
		}
	}

	private bool CanToggle()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Invalid comparison between Unknown and I4
		if ((Object)(object)GameDirector.instance == (Object)null)
		{
			return false;
		}
		if (GameDirector.instance.DisableInput)
		{
			return false;
		}
		if (!SemiFunc.NoTextInputsActive())
		{
			return false;
		}
		return (int)GameDirector.instance.currentState == 2;
	}

	private void Enter()
	{
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: 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_015b: Unknown result type (might be due to invalid IL or missing references)
		PlayerController instance = PlayerController.instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerAvatarScript == (Object)null)
		{
			return;
		}
		Camera val = (((Object)(object)GameDirector.instance != (Object)null) ? GameDirector.instance.MainCamera : null);
		if ((Object)(object)val == (Object)null)
		{
			SoulFlyPlugin.Warn("找不到主相机,无法进入灵魂出窍。");
			return;
		}
		PlayerAvatar playerAvatarScript = instance.playerAvatarScript;
		if (!IsDead(playerAvatarScript))
		{
			playerController = instance;
			playerAvatar = playerAvatarScript;
			visuals = playerAvatarScript.playerAvatarVisuals;
			localCamera = playerAvatarScript.localCamera;
			mainCamera = val;
			cameraParent = ((Component)val).transform.parent;
			aimTransform = (((Object)(object)CameraAim.Instance != (Object)null) ? ((Component)CameraAim.Instance).transform : cameraParent);
			flyPosition = ((Component)val).transform.position;
			Vector3 eulerAngles = ((Component)val).transform.eulerAngles;
			flyYaw = eulerAngles.y;
			flyPitch = NormalizePitch(eulerAngles.x);
			frozenBodyRotation = ((Component)playerAvatarScript).transform.rotation;
			frozenAimRotation = (((Object)(object)aimTransform != (Object)null) ? aimTransform.localRotation : Quaternion.identity);
			SoulActive = true;
			((Component)val).transform.SetParent((Transform)null, true);
			FreezeVisuals();
			SoulFlyPlugin.LogInfo("进入灵魂出窍。");
		}
	}

	private void Exit()
	{
		if (SoulActive)
		{
			SoulActive = false;
			RestoreCamera();
			RestoreVisuals();
			RestoreAim();
			playerController = null;
			playerAvatar = null;
			visuals = null;
			localCamera = null;
			animator = null;
			animatorSpeedCaptured = false;
			mainCamera = null;
			SoulFlyPlugin.LogInfo("退出灵魂出窍。");
		}
	}

	internal void ForceExit()
	{
		if (SoulActive)
		{
			Exit();
		}
	}

	private void RestoreCamera()
	{
		//IL_0079: 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)
		if (!((Object)(object)mainCamera == (Object)null))
		{
			Transform val = (((Object)(object)cameraParent != (Object)null) ? cameraParent : (((Object)(object)aimTransform != (Object)null) ? aimTransform : null));
			if (!((Object)(object)val == (Object)null))
			{
				((Component)mainCamera).transform.SetParent(val, false);
				((Component)mainCamera).transform.localPosition = Vector3.zero;
				((Component)mainCamera).transform.localRotation = Quaternion.identity;
			}
		}
	}

	private void RestoreAim()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)CameraAim.Instance != (Object)null)
		{
			CameraAim.Instance.SetPlayerAim(frozenAimRotation, true);
		}
	}

	private void FreezeVisuals()
	{
		if (!((Object)(object)visuals == (Object)null))
		{
			if (FieldAnimator != null)
			{
				ref Animator reference = ref animator;
				object? value = FieldAnimator.GetValue(visuals);
				reference = (Animator)((value is Animator) ? value : null);
			}
			if ((Object)(object)animator != (Object)null)
			{
				animatorSpeed = animator.speed;
				animatorSpeedCaptured = true;
				animator.speed = 0f;
			}
			if ((Object)(object)visuals.meshParent != (Object)null)
			{
				visuals.meshParent.SetActive(true);
			}
			SetVisibility((ShadowCastingMode)1);
		}
	}

	private void RestoreVisuals()
	{
		if ((Object)(object)animator != (Object)null && animatorSpeedCaptured)
		{
			animator.speed = animatorSpeed;
		}
		if ((Object)(object)visuals != (Object)null)
		{
			SetVisibility((ShadowCastingMode)3);
		}
	}

	private void SetVisibility(ShadowCastingMode mode)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)visuals == (Object)null || MethodApplyLocalVisibility == null)
		{
			return;
		}
		try
		{
			MethodApplyLocalVisibility.Invoke(visuals, new object[1] { mode });
		}
		catch (Exception ex)
		{
			SoulFlyPlugin.Warn("设置模型可见性失败:" + ex.Message);
		}
	}

	private void HoldPlayer()
	{
		//IL_0045: 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)
		if (!((Object)(object)playerController == (Object)null))
		{
			playerController.InputDisable(0.25f);
			playerController.Kinematic(0.25f);
			((Component)playerController).transform.rotation = frozenBodyRotation;
			if ((Object)(object)aimTransform != (Object)null)
			{
				aimTransform.localRotation = frozenAimRotation;
			}
		}
	}

	private void UpdateLook()
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)InputManager.instance == (Object)null))
		{
			float num = (((Object)(object)CameraAim.Instance != (Object)null) ? CameraAim.Instance.AimSpeedGet() : 1f);
			float num2 = ((SoulFlyPlugin.Sensitivity != null) ? SoulFlyPlugin.Sensitivity.Value : 1f);
			float num3 = SemiFunc.InputMouseX();
			float num4 = SemiFunc.InputMouseY();
			if (InputManager.instance.AimIsGamepad())
			{
				Vector2 val = InputManager.instance.GamepadAimDeltaGet();
				num3 = val.x;
				num4 = val.y;
			}
			if (InputManager.instance.AimInvertVerticalGet())
			{
				num4 = 0f - num4;
			}
			flyYaw += num3 * num * num2;
			flyPitch -= num4 * num * num2;
			flyPitch = Mathf.Clamp(flyPitch, -89f, 89f);
		}
	}

	private void UpdateMovement()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: 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)
		Vector2 val = SemiFunc.InputMovement();
		float num = 0f;
		if (SemiFunc.InputHold((InputKey)1))
		{
			num += 1f;
		}
		if (SemiFunc.InputHold((InputKey)12))
		{
			num -= 1f;
		}
		Quaternion val2 = Quaternion.Euler(flyPitch, flyYaw, 0f);
		Vector3 val3 = val2 * new Vector3(val.x, 0f, val.y);
		val3 += Vector3.up * num;
		if (((Vector3)(ref val3)).sqrMagnitude > 1f)
		{
			((Vector3)(ref val3)).Normalize();
		}
		float num2 = ((SoulFlyPlugin.FlySpeed != null) ? SoulFlyPlugin.FlySpeed.Value : 8f);
		if (SemiFunc.InputHold((InputKey)15) && SoulFlyPlugin.SprintMultiplier != null)
		{
			num2 *= SoulFlyPlugin.SprintMultiplier.Value;
		}
		if (num2 < 0f)
		{
			num2 = 0f;
		}
		flyPosition += val3 * (num2 * Time.deltaTime);
	}

	private bool Validate()
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Invalid comparison between Unknown and I4
		if ((Object)(object)playerController == (Object)null || (Object)(object)playerAvatar == (Object)null)
		{
			return false;
		}
		if ((Object)(object)PlayerController.instance != (Object)(object)playerController)
		{
			return false;
		}
		if ((Object)(object)playerController.playerAvatarScript != (Object)(object)playerAvatar)
		{
			return false;
		}
		if ((Object)(object)mainCamera == (Object)null)
		{
			return false;
		}
		if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2)
		{
			return false;
		}
		if (IsDead(playerAvatar))
		{
			return false;
		}
		return true;
	}

	private static bool IsDead(PlayerAvatar avatar)
	{
		if ((Object)(object)avatar == (Object)null)
		{
			return true;
		}
		if (FieldDeadSet != null)
		{
			object value = FieldDeadSet.GetValue(avatar);
			if (value is bool && (bool)value)
			{
				return true;
			}
		}
		if (FieldSpectating != null)
		{
			object value2 = FieldSpectating.GetValue(avatar);
			if (value2 is bool && (bool)value2)
			{
				return true;
			}
		}
		return false;
	}

	internal static Transform PinnedOverrideTransform(PlayerLocalCamera candidate)
	{
		if (!SoulActive || (Object)(object)candidate == (Object)null)
		{
			return null;
		}
		SoulFlyController instance = Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.localCamera == (Object)null || (Object)(object)candidate != (Object)(object)instance.localCamera)
		{
			return null;
		}
		if ((Object)(object)instance.aimTransform != (Object)null)
		{
			return instance.aimTransform;
		}
		return instance.cameraParent;
	}

	internal static bool ShouldFreezeVisuals(PlayerAvatarVisuals target)
	{
		if (!SoulActive || (Object)(object)target == (Object)null)
		{
			return false;
		}
		SoulFlyController instance = Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.visuals == (Object)null)
		{
			return false;
		}
		return (Object)(object)target == (Object)(object)instance.visuals;
	}

	private static float NormalizePitch(float angle)
	{
		if (angle > 180f)
		{
			angle -= 360f;
		}
		return Mathf.Clamp(angle, -89f, 89f);
	}
}
internal static class SoulFlyHotkey
{
	private static bool probed;

	private static bool legacyAvailable = true;

	private static string parsedName;

	private static KeyCode parsedKey = (KeyCode)0;

	internal static bool LegacyInputAvailable()
	{
		if (probed)
		{
			return legacyAvailable;
		}
		probed = true;
		try
		{
			Input.GetKeyDown((KeyCode)0);
			legacyAvailable = true;
		}
		catch (Exception)
		{
			legacyAvailable = false;
			SoulFlyPlugin.Warn("旧输入接口不可用,热键功能将无法响应。");
		}
		return legacyAvailable;
	}

	internal static KeyCode GetHotkey()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		string text = ((SoulFlyPlugin.HotkeyName == null) ? null : SoulFlyPlugin.HotkeyName.Value);
		if (text == parsedName)
		{
			return parsedKey;
		}
		parsedName = text;
		parsedKey = ParseKeyCode(text);
		return parsedKey;
	}

	private static KeyCode ParseKeyCode(string name)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: 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)
		if (string.IsNullOrEmpty(name))
		{
			return (KeyCode)0;
		}
		try
		{
			return (KeyCode)Enum.Parse(typeof(KeyCode), name.Trim(), ignoreCase: true);
		}
		catch (Exception)
		{
			SoulFlyPlugin.Warn("无法解析热键名 " + name + ",热键已禁用。");
			return (KeyCode)0;
		}
	}

	internal static bool HotkeyDown()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if ((int)GetHotkey() == 0)
		{
			return false;
		}
		if (!LegacyInputAvailable())
		{
			return false;
		}
		try
		{
			return Input.GetKeyDown(GetHotkey());
		}
		catch (Exception)
		{
			return false;
		}
	}
}
[HarmonyPatch(typeof(PlayerAvatarVisuals), "Update")]
internal static class PlayerAvatarVisualsUpdatePatch
{
	private static bool Prefix(PlayerAvatarVisuals __instance)
	{
		if (!SoulFlyController.ShouldFreezeVisuals(__instance))
		{
			return true;
		}
		return false;
	}
}
[HarmonyPatch(typeof(CameraAim), "Update")]
internal static class CameraAimUpdatePatch
{
	private static bool Prefix()
	{
		return !SoulFlyController.SoulActive;
	}
}
[HarmonyPatch(typeof(PlayerLocalCamera), "GetOverrideTransform")]
internal static class PlayerLocalCameraOverrideTransformPatch
{
	private static void Postfix(PlayerLocalCamera __instance, ref Transform __result)
	{
		Transform val = SoulFlyController.PinnedOverrideTransform(__instance);
		if ((Object)(object)val != (Object)null)
		{
			__result = val;
		}
	}
}
[BepInProcess("REPO.exe")]
[BepInPlugin("com.aartyns.soulfly", "SoulFly", "1.0.1")]
public class SoulFlyPlugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static SoulFlyPlugin Instance;

	internal static ConfigEntry<string> HotkeyName;

	internal static ConfigEntry<float> FlySpeed;

	internal static ConfigEntry<float> SprintMultiplier;

	internal static ConfigEntry<float> Sensitivity;

	internal static ConfigEntry<bool> Verbose;

	private Harmony harmony;

	private SoulFlyController controller;

	private void Awake()
	{
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		HotkeyName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Hotkey", "Z", "灵魂出窍切换热键键名,取值同 KeyCode 名称,例如 Z、V、F2、LeftAlt、Mouse3;留空表示关闭热键。");
		FlySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FlySpeed", 8f, "灵魂视角的移动速度,单位米/秒。");
		SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SprintMultiplier", 2.5f, "按住冲刺键时灵魂视角的速度倍率。");
		Sensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Sensitivity", 1f, "灵魂视角鼠标灵敏度倍率,1 表示与游戏本体一致。");
		Verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Verbose", false, "输出详细调试日志。");
		harmony = new Harmony("com.aartyns.soulfly");
		harmony.PatchAll();
		GameObject val = new GameObject("SoulFlyController");
		Object.DontDestroyOnLoad((Object)(object)val);
		controller = val.AddComponent<SoulFlyController>();
		Log.LogInfo((object)("SoulFly 已加载,热键:" + HotkeyName.Value));
	}

	private void OnDestroy()
	{
		if ((Object)(object)controller != (Object)null)
		{
			controller.ForceExit();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal static void LogInfo(string message)
	{
		if (Log != null)
		{
			Log.LogInfo((object)message);
		}
	}

	internal static void Debug(string message)
	{
		if (Log != null && Verbose != null && Verbose.Value)
		{
			Log.LogInfo((object)message);
		}
	}

	internal static void Warn(string message)
	{
		if (Log != null)
		{
			Log.LogWarning((object)message);
		}
	}
}