using System; 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.Unity.IL2CPP; using HarmonyLib; using Mirror; using Rewired; using RewiredConsts; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("MHZ")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyCopyright("Copyright © 2026 Masaicker")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("EnhancedControls")] [assembly: AssemblyTitle("EnhancedControls")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] namespace EnhancedControls { [BepInPlugin("mhz.bigwalk.enhancedcontrols", "Enhanced Controls", "1.0.1")] public sealed class EnhancedControlsPlugin : BasePlugin { private sealed class RaisedPropLockAccelerationState { public readonly float beginTime; public RaisedPropLockAccelerationState(float beginTime) { this.beginTime = beginTime; } } private sealed class JumpAssistState { public readonly PlayerCharacter player; private bool wasOnJumpableGround; private bool jumpedSinceGrounded; private float bufferedJumpUntil; private float coyoteJumpUntil; public JumpAssistState(PlayerCharacter player) { this.player = player; } public void UpdateGroundState(float now, bool isOnJumpableGround) { if (isOnJumpableGround) { if (!wasOnJumpableGround) { jumpedSinceGrounded = false; coyoteJumpUntil = 0f; } } else if (wasOnJumpableGround) { coyoteJumpUntil = (jumpedSinceGrounded ? 0f : (now + 0.1f)); } wasOnJumpableGround = isOnJumpableGround; } public bool CanCoyoteJump(float now) { return !wasOnJumpableGround && coyoteJumpUntil > now; } public void BufferJump(float now) { bufferedJumpUntil = now + 0.12f; } public bool TryConsumeBufferedJump(float now) { if (bufferedJumpUntil <= now) { bufferedJumpUntil = 0f; return false; } bufferedJumpUntil = 0f; return true; } public void ClearBufferedJump() { bufferedJumpUntil = 0f; } public void RecordJump() { jumpedSinceGrounded = true; bufferedJumpUntil = 0f; coyoteJumpUntil = 0f; } } private sealed class AutoRunState { public readonly PlayerCharacter player; public readonly Player inputPlayer; public bool isActive; public bool waitingForVerticalRelease; public bool keepSprintingWhileMoving; public bool isControllingMoveAxis; public float virtualMoveY; private readonly float digitalAxisGravity; private readonly float digitalAxisSensitivity; private bool hasNativeMoveY; private float nativeMoveY; public AutoRunState(PlayerCharacter player, Player inputPlayer) { this.player = player; this.inputPlayer = inputPlayer; InputBehavior inputBehavior = inputPlayer.controllers.maps.GetInputBehavior(0); digitalAxisGravity = ((inputBehavior != null) ? inputBehavior.digitalAxisGravity : 3f); digitalAxisSensitivity = ((inputBehavior != null) ? inputBehavior.digitalAxisSensitivity : 3f); } public void StartAutoRun(float physicalMoveY) { if (!isControllingMoveAxis) { virtualMoveY = physicalMoveY; } isActive = true; waitingForVerticalRelease = Mathf.Abs(physicalMoveY) > 0.2f; keepSprintingWhileMoving = false; isControllingMoveAxis = true; } public void StopAutoRun(bool keepSprintingWhileMoving, float physicalMoveY) { isActive = false; waitingForVerticalRelease = false; isControllingMoveAxis = true; this.keepSprintingWhileMoving = keepSprintingWhileMoving || !Mathf.Approximately(virtualMoveY, physicalMoveY); } public void UpdateMoveAxis(float physicalMoveY, float deltaTime) { if (isActive) { virtualMoveY = Mathf.MoveTowards(virtualMoveY, 1f, digitalAxisSensitivity * deltaTime); } else { if (!isControllingMoveAxis) { return; } if (physicalMoveY >= 0.87f) { if (hasNativeMoveY && nativeMoveY >= virtualMoveY) { virtualMoveY = nativeMoveY; isControllingMoveAxis = false; } return; } if (physicalMoveY <= -0.87f && hasNativeMoveY) { virtualMoveY = nativeMoveY; isControllingMoveAxis = false; return; } float num = ((Mathf.Abs(physicalMoveY) <= 0.2f) ? digitalAxisGravity : digitalAxisSensitivity); virtualMoveY = Mathf.MoveTowards(virtualMoveY, physicalMoveY, num * deltaTime); if (Mathf.Approximately(virtualMoveY, physicalMoveY)) { virtualMoveY = physicalMoveY; isControllingMoveAxis = false; } } } public void RecordNativeMoveAxis(float value) { nativeMoveY = value; hasNativeMoveY = true; } } [HarmonyPatch(typeof(PlayerSprinter), "LocalUpdate")] private static class StandUpOnSprintPatch { [HarmonyPrefix] private static void Prefix(PlayerSprinter __instance) { TryStandUp(__instance.pc, Action.sprint); } } [HarmonyPatch(typeof(PlayerSprinter), "LocalUpdate")] private static class AutoRunStatePatch { [HarmonyPostfix] private static void Postfix(PlayerSprinter __instance) { UpdateAutoRun(__instance); } } [HarmonyPatch(typeof(PlayerSitter), "Update")] private static class StandUpOnSitPatch { [HarmonyPrefix] private static void Prefix(PlayerSitter __instance, ref bool __state) { __state = ShouldStandUp(__instance.playerCharacter, __instance, Action.sit); } [HarmonyPostfix] private static void Postfix(PlayerSitter __instance, bool __state) { if (__state && __instance.isSittingLocal) { __instance.SetSittingLocal(false); } } } [HarmonyPatch(typeof(PlayerJumper), "Update")] private static class StandUpOnJumpPatch { [HarmonyPrefix] private static void Prefix(PlayerJumper __instance, ref bool __state) { __state = TryStandUp(__instance.playerCharacter, Action.jump); } [HarmonyPostfix] private static void Postfix(PlayerJumper __instance, bool __state) { if (__state) { __instance.jumpInQueue = false; ClearJumpAssist(__instance.playerCharacter); } else { UpdateJumpAssist(__instance); } } } [HarmonyPatch(typeof(PlayerJumper), "OnJump")] private static class JumpAssistOnJumpPatch { [HarmonyPostfix] private static void Postfix(PlayerJumper __instance) { RecordOriginalJump(__instance); } } [HarmonyPatch(typeof(PlayerGestures), "Update")] private static class RaisedPropLockAccelerationPatch { [HarmonyPrefix] private static void Prefix(PlayerGestures __instance) { AccelerateRaisedPropLock(__instance); } } [HarmonyPatch(typeof(Player), "GetAxis", new Type[] { typeof(int) })] private static class AutoRunMoveAxisPatch { [HarmonyPostfix] private static void Postfix(Player __instance, int actionId, ref float __result) { if (ShouldOverrideAutoRunMoveAxis(__instance, actionId)) { OverrideAutoRunMoveAxis(ref __result); } } } [HarmonyPatch(typeof(LocalizedText), "RefreshAll")] private static class AutoRunHudLocalizationPatch { [HarmonyPostfix] private static void Postfix() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) LocalizationManager instance = LocalizationManager.instance; if (instance != null) { SetAutoRunHudText(instance.currentLanguage); } } } private const string HarmonyId = "mhz.bigwalk.enhancedcontrols"; private const float RaisedPropLockProgressDelay = 0.5f; private const float RaisedPropLockTotalDuration = 2f; private const float OriginalRaisedPropLockProgressStartRatio = 0.4f; private const float JumpBufferDuration = 0.12f; private const float CoyoteTimeDuration = 0.1f; private const float AutoRunAnalogNeutralThreshold = 0.2f; private const float AutoRunAnalogCancelThreshold = 0.87f; private const string AutoRunHudTextEnglish = "AUTO RUN"; private const string AutoRunHudTextSimplifiedChinese = "自动奔跑"; private const string AutoRunHudTextTraditionalChinese = "自動奔跑"; private static RaisedPropLockAccelerationState raisedPropLockAcceleration; private static JumpAssistState jumpAssist; private static AutoRunState autoRunState; private static int autoRunMoveXAction; private static int autoRunMoveYAction; private static GameObject autoRunHud; private static LocalizedText autoRunHudText; private static LocalizationLanguage? autoRunHudLanguage; private static float originalRaisedPropLockDuration; public static ConfigEntry EnableStandUpOptimization { get; private set; } public static ConfigEntry EnableRaisedPropLockAcceleration { get; private set; } public static ConfigEntry EnableJumpAssist { get; private set; } public static ConfigEntry AutoRunKey { get; private set; } public static ConfigEntry AutoRunGamepadKey { get; private set; } public override void Load() { EnableStandUpOptimization = ((BasePlugin)this).Config.Bind("低姿态快速退出 / Quick Low-Posture Exit", "Enabled", true, "坐下、滑铲或过渡时,按坐下、奔跑或跳跃立即起身。\nImmediately stand up with Sit, Sprint, or Jump while sitting, sliding, or transitioning."); EnableRaisedPropLockAcceleration = ((BasePlugin)this).Config.Bind("举物锁定提速 / Raised-Prop Lock Speed", "Enabled", true, "缩短举高道具时锁定姿态的长按时间。\nShortens the hold time to lock the pose while raising a prop."); EnableJumpAssist = ((BasePlugin)this).Config.Bind("跳跃优化 / Jump Assist", "Enabled", true, "加入跳跃缓冲和土狼时间。落地前按跳会自动起跳,走出平台边缘后短暂仍可跳跃。\nAdds jump buffering and coyote time. Queues a jump pressed before landing and allows jumping briefly after walking off a ledge."); AutoRunKey = ((BasePlugin)this).Config.Bind("自动奔跑 / Auto Run", "Key", (KeyCode)120, "按下此键盘按键开始或结束自动奔跑。\nPress this keyboard key to start or stop Auto Run."); AutoRunGamepadKey = ((BasePlugin)this).Config.Bind("自动奔跑 / Auto Run", "Gamepad Key", (KeyCode)332, "按下此手柄按键开始或结束自动奔跑。\nPress this gamepad key to start or stop Auto Run."); autoRunMoveXAction = Action.moveX; autoRunMoveYAction = Action.moveY; originalRaisedPropLockDuration = PlayerActionState.stickyDuration; ((BasePlugin)this).Log.LogInfo((object)"Enhanced Controls loaded."); Harmony.CreateAndPatchAll(typeof(EnhancedControlsPlugin).Assembly, "mhz.bigwalk.enhancedcontrols"); } private static bool ShouldStandUp(PlayerCharacter player, PlayerSitter sitter, int action) { return EnableStandUpOptimization.Value && player != null && ((NetworkBehaviour)player).isLocalPlayer && player.inputPlayer != null && sitter != null && sitter.isSittingLocal && player.inputPlayer.GetButtonDown(action); } private static bool TryStandUp(PlayerCharacter player, int action) { if (player == null) { return false; } PlayerSitter sitter = player.sitter; if (!ShouldStandUp(player, sitter, action)) { return false; } sitter.SetSittingLocal(false); return true; } private static void AccelerateRaisedPropLock(PlayerGestures gestures) { if (!EnableRaisedPropLockAcceleration.Value) { raisedPropLockAcceleration = null; return; } PlayerCharacter val = ((gestures != null) ? gestures.playerCharacter : null); if (val == null || !((NetworkBehaviour)val).isLocalPlayer || val.inputPlayer == null) { return; } if ((!val.inputPlayer.GetButton(Action.waveLeft) && !val.inputPlayer.GetButton(Action.waveRight)) || !gestures.wasHoldingProp) { raisedPropLockAcceleration = null; return; } if (raisedPropLockAcceleration == null) { raisedPropLockAcceleration = new RaisedPropLockAccelerationState(Time.realtimeSinceStartup); } float elapsed = Time.realtimeSinceStartup - raisedPropLockAcceleration.beginTime; SetWaveTimeHeld(gestures, GetMappedLockTime(elapsed)); } private static float GetMappedLockTime(float elapsed) { float num = originalRaisedPropLockDuration * 0.4f; if (elapsed <= 0.5f) { return Mathf.Lerp(0f, num, elapsed / 0.5f); } float num2 = 1.5f; float num3 = Mathf.Clamp01((elapsed - 0.5f) / num2); return Mathf.Lerp(num, originalRaisedPropLockDuration, num3); } private static void SetWaveTimeHeld(PlayerGestures gestures, float timeHeld) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) PlayerActionState leftArmWavingState = gestures.leftArmWavingState; leftArmWavingState.timeHeld = timeHeld; gestures.leftArmWavingState = leftArmWavingState; PlayerActionState rightArmWavingState = gestures.rightArmWavingState; rightArmWavingState.timeHeld = timeHeld; gestures.rightArmWavingState = rightArmWavingState; PlayerActionState sharedArmWavingState = gestures.sharedArmWavingState; sharedArmWavingState.timeHeld = timeHeld; gestures.sharedArmWavingState = sharedArmWavingState; } private static void UpdateJumpAssist(PlayerJumper jumper) { PlayerCharacter val = ((jumper != null) ? jumper.playerCharacter : null); if (!EnableJumpAssist.Value || val == null || !((NetworkBehaviour)val).isLocalPlayer || val.inputPlayer == null) { ClearJumpAssist(val); return; } PlayerGround ground = val.ground; if (ground != null) { PlayerSitter sitter = val.sitter; if (sitter == null || !sitter.isSittingLocal) { if (jumpAssist == null || (Object)(object)jumpAssist.player != (Object)(object)val) { jumpAssist = new JumpAssistState(val); } float realtimeSinceStartup = Time.realtimeSinceStartup; bool isOnJumpableGround = ground.isOnJumpableGround; jumpAssist.UpdateGroundState(realtimeSinceStartup, isOnJumpableGround); bool buttonDown = val.inputPlayer.GetButtonDown(Action.jump); if (isOnJumpableGround) { if (buttonDown) { jumpAssist.ClearBufferedJump(); } else if (jumpAssist.TryConsumeBufferedJump(realtimeSinceStartup)) { jumper.jumpInQueue = true; } } else if (buttonDown) { if (jumpAssist.CanCoyoteJump(realtimeSinceStartup)) { jumpAssist.RecordJump(); jumper.jumpInQueue = false; jumper.ForceAJump(); } else { jumpAssist.BufferJump(realtimeSinceStartup); } } return; } } ClearJumpAssist(val); } private static void RecordOriginalJump(PlayerJumper jumper) { PlayerCharacter val = ((jumper != null) ? jumper.playerCharacter : null); if (val != null && ((NetworkBehaviour)val).isLocalPlayer && (Object)(object)jumpAssist?.player == (Object)(object)val) { jumpAssist.RecordJump(); } } private static void ClearJumpAssist(PlayerCharacter player) { if (player == null || (Object)(object)jumpAssist?.player == (Object)(object)player) { jumpAssist = null; } } private static void UpdateAutoRun(PlayerSprinter sprinter) { //IL_00a0: 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) PlayerCharacter val = ((sprinter != null) ? sprinter.pc : null); if (val == null || !((NetworkBehaviour)val).isLocalPlayer || val.inputPlayer == null) { SetAutoRunHudVisible(isVisible: false); return; } if (autoRunState == null || (Object)(object)autoRunState.player != (Object)(object)val) { autoRunState = new AutoRunState(val, val.inputPlayer); } float physicalMoveAxisRaw = GetPhysicalMoveAxisRaw(val.inputPlayer, autoRunMoveYAction); float physicalMoveAxisRaw2 = GetPhysicalMoveAxisRaw(val.inputPlayer, autoRunMoveXAction); bool flag = HasPhysicalMoveInput(physicalMoveAxisRaw2, physicalMoveAxisRaw); if (Input.GetKeyDown(AutoRunKey.Value) || Input.GetKeyDown(AutoRunGamepadKey.Value)) { if (autoRunState.isActive) { autoRunState.StopAutoRun(flag, physicalMoveAxisRaw); } else { autoRunState.StartAutoRun(physicalMoveAxisRaw); sprinter.isSprinting = true; } FinishAutoRunUpdate(sprinter, autoRunState, flag, physicalMoveAxisRaw); return; } if (!autoRunState.isActive) { FinishAutoRunUpdate(sprinter, autoRunState, flag, physicalMoveAxisRaw); return; } if (autoRunState.waitingForVerticalRelease) { if (Mathf.Abs(physicalMoveAxisRaw) <= 0.2f) { autoRunState.waitingForVerticalRelease = false; } } else if (Mathf.Abs(physicalMoveAxisRaw) >= 0.87f) { autoRunState.StopAutoRun(flag, physicalMoveAxisRaw); } FinishAutoRunUpdate(sprinter, autoRunState, flag, physicalMoveAxisRaw); } private static void FinishAutoRunUpdate(PlayerSprinter sprinter, AutoRunState state, bool hasPhysicalMoveInput, float rawMoveY) { state.UpdateMoveAxis(rawMoveY, Time.deltaTime); if (state.isActive) { sprinter.isSprinting = true; } else { KeepSprintingWhileMoving(sprinter, state, hasPhysicalMoveInput); } SetAutoRunHudVisible(state.isActive); } private static float GetPhysicalMoveAxisRaw(Player inputPlayer, int actionId) { return inputPlayer.GetAxisRaw(actionId); } private static bool HasPhysicalMoveInput(float rawMoveX, float rawMoveY) { return Mathf.Abs(rawMoveX) > 0.2f || Mathf.Abs(rawMoveY) > 0.2f; } private static void KeepSprintingWhileMoving(PlayerSprinter sprinter, AutoRunState state, bool hasPhysicalMoveInput) { if (state.keepSprintingWhileMoving) { if (hasPhysicalMoveInput || state.isControllingMoveAxis) { sprinter.isSprinting = true; } else { state.keepSprintingWhileMoving = false; } } } private static void SetAutoRunHudVisible(bool isVisible) { if (!isVisible) { if ((Object)(object)autoRunHud != (Object)null && autoRunHud.activeSelf) { autoRunHud.SetActive(false); } return; } if ((Object)(object)autoRunHud == (Object)null) { CreateAutoRunHud(); } if ((Object)(object)autoRunHud != (Object)null && !autoRunHud.activeSelf) { autoRunHud.SetActive(true); } } private static void CreateAutoRunHud() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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) WorldMenuManager instance = WorldMenuManager.instance; object obj; if (instance == null) { obj = null; } else { TeachingHud teachingHud = instance.teachingHud; obj = ((teachingHud != null) ? teachingHud.localizedText : null); } LocalizedText val = (LocalizedText)obj; Transform val2 = ((instance != null) ? instance.hideableHud : null); if (val != null && val2 != null) { LocalizedText val3 = Object.Instantiate(val, val2); val3.noGlyphs = true; TMP_Text textElement = val3.textElement; if (textElement != null) { Color color = ((Graphic)textElement).color; color.a = 1f; ((Graphic)textElement).color = color; } CanvasGroup component = ((Component)val3).GetComponent(); if (component != null) { component.alpha = 1f; } RectTransform component2 = ((Component)val3).GetComponent(); if (component2 != null) { component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(0f, 1f); component2.pivot = new Vector2(0f, 1f); component2.anchoredPosition = new Vector2(28f, -28f); component2.sizeDelta = new Vector2(250f, 42f); } autoRunHud = ((Component)val3).gameObject; autoRunHudText = val3; autoRunHudLanguage = null; LocalizationManager instance2 = LocalizationManager.instance; SetAutoRunHudText((LocalizationLanguage)((instance2 == null) ? 1 : ((int)instance2.currentLanguage))); } } private static void SetAutoRunHudText(LocalizationLanguage language) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (autoRunHud != null && autoRunHudText != null && autoRunHudLanguage != (LocalizationLanguage?)language) { autoRunHudText.ChangeValue(GetAutoRunHudText(language)); autoRunHudLanguage = language; } } private static string GetAutoRunHudText(LocalizationLanguage language) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if (1 == 0) { } string result = (((int)language == 6) ? "自动奔跑" : (((int)language != 15) ? "AUTO RUN" : "自動奔跑")); if (1 == 0) { } return result; } private static bool ShouldOverrideAutoRunMoveAxis(Player inputPlayer, int actionId) { int result; if (actionId == autoRunMoveYAction) { AutoRunState obj = autoRunState; if (obj != null && obj.isControllingMoveAxis) { result = ((autoRunState.inputPlayer == inputPlayer) ? 1 : 0); goto IL_002c; } } result = 0; goto IL_002c; IL_002c: return (byte)result != 0; } private static void OverrideAutoRunMoveAxis(ref float value) { autoRunState.RecordNativeMoveAxis(value); value = autoRunState.virtualMoveY; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }