summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-01-27 14:59:24 -0500
committerAndrew Opalach <andrew@akon.city> 2026-01-27 14:59:24 -0500
commitb761d64ecc93c00fce3cb878d476451056500934 (patch)
tree1b78cfc63c5520b64a6a0a5de6d42dcbcdf9eb31
parentaba0c570ee604a73880b522852c8117b86c08465 (diff)
downloadNewCamera-b761d64ecc93c00fce3cb878d476451056500934.tar.gz
NewCamera-b761d64ecc93c00fce3cb878d476451056500934.tar.bz2
NewCamera-b761d64ecc93c00fce3cb878d476451056500934.zip
Input handling cleanup and fixes
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rwxr-xr-xPlugin.cs194
1 files changed, 119 insertions, 75 deletions
diff --git a/Plugin.cs b/Plugin.cs
index 57867e5..4bc653d 100755
--- a/Plugin.cs
+++ b/Plugin.cs
@@ -41,9 +41,10 @@ using SharpPluginLoader.Core.Configuration;
// - Adjust SSAO/General A/B Graphical Tweaks
// - Freeze Game
// - Exit Free Camera
+// - Open Gestures Menu
+// - Open Poses Menu
// @TODO:
-// - Document some not self-explanatory code locations from notes.
// - General "A/B Graphical Settings" function.
// - Save toggle state to config file.
// - Include Hide Weapon.
@@ -60,6 +61,7 @@ using SharpPluginLoader.Core.Configuration;
// - Adjust SSAO in cutscenes.
// - Read LOD bias setting from in-game setting (Low, Medium or High).
// - Make left stick input a curve like Wilds.
+// - Deadzone? MonsterHunterWorld.exe+5831DB - 0F2F 0D 5692AB04 - comiss xmm1,[MonsterHunterWorld.exe+503C438]
// - Ability to lock camera to a the player/a joint.
// - Simplify and document input handling/blocking logic.
// - Find a way to block other inputs while button1 is down (and blocked).
@@ -73,7 +75,6 @@ using SharpPluginLoader.Core.Configuration;
// - Hanging objects in the Seliana Gathering Hub (some events).
// - Manully set free camera viewport index.
// - Option to override in-game viewmode.
-// - +right and +forward to move character.
// Known Issues:
// - Camera pitch wrap around while in the tent will sometimes flicker at the point of wrapping.
@@ -305,7 +306,7 @@ namespace MHWNewCamera
private delegate void WritePadInputDelegate(nint unknownPtr, nint unknownPtr2, nint unknownPtr3);
private Hook<WritePadInputDelegate>? writePadInputHook;
- private delegate float CheckMovementDelegate(int stickValue);
+ private delegate float CheckMovementDelegate(int stickValue, float alwaysZero);
private Hook<CheckMovementDelegate>? checkMovementHook;
private delegate void CollisionCheckDelegate(nint unknownPtr, nint unknownPtr2);
@@ -760,7 +761,7 @@ namespace MHWNewCamera
// Place where we can change the analog stick value the game uses for player movement.
addr = PatternScanner.FindFirst(Pattern.FromString("66 0F 6E C1 0F 5B C0 85 C9 78 11"));
#if ADDR_ASSERTS
- Trace.Assert(addr == 0x142107CB0); // int
+ Trace.Assert(addr == 0x142107CB0); // int, float
#endif
checkMovementHook = Hook.Create<CheckMovementDelegate>(addr, CheckMovementHook);
@@ -944,6 +945,7 @@ namespace MHWNewCamera
zeroVolumetricDownsample.Enable();
}
+ // Player + ECCC = How far underwater is the player.
jmpOverHotSpringsEval = new Patch((nint)0x1417C1B03, [0xEB]);
jmpOverHotSpringsSteam = new Patch((nint)0x14203A494, [0xE9, 0x8D, 0x00, 0x00, 0x00, 0x90]);
@@ -1449,15 +1451,22 @@ namespace MHWNewCamera
setNearClip(camera, !guessAltNearClipSet(camera));
}
}
- if (buttonWasDown(Button.Triangle))
+ if (buttonWasDown(Button.R1))
{
if (buttonWasPressed(Button.Right))
{
- cameraRoll = (restoreRoll != null) ? (double)restoreRoll : 0.0f;
+ cameraRoll = (restoreRoll != null) ? (double)restoreRoll : 0.0;
}
if (buttonWasPressed(Button.Up))
{
- cameraFov = (restoreFov != null) ? (double)restoreFov : DEFAULT_FOV;
+ if (restoreFov != null)
+ {
+ cameraFov = (float)Math.Clamp((double)restoreFov * (previousFov / DEFAULT_FOV), 1.0, 179.0);
+ }
+ else
+ {
+ cameraFov = DEFAULT_FOV;
+ }
}
}
else if (!unlockInputForMenu || unlockInputHideMenu)
@@ -1785,13 +1794,11 @@ namespace MHWNewCamera
offsetPerspective = false;
}
- if (pCamera != null)
+ applyPerspective = offsetPerspective && !freeCamera && pCamera != null;
+ if (applyPerspective)
{
- // previousFov is the pre-offset FOV value.
- previousFov = pCamera.FieldOfView;
+ previousFov = pCamera!.FieldOfView; // Pre-offset FOV value.
}
-
- applyPerspective = offsetPerspective && !freeCamera && pCamera != null;
bool perspectiveFovOnly = false;
if (applyPerspective)
{
@@ -2007,7 +2014,7 @@ namespace MHWNewCamera
{
if (applyShadowBias)
{
- // After this function this value is written to the render params then maxss'd with the HQ value before use.
+ // If HQ Mode is enabled, this value will be maxss'd with the HQ value before use.
MemoryUtil.WriteBytes(unknownPtr2 + 0x17C, BitConverter.GetBytes(biasOverride));
}
if (applyShadowRadius)
@@ -2196,6 +2203,20 @@ namespace MHWNewCamera
writePadInputHook!.Original(unknownPtr, unknownPtr2, unknownPtr3);
+ /*
+ // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74
+ bool playerInMenu = false;
+ nint inMenuOffset = MemoryUtil.Read<nint>(0x1451C4640);
+ if (inMenuOffset != 0x0)
+ {
+ inMenuOffset = MemoryUtil.Read<nint>(inMenuOffset + 0x13FD0);
+ if (inMenuOffset != 0x0)
+ {
+ playerInMenu = MemoryUtil.Read<int>(inMenuOffset + 0xB734) == 1;
+ }
+ }
+ */
+
bool readInputsPostHook = false;
if (enableCombo && freeCameraCombo != null)
@@ -2213,21 +2234,9 @@ namespace MHWNewCamera
lastPadDown = PadDown;
readInputsPostHook = true;
}
- // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74
- bool playerInMenu = false;
- /*
- nint inMenuOffset = MemoryUtil.Read<nint>(0x1451C4640);
- if (inMenuOffset != 0)
- {
- inMenuOffset = MemoryUtil.Read<nint>(inMenuOffset + 0x13FD0);
- if (inMenuOffset != 0)
- {
- playerInMenu = MemoryUtil.Read<int>(inMenuOffset + 0xB734) == 1;
- }
- }
- */
+
uint b1u = (uint)b1;
- if (!playerInMenu && (comboButton1Down || enableFreeCamera || !buttonWasDown(b2)))
+ if (comboButton1Down || enableFreeCamera || !buttonWasDown(b2))
{
if ((PadDown & b1u) == b1u)
{
@@ -2238,19 +2247,16 @@ namespace MHWNewCamera
}
if (comboButton1Down)
{
- if (((PadRel & b1u) == b1u) || playerInMenu)
+ if (((PadRel & b1u) == b1u))
{
comboButton1Down = false;
}
- if (!playerInMenu)
- {
- PadTrg &= ~b1u;
- PadRel &= ~b1u;
- PadChg &= ~b1u;
- MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg));
- MemoryUtil.WriteBytes(controllerAddr() + 0x1A4, BitConverter.GetBytes(PadRel));
- MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg));
- }
+ PadTrg &= ~b1u;
+ PadRel &= ~b1u;
+ PadChg &= ~b1u;
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg));
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1A4, BitConverter.GetBytes(PadRel));
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg));
}
}
}
@@ -2374,19 +2380,20 @@ namespace MHWNewCamera
readInputsPostHook = true;
}
uint Mask = 0;
+ uint StartSelectMask = (uint)Button.Options | (uint)Button.Share;
+ uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right;
+ 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;
if (unlockInputForMenu)
{
- uint FaceButtonMask = (uint)Button.Square | (uint)Button.Triangle;
- uint StartSelectMask = (uint)Button.Options | (uint)Button.Share;
+ // Idealy we wouldn't block Y or X here but triggering Rearrange or Edit Shoutout in
+ // the gesture menu can desync our primitive "still in menu" handling when B is pressed.
+ uint FaceButtonMask = (uint)Button.Triangle | (uint)Button.Square;
Mask = FaceButtonMask | StartSelectMask;
if (unlockInputHideMenu)
{
- // Still allow A/Cross.
- Mask |= (uint)Button.Circle;
- uint DPadMask = (uint)Button.Up | (uint)Button.Down | (uint)Button.Left | (uint)Button.Right;
- 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;
+ Mask |= (uint)Button.Circle; // Still allow A/Cross.
Mask |= DPadMask | BumperMask | StickMask;
}
else if (buttonWasReleased(Button.Circle))
@@ -2398,11 +2405,6 @@ namespace MHWNewCamera
else
{
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;
Mask = FaceButtonMask | DPadMask | StartSelectMask | BumperMask | StickMask;
}
if (enableCombo && freeCameraCombo != null)
@@ -2419,8 +2421,7 @@ namespace MHWNewCamera
MemoryUtil.WriteBytes(controllerAddr() + 0x1A0, BitConverter.GetBytes(PadTrg));
MemoryUtil.WriteBytes(controllerAddr() + 0x1A4, BitConverter.GetBytes(PadRel));
MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg));
- // Left and right trigger.
- MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0));
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); // Left and right trigger.
MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0));
}
@@ -2455,7 +2456,7 @@ namespace MHWNewCamera
if (blockInput)
{
- if (buttonWasDown(Button.Triangle))
+ if (buttonWasDown(Button.R1))
{
if (buttonWasPressed(Button.Down))
{
@@ -2497,12 +2498,12 @@ namespace MHWNewCamera
}
}
}
- else if (freeCameraFromViewMode && buttonWasPressed(Button.Circle))
+ else if (freeCameraFromViewMode && !unlockInputForMenu && buttonWasPressed(Button.Circle))
{
enableFreeCamera = false;
}
- if (buttonWasPressed(Button.Square))
+ if (!unlockInputForMenu && buttonWasPressed(Button.Triangle))
{
nint baseAddr = MemoryUtil.Read<nint>(0x1451C4640);
// MonsterHunterWorld.exe+1ADA26A - 48 8B 83 18400100 - mov rax,[rbx+00014018]
@@ -2520,17 +2521,30 @@ namespace MHWNewCamera
}
}
}
+ else
+ {
+ if (plusRight != 0.0f)
+ {
+ int Lx = (int)(Int16.MaxValue * Math.Clamp(plusRight, -1.0f, 1.0f));
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1B8, BitConverter.GetBytes(Lx));
+ }
+ if (plusForward != 0.0f)
+ {
+ int Ly = (int)(Int16.MaxValue * Math.Clamp(plusForward, -1.0f, 1.0f));
+ MemoryUtil.WriteBytes(controllerAddr() + 0x1BC, BitConverter.GetBytes(Ly));
+ }
+ }
}
- private float CheckMovementHook(int stickValue)
+ private float CheckMovementHook(int stickValue, float alwaysZero)
{
if (disableMod)
{
- return checkMovementHook!.Original(stickValue);
+ return checkMovementHook!.Original(stickValue, alwaysZero);
}
#if HOOK_ORDER_ASSERTS
- debugLog($"CheckMovementHook({stickValue}) @ {frameTick}");
+ debugLog($"CheckMovementHook({stickValue:x}, {alwaysZero}) @ {frameTick}");
#endif
if (freeCamera && !((unlockMovementHeld || unlockMovementToggled) && !unlockMovementPause))
@@ -2538,7 +2552,7 @@ namespace MHWNewCamera
stickValue = 0;
}
- return checkMovementHook!.Original(stickValue);
+ return checkMovementHook!.Original(stickValue, alwaysZero);
}
private void CollisionCheckHook(nint unknownPtr, nint unknownPtr2)
@@ -2557,19 +2571,19 @@ namespace MHWNewCamera
if (enableCrawl && player != null)
{
nint controlsAddr = MemoryUtil.Read<nint>(player.Instance + 0x12608);
+ bool combatControls = false;
if (controlsAddr != 0x0)
{
- bool combatControls = MemoryUtil.Read<byte>(controlsAddr + 0xB18) == 0x80;
- if (combatControls)
- {
- procEnvironmentCollision.Invoke(player.Instance, psuedoObject1);
- procEnvironmentCollision.Invoke(player.Instance, psuedoObject2);
- }
- else
- {
- // @TODO: Test this.
- enableCrawl = false;
- }
+ combatControls = MemoryUtil.Read<byte>(controlsAddr + 0xB18) == 0x80;
+ }
+ if (combatControls)
+ {
+ procEnvironmentCollision.Invoke(player.Instance, psuedoObject1);
+ procEnvironmentCollision.Invoke(player.Instance, psuedoObject2);
+ }
+ else
+ {
+ enableCrawl = false;
}
}
@@ -3710,12 +3724,24 @@ namespace MHWNewCamera
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
+ ImGui.Text("Press Y");
+ ImGui.TableSetColumnIndex(1);
+ ImGui.Text("Open Gestures Menu");
+
+ ImGui.TableNextRow();
+ ImGui.TableSetColumnIndex(0);
ImGui.Text("Hold Select");
ImGui.TableSetColumnIndex(1);
ImGui.Text("");
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
+ ImGui.Text(" + Press Y");
+ ImGui.TableSetColumnIndex(1);
+ ImGui.Text("Open Poses Menu");
+
+ ImGui.TableNextRow();
+ ImGui.TableSetColumnIndex(0);
ImGui.Text(" + Press B");
ImGui.TableSetColumnIndex(1);
ImGui.Text("Toggle Depth of Field");
@@ -3734,7 +3760,7 @@ namespace MHWNewCamera
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
- ImGui.Text("Hold Y");
+ ImGui.Text("Hold RB");
ImGui.TableSetColumnIndex(1);
ImGui.Text("");
@@ -3872,7 +3898,7 @@ namespace MHWNewCamera
nint controlsAddr = MemoryUtil.Read<nint>(player.Instance + 0x12608);
nint zoneStateAddr = MemoryUtil.Read<nint>(0x1451C42B8);
bool combatControls = false;
- if (controlsAddr != 0x0 || zoneStateAddr == 0x0)
+ if (controlsAddr != 0x0 && zoneStateAddr != 0x0)
{
#if QUARANTINED_FEATURES
bool passiveFlag = MemoryUtil.Read<byte>(zoneStateAddr + 0xD2EA) == 1;
@@ -3973,6 +3999,8 @@ namespace MHWNewCamera
}
if (ImGui.Button("Sit in Hot Springs"))
{
+ // Run sit in hot springs action:
+ // MonsterHunterWorld.exe+17601F0 - 48 89 5C 24 08 - mov [rsp+08],rbx
MemoryUtil.WriteBytes(player.ActionController.Instance + 0xC0, [0x65, 0x00, 0x00, 0x00]);
MemoryUtil.WriteBytes(player.ActionController.Instance + 0xBC, [0x01, 0x00, 0x00, 0x00]);
}
@@ -4373,7 +4401,7 @@ namespace MHWNewCamera
}
if (ImGui.BeginItemTooltip())
{
- ImGui.Text("Enable the game's built-in \"HQ Mode\" and associated tweaks to not tank performance.\nBy default HQ Mode jacks up various rendering parameters and enables HQ Shadows.\nSome of the values are put too high to work for general gameplay.\nThis option adjusts the following parameters:\n SSAO Max Sample Num HQ: 64 -> 16\n SSLR Accurate Threshold HQ: 0.5 -> 0.2\nAs well as SSAO Dispersion: 10.0 -> 1.75 to fix a grid artifact in the SSAO rendering.");
+ ImGui.Text("Enable the game's built-in \"HQ Mode\" and associated tweaks to not tank performance.\nBy default, HQ Mode jacks up various rendering parameters and enables HQ Shadows.\nSome of the values are put too high to work for general gameplay.\nThis tweak adjusts the following parameters:\n SSAO Max Sample Num HQ: 64 -> 16\n SSLR Accurate Threshold HQ: 0.5 -> 0.2\nAs well as SSAO Dispersion: 10.0 -> 1.75 to mitigate a grid artifact in the SSAO rendering.");
ImGui.EndTooltip();
}
@@ -4784,8 +4812,24 @@ namespace MHWNewCamera
ImGui.Text($" X: {PadRx}");
ImGui.Text($" Y: {PadRy}");
ImGui.Text($" RT: {PadRz}");
- ImGui.DragFloat("+right", ref plusRight, 0.02f);
- ImGui.DragFloat("+forward", ref plusForward, 0.02f);
+ ImGui.PushItemWidth(width * 0.125f);
+ // @TODO: Function to adjust with camera movement?
+ ImGui.DragFloat("+Right", ref plusRight, 0.01f);
+ ImGui.SameLine();
+ ImGui.DragFloat("+Forward", ref plusForward, 0.01f);
+ ImGui.SameLine();
+ if (ImGui.Button("Flip"))
+ {
+ if (plusRight != 0.0f)
+ {
+ plusRight = -plusRight;
+ }
+ if (plusForward != 0.0f)
+ {
+ plusForward = -plusForward;
+ }
+ }
+ ImGui.PopItemWidth();
ImGui.PopID();
ImGui.Separator();