From 3b4ffba9f594aeba929cdc14820a03ed3131aadc Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 9 Nov 2025 12:13:27 -0500 Subject: Fix input handling with 2+ controllers connected - Also disable Start/Select, RB/LB, and stick direction input in free camera. - Update config defaults. Signed-off-by: Andrew Opalach --- Config.cs | 10 ++-- Plugin.cs | 158 ++++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 97 insertions(+), 71 deletions(-) diff --git a/Config.cs b/Config.cs index 4ff79e1..ad3caa6 100755 --- a/Config.cs +++ b/Config.cs @@ -7,10 +7,10 @@ namespace MHWNewCamera { public struct Settings { - public const float DEFAULT_SPEED = 3.00f; - public const float DEFAULT_ZOOM_SPEED = 1.0f; + public const float DEFAULT_SPEED = 4.5f; + public const float DEFAULT_ZOOM_SPEED = 0.02f; public const float DEFAULT_SPEED_MODIFIER = 0.25f; - public const float DEFAULT_SENSITIVITY = 1.95f; + public const float DEFAULT_SENSITIVITY = 0.04f; public const double DEFAULT_PITCH_LIMIT = -1.0; public const double MAX_PITCH_LIMIT = 89.95; public const int DEFAULT_DEADZONE = 4750; @@ -111,8 +111,8 @@ namespace MHWNewCamera public bool ApplyLodFactors { get; set; } = false; public float LodFactor1 { get; set; } = 0.0f; public float LodFactor2 { get; set; } = 0.0f; - public float FoliageLodFactor { get; set; } = 1.0f; - public float TerrainLodFactor { get; set; } = 32.0f; + public float FoliageLodFactor { get; set; } = 64.0f; + public float TerrainLodFactor { get; set; } = 64.0f; public bool LargerFoliageSwayRange { get; set; } = false; } } diff --git a/Plugin.cs b/Plugin.cs index bfffa53..2d80ce2 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -17,18 +17,19 @@ using System.Diagnostics; #endif // @TODO: +// - Special case freecam for cutscenes and canteen animations. +// - Glass objects in research base and on the botanical research center table still fade. +// - Contact shadow resolution. // - Thoroughly test "Disable Mod". // - Improve AOB scans. // - How to change closer shadow "fade" range. // - Reduce the pop-in caused by updating shadow blobs. // - Snow LOD pop-in. -// - Contact shadow resolution. -// - White vase thing in research base still fades when close. +// - Stop animation rate lowering at distance. // - Display equiped armor in the debug UI. // - Manully set freecam viewport index. // - Override in-game viewmode. // - +right and +forward to move character. -// - Special case freecam for cutscenes and canteen animations. // Steam proton launch command: // env DOTNET_ROOT="" WINEDLLOVERRIDES="msvcrt,dinput8=n,b" %command% @@ -99,10 +100,19 @@ namespace MHWNewCamera private bool comboButton1Down = false; private uint lastPadDown = 0; + private uint? prevPadDown = null; private bool buttonWasDown(Button button) { return (lastPadDown & (uint)button) == (uint)button; } + private bool buttonWasPressed(Button button) + { + return (lastPadDown & (uint)button) == (uint)button && (prevPadDown & (uint)button) != (uint)button; + } + private bool buttonWasReleased(Button button) + { + return (lastPadDown & (uint)button) != (uint)button && (prevPadDown & (uint)button) == (uint)button; + } private double cameraFov = DEFAULT_FOV; private float cameraForward = 0.0f; @@ -269,6 +279,7 @@ namespace MHWNewCamera private static readonly MtObject sMhSteamController = SingletonManager.GetSingleton("sMhSteamController")!; private nint controllerAddr() => sMhSteamController.Instance; + private nint primaryPad = 0x0; private static readonly MtObject sOtomo = SingletonManager.GetSingleton("sOtomo")!; @@ -622,9 +633,13 @@ namespace MHWNewCamera #if HOOK_ORDER_ASSERTS Trace.Assert(hookOrder == 0 || hookOrder == 3); hookOrder = 0; - frameTick++; + if (frameTick == int.MaxValue) frameTick = 0; + else frameTick++; + debugLog($"OnUpdate() @ {frameTick}"); #endif + primaryPad = 0x0; + // Consider that pCamera could become an invalid pointer. checkPlayerChange(); } @@ -1117,19 +1132,31 @@ namespace MHWNewCamera // I haven't thought about or tested enough to know if it should be a performance consideration. private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { - if (disableMod) + // Assumes the primary pad always comes first. + if (primaryPad == 0x0) + { + primaryPad = unknownPtr2; + } + + if (disableMod || unknownPtr2 != primaryPad) { writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); return; } - uint PadDown = 0, PadTrg = 0, PadRel = 0, PadChg = 0; - if ((enableCombo && freeCameraCombo != null && disableComboButton1) && comboButton1Down) + Button b1 = 0u, b2 = 0u; + // PadOld = 0x19C + uint PadDown = 0u, PadTrg = 0u, PadRel = 0u, PadChg = 0u; + if (enableCombo && freeCameraCombo != null) { - PadDown = MemoryUtil.Read(controllerAddr() + 0x198); - uint b1 = (uint)freeCameraCombo[0]; - PadDown |= b1; - MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + b1 = freeCameraCombo[0]; + b2 = freeCameraCombo[1]; + if (disableComboButton1 && comboButton1Down) + { + PadDown = MemoryUtil.Read(controllerAddr() + 0x198); + PadDown |= (uint)b1; + MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + } } writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3); @@ -1138,8 +1165,6 @@ namespace MHWNewCamera if (enableCombo && freeCameraCombo != null) { - Button b1 = freeCameraCombo[0]; - Button b2 = freeCameraCombo[1]; if (disableComboButton1) { if (!readInputsPostHook) @@ -1148,11 +1173,12 @@ namespace MHWNewCamera PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); + prevPadDown = prevPadDown == null ? PadDown : lastPadDown; lastPadDown = PadDown; readInputsPostHook = true; } uint b1u = (uint)b1; - if (comboButton1Down || enableFreeCamera || !Input.IsDown(b2)) + if (comboButton1Down || enableFreeCamera || !buttonWasDown(b2)) { if ((PadDown & b1u) == b1u) { @@ -1175,46 +1201,87 @@ namespace MHWNewCamera MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); } } - if ((comboButton1Down || (!disableComboButton1 && Input.IsDown(b1))) && Input.IsPressed(b2)) - { - enableFreeCamera = !enableFreeCamera; - } + } + + if (!readInputsPostHook) + { + PadDown = MemoryUtil.Read(controllerAddr() + 0x198); + prevPadDown = prevPadDown == null ? PadDown : lastPadDown; + lastPadDown = PadDown; + } + + if ((comboButton1Down || (!disableComboButton1 && buttonWasDown(b1))) && buttonWasPressed(b2)) + { + enableFreeCamera = !enableFreeCamera; } if (enableFreeCamera) { - if (!unlockMovementHeld && Input.IsPressed(Button.L2)) + if (!unlockInputToggled) + { + if (!readInputsPostHook) + { + PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); + PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); + PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); + readInputsPostHook = true; + } + uint FaceButtonMask = (uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle; + uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right; + uint StartSelectMask = (uint)Button.Options | (uint)Button.Share; + uint BumperMask = (uint)Button.L1 | (uint)Button.R1; + uint StickMask = (uint)Button.LsUp | (uint)Button.LsDown | (uint)Button.LsLeft | (uint)Button.LsRight | + (uint)Button.RsUp | (uint)Button.RsDown | (uint)Button.RsLeft | (uint)Button.RsRight; + uint Mask = FaceButtonMask | DPadMask | StartSelectMask | BumperMask | StickMask; + if (enableCombo && freeCameraCombo != null) + { + Mask &= ~((uint)b1 | (uint)b2); + } + PadDown &= ~Mask; + PadTrg &= ~Mask; + PadRel &= ~Mask; + PadChg &= ~Mask; + MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadRel)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); + // Left and right trigger. + MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0)); + } + + if (!unlockMovementHeld && buttonWasPressed(Button.L2)) { unlockMovementHeld = true; } - else if (unlockMovementHeld && Input.IsReleased(Button.L2)) + else if (unlockMovementHeld && buttonWasReleased(Button.L2)) { unlockMovementHeld = false; unlockMovementPause = false; } if (unlockMovementHeld) { - if (Input.IsPressed(Button.L1)) + if (buttonWasPressed(Button.L1)) { unlockMovementToggled = !unlockMovementToggled; } // Temporarily disable for zoom mode. - if (Input.IsDown(Button.R2)) + if (buttonWasDown(Button.R2)) { unlockMovementPause = true; } - else if (Input.IsReleased(Button.R2)) + else if (buttonWasReleased(Button.R2)) { unlockMovementPause = false; } } - if (Input.IsDown(Button.L2) && Input.IsPressed(Button.R1)) + if (buttonWasDown(Button.L2) && buttonWasPressed(Button.R1)) { unlockInputToggled = !unlockInputToggled; } - if (Input.IsDown(Button.R2) && Input.IsPressed(Button.R1)) + if (buttonWasDown(Button.R2) && buttonWasPressed(Button.R1)) { if (uiToggled) { @@ -1226,47 +1293,6 @@ namespace MHWNewCamera } uiToggled = !uiToggled; } - - if (!readInputsPostHook) - { - PadDown = MemoryUtil.Read(controllerAddr() + 0x198); - lastPadDown = PadDown; - } - - if (!unlockInputToggled) - { - if (!readInputsPostHook) - { - PadTrg = MemoryUtil.Read(controllerAddr() + 0x1A0); - PadRel = MemoryUtil.Read(controllerAddr() + 0x1A4); - PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); - readInputsPostHook = true; - } - uint FaceButtonMask = (uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle; - uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right; - if (enableCombo && freeCameraCombo != null) - { - uint b1 = (uint)freeCameraCombo[0]; - uint b2 = (uint)freeCameraCombo[1]; - FaceButtonMask &= ~(b1 | b2); - DPadMask &= ~(b1 | b2); - } - PadDown &= ~DPadMask; - PadDown &= ~FaceButtonMask; - //PadDown &= ~((uint)Button.R1 | (uint)Button.L1); - PadTrg &= ~DPadMask; - PadTrg &= ~FaceButtonMask; - //PadTrg &= ~((uint)Button.R1 | (uint)Button.L1); - PadChg &= ~DPadMask; - PadChg &= ~FaceButtonMask; - //PadChg &= ~((uint)Button.R1 | (uint)Button.L1); - MemoryUtil.WriteBytes(controllerAddr() + 0x198, BitConverter.GetBytes(PadDown)); - MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg)); - MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); - // Left and right trigger. - MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); - MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0)); - } } } -- cgit v1.2.3-101-g0448