From f68ae091abb6870f04f1ce2774ec64c254b74341 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 11 Jan 2026 19:21:38 -0500 Subject: Bind changes Signed-off-by: Andrew Opalach --- Config.cs | 2 +- Plugin.cs | 294 +++++++++++++++++++++++++++++++++++-------------------------- README.txt | 2 +- 3 files changed, 169 insertions(+), 129 deletions(-) diff --git a/Config.cs b/Config.cs index a5d42d5..de29aa4 100755 --- a/Config.cs +++ b/Config.cs @@ -119,7 +119,7 @@ namespace MHWNewCamera public bool HigherShadowDetailInHoarfrost { get; set; } = false; public bool DisableLodLimits { get; set; } = false; public bool ApplyLodFactors { get; set; } = false; - public float FoliageLodBias { get; set; } = 3.5f; + public float FoliageLodBias { get; set; } = 3.0f; public float TerrainLodBias { get; set; } = 6.0f; public float FoliageLodFactor { get; set; } = 0.0f; public float TerrainLodFactor { get; set; } = 0.0f; diff --git a/Plugin.cs b/Plugin.cs index 87c958b..a32f3fa 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -18,11 +18,16 @@ using System.Diagnostics; #endif // @TODO: -// - Bind to switch camera preset. -// - More multiple controller testing. +// - Find a way to enable crouching and crawling on command. +// - Option to ignore camera change (update position, test open book and close). +// - Simplify and document input handling/blocking logic. +// - Find a way to block other inputs while button1 is down (and blocked). +// - More multiple controller testing (3 controllers, steam input, windows). // - Thoroughly test "Disable Mod". // - Improve AOB scans. -// - Glass objects in research base and on the botanical research center table still fade. +// - Some objects still fade. +// - Glass objects in research base and on the botanical research center table. +// - Decals on floor near Astera lift. // - Snow LOD pop-in. // - Stop animation rate lowering at distance. // - Manully set freecam viewport index. @@ -31,8 +36,8 @@ using System.Diagnostics; // Known Issues: // - Camera pitch wrap around while in the tent will sometimes flicker at the point of wrapping. -// Likely due to the unpredictable position of SetCameraTentHook() in the chain of hooks. -// Updating the free camera state within SetCameraTentHook() is not a solution because it comes out laggy. +// - Likely due to the unpredictable position of SetCameraTentHook() in the chain of hooks. Updating +// free camera state within SetCameraTentHook() is not a solution because it comes out laggy. // Steam proton launch command: // env DOTNET_ROOT="" WINEDLLOVERRIDES="msvcrt,dinput8=n,b" %command% @@ -75,7 +80,7 @@ using System.Diagnostics; // If this is broken, two of them will be invisible. // // 2x Shadow Resolution: -// - The shadow of the \"Waterfall Bridge\" lift in Astera. +// - The shadow of the "Waterfall Bridge" lift in Astera. // - Walk up the stairs towards the canteen and the shadow of the lift will fade-out. Move the camera // back and forth and make sure the lower resolution shadow aligns with the higher res one. @@ -153,6 +158,7 @@ namespace MHWNewCamera private uint lastPadDown = 0; private uint? prevPadDown = null; private bool unlockInputToggled = false; + private bool inputBlockedForToggle = false; private bool buttonWasDown(Button button) { return (lastPadDown & (uint)button) == (uint)button; @@ -249,10 +255,12 @@ namespace MHWNewCamera shadowRes4_3x.Disable(); } - private float foliageLodBias = 3.0f; - private float terrainLodBias = 3.0f; - private float foliageLodFactor = 1.0f; - private float terrainLodFactor = 1.0f; + private float foliageLodBias; + private float terrainLodBias; + private float prevFoliageLodBias = 0.0f; + private float prevTerrainLodBias = 0.0f; + private float foliageLodFactor; + private float terrainLodFactor; private bool disableLodLimits = false; private Patch defaultViewModeLodLimit; @@ -675,75 +683,28 @@ namespace MHWNewCamera nint baseAddr = MemoryUtil.Read(0x1451C4368); if (toggleOn) { + if (prevFoliageLodBias <= 0.0f) { + prevFoliageLodBias = MemoryUtil.Read(baseAddr + 0x21C); + if (prevFoliageLodBias > 3.0f) prevFoliageLodBias = 3.0f; + } MemoryUtil.WriteBytes(baseAddr + 0x21C, BitConverter.GetBytes(foliageLodBias)); + if (prevTerrainLodBias <= 0.0f) { + prevTerrainLodBias = MemoryUtil.Read(baseAddr + 0x220); + if (prevTerrainLodBias > 3.0f) prevTerrainLodBias = 3.0f; + } MemoryUtil.WriteBytes(baseAddr + 0x220, BitConverter.GetBytes(terrainLodBias)); MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(foliageLodFactor)); MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(terrainLodFactor)); } else { - MemoryUtil.WriteBytes(baseAddr + 0x21C, BitConverter.GetBytes(3.0f)); // LOD Bias: "High". - MemoryUtil.WriteBytes(baseAddr + 0x220, BitConverter.GetBytes(3.0f)); // LOD Bias: "High". + MemoryUtil.WriteBytes(baseAddr + 0x21C, BitConverter.GetBytes(prevFoliageLodBias)); + MemoryUtil.WriteBytes(baseAddr + 0x220, BitConverter.GetBytes(prevTerrainLodBias)); MemoryUtil.WriteBytes(baseAddr + 0x224, BitConverter.GetBytes(1.0f)); MemoryUtil.WriteBytes(baseAddr + 0x228, BitConverter.GetBytes(1.0f)); } } - /* - private bool areLodLimitsDisabled() - { - nint addrAddr = MemoryUtil.Read(0x1451C4148); - nint baseAddr = MemoryUtil.Read(addrAddr + 0xAF828); - nint addrStart = baseAddr + 0xEB9C; - bool faceLimit = MemoryUtil.Read(addrStart) == 0x0; - bool faceShadowLimit = MemoryUtil.Read(addrStart + 0x4) == 0x0; - bool playerLimit = MemoryUtil.Read(addrStart + 0x8) == 0x0; - bool playerShadowLimit = MemoryUtil.Read(addrStart + 0xC) == 0x0; - bool otomoLimit = MemoryUtil.Read(addrStart + 0x10) == 0x0; - bool otomoShadowLimit = MemoryUtil.Read(addrStart + 0x14) == 0x0; - bool npcLimit = MemoryUtil.Read(addrStart + 0x18) == 0x0; - bool npcShadowLimit = MemoryUtil.Read(addrStart + 0x1C) == 0x0; - bool simpleNpcLimit = MemoryUtil.Read(addrStart + 0x20) == 0x0; - bool simpleNpcShadowLimit = MemoryUtil.Read(addrStart + 0x24) == 0x0; - return faceLimit && faceShadowLimit && playerLimit && playerShadowLimit && - otomoLimit && otomoShadowLimit && npcLimit && npcShadowLimit && - simpleNpcLimit && simpleNpcShadowLimit; - } - - private void setLodLimits(bool limitOn) - { - nint addrAddr = MemoryUtil.Read(0x1451C4148); - nint baseAddr = MemoryUtil.Read(addrAddr + 0xAF828); - nint addrStart = baseAddr + 0xEB9C; - if (limitOn) - { - MemoryUtil.WriteBytes(addrStart, [0x1]); - MemoryUtil.WriteBytes(addrStart + 0x4, [0x3]); - MemoryUtil.WriteBytes(addrStart + 0x8, [0x1]); - MemoryUtil.WriteBytes(addrStart + 0xC, [0x3]); - MemoryUtil.WriteBytes(addrStart + 0x10, [0x1]); - MemoryUtil.WriteBytes(addrStart + 0x14, [0x3]); - MemoryUtil.WriteBytes(addrStart + 0x18, [0x1]); - MemoryUtil.WriteBytes(addrStart + 0x1C, [0x3]); - MemoryUtil.WriteBytes(addrStart + 0x20, [0x2]); - MemoryUtil.WriteBytes(addrStart + 0x24, [0x3]); - } - else - { - MemoryUtil.WriteBytes(addrStart, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x4, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x8, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0xC, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x10, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x14, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x18, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x1C, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x20, [0x0]); - MemoryUtil.WriteBytes(addrStart + 0x24, [0x0]); - } - } - */ - public void OnLoad() { Config config = ConfigManager.GetConfig(this); @@ -868,6 +829,7 @@ namespace MHWNewCamera private void disableFreeCamera() { freeCamera = false; + unlockInputToggled = false; if (preDetachFov != null) { cameraFov = (double)preDetachFov; @@ -1177,6 +1139,7 @@ namespace MHWNewCamera } if (vCamera != camera) { + // We're assuming vCamera isn't an invalid pointer, but there's no assurance of that. if (vCamera != null) { camera.NearClip = vCamera.NearClip; @@ -1433,6 +1396,27 @@ namespace MHWNewCamera } } + private void setPerspectivePreset(Config.Preset preset) + { + cameraFov = preset.FOV; + cameraForward = preset.Forward; + cameraRight = preset.Right; + cameraXOffset = 0.0f; + cameraYOffset = preset.Up; + cameraZOffset = 0.0f; + cameraRoll = preset.Roll; + if (preDetachRoll != null) + { + preDetachRoll = cameraRoll; + } + disableFading = preset.DisableFading; + if (pCameraViewportIndex >= 0) + { + setDisableFadingObjects(pCameraViewportIndex, disableFading); + } + setDisableCharacterFade(disableFading); + } + // This can undoubtedly be simplified. private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { @@ -1517,25 +1501,48 @@ namespace MHWNewCamera lastPadDown = PadDown; } - bool blockInput = !unlockInputToggled; - if (buttonWasDown(Button.L2)) + if ((comboButton1Down || (!disableComboButton1 && buttonWasDown(b1)))) { - if (buttonWasReleased(Button.R1)) + if (buttonWasPressed(b2)) { - unlockInputToggled = !unlockInputToggled; - blockInput = true; + enableFreeCamera = !enableFreeCamera; } - else if (buttonWasDown(Button.R1)) + int presetSelect = (buttonWasPressed(Button.Up) ? -1 : 0) + (buttonWasPressed(Button.Down) ? 1 : 0); + if (presetSelect != 0) { - blockInput = true; + Config config = ConfigManager.GetConfig(this); + Dictionary.KeyCollection presetKeys = config.Presets.Keys; + if (presetKeys.Count > 0) + { + if (config.Selected != "") + { + int selectedIndex; + for (selectedIndex = 0; selectedIndex < presetKeys.Count; selectedIndex++) + { + string presetKey = presetKeys.ElementAt(selectedIndex); + if (presetKey == config.Selected) break; + } + selectedIndex += presetSelect; + if (selectedIndex >= presetKeys.Count) + { + selectedIndex -= presetKeys.Count; + } + else if (selectedIndex < 0) + { + selectedIndex += presetKeys.Count; + } + config.Selected = presetKeys.ElementAt(selectedIndex); + } + else + { + config.Selected = presetKeys.ElementAt((presetSelect == 1) ? 0 : presetKeys.Count - 1); + } + setPerspectivePreset(config.Presets[config.Selected]); + ConfigManager.SaveConfig(this); + } } } - if ((comboButton1Down || (!disableComboButton1 && buttonWasDown(b1))) && buttonWasPressed(b2)) - { - enableFreeCamera = !enableFreeCamera; - } - if (unlockMovementHeld && buttonWasReleased(Button.R2)) { unlockMovementHeld = false; @@ -1544,6 +1551,31 @@ namespace MHWNewCamera if (enableFreeCamera) { + bool blockInput = !unlockInputToggled; + + // Hold both buttons and release either. We have to block until + // release or it will get annoying to toggle input while on a menu. + if (buttonWasDown(Button.R2)) + { + if (buttonWasReleased(Button.R1)) + { + unlockInputToggled = !unlockInputToggled; + inputBlockedForToggle = false; + blockInput = true; + } + else if (buttonWasDown(Button.R1)) + { + inputBlockedForToggle = true; + blockInput = true; + } + } + else if (buttonWasReleased(Button.R2) && inputBlockedForToggle) + { + unlockInputToggled = !unlockInputToggled; + inputBlockedForToggle = false; + blockInput = true; + } + if (blockInput) { if (!readInputsPostHook) @@ -1715,6 +1747,11 @@ namespace MHWNewCamera debugLog($"EvalDepthOfFieldHook({unknownPtr}, {unknownPtr2}) @ {frameTick}"); #endif // Possibly of interest: +0x1DE, +0x1DF. + // We're assuming the previous dofPointer will still be valid, but that might not be true. + if (dofPointer != 0x0 && unknownPtr != dofPointer && wasDofAllowed != null) { + MemoryUtil.WriteBytes(dofPointer + 0x1DD, ((bool)wasDofAllowed) ? [0x1] : [0x0]); + wasDofAllowed = null; + } dofPointer = unknownPtr; if (!forceOffDof) { @@ -1787,11 +1824,12 @@ namespace MHWNewCamera } if (vp.Camera != null) { - var camera = vp.Camera; + Camera camera = vp.Camera; + bool usedByFreeCamera = freeCamera && enableFreeCamera && camera == vCamera; if (debug) ImGui.Text($"Camera Pointer: {camera.Instance:x}"); if (ImGui.DragFloat("FOV", ref camera.FieldOfView, 0.1f)) { - if (freeCamera && i == vCameraViewportIndex) + if (usedByFreeCamera) { cameraFov = camera.FieldOfView; } @@ -1808,7 +1846,7 @@ namespace MHWNewCamera if (debug) ImGui.InputFloat("Aspect Ratio", ref camera.AspectRatio); ImGui.InputFloat("Near Clip", ref camera.NearClip); ImGui.InputFloat("Far Clip", ref camera.FarClip); - if (freeCamera && i == vCameraViewportIndex) + if (usedByFreeCamera) { ImGui.DragFloat3("Position", ref cameraPosition, 0.425f); } @@ -1887,7 +1925,7 @@ namespace MHWNewCamera ConfigManager.SaveConfig(this); } } - if (debug || !(freeCamera && i == vCameraViewportIndex)) + if (debug) { bool move = camera.Move; if (ImGui.Checkbox("Move", ref move)) @@ -1899,9 +1937,6 @@ namespace MHWNewCamera ImGui.Text("Uncheck this to allow manually overriding the camera position.\nIf your camera is frozen, make sure this is checked."); ImGui.EndTooltip(); } - } - if (debug) - { ImGui.SameLine(); bool fix = camera.Fix; if (ImGui.Checkbox("Fix", ref fix)) @@ -1911,6 +1946,11 @@ namespace MHWNewCamera } if (camera == vCamera) { + if (!usedByFreeCamera) + { + ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); + } + // If our camera hooks aren't being run, these values won't be updated. float yaw = (float)cameraYaw; if (ImGui.DragFloat("Yaw", ref yaw, 0.2f)) { @@ -1926,11 +1966,16 @@ namespace MHWNewCamera { cameraRoll = offsetRoll; } - if (camera == pCamera && !freeCamera) + if (!usedByFreeCamera) { - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + ImGui.PopItemFlag(); } + // Try to grey out offsets when they probably have no effect. + if ((camera == pCamera && !usedByFreeCamera) && camera.Move) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } ImGui.Text("Offsets"); float offsetForward = 0.0f; if (ImGui.DragFloat("Forward", ref offsetForward, 0.425f)) @@ -1940,7 +1985,7 @@ namespace MHWNewCamera camera.Position.X += forward.X * offsetForward; camera.Position.Y += forward.Y * offsetForward; camera.Position.Z += forward.Z * offsetForward; - cameraPosition = camera.Position; + if (usedByFreeCamera) cameraPosition = camera.Position; } float offsetRight = 0.0f; if (ImGui.DragFloat("Right", ref offsetRight, 0.425f)) @@ -1951,15 +1996,15 @@ namespace MHWNewCamera right = Quaternion.Normalize(right); camera.Position.X += right.X * offsetRight; camera.Position.Z += right.Z * offsetRight; - cameraPosition = camera.Position; + if (usedByFreeCamera) cameraPosition = camera.Position; } float offsetUp = 0.0f; if (ImGui.DragFloat("Up", ref offsetUp, 0.425f)) { camera.Position.Y += offsetUp; - cameraPosition = camera.Position; + if (usedByFreeCamera) cameraPosition = camera.Position; } - if (camera == pCamera && !freeCamera) + if (camera == pCamera && !(freeCamera || enableFreeCamera)) { ImGui.PopStyleVar(); } @@ -2182,25 +2227,8 @@ namespace MHWNewCamera if (ImGui.Selectable(presetKey, isSelected)) { config.Selected = presetKey; + setPerspectivePreset(config.Presets[config.Selected]); ConfigManager.SaveConfig(this); - Config.Preset preset = config.Presets[config.Selected]; - cameraFov = preset.FOV; - cameraForward = preset.Forward; - cameraRight = preset.Right; - cameraXOffset = 0.0f; - cameraYOffset = preset.Up; - cameraZOffset = 0.0f; - cameraRoll = preset.Roll; - if (preDetachRoll != null) - { - preDetachRoll = cameraRoll; - } - disableFading = preset.DisableFading; - if (pCameraViewportIndex >= 0) - { - setDisableFadingObjects(pCameraViewportIndex, disableFading); - } - setDisableCharacterFade(disableFading); } if (isSelected) ImGui.SetItemDefaultFocus(); } @@ -2299,16 +2327,16 @@ namespace MHWNewCamera { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } - ImGui.Checkbox("Unlock Player Movement", ref unlockMovementToggled); + ImGui.Checkbox("Unlock Input to the Game", ref unlockInputToggled); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Hold RT + Press LB."); + ImGui.Text("Hold RT + RB, Release Either."); ImGui.EndTooltip(); } - ImGui.Checkbox("Unlock Input to the Game", ref unlockInputToggled); + ImGui.Checkbox("Unlock Player Movement", ref unlockMovementToggled); if (ImGui.BeginItemTooltip()) { - ImGui.Text("Hold LT + Press RB."); + ImGui.Text("Hold RT + Press LB."); ImGui.EndTooltip(); } ImGui.Checkbox("Lock Vertical Movement and Apply Speed Modifier", ref lockVerticalToggled); @@ -2466,7 +2494,12 @@ namespace MHWNewCamera ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); - ImGui.Text("Hold LT + Press RB"); + ImGui.Text("Hold RT + RB, Release Either"); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Can effectively be treated as press RT + RB, but you probably want to press RT first in you're on a menu."); + ImGui.EndTooltip(); + } ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Unlock Input to the Game"); if (ImGui.BeginItemTooltip()) @@ -2517,7 +2550,7 @@ namespace MHWNewCamera ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); - ImGui.Text("Hold LT & RT"); + ImGui.Text("Hold LT + RT"); ImGui.TableSetColumnIndex(1); ImGui.Text("Zoom with Left Stick Up/Down"); if (ImGui.BeginItemTooltip()) @@ -2959,14 +2992,13 @@ namespace MHWNewCamera { if (pCamera != null) { + ImGui.Text("Perspective Camera"); ImGui.Text($"Player Camera: {pCamera.Instance:x}"); ImGui.Text($"Applying Offset: {applyPerspective}"); ImGui.Text($"previousCameraAnimState: {previousCameraAnimState}"); - ImGui.Text($"dofPointer: {dofPointer:x}"); - ImGui.Text($"shadowCascadeValue: {lastShadowCascadeValue}"); - ImGui.Text($"shadowBias: {lastShadowBias}"); - ImGui.Text($"shadowRadius: {lastShadowRadius}"); - ImGui.Text($"shadowSampleNum: {lastShadowSampleNum}"); + ImGui.DragFloat("X Offset", ref cameraXOffset, 0.425f); + ImGui.DragFloat("Y Offset", ref cameraYOffset, 0.425f); + ImGui.DragFloat("Z Offset", ref cameraZOffset, 0.425f); ImGui.Separator(); } @@ -3036,14 +3068,11 @@ namespace MHWNewCamera ImGui.Text("Palico/Otomo"); ImGui.Text($"Pointer: {sOtomo.Instance:x}"); ImGui.PopID(); + + ImGui.Separator(); } - ImGui.Separator(); - ImGui.PushID("Camera"); - ImGui.Text("Perspective Camera"); - ImGui.DragFloat("X Offset", ref cameraXOffset, 0.425f); - ImGui.DragFloat("Y Offset", ref cameraYOffset, 0.425f); - ImGui.DragFloat("Z Offset", ref cameraZOffset, 0.425f); + ImGui.PushID("Viewports"); ImGui.Text("Viewports"); for (int i = 0; i < 8; i++) { @@ -3058,6 +3087,17 @@ namespace MHWNewCamera ImGui.Separator(); + ImGui.Text("Graphics"); + ImGui.Text($"dofPointer: {dofPointer:x}"); + ImGui.Text($"prevFoliageLodBias: {prevFoliageLodBias}"); + ImGui.Text($"prevTerrainLodBias: {prevTerrainLodBias}"); + ImGui.Text($"shadowCascadeValue: {lastShadowCascadeValue}"); + ImGui.Text($"shadowBias: {lastShadowBias}"); + ImGui.Text($"shadowRadius: {lastShadowRadius}"); + ImGui.Text($"shadowSampleNum: {lastShadowSampleNum}"); + + ImGui.Separator(); + ImGui.PushID("Pad"); ImGui.Text("Pad"); ImGui.Text($"Pointer: {controllerAddr():x}"); diff --git a/README.txt b/README.txt index 2073c34..9d33fe6 100644 --- a/README.txt +++ b/README.txt @@ -2,4 +2,4 @@ https://www.nexusmods.com/monsterhunterworld/mods/8300 + https://www.nexusmods.com/monsterhunterworld/mods/8366 + -// vim: set ft=asciidoc: +// vim: set syntax=asciidoc: -- cgit v1.2.3-101-g0448