From 63fea5c80f4b2ad00439154d3916ebc291496b41 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 4 Feb 2026 18:17:29 -0500 Subject: Orbit player feature Signed-off-by: Andrew Opalach --- Plugin.cs | 719 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 424 insertions(+), 295 deletions(-) diff --git a/Plugin.cs b/Plugin.cs index 4bc653d..f454e77 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -2,6 +2,7 @@ //#define HOOK_ORDER_ASSERTS //#define LOG_DEBUG_MESSAGES #define SIMPLE_KEYBOARD_LAYER +#define MONSTERS_LIST //#define QUARANTINED_FEATURES using ImGuiNET; @@ -45,6 +46,7 @@ using SharpPluginLoader.Core.Configuration; // - Open Poses Menu // @TODO: +// - Hide Hunter's Knife/Slinger. // - General "A/B Graphical Settings" function. // - Save toggle state to config file. // - Include Hide Weapon. @@ -80,6 +82,8 @@ using SharpPluginLoader.Core.Configuration; // - 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 // free camera state within SetCameraTentHook() is not a solution because it comes out laggy. +// - With Passive mode enabled out in the field, if you go into a tent, change equipment and quickly leave +// the tent the game freezes/uses the wrong camera. // Steam proton launch command: // env DOTNET_ROOT="" WINEDLLOVERRIDES="msvcrt,dinput8=n,b" %command% @@ -179,6 +183,7 @@ namespace MHWNewCamera private bool disableMod = false; private static readonly MtObject sMain = SingletonManager.GetSingleton("sMhMain")!; + private bool freezeGame = false; private float cameraSpeed; private float cameraSpeedModifier; @@ -206,19 +211,24 @@ namespace MHWNewCamera private bool freeCameraFallback = false; private Camera? vCamera = null; private int vCameraViewportIndex = -1; - private double cameraFrameX; - private double cameraFrameY; - private double cameraFrameZ; - private Vector3 cameraPosition; - private Vector3 cameraTarget; private double? restoreFov = null; private double? restoreRoll = null; private float? restoreNearClip = null; + private Vector3 cameraPosition; + private Vector3 cameraTarget; + private double cameraFrameX; + private double cameraFrameY; + private double cameraFrameZ; private bool unlockMovementHeld = false; private bool unlockMovementToggled = false; private bool unlockMovementPause = false; + private bool playerMovementLocked => !(unlockMovementHeld || unlockMovementToggled) || unlockMovementPause; private bool lockVerticalToggled = false; - private bool freezeGame = false; + private bool orbitPlayer = false; + private bool orbitIgnoreCamera = false; + private float orbitMovementRotation = 0.0f; + private float orbitForward = 350.0f; + private float orbitY = 150.0f; private bool enableOffsetPerspective = false; private bool offsetPerspective = false; @@ -239,11 +249,16 @@ namespace MHWNewCamera private int keyboardLookValue; #endif + private static readonly MtObject sMhMouse = SingletonManager.GetSingleton("sMhMouse")!; + private static readonly MtObject sMhKeyboard = SingletonManager.GetSingleton("sMhKeyboard")!; + private static readonly MtObject sMhSteamController = SingletonManager.GetSingleton("sMhSteamController")!; private nint controllerAddr() => sMhSteamController.Instance; private nint primaryPad = 0x0; + private int PadLx, PadLy; + private int PadRx, PadRy; - private uint lastPadDown = 0; + private uint lastPadDown = 0u; private uint? prevPadDown = null; private bool unlockInputToggled = false; private bool unlockInputForMenu = false; @@ -549,9 +564,11 @@ namespace MHWNewCamera private bool disableHotSpringsSteam = false; private Patch jmpOverHotSpringsSteam; +#if QUARANTINED_FEATURES private NativeAction setPassiveMode; private NativeAction setPlayerController1; private NativeAction setPlayerController2; +#endif private bool enableCrawl = false; private NativeAction procEnvironmentCollision; @@ -613,17 +630,8 @@ namespace MHWNewCamera stickDeadzone = camera.StickDeadzone; alternateNearClip = camera.AlternateNearClip; + // @TODO: offsetPerspective doesn't affect disableCharacterFade when it is supposed to. enableOffsetPerspective = config.PerspectiveCameraEnabled; - if (config.Selected != "") - { - Config.Preset preset = config.Presets[config.Selected]; - cameraFov = preset.FieldOfView; - cameraForward = preset.Forward; - cameraRight = preset.Right; - cameraYOffset = preset.Up; - cameraRoll = preset.Roll; - disableFading = preset.DisableFading; - } Config.GraphicalTweaks graphics = config.Graphics; tripleShadowRes = graphics.TripleShadowResolution; @@ -649,9 +657,11 @@ namespace MHWNewCamera { Config config = loadConfig(); +#if QUARANTINED_FEATURES setPassiveMode = new NativeAction(0x142035020); setPlayerController1 = new NativeAction(0x141F73850); setPlayerController2 = new NativeAction(0x14118DDC0); +#endif procEnvironmentCollision = new NativeAction(0x141F737D0); psuedoObject1 = (nint)NativeMemory.AllocZeroed(0x7C); @@ -779,7 +789,7 @@ namespace MHWNewCamera #if ADDR_ASSERTS Trace.Assert(addr == 0x141E55D9E); #endif - swapMinimapFollowsCamera = new Patch(addr + 0x3, [0xE9]); // je -> jmp + swapMinimapFollowsCamera = new Patch(addr + 0x3, [0xE9]); // je -> jmp. addr = PatternScanner.FindFirst(Pattern.FromString("48 89 5C 24 18 48 89 6C 24 20 57 48 83 EC 20 48 8B 59 68 48 8B FA 48 8B E9 48 85 DB 0F 84 ?? ?? ?? ?? 4C 89 74 24 38 4C 8B B3 80 00 00 00 4D 85 F6")); #if ADDR_ASSERTS @@ -787,13 +797,13 @@ namespace MHWNewCamera #endif jmpOverUi = new Patch(addr + 0x1c, [0xE9, 0x65, 0x01, 0x00, 0x00, 0x90]); - jmpOverDof = new Patch((nint)0x1424233C6, [0xEB]); // je -> jmp + jmpOverDof = new Patch((nint)0x1424233C6, [0xEB]); // je -> jmp. addr = PatternScanner.FindFirst(Pattern.FromString("CC 48 89 5C 24 18 57 48 83 EC 30 48 89 74 24 48 48 8B D9 E8 ?? ?? ?? ?? 48 8B 8B B0 0D 00 00 8B 81 54 89 00 00 C1 E8 0D A8 01")); #if ADDR_ASSERTS Trace.Assert(addr == 0x1411A6A9F); #endif - noopCharacterFade = new Patch(addr + 0x13, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+11A6D50 + noopCharacterFade = new Patch(addr + 0x13, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+11A6D50. if (disableCharacterFade && !disableMod) { noopCharacterFade.Enable(); @@ -804,10 +814,10 @@ namespace MHWNewCamera Trace.Assert(addr == 0x14043FF80); Trace.Assert(MemoryUtil.Read(0x142E4FE5C) == 3.0f); #endif - shadowRes1_3x = new Patch(addr + 0x8, [0xD0, 0xFE, 0xA0, 0x02]); // 3.0 + shadowRes1_3x = new Patch(addr + 0x8, [0xD0, 0xFE, 0xA0, 0x02]); // 3.0. shadowRes1_1 = new Patch(addr + 0x65, [0x17]); // Always set "Value is not 1.0" flag. - shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss - shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss + shadowRes1_2 = new Patch(addr + 0x68, [0x59]); // movss -> mulss. + shadowRes1_3 = new Patch(addr + 0x77, [0x59]); // movss -> mulss. // shadowRes2/3 control the detail of the infrequently updated fallback shadows. addr = PatternScanner.FindFirst(Pattern.FromString("83 FA FF 74 06 89 91 1C 55 00 00 8B 91 30 55 00 00 83 FA FF 7F 06 8B 91 1C 55 00 00 85 D2 74 4B 83 EA 01 74 3B 83 EA 01 74 2B 83 EA 01 74 1B 83 FA 01 74 0B C7 81 20 55 00 00 01 00 00 00 C3 C7 81 20 55 00 00 00 10 00 00")); @@ -817,9 +827,9 @@ namespace MHWNewCamera shadowRes2 = new Patch(addr + 0x3F, [ 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, - 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, // High - 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC3, // Mid - 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xC3 // Low + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xC3, // High. + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xC3, // Mid. + 0xC7, 0x81, 0x20, 0x55, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xC3 // Low. ]); addr = PatternScanner.FindFirst(Pattern.FromString("89 91 30 55 00 00 83 FA FF 7F 06 8B 91 1C 55 00 00 85 D2 74 4B 83 EA 01 74 3B 83 EA 01 74 2B 83 EA 01 74 1B 83 FA 01 74 0B C7 81 20 55 00 00 01 00 00 00 C3 C7 81 20 55 00 00 00 10 00 00")); @@ -922,6 +932,7 @@ namespace MHWNewCamera addressHigherValueForFoliageSway.Enable(); } + // Found using mFrameSkipNum annotation from MHW-DTI-Dumps. zeroFrameSkip = new Patch((nint)0x142246948, [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90]); if (disableReducedRateAnimations && !disableMod) { @@ -996,7 +1007,7 @@ namespace MHWNewCamera #if ADDR_ASSERTS Trace.Assert(addr + 0x40 == 0x141BFFF75); #endif - disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+1325810 + disableGravityEval = new Patch(addr + 0x40, [0x90, 0x90, 0x90, 0x90, 0x90]); // call MonsterHunterWorld.exe+1325810. } } @@ -1078,9 +1089,39 @@ namespace MHWNewCamera } } + private void setPerspectivePreset(Config.Preset preset) + { + cameraFov = preset.FieldOfView; + if (restoreFov != null) + { + restoreFov = cameraFov; + } + orbitForward += cameraForward - preset.Forward; + cameraForward = preset.Forward; + cameraRight = preset.Right; + cameraXOffset = 0.0f; + cameraYOffset = preset.Up; + cameraZOffset = 0.0f; + cameraRoll = preset.Roll; + if (restoreRoll != null) + { + restoreRoll = cameraRoll; + } + disableFading = preset.DisableFading; + if (pCameraViewportIndex >= 0) + { + setDisableFadingObjects(pCameraViewportIndex, disableFading); + } + setDisableCharacterFade(disableFading); + } + public void OnLoad() { Config config = ConfigManager.GetConfig(this); + if (config.Selected != "") + { + setPerspectivePreset(config.Presets[config.Selected]); + } Config.GraphicalTweaks graphics = config.Graphics; foliageLODBias = graphics.FoliageLODBias; terrainLODBias = graphics.TerrainLODBias; @@ -1144,6 +1185,9 @@ namespace MHWNewCamera #endif primaryPad = 0x0; + // Zero pad input in case no controllers are connected. + PadLx = 0; PadLy = 0; + PadRx = 0; PadRy = 0; if (freeCameraFallback) { @@ -1373,7 +1417,6 @@ namespace MHWNewCamera } else { - //deltaTime = camera.DeltaTime; deltaTime = MemoryUtil.Read(sMain.Instance + 0x94); } @@ -1384,18 +1427,16 @@ namespace MHWNewCamera cameraFrameY = 0.0; cameraFrameZ = 0.0; + // PadLx/y is read in WritePadInputHook(). if (buttonWasDown(Button.L2) && buttonWasDown(Button.R2)) // Left stick zoom. { - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; double Ly = PadLy / (Int16.MaxValue / adjustedZoomSpeed(deltaTime)); cameraFov = Math.Clamp(cameraFov - Ly, 1.0, 179.0); } - else if (!(unlockMovementHeld || unlockMovementToggled)) // Move camera. + else if (playerMovementLocked || orbitPlayer) // Move camera. { - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); if (Math.Abs(PadLy) < stickDeadzone) PadLy = 0; - int PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); if (Math.Abs(PadLx) < stickDeadzone) PadLx = 0; #if SIMPLE_KEYBOARD_LAYER if (keyboardEnabled) @@ -1406,39 +1447,58 @@ namespace MHWNewCamera if (Input.IsDown(Key.Right)) PadLx += Int16.MaxValue; } #endif - double Lx = PadLx / (Int16.MaxValue / adjustedSpeed); double Ly = PadLy / (Int16.MaxValue / adjustedSpeed); + double Lx = PadLx / (Int16.MaxValue / adjustedSpeed); - Quaternion forward = getForward(cameraPosition, cameraTarget); - - // Invert diagonal directions when upside down for movement consistency. - if (cameraWrapState == 1) - { - forward.X = -forward.X; - forward.Z = -forward.Z; - } - - if (lockVerticalAndModifySpeed) + if (orbitPlayer) { - forward.Y = 0.0f; + if (playerMovementLocked) + { + orbitForward -= (float)Ly; + if (orbitForward < 0.01f) + { + orbitForward = 0.01f; + } + } + orbitMovementRotation += (float)(Lx / 5.0); + if (orbitMovementRotation >= 180.0f) + { + orbitMovementRotation -= 360.0f; + } + else if (orbitMovementRotation < -180.0f) + { + orbitMovementRotation += 360.0f; + } } - - Quaternion right = forward; - right.Y = 0.0f; - right = getRight(right); - forward = Quaternion.Normalize(forward); - right = Quaternion.Normalize(right); - cameraFrameX += right.X * Lx; - cameraFrameZ += right.Z * Lx; - cameraFrameX += forward.X * Ly; - cameraFrameY += forward.Y * Ly; - cameraFrameZ += forward.Z * Ly; - - if (plusForward != 0.0f) + else { - cameraFrameX += forward.X * plusForward * deltaTime; - cameraFrameY += forward.Y * plusForward * deltaTime; - cameraFrameZ += forward.Z * plusForward * deltaTime; + Quaternion forward = getForward(cameraPosition, cameraTarget); + if (cameraWrapState == 1) + { + // Invert diagonal directions when upside down for movement consistency. + forward.X = -forward.X; + forward.Z = -forward.Z; + } + if (lockVerticalAndModifySpeed) + { + forward.Y = 0.0f; + } + Quaternion right = forward; + right.Y = 0.0f; + right = getRight(right); + forward = Quaternion.Normalize(forward); + right = Quaternion.Normalize(right); + cameraFrameX += right.X * Lx; + cameraFrameZ += right.Z * Lx; + cameraFrameX += forward.X * Ly; + cameraFrameY += forward.Y * Ly; + cameraFrameZ += forward.Z * Ly; + if (plusForward != 0.0f) + { + cameraFrameX += forward.X * plusForward * deltaTime; + cameraFrameY += forward.Y * plusForward * deltaTime; + cameraFrameZ += forward.Z * plusForward * deltaTime; + } } } @@ -1473,11 +1533,25 @@ namespace MHWNewCamera { if (buttonWasDown(Button.Up)) { - cameraFrameY += adjustedSpeed / 2.0; + if (orbitPlayer) + { + orbitY += (float)(adjustedSpeed / 2.0); + } + else + { + cameraFrameY += adjustedSpeed / 2.0; + } } if (buttonWasDown(Button.Down)) { - cameraFrameY -= adjustedSpeed / 2.0; + if (orbitPlayer) + { + orbitY -= (float)(adjustedSpeed / 2.0); + } + else + { + cameraFrameY -= adjustedSpeed / 2.0; + } } if (buttonWasDown(Button.Left)) { @@ -1524,10 +1598,8 @@ namespace MHWNewCamera } #endif - // Camera look. - int PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); + // Camera look. PadRx/y is read in WritePadInputHook(). if (Math.Abs(PadRx) < stickDeadzone) PadRx = 0; - int PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); if (Math.Abs(PadRy) < stickDeadzone) PadRy = 0; #if SIMPLE_KEYBOARD_LAYER if (keyboardEnabled) @@ -1542,6 +1614,10 @@ namespace MHWNewCamera double Rx = PadRx / (Int16.MaxValue / adjustedSensitivity); double Ry = PadRy / (Int16.MaxValue / adjustedSensitivity); cameraYaw += Rx; + if (plusRight != 0.0f) + { + cameraYaw += plusRight * deltaTime; + } if (cameraYaw >= 180.0) { cameraYaw -= 360.0; @@ -1589,22 +1665,34 @@ namespace MHWNewCamera cameraRoll -= 360.0; } - if (plusRight != 0.0) + Player? player = Player.MainPlayer; + if (orbitPlayer && player != null) + { + Vector3 up = new Vector3(0.0f, 1.0f, 0.0f); + Quaternion rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); + up = Vector3.Transform(up, rotation); + cameraTarget = player.Position; + cameraTarget.X += (float)(orbitY * up.X); + cameraTarget.Y += (float)(orbitY * up.Y); + cameraTarget.Z += (float)(orbitY * up.Z); + double dist = orbitForward; + cameraPosition.X = cameraTarget.X - (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw))); + cameraPosition.Y = cameraTarget.Y - (float)(dist * Math.Sin(Double.DegreesToRadians(cameraPitch))); + cameraPosition.Z = cameraTarget.Z - (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw))); + } + else { - cameraYaw += plusRight * deltaTime; + cameraPosition.X += (float)cameraFrameX; + cameraPosition.Y += (float)cameraFrameY; + cameraPosition.Z += (float)cameraFrameZ; + // 700.0 is the same value the game uses for the player camera. The in-game view mode + // uses 1.0 like I did here before, which is really bad for precision. + double dist = 700.0 - cameraForward; + cameraTarget.X = cameraPosition.X + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw))); + cameraTarget.Y = cameraPosition.Y + (float)(dist * Math.Sin(Double.DegreesToRadians(cameraPitch))); + cameraTarget.Z = cameraPosition.Z + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw))); } - cameraPosition.X += (float)cameraFrameX; - cameraPosition.Y += (float)cameraFrameY; - cameraPosition.Z += (float)cameraFrameZ; - - // 700.0 is the same value the game uses for the player camera. The in-game view mode - // uses 1.0 like I did here before, which is really bad for precision. - double dist = 700.0 - cameraForward; - cameraTarget.X = cameraPosition.X + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Cos(Double.DegreesToRadians(cameraYaw))); - cameraTarget.Y = cameraPosition.Y + (float)(dist * Math.Sin(Double.DegreesToRadians(cameraPitch))); - cameraTarget.Z = cameraPosition.Z + (float)(dist * Math.Cos(Double.DegreesToRadians(cameraPitch)) * Math.Sin(Double.DegreesToRadians(cameraYaw))); - camera.Position = cameraPosition; camera.Target = cameraTarget; camera.FieldOfView = (float)cameraFov; @@ -2146,31 +2234,28 @@ namespace MHWNewCamera } } - private void setPerspectivePreset(Config.Preset preset) + /* + // https://github.com/HunterPie/HunterPie/blob/fa73f81ed0cdc921a6cf63f96c0fcff3688d88c2/HunterPie.Integrations/Datasources/MonsterHunterWorld/Entity/Game/MHWGame.cs#L74 + private bool playerInMenu() { - cameraFov = preset.FieldOfView; - cameraForward = preset.Forward; - cameraRight = preset.Right; - cameraXOffset = 0.0f; - cameraYOffset = preset.Up; - cameraZOffset = 0.0f; - cameraRoll = preset.Roll; - if (restoreRoll != null) + bool inMenu = false; + nint baseAddr = MemoryUtil.Read(0x1451C4640); + if (baseAddr != 0x0) { - restoreRoll = cameraRoll; - } - disableFading = preset.DisableFading; - if (pCameraViewportIndex >= 0) - { - setDisableFadingObjects(pCameraViewportIndex, disableFading); + baseAddr = MemoryUtil.Read(baseAddr + 0x13FD0); + if (baseAddr != 0x0) + { + inMenu = MemoryUtil.Read(baseAddr + 0xB734) == 1; + } } - setDisableCharacterFade(disableFading); + return inMenu; } + */ // This can undoubtedly be simplified. private void WritePadInputHook(nint unknownPtr, nint unknownPtr2, nint unknownPtr3) { - // Assumes the primary pad always comes first. + // Assume the primary pad always comes first. if (primaryPad == 0x0) { primaryPad = unknownPtr2; @@ -2203,22 +2288,13 @@ 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(0x1451C4640); - if (inMenuOffset != 0x0) - { - inMenuOffset = MemoryUtil.Read(inMenuOffset + 0x13FD0); - if (inMenuOffset != 0x0) - { - playerInMenu = MemoryUtil.Read(inMenuOffset + 0xB734) == 1; - } - } - */ - bool readInputsPostHook = false; + PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); + PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); + PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); + PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); + if (enableCombo && freeCameraCombo != null) { if (disableComboButton1) @@ -2379,7 +2455,8 @@ namespace MHWNewCamera PadChg = MemoryUtil.Read(controllerAddr() + 0x1A8); readInputsPostHook = true; } - uint Mask = 0; + + uint Mask = 0u; 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; @@ -2405,12 +2482,13 @@ namespace MHWNewCamera else { uint FaceButtonMask = (uint)Button.Cross | (uint)Button.Circle | (uint)Button.Square | (uint)Button.Triangle; - Mask = FaceButtonMask | DPadMask | StartSelectMask | BumperMask | StickMask; + Mask = FaceButtonMask | StartSelectMask | DPadMask | BumperMask | StickMask; } if (enableCombo && freeCameraCombo != null) { Mask &= ~((uint)b1 | (uint)b2); } + PadDown &= ~Mask; //PadOld &= ~Mask; PadTrg &= ~Mask; @@ -2423,10 +2501,32 @@ namespace MHWNewCamera MemoryUtil.WriteBytes(controllerAddr() + 0x1A8, BitConverter.GetBytes(PadChg)); MemoryUtil.WriteBytes(controllerAddr() + 0x1C0, BitConverter.GetBytes(0)); // Left and right trigger. MemoryUtil.WriteBytes(controllerAddr() + 0x1C1, BitConverter.GetBytes(0)); + MemoryUtil.WriteBytes(controllerAddr() + 0x1B0, BitConverter.GetBytes(0)); // Rx/y. + MemoryUtil.WriteBytes(controllerAddr() + 0x1B4, BitConverter.GetBytes(0)); } if (enableFreeCamera) { + if (playerMovementLocked) + { + MemoryUtil.WriteBytes(controllerAddr() + 0x1B8, BitConverter.GetBytes(0)); // Lx/y. + MemoryUtil.WriteBytes(controllerAddr() + 0x1BC, BitConverter.GetBytes(0)); + } + + if (orbitPlayer) + { + if (plusRight != 0.0f && !playerMovementLocked) + { + 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)); + } + } + if (!unlockMovementHeld && buttonWasPressed(Button.R2)) { unlockMovementHeld = true; @@ -2503,6 +2603,26 @@ namespace MHWNewCamera enableFreeCamera = false; } + if (buttonWasPressed(Button.Options) && (plusRight != 0.0f || plusForward != 0.0f)) + { + if (buttonWasDown(Button.Share)) + { + plusRight = 0.0f; + plusForward = 0.0f; + } + else + { + if (plusRight != 0.0f) + { + plusRight = -plusRight; + } + if (plusForward != 0.0f) + { + plusForward = -plusForward; + } + } + } + if (!unlockInputForMenu && buttonWasPressed(Button.Triangle)) { nint baseAddr = MemoryUtil.Read(0x1451C4640); @@ -2521,19 +2641,6 @@ 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, float alwaysZero) @@ -2547,9 +2654,20 @@ namespace MHWNewCamera debugLog($"CheckMovementHook({stickValue:x}, {alwaysZero}) @ {frameTick}"); #endif - if (freeCamera && !((unlockMovementHeld || unlockMovementToggled) && !unlockMovementPause)) + if (freeCamera) { - stickValue = 0; + if (orbitPlayer && orbitIgnoreCamera && vCamera != null) + { + // Control the camera's influence on player movement separately. + double dist = 700.0 - cameraForward; + vCamera.Target.X = cameraPosition.X + (float)(dist * Math.Cos(Double.DegreesToRadians(orbitMovementRotation))); + vCamera.Target.Y = cameraPosition.Y; + vCamera.Target.Z = cameraPosition.Z + (float)(dist * Math.Sin(Double.DegreesToRadians(orbitMovementRotation))); + } + if (playerMovementLocked && (plusRight == 0.0f && plusForward == 0.0f)) + { + stickValue = 0; + } } return checkMovementHook!.Original(stickValue, alwaysZero); @@ -2725,100 +2843,6 @@ namespace MHWNewCamera fxaaHook!.Original(unknownPtr, unknownPtr2); } - private void disableAllCollisionHooks() - { - if (disableExtraGravity) - { - disableExtraGravity = false; - disableExtraGravityDisable(); - } - if (disableGravity) - { - disableGravity = false; - disableGravityDisable(); - } - if (disableExtraCollision) - { - disableExtraCollision = false; - disableExtraCollisionDisable(); - } - if (disableCollision) - { - disableCollision = false; - disableCollisionDisable(); - } - } - - private static T drawRenderParameter(string name, nint baseAddr = 0x0, nint offset = 0x0, bool zeroToOne = false) where T : unmanaged - { - nint addr = baseAddr + offset; - T? currentValue = null; - if (currentValue == null) - { - currentValue = MemoryUtil.Read(addr); - } - if (typeof(T) == typeof(float)) - { - float valueF = Convert.ToSingle(currentValue); - if (zeroToOne) - { - if (ImGui.DragFloat(name, ref valueF, 0.01f, 0.0f, 1.0f, "%.6f")) - { - MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); - } - } - else - { - if (ImGui.InputFloat(name, ref valueF, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags.EnterReturnsTrue)) - { - MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); - } - } - return (T)Convert.ChangeType(valueF, typeof(T)); - } - else if (typeof(T) == typeof(int)) - { - int valueI = Convert.ToInt32(currentValue); - if (ImGui.InputInt(name, ref valueI, 0, 0, ImGuiInputTextFlags.EnterReturnsTrue)) - { - MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueI)); - } - return (T)Convert.ChangeType(valueI, typeof(T)); - } - else if (typeof(T) == typeof(byte)) - { - bool valueSwitch = Convert.ToByte(currentValue) == 0x1; - if (ImGui.Checkbox(name, ref valueSwitch)) - { - MemoryUtil.WriteBytes(addr, valueSwitch ? [0x1] : [0x0]); - } - return (T)Convert.ChangeType(valueSwitch, typeof(T)); - } - return (T)currentValue; - } - - private static void inputSSAOParameters(SSAOParameters? parameters, nint baseAddr) - { - if (parameters == null) - { - drawRenderParameter("SSAO Depth Bias", baseAddr, 0xB4B0); - drawRenderParameter("SSAO Sloped Depth Bias", baseAddr, 0xB4B4); - drawRenderParameter("SSAO Max Depth Bias", baseAddr, 0xB4B8); - drawRenderParameter("SSAO Dispersion", baseAddr, 0xB4BC); - drawRenderParameter("SSAO Effect", baseAddr, 0xB430); - drawRenderParameter("SSAO Effect GI", baseAddr, 0xB434); - drawRenderParameter("SSAO Depth Difference", baseAddr, 0xB4C0); - drawRenderParameter("SSAO Samples Per Pixel", baseAddr, 0xB4C4); - drawRenderParameter("SSAO Max Sample Num", baseAddr, 0xB4C8); - drawRenderParameter("SSAO Max Sample Num HQ", baseAddr, 0xB4D0); - drawRenderParameter("SSAO Radius", baseAddr, 0xB4D4); - drawRenderParameter("SSAO Bias", baseAddr, 0xB4D8); - drawRenderParameter("SSAO Intensity", baseAddr, 0xB4E0); - drawRenderParameter("SSAO Use HiZ", baseAddr, 0xB4E5); - drawRenderParameter("SSAO Edge Atten Rate", baseAddr, 0xB4DC); - } - } - private void drawViewportInfo(int i, float width, Config config, bool debug) { Viewport vp = CameraSystem.GetViewport(i); @@ -3032,6 +3056,130 @@ namespace MHWNewCamera } } + private void drawAnimationInfo(Entity entity) + { + ActionInfo currentActionInfo = entity.ActionController.CurrentAction; + SharpPluginLoader.Core.Actions.Action? currentAction = null; + if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3) + { + ActionList actionList = entity.ActionController.GetActionList(currentActionInfo.ActionSet); + if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count) + { + currentAction = actionList[currentActionInfo.ActionId]; + } + } + AnimationId currentAnimation = entity.CurrentAnimation; + ImGui.Text("Action/Animation:"); + ImGui.Text($"ActionController: {entity.ActionController.Instance:x}"); + ImGui.Text($" Current: {currentAction} {currentActionInfo}, {currentAnimation}"); + if (currentAction != null) + { + ImGui.Text($" Active Time: {currentAction.ActiveTime}"); + ImGui.Text($" Delta Sec: {currentAction.DeltaSec}"); + } + AnimationLayerComponent? animationLayer = entity.AnimationLayer; + if (animationLayer != null) + { + ImGui.Text($"AnimationLayer: {animationLayer.Instance:x}"); + ImGui.Text($" Speed: {animationLayer.Speed:0.000}"); + ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}"); + } + } + + private static T drawRenderParameter(string name, nint baseAddr = 0x0, nint offset = 0x0, bool zeroToOne = false) where T : unmanaged + { + nint addr = baseAddr + offset; + T? currentValue = null; + if (currentValue == null) + { + currentValue = MemoryUtil.Read(addr); + } + if (typeof(T) == typeof(float)) + { + float valueF = Convert.ToSingle(currentValue); + if (zeroToOne) + { + if (ImGui.DragFloat(name, ref valueF, 0.01f, 0.0f, 1.0f, "%.6f")) + { + MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); + } + } + else + { + if (ImGui.InputFloat(name, ref valueF, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags.EnterReturnsTrue)) + { + MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueF)); + } + } + return (T)Convert.ChangeType(valueF, typeof(T)); + } + else if (typeof(T) == typeof(int)) + { + int valueI = Convert.ToInt32(currentValue); + if (ImGui.InputInt(name, ref valueI, 0, 0, ImGuiInputTextFlags.EnterReturnsTrue)) + { + MemoryUtil.WriteBytes(addr, BitConverter.GetBytes(valueI)); + } + return (T)Convert.ChangeType(valueI, typeof(T)); + } + else if (typeof(T) == typeof(byte)) + { + bool valueSwitch = Convert.ToByte(currentValue) == 0x1; + if (ImGui.Checkbox(name, ref valueSwitch)) + { + MemoryUtil.WriteBytes(addr, valueSwitch ? [0x1] : [0x0]); + } + return (T)Convert.ChangeType(valueSwitch, typeof(T)); + } + return (T)currentValue; + } + + private static void inputSSAOParameters(SSAOParameters? parameters, nint baseAddr) + { + if (parameters == null) + { + drawRenderParameter("SSAO Depth Bias", baseAddr, 0xB4B0); + drawRenderParameter("SSAO Sloped Depth Bias", baseAddr, 0xB4B4); + drawRenderParameter("SSAO Max Depth Bias", baseAddr, 0xB4B8); + drawRenderParameter("SSAO Dispersion", baseAddr, 0xB4BC); + drawRenderParameter("SSAO Effect", baseAddr, 0xB430); + drawRenderParameter("SSAO Effect GI", baseAddr, 0xB434); + drawRenderParameter("SSAO Depth Difference", baseAddr, 0xB4C0); + drawRenderParameter("SSAO Samples Per Pixel", baseAddr, 0xB4C4); + drawRenderParameter("SSAO Max Sample Num", baseAddr, 0xB4C8); + drawRenderParameter("SSAO Max Sample Num HQ", baseAddr, 0xB4D0); + drawRenderParameter("SSAO Radius", baseAddr, 0xB4D4); + drawRenderParameter("SSAO Bias", baseAddr, 0xB4D8); + drawRenderParameter("SSAO Intensity", baseAddr, 0xB4E0); + drawRenderParameter("SSAO Use HiZ", baseAddr, 0xB4E5); + drawRenderParameter("SSAO Edge Atten Rate", baseAddr, 0xB4DC); + } + } + + private void disableAllCollisionHooks() + { + if (disableExtraGravity) + { + disableExtraGravity = false; + disableExtraGravityDisable(); + } + if (disableGravity) + { + disableGravity = false; + disableGravityDisable(); + } + if (disableExtraCollision) + { + disableExtraCollision = false; + disableExtraCollisionDisable(); + } + if (disableCollision) + { + disableCollision = false; + disableCollisionDisable(); + } + } + private void tryToDisableMod(Player? player) { disableAllCollisionHooks(); @@ -3184,7 +3332,7 @@ namespace MHWNewCamera Config config = ConfigManager.GetConfig(this); float width = ImGui.GetWindowWidth(); - // If we use vCamera or pCamera here, we need to verify they're not invalid. + // If we use vCamera or pCamera here, we need to ensure they're not invalid. Player? player = checkPlayerChange(); checkCurrentVisibleCamera(player); @@ -3457,6 +3605,14 @@ namespace MHWNewCamera ImGui.Checkbox("Unlock Input", ref unlockInputToggled); ImGui.Checkbox("Unlock Player Movement", ref unlockMovementToggled); ImGui.Checkbox("Lock Vertical Movement and Apply Speed Modifier", ref lockVerticalToggled); + ImGui.Checkbox("Orbit Player", ref orbitPlayer); + ImGui.SameLine(); + ImGui.Checkbox("Ignore Camera Direction", ref orbitIgnoreCamera); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Left stick right/left will gradually shift your forward direction."); + ImGui.EndTooltip(); + } if (!freeCamera) { ImGui.PopStyleVar(); @@ -3546,7 +3702,6 @@ namespace MHWNewCamera } ImGui.PopItemWidth(); } - ImGui.PopID(); ImGui.Separator(); @@ -3576,6 +3731,7 @@ namespace MHWNewCamera noopCharacterFade.Disable(); } } + ImGui.PopID(); ImGui.Separator(); @@ -4028,7 +4184,7 @@ namespace MHWNewCamera } if (ImGui.BeginItemTooltip()) { - ImGui.Text("Disable check for being about halfway submerged in water to stay sitting"); + ImGui.Text("Disable check for being about halfway submerged in water to stay sitting."); ImGui.EndTooltip(); } @@ -4531,7 +4687,7 @@ namespace MHWNewCamera } if (ImGui.BeginItemTooltip()) { - ImGui.Text("Don't reduce an animal's animation rate when they're far from the camera."); + ImGui.Text("Ignore the frame skip set on an animal's animation when they get farther from the camera."); ImGui.EndTooltip(); } @@ -4584,32 +4740,7 @@ namespace MHWNewCamera ImGui.Text("Player:"); ImGui.Text($"Address: {player.Instance:x}"); - ImGui.Text($"ActionController: {player.ActionController.Instance:x}"); - ActionInfo currentActionInfo = player.ActionController.CurrentAction; - SharpPluginLoader.Core.Actions.Action? currentAction = null; - if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3) - { - ActionList actionList = player.ActionController.GetActionList(currentActionInfo.ActionSet); - if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count) - { - currentAction = actionList[currentActionInfo.ActionId]; - } - } - AnimationLayerComponent? animationLayer = player.AnimationLayer; - AnimationId currentAnimation = player.CurrentAnimation; - ImGui.Text("Action/Animation:"); - ImGui.Text($" Current: {currentAction} {currentActionInfo}, {currentAnimation}"); - if (animationLayer != null) - { - ImGui.Text($" Speed: {animationLayer.Speed:0.000}"); - ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}"); - } - if (currentAction != null) - { - ImGui.Text($" Active Time: {currentAction.ActiveTime}"); - // An experiment to test potential animation error could be try to keep deltasec as consistent as possible. - ImGui.Text($" Delta Sec: {currentAction.DeltaSec}"); - } + drawAnimationInfo(player); bool move = player.Move; if (ImGui.Checkbox("Move", ref move)) @@ -4634,55 +4765,29 @@ namespace MHWNewCamera ImGui.Separator(); } - /* +#if MONSTERS_LIST if (ImGui.CollapsingHeader("Monsters")) { Monster[] monsters = Monster.GetAllMonsters(); - foreach (Monster monster in monsters) + for (int i = monsters.Length - 1; i >= 0; i--) { + Monster monster = monsters[i]; ImGui.PushID(monster.Instance); - ImGui.Text($"{monster.Name}: Instance: {monster.Instance:x}"); - if (monster.AnimationLayer != null) - { - ImGui.Text($" AnimationLayer: {monster.AnimationLayer.Instance:x}"); - } - ActionInfo currentActionInfo = monster.ActionController.CurrentAction; - SharpPluginLoader.Core.Actions.Action? currentAction = null; - if (currentActionInfo.ActionSet >= 0 && currentActionInfo.ActionSet <= 3) - { - ActionList actionList = monster.ActionController.GetActionList(currentActionInfo.ActionSet); - if (currentActionInfo.ActionId >= 0 && currentActionInfo.ActionId < actionList.Count) - { - currentAction = actionList[currentActionInfo.ActionId]; - } - } - if (currentAction != null) - { - ImGui.Text($" Action: {currentAction.Instance:x}, Flags: {currentAction.Flags:x}"); - ImGui.Text($" Active Time: {currentAction.ActiveTime}"); - ImGui.Text($" Delta Sec: {currentAction.DeltaSec}"); - } + ImGui.Text($"{monster.Name}:"); + ImGui.Text($" Address: {monster.Instance:x}"); ImGui.DragFloat3("Position", ref monster.Position, 0.5f); - if (player != null) - { - ImGui.DragFloat3("Player Reference", ref player.Position, 0.5f); - } + drawAnimationInfo(monster); ImGui.PopID(); + ImGui.Separator(); } } - */ +#endif ImGui.Text("Graphics:"); - - ImGui.Text($"Fps: {MemoryUtil.Read(sMain.Instance + 0x58)}"); + // Names and locations taken from MHW-DTI-Dumps/wip_dump_15_20_00.h. ImGui.Text($"Max Fps: {MemoryUtil.Read(sMain.Instance + 0x5C)}"); - ImGui.Text($"Actual Fps: {MemoryUtil.Read(sMain.Instance + 0x64)}"); - ImGui.Text($"Real Fps: {MemoryUtil.Read(sMain.Instance + 0x68)}"); - ImGui.Text($"Delta Time Adjust: {MemoryUtil.Read(sMain.Instance + 0x92) == 0x1}"); + ImGui.Text($"Fps: {MemoryUtil.Read(sMain.Instance + 0x68)}"); ImGui.Text($"Delta Time: {MemoryUtil.Read(sMain.Instance + 0x94)}"); - //ImGui.Text($"Delta Time Border: {MemoryUtil.Read(sMain.Instance + 0x98)}"); - //ImGui.Text($"Delta Time Limit: {MemoryUtil.Read(sMain.Instance + 0x9C)}"); - ImGui.Text($"Delta Sec: {MemoryUtil.Read(sMain.Instance + 0xA0)}"); ImGui.Text($"prevFoliageLODBias: {prevFoliageLODBias}"); ImGui.Text($"prevTerrainLODBias: {prevTerrainLODBias}"); @@ -4795,29 +4900,41 @@ namespace MHWNewCamera ImGui.Separator(); + ImGui.PushID("Mouse/Keyboard"); + ImGui.Text("Mouse:"); + ImGui.Text($"Address: {sMhMouse.Instance:x}"); + ImGui.Text("Keyboard:"); + ImGui.Text($"Address: {sMhKeyboard.Instance:x}"); + ImGui.PopID(); + ImGui.PushID("Pad"); ImGui.Text("Pad:"); ImGui.Text($"Address: {controllerAddr():x}"); - int PadRx = MemoryUtil.Read(controllerAddr() + 0x1B0); - int PadRy = MemoryUtil.Read(controllerAddr() + 0x1B4); - int PadLx = MemoryUtil.Read(controllerAddr() + 0x1B8); - int PadLy = MemoryUtil.Read(controllerAddr() + 0x1BC); + int Rx = MemoryUtil.Read(controllerAddr() + 0x1B0); + int Ry = MemoryUtil.Read(controllerAddr() + 0x1B4); + int Lx = MemoryUtil.Read(controllerAddr() + 0x1B8); + int Ly = MemoryUtil.Read(controllerAddr() + 0x1BC); byte PadRz = MemoryUtil.Read(controllerAddr() + 0x1C0); byte PadLz = MemoryUtil.Read(controllerAddr() + 0x1C1); ImGui.Text("Left Stick:"); - ImGui.Text($" X: {PadLx}"); - ImGui.Text($" Y: {PadLy}"); + ImGui.Text($" X: {Lx} ({PadLx})"); + ImGui.Text($" Y: {Ly} ({PadLy})"); ImGui.Text($" LT: {PadLz}"); ImGui.Text("Right Stick:"); - ImGui.Text($" X: {PadRx}"); - ImGui.Text($" Y: {PadRy}"); + ImGui.Text($" X: {Rx} ({PadRx})"); + ImGui.Text($" Y: {Ry} ({PadRy})"); ImGui.Text($" RT: {PadRz}"); 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("Reset")) + { + plusRight = 0.0f; + plusForward = 0.0f; + } + ImGui.SameLine(); if (ImGui.Button("Flip")) { if (plusRight != 0.0f) @@ -4833,6 +4950,18 @@ namespace MHWNewCamera ImGui.PopID(); ImGui.Separator(); + + ImGui.PushID("Orbit"); + ImGui.Text("Orbital Camera:"); + ImGui.PushItemWidth(width * 0.15f); + ImGui.DragFloat("Forward", ref orbitForward, 1.0f); + ImGui.SameLine(); + ImGui.DragFloat("Target Y", ref orbitY, 1.0f); + ImGui.DragFloat("Movement Rotation", ref orbitMovementRotation, 1.0f); + ImGui.PopItemWidth(); + ImGui.PopID(); + + ImGui.Separator(); } ImGui.PopID(); -- cgit v1.2.3-101-g0448