From d40ec05f3e61b51be0b6a7797fc11e0b626d238b Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Tue, 2 Jun 2026 22:23:53 -0400 Subject: Organize joints, cleanup for new release Signed-off-by: Andrew Opalach --- Plugin.cs | 1785 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 1286 insertions(+), 499 deletions(-) diff --git a/Plugin.cs b/Plugin.cs index 01f7ab7..9220b3b 100755 --- a/Plugin.cs +++ b/Plugin.cs @@ -1,11 +1,12 @@ -#define ENABLE_ASSERTS +//#define ENABLE_ASSERTS //#define HOOK_ORDER_ASSERTS //#define LOG_DEBUG_MESSAGES #define MOUSE_AND_KEYBOARD_LAYER -#define QUARANTINED_FEATURES +//#define QUARANTINED_FEATURES using System.Numerics; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; #if ENABLE_ASSERTS using System.Diagnostics; #endif @@ -20,7 +21,6 @@ using SharpPluginLoader.Core.Memory; using SharpPluginLoader.Core.Actions; using SharpPluginLoader.Core.Components; using SharpPluginLoader.Core.Configuration; -using WorldTuningTool; // Tentative List of Actions: // - Toggle Free Camera @@ -48,16 +48,14 @@ using WorldTuningTool; // - Open Poses Menu // @TODO: -// - Collect armor parts logic. -// - Map joints to parts. +// - Pass on ImGui flicker. +// - Cleanup math. // - pCamera refactor. -// - Structured tuning tool interop. // - Attempt to document all test cases I can think of. -// - Wasd for ignore camera direction. -// - Make audio like waterfall follow camera position instead of player position. -// - Audio high/lowpass? // - Centralize all bindings to get a better idea of how to structure custom binds. -// - Use GetRef<>. +// - WASD for ignore camera direction. +// - Make audio like waterfall follow camera position instead of player position. +// - Audio high/lowpass possible? // - Save toggle state to config file. // - Include Hide Weapon. // - Hunter effects: @@ -138,6 +136,37 @@ using WorldTuningTool; namespace NewCamera { + public static class TuningToolInterop + { + public static string PluginName = "World Tuning Tool"; + public static dynamic? Instance = null; + + public static bool InitFromLoadedInstance() + { +#if QUARANTINED_FEATURES + Instance = IPlugin.GetInstance(PluginName); +#endif + return Instance != null; + } + + public static int AddOverride(string name, Vector4 v4, int i1) + { + if (Instance != null) + { + return Instance.AddOverride(name, v4, i1); + } + return 0; + } + + public static void RemoveOverride(int id) + { + if (Instance != null) + { + Instance.RemoveOverride(id); + } + } + } + public unsafe class Plugin : IPlugin { public string Name => "New Camera"; @@ -157,8 +186,6 @@ namespace NewCamera private bool disableMod = false; - private WorldTuningTool.Interop tuningTool = new WorldTuningTool.Interop(); - private static readonly MtObject sMain = SingletonManager.GetSingleton("sMhMain")!; private bool freezeGame = false; private bool decoupleDtFromGameTime = false; @@ -211,6 +238,7 @@ namespace NewCamera private float orbitDistance = 350.0f; private float orbitY = 150.0f; private float orbitRight = 0.0f; + private int orbitJoint = -1; private bool enableOffsetPerspective = false; private bool offsetPerspective = false; @@ -262,6 +290,13 @@ namespace NewCamera private float plusRight = 0.0f; private float plusForward = 0.0f; + private bool sortMonsters = true; + private bool sortAnimals = true; + + private string modelFilter = ""; + private bool modelFilterIsRegex = false; + private Regex? modelRegex = null; + private delegate void ProcessCameraDelegate(nint cameraPointer); private Hook? setCameraHook; private Hook? calculateCameraHook; @@ -368,100 +403,142 @@ namespace NewCamera private bool hideKnife = false; private bool hideSlinger = false; - // List of Joints: - // Hip (1_0) - // Right Leg (2_0) - // Left Leg (2_1) - // Lower Back (2_2) - // Left Knee (3_1) - // Right Knee (3_2) - // Upper Back (3_4) - // Lower Neck (4_0) - // Right Ankle (4_1) - // Left Ankle (4_5) - // Left Shoulder (4_7) - // Right Shoulder (4_8) - // Left Toes (5_2) - // Right Shoulder2 (5_3) - // Upper Neck (5_4) - // Left Shoulder2 (5_5) - // Right Toes (5_6) - // Right Elbow (6_4) - // Left Elbow (6_5) - // Left Wrist (7_1) - // Right Wrist (7_4) - // Left Palm (8_0) - // Left Middle (8_2) - // Left Index (8_3) - // Right Palm (8_4) - // Left Thumb (8_5) - // Right Thumb (8_7) - // Right Index (8_11) - // Right Middle (8_12) - // Right Index T (9_0) - // Left Pinky T (9_1) - // Left Thumb T (9_2) - // Left Index T (9_3) - // Left Middle T (9_4) - // Left Ring T (9_5) - // Right Middle T (9_6) - // Right Thumb T (9_7) - // Right Ring T (9_8) - // Right Pinky T (9_9) - // Right Index P (A_0) - // Right Thumb P (A_1) - // Left Pinky P (A_2) - // Left Ring P (A_3) - // Left Middle P (A_4) - // Right Ring P (A_5) - // Left Index P (A_6) - // Left Thumb P (A_7) - // Right Middle P (A_8) - // Right Pinky P (A_9) - // Left Pinky D (B_0) - // Right Pinky D (B_1) - // Left Ring D (B_2) - // Right Ring D (B_3) - - private struct Armor + private static class Armor + { + public const byte Body = 0; + public const byte Helmet = 1; + public const byte Arm = 2; + public const byte Waist = 3; + public const byte Leg = 4; + public const byte Face = 5; + public const byte EyeLens = 6; + public const byte Hair = 7; + } + + private static class Joint { - public const int Body = 0; - public const int Helmet = 1; - public const int Arm = 2; - public const int Waist = 3; - public const int Leg = 4; - public const int Face = 5; - }; - - private nint[] playerArmor = new nint[6] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + public const byte Root = 0; + public const byte Root2 = 1; // Animations use this root. + public const byte LowerBack = 2; + public const byte UpperBack = 3; + public const byte LowerNeck = 4; + public const byte LowerNeckNull = 5; + public const byte UpperNeck = 6; + public const byte LeftCollarbone = 7; + public const byte LeftShoulderNull = 8; + public const byte LeftShoulder = 9; + public const byte LeftElbow = 10; + public const byte LeftWrist = 11; + public const byte LeftWristNull = 12; + public const byte LeftThumbLow = 13; + public const byte LeftThumbMid = 14; + public const byte LeftThumbHigh = 15; + public const byte LeftIndexLow = 16; + public const byte LeftIndexMid = 17; + public const byte LeftIndexHigh = 18; + public const byte LeftMiddleLow = 19; + public const byte LeftMiddleMid = 20; + public const byte LeftMiddleHigh = 21; + public const byte LeftPalm = 22; + public const byte LeftRingLow = 23; + public const byte LeftRingMid = 24; + public const byte LeftRingHigh = 25; + public const byte LeftPinkyLow = 26; + public const byte LeftPinkyMid = 27; + public const byte LeftPinkyHigh = 28; + public const byte LeftArmUnk1 = 29; + public const byte LeftArmUnk2 = 30; + public const byte LeftArmUnk3 = 31; + public const byte LeftArmUnk4 = 32; + public const byte LeftArmUnk5 = 33; + public const byte LeftArmUnk6 = 34; + public const byte LeftArmUnk7 = 35; + public const byte RightCollarbone = 36; + public const byte RightShoulder = 37; + public const byte RightElbow = 38; + public const byte RightWrist = 39; + public const byte RightWristNull = 40; + public const byte RightThumbLow = 41; + public const byte RightThumbMid = 42; + public const byte RightThumbHigh = 43; + public const byte RightIndexLow = 44; + public const byte RightIndexMid = 45; + public const byte RightIndexHigh = 46; + public const byte RightMiddleLow = 47; + public const byte RightMiddleMid = 48; + public const byte RightMiddleHigh = 49; + public const byte RightPalm = 50; + public const byte RightRingLow = 51; + public const byte RightRingMid = 52; + public const byte RightRingHigh = 53; + public const byte RightPinkyLow = 54; + public const byte RightPinkyMid = 55; + public const byte RightPinkyHigh = 56; + public const byte RightArmUnk1 = 57; + public const byte RightArmUnk2 = 58; + public const byte RightArmUnk3 = 59; + public const byte RightArmUnk4 = 60; + public const byte Unknown1 = 61; + public const byte Unknown2 = 62; + public const byte LeftHip = 63; + public const byte LeftKnee = 64; + public const byte LeftAnkle = 65; + public const byte LeftToes = 66; + public const byte LeftAnkleNull = 67; + public const byte LeftKneeNull = 68; + public const byte LeftHipNull = 69; + public const byte Unknown3 = 70; + public const byte Unknown4 = 71; + public const byte RightHip = 72; + public const byte RightKnee = 73; + public const byte RightAnkle = 74; + public const byte RightToes = 75; + public const byte RightAnkleNull = 76; + public const byte RightKneeNull = 77; + public const byte RightHipNull = 78; + public const byte Unknown5 = 79; + public const byte Unknown6 = 80; + public const byte Unknown7 = 81; + public const byte Unknown8 = 82; + public const byte Unknown9 = 83; + public const byte Unknown10 = 84; + public const byte Unknown11 = 85; + } + + private nint[] playerArmor = new nint[8]; + private nint[] playerJoints = new nint[86]; + + private delegate void UpdateJoints(nint obj); + private Hook? updateJointsHook; + private delegate void UpdateJointChild(nint child, nint joint, nint obj); private List bodyJoints = new List(); - //private List faceJoints = new List(); - private List jiggleBones = new List(); + private List ignoredJoints = new List(); + private Dictionary> jointOffsets = new Dictionary>(); + private bool didJointOffset = false; + +#if QUARANTINED_FEATURES + private delegate void UpdateIK(nint superOfChild, nint joint, nint obj); + private Hook? updateIKHook; + private Dictionary> ikOffsets = new Dictionary>(); +#endif private List ikJoints = new List(); + private bool ikForcedOff = false; + private Patch forceDisableIK; + + private List jiggleBones = new List(); private bool attachToChest = false; private bool swapChestSides = false; private float chestMoveScale = 0.25f; private nint chestBone1 = 0x0; private nint chestBone2 = 0x0; + private List faceJoints = new List(); /* private bool overrideFacePose; private Patch noopFacePose; private Patch noopFacePoseUpdate; */ - private bool ikForcedOff = false; - private Patch forceDisableIK; - private delegate void UpdateJoints(nint obj, nint unknownPtr, int unknownInt, int unknownInt2); - private Hook? updateJointsHook; - private delegate void UpdateJointChild(nint child, nint joint, nint obj); - private Dictionary> jointOffsets = new Dictionary>(); - private bool didJointOffset = false; - - private delegate void UpdateIK(nint superOfChild, nint joint, nint obj); - private Hook? updateIKHook; - private Dictionary> ikOffsets = new Dictionary>(); - /* private delegate void ChangeEquipment(nint unknownPtr, int unknownInt); private Hook? changeEquipmentHook; @@ -528,11 +605,12 @@ namespace NewCamera disableGravityEval.Disable(); } - private enum ZoneState : int { + private enum ZoneState : int + { Unknown = 0, Hub = 1, Combat = 2 - }; + } #if QUARANTINED_FEATURES private ZoneState forceZoneState = ZoneState.Unknown; @@ -812,16 +890,22 @@ namespace NewCamera getSaveSlotGuiAddr = new NativeFunction(0x141AC0B60); getPlayerSettingsAddr = new NativeFunction(0x141B8DBB0); - //noopFacePose = new Patch(new nint(0x14237B093), [0x90, 0x90, 0x90, 0x90, 0x90]); - //noopFacePoseUpdate = new Patch(new nint(0x14223BAAB), [0x90, 0x90, 0x90, 0x90, 0x90]); + /* + noopFacePose = new Patch(new nint(0x14237B093), [0x90, 0x90, 0x90, 0x90, 0x90]); + noopFacePoseUpdate = new Patch(new nint(0x14223BAAB), [0x90, 0x90, 0x90, 0x90, 0x90]); + */ forceDisableIK = new Patch(new nint(0x14031FD40), [0xC6, 0x81, 0x81, 0x01, 0x00, 0x00, 0x00, 0xC3]); - updateJointsHook = Hook.Create(0x14223B870, UpdateJointsHook); + updateJointsHook = Hook.Create(0x14223BA30, UpdateJointsHook); +#if QUARANTINED_FEATURES updateIKHook = Hook.Create(0x142472C00, UpdateIKHook); +#endif - //changeEquipmentHook = Hook.Create(0x141DDEF80, ChangeEquipmentHook); // nint, int - //newEquipmentPointer = new NativeFunction(0x141DE56A0); + /* + changeEquipmentHook = Hook.Create(0x141DDEF80, ChangeEquipmentHook); // nint, int + newEquipmentPointer = new NativeFunction(0x141DE56A0); + */ // Player + ECCC = How far underwater is the player. jmpOverHotSpringsEval = new Patch(new nint(0x1417C1B03), [0xEB]); @@ -865,12 +949,12 @@ namespace NewCamera Assert(addr + 0x8 == 0x1413259ED); #endif disableGravityYUpdate = new Patch(addr + 0x8, [ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, ]); disableGravityXZUpdate = new Patch(addr, [ - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // Will already be applied. - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // Will already be applied. + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 ]); addr = PatternScanner.FindFirst(Pattern.FromString("F3 0F 11 97 54 15 00 00 F3 0F 11 8F 58 15 00 00 F3 0F 10 47 68 F3 0F 5E D8 44 89 B7 6C 15 00 00 F3 0F 5E D0 F3 0F 5E C8 F3 0F 11 9F 60 15 00 00 F3 0F 11 97 64 15 00 00 F3 0F 11 8F 68 15 00 00")); @@ -963,13 +1047,13 @@ namespace NewCamera } if (config.TuningToolInterop) { - if (tuningTool.InitFromLoadedInstance()) + if (TuningToolInterop.InitFromLoadedInstance()) { - Log.Info($"Successfully loaded '{WorldTuningTool.Interop.PluginName}' instance"); + Log.Info($"Successfully loaded '{TuningToolInterop.PluginName}' instance"); } else { - Log.Warn($"Couldn't find loaded '{WorldTuningTool.Interop.PluginName}' instance, features will be missing"); + Log.Warn($"Couldn't find loaded '{TuningToolInterop.PluginName}' instance, features will be missing"); } } } @@ -1019,9 +1103,20 @@ namespace NewCamera return new Player(playerAddr); } + private Player? getPlayer() { return Player.MainPlayer; } + private Player? getPlayerWithFallback() + { + Player? player = getPlayer(); + if (player == null) + { + player = getPlayerFromSaveSlot(); + } + return player; + } + private Player? checkPlayerChange() { - Player? player = Player.MainPlayer; + Player? player = getPlayer(); if (player != lastPlayer) { pCamera = null; @@ -1164,12 +1259,12 @@ namespace NewCamera { if (disableNearDofOverride != 0) { - tuningTool.RemoveOverride(disableNearDofOverride); + TuningToolInterop.RemoveOverride(disableNearDofOverride); disableNearDofOverride = 0; } else { - disableNearDofOverride = tuningTool.AddOverride("Near Enable", new Vector4(), 0); + disableNearDofOverride = TuningToolInterop.AddOverride("Near Enable", new Vector4(), 0); } } } @@ -1217,12 +1312,7 @@ namespace NewCamera advanceFrame--; } - player = Player.MainPlayer; - if (player == null) - { - player = getPlayerFromSaveSlot(); - } - + player = getPlayerWithFallback(); if (player != null) { if (hideWeapon) @@ -1377,7 +1467,7 @@ namespace NewCamera forceMinimapFollowsCamera.Enable(); /* //MemoryUtil.GetRef(psuedoViewModeObject + 0x10) = vCamera.Instance; - Player? player = Player.MainPlayer; + Player? player = getPlayer(); if (player != null) { MemoryUtil.GetRef(psuedoViewModeObject + 0x118) = player.Instance; @@ -1509,18 +1599,22 @@ namespace NewCamera orbitDistance = 3.00f; } } + if (plusRight != 0.0f) + { + orbitMovementRotation += plusRight; + } } else { orbitMovementRotation += Lx / 5.0f; - if (orbitMovementRotation >= 180.0f) - { - orbitMovementRotation -= 360.0f; - } - else if (orbitMovementRotation < -180.0f) - { - orbitMovementRotation += 360.0f; - } + } + if (orbitMovementRotation >= 180.0f) + { + orbitMovementRotation -= 360.0f; + } + else if (orbitMovementRotation < -180.0f) + { + orbitMovementRotation += 360.0f; } } else @@ -1685,7 +1779,7 @@ namespace NewCamera } #endif cameraYaw += Rx; - if (plusRight != 0.0f) + if (plusRight != 0.0f && !orbitPlayer) { cameraYaw += plusRight * deltaTime; } @@ -1699,9 +1793,14 @@ namespace NewCamera { cameraYaw += 360.0f; } - if (cameraPitchLimit >= 0.0f) + float pitchLimit = cameraPitchLimit; + if (orbitJoint >= 0 && pitchLimit == -1.0f) + { + pitchLimit = Config.Settings.MAX_PITCH_LIMIT; + } + if (pitchLimit >= 0.0f) { - cameraPitch = Math.Clamp(cameraPitch, -cameraPitchLimit, cameraPitchLimit); + cameraPitch = Math.Clamp(cameraPitch, -pitchLimit, pitchLimit); } else { @@ -1739,18 +1838,42 @@ namespace NewCamera if (orbitPlayer && player != null) { - Quaternion rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); + Quaternion rotation; + bool targetJoint = orbitJoint >= 0 && orbitJoint < bodyJoints.Count; + if (targetJoint) + { + nint jointAddr = bodyJoints[orbitJoint]; + cameraTarget = MemoryUtil.GetRef(jointAddr + 0x50); + rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); + rotation *= MemoryUtil.GetRef(jointAddr + 0x70); + rotation *= Quaternion.CreateFromYawPitchRoll( + Single.DegreesToRadians(-cameraYaw), + Single.DegreesToRadians(-cameraPitch), + Single.DegreesToRadians(-cameraRoll)); + } + else + { + cameraTarget = player.Position; + rotation = new Quaternion(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); + } Vector3 up = Vector3.Transform(new Vector3(0.0f, 1.0f, 0.0f), rotation); Vector3 right = Vector3.Transform(new Vector3(1.0f, 0.0f, 0.0f), rotation); orbitY += cameraFrame.Y; - cameraTarget = player.Position; cameraTarget += orbitY * up; cameraTarget.X += orbitRight * right.X; cameraTarget.Z += orbitRight * right.Z; float dist = orbitDistance; - cameraPosition.X = cameraTarget.X - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Cos(Single.DegreesToRadians(cameraYaw)); - cameraPosition.Y = cameraTarget.Y - dist * MathF.Sin(Single.DegreesToRadians(cameraPitch)); - cameraPosition.Z = cameraTarget.Z - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Sin(Single.DegreesToRadians(cameraYaw)); + if (targetJoint) + { + Vector3 forward = Vector3.Transform(new Vector3(0.0f, 0.0f, 1.0f), rotation); + cameraPosition = cameraTarget - forward * dist; + } + else + { + cameraPosition.X = cameraTarget.X - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Cos(Single.DegreesToRadians(cameraYaw)); + cameraPosition.Y = cameraTarget.Y - dist * MathF.Sin(Single.DegreesToRadians(cameraPitch)); + cameraPosition.Z = cameraTarget.Z - dist * MathF.Cos(Single.DegreesToRadians(cameraPitch)) * MathF.Sin(Single.DegreesToRadians(cameraYaw)); + } } else { @@ -1777,7 +1900,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"SetCameraHook({cameraPointer:X}) @ {frameTick}"); + debugLog($"SetCameraHook(0x{cameraPointer:X}) @ {frameTick}"); Assert(hookOrder == 0); hookOrder = 1; #endif @@ -1826,7 +1949,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"CalculateCameraHook({cameraPointer:X}) @ {frameTick}"); + debugLog($"CalculateCameraHook(0x{cameraPointer:X}) @ {frameTick}"); Assert(hookOrder == 2); hookOrder = 3; #endif @@ -1908,7 +2031,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"CheckCameraHook({cameraPointer:X}) @ {frameTick}"); + debugLog($"CheckCameraHook(0x{cameraPointer:X}) @ {frameTick}"); Assert(hookOrder == 1); hookOrder = 2; #endif @@ -1941,7 +2064,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"StartViewMode({viewModeObject:X}) @ {frameTick}"); + debugLog($"StartViewMode(0x{viewModeObject:X}) @ {frameTick}"); #endif if (vCamera != null) @@ -1961,7 +2084,7 @@ namespace NewCamera #if HOOK_ORDER_ASSERTS // The order of this hook between SetCameraHook() and CalculateCameraHook() is inconsistent. - debugLog($"SetCameraTentHook({unknownPtr:X}) @ {frameTick}"); + debugLog($"SetCameraTentHook(0x{unknownPtr:X}) @ {frameTick}"); #endif if (freeCamera && vCamera != null) @@ -1991,7 +2114,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"SetCameraCutsceneHook({unknownPtr:X}) @ {frameTick}"); + debugLog($"SetCameraCutsceneHook(0x{unknownPtr:X}) @ {frameTick}"); #endif setCameraCutsceneHook!.Original(unknownPtr); @@ -2034,7 +2157,7 @@ namespace NewCamera decoupleDtFromGameTime = true; if (forceOffMotionBlurOverride == 0) { - forceOffMotionBlurOverride = tuningTool.AddOverride("Shutter Speed", new Vector4(0.0f), 0); + forceOffMotionBlurOverride = TuningToolInterop.AddOverride("Shutter Speed", new Vector4(0.0f), 0); } } else @@ -2042,7 +2165,7 @@ namespace NewCamera decoupleDtFromGameTime = false; if (forceOffMotionBlurOverride != 0) { - tuningTool.RemoveOverride(forceOffMotionBlurOverride); + TuningToolInterop.RemoveOverride(forceOffMotionBlurOverride); forceOffMotionBlurOverride = 0; } } @@ -2052,7 +2175,7 @@ namespace NewCamera private bool playerInMenu() { // This doesn't align with in-game mouse controls. This can be observed when closing the pause - // menu and there is a brief moment where the camera moves -> freezes again -> then starts normally. + // menu where there is a brief moment the camera moves -> freezes again -> then starts normally. return !freeCameraNoMenu && MemoryUtil.GetRef(Gui.SingletonInstance.Instance + 0x147A8) == 0x1; } @@ -2072,7 +2195,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"WritePadInputHook({unknownPtr:X}, {unknownPtr2:X}, {unknownPtr3:X}) @ {frameTick}"); + debugLog($"WritePadInputHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}, 0x{unknownPtr3:X}) @ {frameTick}"); #endif Button b1 = 0u, b2 = 0u; @@ -2241,7 +2364,7 @@ namespace NewCamera if (orbitPlayer) { - if (plusRight != 0.0f && !playerMovementLocked) + if (plusRight != 0.0f && !playerMovementLocked && !orbitIgnoreCamera) { int Lx = (int)(Int16.MaxValue * Math.Clamp(plusRight, -1.0f, 1.0f)); MemoryUtil.GetRef(sMhController.Instance + 0x1B8) = Lx; @@ -2286,7 +2409,7 @@ namespace NewCamera { if (buttonWasPressed(Button.Down)) { - Player? player = Player.MainPlayer; + Player? player = getPlayer(); if (player != null) { // Y - 150 to approximately align the players head with the camera. @@ -2309,12 +2432,12 @@ namespace NewCamera { if (disableNearDofOverride != 0) { - tuningTool.RemoveOverride(disableNearDofOverride); + TuningToolInterop.RemoveOverride(disableNearDofOverride); disableNearDofOverride = 0; } else { - disableNearDofOverride = tuningTool.AddOverride("Near Enable", new Vector4(), 0); + disableNearDofOverride = TuningToolInterop.AddOverride("Near Enable", new Vector4(), 0); } } } @@ -2344,11 +2467,11 @@ namespace NewCamera } if (!unlockInputForMenu && buttonWasPressed(Button.Triangle)) { - Player? player = Player.MainPlayer; + Player? player = getPlayer(); if (player != null) { nint baseAddr = MemoryUtil.Read(0x1451C4640); - // MonsterHunterWorld.exe+1ADA26A - 48 8B 83 18400100 - mov rax,[rbx+00014018] + // MonsterHunterWorld.exe+1ADA26A - mov rax,[rbx+00014018] nint gesturesAddr = MemoryUtil.Read(baseAddr + 0x14018); if (buttonWasDown(Button.Share)) // MonsterHunterWorld.exe+1EC8000 { @@ -2405,11 +2528,11 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"CollisionCheckHook({unknownPtr:X}, {unknownPtr2:X}) @ {frameTick}"); + debugLog($"CollisionCheckHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}) @ {frameTick}"); #endif Player? player = null; - if (enableCrawl && (player = Player.MainPlayer) != null) + if (enableCrawl && (player = getPlayer()) != null) { nint controlsAddr = MemoryUtil.Read(player.Instance + 0x12608); bool combatControls = false; @@ -2441,7 +2564,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"SetZoneStateHook({player:X}, {flags:X}) @ {frameTick}"); + debugLog($"SetZoneStateHook(0x{player:X}, 0x{flags:X}) @ {frameTick}"); #endif nint zoneStateAddr = MemoryUtil.Read(0x1451C42B8); @@ -2492,18 +2615,14 @@ namespace NewCamera return; } - Player? player = Player.MainPlayer; - if (player == null) - { - player = getPlayerFromSaveSlot(); - } + Player? player = getPlayerWithFallback(); if (player != null && entity == player && playerOpacityOverride != 1.0f) { MemoryUtil.GetRef(player.Instance + 0x78E0) = playerOpacityOverride; } } - private string parsePartName(string fullString) + private static string extractPartName(string fullString) { string partName = ""; if (fullString.StartsWith("pl\\f_equip")) @@ -2512,11 +2631,11 @@ namespace NewCamera } else if (fullString.StartsWith("pl\\hair")) { - partName = fullString.Split('\\')[1]; + partName = fullString.Split('\\')[2]; } else if (fullString.StartsWith("pl\\f_face")) { - partName = fullString.Split('\\')[2]; + partName = fullString.Split('\\')[4].Substring(2); } else if (fullString.StartsWith("wp\\slg")) { @@ -2535,48 +2654,29 @@ namespace NewCamera private void collectArmorParts(nint baseAddr, nint addr) { - string partName = parsePartName(Marshal.PtrToStringAnsi(addr + 0xC)!); - if (partName == "body") + int part; + string partName = extractPartName(Marshal.PtrToStringAnsi(addr + 0xC)!); + if (partName == "body") part = Armor.Body; + else if (partName == "helm") part = Armor.Helmet; + else if (partName == "arm") part = Armor.Arm; + else if (partName == "wst") part = Armor.Waist; + else if (partName == "leg") part = Armor.Leg; + else if (partName == "face000") part = Armor.Face; + else if (partName == "face000_eyelens") part = Armor.EyeLens; + else if (partName.StartsWith("hair")) part = Armor.Hair; + else return; + playerArmor[part] = baseAddr; + + if (part == Armor.Body) { - playerArmor[Armor.Body] = baseAddr; chestBone1 = 0x0; chestBone2 = 0x0; } - else if (partName == "helm") - { - playerArmor[Armor.Helmet] = baseAddr; - } - else if (partName == "arm") - { - playerArmor[Armor.Arm] = baseAddr; - } - else if (partName == "wst") - { - playerArmor[Armor.Waist] = baseAddr; - } - else if (partName == "leg") - { - playerArmor[Armor.Leg] = baseAddr; - } - else if (partName == "face000") - { - playerArmor[Armor.Face] = baseAddr; - } int jointCount = MemoryUtil.Read(baseAddr + 0x4A0); nint jointAddr = MemoryUtil.Read(baseAddr + 0x4A8); for (int i = 0; i < jointCount; i++) { - if (partName == "body") - { - bodyJoints.Add(jointAddr); - } - /* - else if (partName == "face000") - { - faceJoints.Add(jointAddr); - } - */ nint childAddr = MemoryUtil.Read(jointAddr + 0x8); if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x142F21A90) { @@ -2584,7 +2684,14 @@ namespace NewCamera if (childAddr != 0x0) { nint childVtable = MemoryUtil.Read(childAddr); - if (childVtable == 0x143524BD8) + if (childVtable == 0x1435195B8) // Jiggle Bone Container. + { + if (part == Armor.Body) + { + ignoredJoints.Add(jointAddr); + } + } + else if (childVtable == 0x143524BD8) { childAddr = MemoryUtil.Read(childAddr + 0x188); if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x143519530) @@ -2595,8 +2702,9 @@ namespace NewCamera if (!jiggleBones.Contains(jiggleData)) { jiggleBones.Add(jiggleData); - if (partName == "body") + if (part == Armor.Body) { + // Guess that chest bones are the last jiggle bones. if (chestBone1 == 0x0) { chestBone1 = jiggleData; @@ -2617,223 +2725,678 @@ namespace NewCamera } } } + if (part == Armor.Body) + { + ignoredJoints.Add(jointAddr); + } } else if (childVtable == 0x143249170) { childAddr = MemoryUtil.Read(childAddr + 0x188); if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x1432492F0) { - if (!ikJoints.Contains(jointAddr)) - { - ikJoints.Add(jointAddr); - } + ikJoints.Add(jointAddr); } } } } + if (part == Armor.Body) + { + bodyJoints.Add(jointAddr); + } + else if (part == Armor.Face) + { + faceJoints.Add(jointAddr); + } jointAddr += 0xC0; } - if (partName == "body") + if (part == Armor.Body) { - bodyJoints.Sort(delegate(nint x, nint y) - { - return MemoryUtil.Read(x + 0x14) - MemoryUtil.Read(y + 0x14); - }); - for (int i = jointOffsets.Count - 1; i >= 0; i--) + int extraBonesOffset = 0; + int skipExtraBones = 0; + for (int i = 0; i < bodyJoints.Count; i++) { - jointAddr = jointOffsets.Keys.ElementAt(i); - if (!bodyJoints.Contains(jointAddr)) + jointAddr = bodyJoints[i]; + if (ignoredJoints.Contains(jointAddr)) { - jointOffsets.Remove(jointAddr); + extraBonesOffset++; + continue; } - } - for (int i = ikOffsets.Count - 1; i >= 0; i--) - { - jointAddr = ikOffsets.Keys.ElementAt(i); - if (!bodyJoints.Contains(jointAddr)) + byte treeLevel = MemoryUtil.Read(jointAddr + 0x14); + if (skipExtraBones > 0) + { + if (treeLevel != skipExtraBones) + { + extraBonesOffset++; + continue; + } + skipExtraBones = 0; + } + int adjustedIndex = i - extraBonesOffset; + if (adjustedIndex >= playerJoints.Length) + { + break; + } + // Guess that all extra joints come between Unknown2 and LeftHip and + // that none of them are at level 2 like LeftHip. + if (adjustedIndex == Joint.Unknown2) { - ikOffsets.Remove(jointAddr); + skipExtraBones = 2; } + playerJoints[i - extraBonesOffset] = jointAddr; + } + foreach (nint joint in jointOffsets.Where(e => !bodyJoints.Contains(e.Key)).Select(e => e.Key).ToList()) + { + jointOffsets.Remove(joint); + } +#if QUARANTINED_FEATURES + foreach (nint joint in ikOffsets.Where(e => !bodyJoints.Contains(e.Key)).Select(e => e.Key).ToList()) + { + ikOffsets.Remove(joint); } +#endif } } - private void drawArmorParts(nint armorAddr) + private void drawJoint(nint jointAddr) { - ImGui.PushID(armorAddr); - nint partsAddr = MemoryUtil.Read(armorAddr + 0x2A0); - string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!; - string partName = parsePartName(fullString); - ImGui.Text($"{partName} ({partsAddr:X}, {fullString} @ {armorAddr:X}):"); - int numParts = MemoryUtil.Read(partsAddr + 0x54C); - nint baseInner = MemoryUtil.Read(partsAddr + 0xC8); - nint offset = MemoryUtil.Read(partsAddr + 0x408); - bool toggleAll = ImGui.Button("Toggle All"); - for (int i = 0; i < numParts; i++) + if (jointAddr == 0x0) return; + ImGui.PushID(jointAddr); + ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jointAddr + 0x50), 0.005f); + bool ikJoint = false; +#if QUARANTINED_FEATURES + if (ikJoints.Contains(jointAddr)) { - nint baseOffset = offset + (i * 0x4) + (numParts * 0x4); - ref byte bIndex = ref MemoryUtil.GetRef(baseOffset); - baseOffset = baseInner + ((bIndex + (bIndex * 4)) << 4); - ref byte bEnabled = ref MemoryUtil.GetRef(baseOffset); - ref byte bSub = ref MemoryUtil.GetRef(baseOffset + 0xB); - if (toggleAll) + if (!ikOffsets.ContainsKey(jointAddr)) { - (bEnabled, bSub) = (bSub, bEnabled); + if (ImGui.Button("Add IK Offset")) + { + ikOffsets.Add(jointAddr, new List() + { + new Vector3() + }); + } } - bool isVisible = bEnabled != 0x0; - if (ImGui.Checkbox($"##Part #{i}", ref isVisible)) + else { - (bEnabled, bSub) = (bSub, bEnabled); + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + Vector3 v = ikOffsets[jointAddr][0]; + if (ImGui.DragFloat3($"Offset", ref v, 0.025f)) + { + ikOffsets[jointAddr][0] = v; + } + if (doRemove) ikOffsets.Remove(jointAddr); } - if (ImGui.BeginItemTooltip()) + //ikJoint = true; + } +#endif + ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); + if (ikJoint) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + bool hasOffset = jointOffsets.ContainsKey(jointAddr); + if (!hasOffset) + { + if (ImGui.Button("Add Offset")) { - ImGui.Text($"Part #{i}"); - ImGui.EndTooltip(); + jointOffsets.Add(jointAddr, new List() + { + new Vector3() + }); } - if (i % 10 != 9 && i != numParts - 1) + if (ikJoint) { ImGui.SameLine(); } } - if (ImGui.CollapsingHeader("Joints")) + if (ikJoint) + { + ImGui.Text("(Enforced by Inverse Kinematics)"); + ImGui.PopStyleVar(); + } + if (hasOffset) { - if (partName == "body") + bool doRemove = ImGui.Button("X"); + ImGui.SameLine(); + if (ImGui.Button("Reset")) { - ImGui.Checkbox("Attach to Chest", ref attachToChest); - if (ImGui.BeginItemTooltip()) - { - ImGui.Text("While in Free Camera, hold LT + RT and move your joysticks (armor has to have jiggle physics)."); - ImGui.EndTooltip(); - } - ImGui.Checkbox("Swap Sides", ref swapChestSides); - ImGui.DragFloat("Scale", ref chestMoveScale); - if (ImGui.CollapsingHeader("Jiggle Bones")) - { - for (int i = 0; i < jiggleBones.Count; i++) - { - nint jiggleData = jiggleBones[i]; - if (ImGui.CollapsingHeader($"Jiggle Bones #{i} ({jiggleData:X})")) - { - ImGui.DragFloat3("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0)); - } - } - foreach (nint jiggleData in jiggleBones) - { - - } - } - ImGui.Separator(); - for (int i = 0; i < bodyJoints.Count; i++) - { - nint jointAddr = bodyJoints[i]; - ImGui.PushID(jointAddr); - byte jointGroup = MemoryUtil.Read(jointAddr + 0x14); - if (ImGui.CollapsingHeader($"Joint #{i} ({jointAddr:X}, {jointGroup:X})")) - { - ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); - if (partName != "face000") - { - if (!jointOffsets.ContainsKey(jointAddr)) - { - if (ImGui.Button("Add Offset")) - { - jointOffsets.Add(jointAddr, new List() - { - new Vector3() - }); - } - } - else - { - bool doRemove = ImGui.Button("X"); - ImGui.SameLine(); - Vector3 v = jointOffsets[jointAddr][0]; - if (ImGui.DragFloat3($"Rotation Offset", ref v, 0.005f)) - { - jointOffsets[jointAddr][0] = v; - } - if (doRemove) jointOffsets.Remove(jointAddr); - } - if (ikJoints.Contains(jointAddr)) - { - if (!ikOffsets.ContainsKey(jointAddr)) - { - if (ImGui.Button("Add IK Offset")) - { - ikOffsets.Add(jointAddr, new List() - { - new Vector3() - }); - } - } - else - { - bool doRemove = ImGui.Button("X"); - ImGui.SameLine(); - Vector3 v = ikOffsets[jointAddr][0]; - if (ImGui.DragFloat3($"Position Offset", ref v, 0.025f)) - { - ikOffsets[jointAddr][0] = v; - } - if (doRemove) ikOffsets.Remove(jointAddr); - } - } - } - } - ImGui.PopID(); - } + jointOffsets[jointAddr][0] = new Vector3(); } - /* - else if (partName == "face000") + ImGui.SameLine(); + Vector3 v = jointOffsets[jointAddr][0]; + if (ImGui.DragFloat3($"Offset", ref v, 0.005f)) { - if (ImGui.Checkbox("Override Pose", ref overrideFacePose)) - { - if (overrideFacePose) - { - noopFacePose.Enable(); - noopFacePoseUpdate.Enable(); - } - else - { - noopFacePose.Disable(); - noopFacePoseUpdate.Disable(); - } - } - for (int i = 0; i < faceJoints.Count; i++) - { - nint jointAddr = faceJoints[i]; - ImGui.PushID(jointAddr); - if (ImGui.CollapsingHeader($"Joint #{i} ({jointAddr:X})")) - { - ImGui.DragFloat4("Position", ref MemoryUtil.GetRef(jointAddr + 0x50), 0.005f); - ImGui.DragFloat4("Rotation", ref MemoryUtil.GetRef(jointAddr + 0x70), 0.005f); - } - ImGui.PopID(); - } + jointOffsets[jointAddr][0] = v; } - */ + if (doRemove) jointOffsets.Remove(jointAddr); } ImGui.PopID(); } - private void dropArmorState() - { - Array.Clear(playerArmor, 0, playerArmor.Length); - bodyJoints.Clear(); - //faceJoints.Clear(); - jiggleBones.Clear(); - } - - private void dropJointOffsets() + private void drawJointLeaf(ref List joints, int i) { - jointOffsets.Clear(); - ikOffsets.Clear(); + if (i >= joints.Count) return; + nint jointAddr = joints[i]; + byte treeLevel = MemoryUtil.Read(jointAddr + 0x14); + ImGui.PushID(jointAddr); + if (ImGui.CollapsingHeader($"Joint #{i} (0x{jointAddr:X}, tree_level: 0x{treeLevel:X})")) + { + drawJoint(jointAddr); + } + ImGui.PopID(); + drawJointLeaf(ref joints, i + 1); } - private bool collectArmorAndJoints(Player player) + private void drawJoints(float width) { - nint bodyArmorParts = MemoryUtil.Read(player.Instance + 0x2A0); - if (bodyArmorParts == 0x0) + ImGui.PushItemWidth(width * 0.75f); + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed; + if (ImGui.TreeNodeEx("Root", flags)) + { + drawJoint(playerJoints[Joint.Root2]); + ImGui.TreePop(); + } + ImGui.PushID("Neck"); + if (ImGui.TreeNodeEx("Neck", flags)) + { + if (ImGui.TreeNodeEx("Upper", flags)) + { + drawJoint(playerJoints[Joint.UpperNeck]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Lower", flags)) + { + drawJoint(playerJoints[Joint.LowerNeck]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Neck. + ImGui.PushID("Back"); + if (ImGui.TreeNodeEx("Back", flags)) + { + if (ImGui.TreeNodeEx("Upper", flags)) + { + drawJoint(playerJoints[Joint.UpperBack]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Lower", flags)) + { + drawJoint(playerJoints[Joint.LowerBack]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Back. + ImGui.PushID("Right Arm"); + if (ImGui.TreeNodeEx("Right Arm", flags)) + { + if (ImGui.TreeNodeEx("Collarbone", flags)) + { + drawJoint(playerJoints[Joint.RightCollarbone]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Shoulder", flags)) + { + drawJoint(playerJoints[Joint.RightShoulder]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Elbow", flags)) + { + drawJoint(playerJoints[Joint.RightElbow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Wrist", flags)) + { + drawJoint(playerJoints[Joint.RightWrist]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Right Arm. + ImGui.PushID("Right Hand"); + if (ImGui.TreeNodeEx("Right Hand", flags)) + { + ImGui.PushID("Thumb"); + if (ImGui.TreeNodeEx("Thumb", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.RightThumbLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.RightThumbMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.RightThumbHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Index"); + if (ImGui.TreeNodeEx("Index", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.RightIndexLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.RightIndexMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.RightIndexHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Middle"); + if (ImGui.TreeNodeEx("Middle", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.RightMiddleLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.RightMiddleMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.RightMiddleHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Ring"); + if (ImGui.TreeNodeEx("Ring", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.RightRingLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.RightRingMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.RightRingHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Pinky"); + if (ImGui.TreeNodeEx("Pinky", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.RightPinkyLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.RightPinkyMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.RightPinkyHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + if (ImGui.TreeNodeEx("Palm", flags)) + { + drawJoint(playerJoints[Joint.RightPalm]); + ImGui.TreePop(); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Outer Palm/Pinky+Ring"); + ImGui.EndTooltip(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Right Hand. + ImGui.PushID("Right Leg"); + if (ImGui.TreeNodeEx("Right Leg", flags)) + { + if (ImGui.TreeNodeEx("Hip", flags)) + { + drawJoint(playerJoints[Joint.RightHip]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Knee", flags)) + { + drawJoint(playerJoints[Joint.RightKnee]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Ankle", flags)) + { + drawJoint(playerJoints[Joint.RightAnkle]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Toes", flags)) + { + drawJoint(playerJoints[Joint.RightToes]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Right Leg. + ImGui.PushID("Left Arm"); + if (ImGui.TreeNodeEx("Left Arm", flags)) + { + if (ImGui.TreeNodeEx("Collarbone", flags)) + { + drawJoint(playerJoints[Joint.LeftCollarbone]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Shoulder", flags)) + { + drawJoint(playerJoints[Joint.LeftShoulder]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Elbow", flags)) + { + drawJoint(playerJoints[Joint.LeftElbow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Wrist", flags)) + { + drawJoint(playerJoints[Joint.LeftWrist]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Left Arm. + ImGui.PushID("Left Hand"); + if (ImGui.TreeNodeEx("Left Hand", flags)) + { + ImGui.PushID("Thumb"); + if (ImGui.TreeNodeEx("Thumb", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.LeftThumbLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.LeftThumbMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.LeftThumbHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Index"); + if (ImGui.TreeNodeEx("Index", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.LeftIndexLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.LeftIndexMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.LeftIndexHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Middle"); + if (ImGui.TreeNodeEx("Middle", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.LeftMiddleLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.LeftMiddleMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.LeftMiddleHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Ring"); + if (ImGui.TreeNodeEx("Ring", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.LeftRingLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.LeftRingMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.LeftRingHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + ImGui.PushID("Pinky"); + if (ImGui.TreeNodeEx("Pinky", flags)) + { + if (ImGui.TreeNodeEx("Base", flags)) + { + drawJoint(playerJoints[Joint.LeftPinkyLow]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Middle", flags)) + { + drawJoint(playerJoints[Joint.LeftPinkyMid]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Tip", flags)) + { + drawJoint(playerJoints[Joint.LeftPinkyHigh]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); + if (ImGui.TreeNodeEx("Palm", flags)) + { + drawJoint(playerJoints[Joint.LeftPalm]); + ImGui.TreePop(); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Outer Palm/Pinky+Ring"); + ImGui.EndTooltip(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Left Hand. + ImGui.PushID("Left Leg"); + if (ImGui.TreeNodeEx("Left Leg", flags)) + { + if (ImGui.TreeNodeEx("Hip", flags)) + { + drawJoint(playerJoints[Joint.LeftHip]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Knee", flags)) + { + drawJoint(playerJoints[Joint.LeftKnee]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Ankle", flags)) + { + drawJoint(playerJoints[Joint.LeftAnkle]); + ImGui.TreePop(); + } + if (ImGui.TreeNodeEx("Toes", flags)) + { + drawJoint(playerJoints[Joint.LeftToes]); + ImGui.TreePop(); + } + ImGui.TreePop(); + } + ImGui.PopID(); // Left Leg. + ImGui.Separator(); + ImGui.Checkbox("Attach to Chest", ref attachToChest); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("While in Free Camera, hold LT + RT and move your joysticks (armor has to have jiggle physics)."); + ImGui.EndTooltip(); + } + if (!attachToChest) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); + } + ImGui.SameLine(); + ImGui.Checkbox("Swap Sides", ref swapChestSides); + ImGui.SetNextItemWidth(width * 0.35f); + ImGui.DragFloat("Scale", ref chestMoveScale, 0.001f); + if (!attachToChest) + { + ImGui.PopStyleVar(); + } + if (ImGui.CollapsingHeader("Jiggle Bones")) + { + for (int i = 0; i < jiggleBones.Count; i++) + { + nint jiggleData = jiggleBones[i]; + ImGui.PushID(jiggleData); + if (ImGui.CollapsingHeader($"Jiggle Bones #{i} (0x{jiggleData:X})")) + { + ImGui.DragFloat3("Position", ref MemoryUtil.GetRef(jiggleData + 0xD0)); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Drag this position around to influence the bone."); + ImGui.EndTooltip(); + } + } + ImGui.PopID(); + } + } + ImGui.Separator(); + if (ImGui.CollapsingHeader("All Joints")) + { + drawJointLeaf(ref bodyJoints, 0); + } + ImGui.PopItemWidth(); + } + + private void drawArmorParts(nint armorAddr, nint partsAddr = 0x0) + { + if (partsAddr == 0x0) + { + if (armorAddr == 0x0 || (partsAddr = MemoryUtil.Read(armorAddr + 0x2A0)) == 0x0) + { + return; + } + } + ImGui.PushID(partsAddr); + string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!; + if (armorAddr != 0x0) + { + string partName = extractPartName(fullString); + ImGui.Text($"{partName} (0x{armorAddr:X}, {fullString} @ 0x{partsAddr:X}):"); + } + else + { + ImGui.Text($"{fullString} @ 0x{partsAddr:X}:"); + } + const int partsPerLine = 10; + nint baseInner = MemoryUtil.Read(partsAddr + 0xC8); + nint baseOffset = MemoryUtil.Read(partsAddr + 0x408); + int numParts = MemoryUtil.Read(partsAddr + 0x54C); + bool toggleAll = ImGui.Button("Toggle All"); + for (int i = 0; i < numParts; i++) + { + nint offset = baseOffset + (i * 0x4) + (numParts * 0x4); + ref byte bIndex = ref MemoryUtil.GetRef(offset); + offset = baseInner + ((bIndex + (bIndex * 4)) << 4); + ref byte bVisible = ref MemoryUtil.GetRef(offset); + ref byte bSub = ref MemoryUtil.GetRef(offset + 0xB); + if (toggleAll) + { + (bVisible, bSub) = (bSub, bVisible); + } + bool isVisible = bVisible != 0x0; + if (ImGui.Checkbox($"##Part #{i}", ref isVisible)) + { + (bVisible, bSub) = (bSub, bVisible); + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text($"Part #{i}"); + ImGui.EndTooltip(); + } + if (i != numParts - 1 && i % partsPerLine != partsPerLine - 1) + { + ImGui.SameLine(); + } + } + ImGui.PopID(); + } + + private void dropArmorState() + { + Array.Clear(playerArmor, 0, playerArmor.Length); + Array.Clear(playerJoints, 0, playerJoints.Length); + bodyJoints.Clear(); + ignoredJoints.Clear(); + jiggleBones.Clear(); + faceJoints.Clear(); + } + + private void dropJointOffsets() + { + jointOffsets.Clear(); +#if QUARANTINED_FEATURES + ikOffsets.Clear(); +#endif + } + + private bool collectArmorAndJoints(Player player) + { + nint bodyArmorParts = MemoryUtil.Read(player.Instance + 0x2A0); + if (bodyArmorParts == 0x0) { return false; } @@ -2858,17 +3421,29 @@ namespace NewCamera nint childAddr = MemoryUtil.Read(armorAddr + 0x548); if (childAddr != 0x0) { - if (MemoryUtil.Read(childAddr) == 0x143451520) + if (MemoryUtil.Read(childAddr) == 0x143451520) // Face. { nint ownerAddr = MemoryUtil.Read(childAddr + 0x998); - if (playerArmor[Armor.Face] != 0x0 || ownerAddr != player.Instance) + if (ownerAddr != player.Instance) { continue; } - partsAddr = MemoryUtil.Read(childAddr + 0x2A0); - if (partsAddr != 0x0) + if (playerArmor[Armor.Face] == 0x0) { - collectArmorParts(childAddr, partsAddr); + partsAddr = MemoryUtil.Read(childAddr + 0x2A0); + if (partsAddr != 0x0) + { + collectArmorParts(childAddr, partsAddr); + } + childAddr = MemoryUtil.Read(childAddr + 0x9C8); + if (childAddr != 0x0 && MemoryUtil.Read(childAddr) == 0x143505E98) // Eye lens. + { + partsAddr = MemoryUtil.Read(childAddr + 0x2A0); + if (partsAddr != 0x0) + { + collectArmorParts(childAddr, partsAddr); + } + } } } else if (childAddr != player.Instance) @@ -2886,36 +3461,38 @@ namespace NewCamera return true; } - private void UpdateJointsHook(nint obj, nint unknownPtr, int unknownInt, int unknownInt2) + private void refreshArmorState(Player player) { - if (jointOffsets.Count > 0 && !didJointOffset) + dropArmorState(); + if (!collectArmorAndJoints(player)) { - Player? player = Player.MainPlayer; - if (player == null) - { - player = getPlayerFromSaveSlot(); - } + dropJointOffsets(); + } + } + + private void UpdateJointsHook(nint obj) + { + if (!disableMod && !didJointOffset && (jointOffsets.Count > 0 || hideKnife || (enableFreeCamera && orbitPlayer && orbitJoint >= 0))) + { + Player? player = getPlayerWithFallback(); if (player != null && obj == player.Instance) { - dropArmorState(); - if (!collectArmorAndJoints(player)) + refreshArmorState(player); + foreach ((nint addr, List offsets) in jointOffsets) { - dropJointOffsets(); + MemoryUtil.GetRef(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(offsets[0].X, offsets[0].Y, offsets[0].Z); } + didJointOffset = true; if (playerArmor[Armor.Waist] != 0x0) { MemoryUtil.GetRef(playerArmor[Armor.Waist] + 0x2D0) = hideKnife ? (byte)0xFD : (byte)0xFF; } - foreach ((nint addr, List offsets) in jointOffsets) - { - MemoryUtil.GetRef(addr + 0x70) *= Quaternion.CreateFromYawPitchRoll(offsets[0].X, offsets[0].Y, offsets[0].Z); - } - didJointOffset = true; } } - updateJointsHook!.Original(obj, unknownPtr, unknownInt, unknownInt2); + updateJointsHook!.Original(obj); } +#if QUARANTINED_FEATURES private void UpdateIKHook(nint superOfChild, nint joint, nint obj) { if (ikOffsets.ContainsKey(joint)) @@ -2925,6 +3502,7 @@ namespace NewCamera } updateIKHook!.Original(superOfChild, joint, obj); } +#endif /* private void ChangeEquipmentHook(nint unknownPtr, int unknownInt) @@ -2950,7 +3528,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"UnderwaterCheckHook({unknownPtr:X}) @ {frameTick}"); + debugLog($"UnderwaterCheckHook(0x{unknownPtr:X}) @ {frameTick}"); #endif cameraIsUnderwater = MemoryUtil.Read(unknownPtr + 0x1E83) == 0x1; @@ -2965,7 +3543,7 @@ namespace NewCamera } #if HOOK_ORDER_ASSERTS - debugLog($"CameraEffectHook({unknownPtr:X}, {unknownPtr2:X}, {unknownPtr3:X}) @ {frameTick}"); + debugLog($"CameraEffectHook(0x{unknownPtr:X}, 0x{unknownPtr2:X}, 0x{unknownPtr3:X}) @ {frameTick}"); #endif byte[]? underwaterValues = null; @@ -3014,9 +3592,9 @@ namespace NewCamera Viewport vp = CameraSystem.GetViewport(i); if (debug) { - ImGui.Text($"Address: {vp.Instance:X}"); + ImGui.Text($"Address: 0x{vp.Instance:X}"); ImGui.Text($"Visible: {vp.Visible}"); - ImGui.Text($"Region: {vp.Region.X} {vp.Region.Y} {vp.Region.Width} {vp.Region.Height}"); + ImGui.Text($"Region: {vp.Region.Width}x{vp.Region.Height} ({vp.Region.X},{vp.Region.Y})"); } else { @@ -3039,48 +3617,8 @@ namespace NewCamera { Camera camera = vp.Camera; bool usedByFreeCamera = freeCamera && enableFreeCamera && camera == vCamera; - if (debug) ImGui.Text($"Camera Pointer: {camera.Instance:X}"); - Player? player = checkPlayerChange(); - if (debug && player != null) - { - // MonsterHunterWorld.exe+12A9AEC - mov rcx,[rdi+00001E90] - // MonsterHunterWorld.exe+11A9AB9 - add rcx,00001410 - // MonsterHunterWorld.exe+12A9AE0 - mov rcx,[MonsterHunterWorld.exe+5013950] - ImGui.Text("Camera Distance"); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); - nint playerCameraAddr = MemoryUtil.Read(player.Instance + 0x14F8); - playerCameraAddr = MemoryUtil.Read(playerCameraAddr + 0x1410 + 0x1E90); - ref byte settingB = ref MemoryUtil.GetRef(getPlayerSettings() + 0x1403FD); - int settingI = settingB; - ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); - if (ImGui.RadioButton("Close", ref settingI, 0)) - { - settingB = (byte)settingI; - } - ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); - if (ImGui.RadioButton("Default", ref settingI, 1)) - { - settingB = (byte)settingI; - } - ImGui.SameLine(); - ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); - if (ImGui.RadioButton("Far", ref settingI, 2)) - { - settingB = (byte)settingI; - } - nint viewParamOffset = getViewParamOffset.Invoke(playerCameraAddr + 0x1380, 0, 0xC9); - if (viewParamOffset != 0x0) - { - ImGui.DragFloat3("Close", ref MemoryUtil.GetRef(viewParamOffset + 0x20), 0.1f); - } - viewParamOffset = getViewParamOffset.Invoke(playerCameraAddr + 0x1380, 0, 0xCA); - if (viewParamOffset != 0x0) - { - ImGui.DragFloat3("Far", ref MemoryUtil.GetRef(viewParamOffset + 0x20), 0.1f); - } - } + if (debug) ImGui.Text($"Camera Pointer: 0x{camera.Instance:X}"); + if (ImGui.DragFloat("Field of View", ref camera.FieldOfView, 0.1f)) { if (usedByFreeCamera) @@ -3088,7 +3626,7 @@ namespace NewCamera cameraFov = camera.FieldOfView; } } - if (camera == pCamera) + if (enableOffsetPerspective && camera == pCamera) { ImGui.Text($"Internal FOV: {previousFov}"); if (ImGui.BeginItemTooltip()) @@ -3200,12 +3738,70 @@ namespace NewCamera camera.Fix = fix; } } + if (camera == pCamera) + { + Player? player = checkPlayerChange(); + if (!debug && player != null) + { + ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 7.0f)); + ImGui.Text("Camera Distance"); + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("To save this setting, save your game."); + ImGui.EndTooltip(); + } + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + ref byte settingB = ref MemoryUtil.GetRef(getPlayerSettings() + 0x1403FD); + int settingI = settingB; + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + if (ImGui.RadioButton("Close", ref settingI, 0)) + { + settingB = (byte)settingI; + } + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + if (ImGui.RadioButton("Default", ref settingI, 1)) + { + settingB = (byte)settingI; + } + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + if (ImGui.RadioButton("Far", ref settingI, 2)) + { + settingB = (byte)settingI; + } + // MonsterHunterWorld.exe+12A9AEC - mov rcx,[rdi+00001E90] + // MonsterHunterWorld.exe+11A9AB9 - add rcx,00001410 + // MonsterHunterWorld.exe+12A9AE0 - mov rcx,[MonsterHunterWorld.exe+5013950] + nint playerCameraAddr = MemoryUtil.Read(player.Instance + 0x14F8); + if (playerCameraAddr != 0x0) + { + playerCameraAddr = MemoryUtil.Read(playerCameraAddr + 0x1410 + 0x1E90); + } + if (playerCameraAddr != 0x0) + { + ImGui.Text("Offset"); + nint viewParamOffset = getViewParamOffset.Invoke(playerCameraAddr + 0x1380, 0, 0xC9); + if (viewParamOffset != 0x0) + { + ImGui.DragFloat3("Close", ref MemoryUtil.GetRef(viewParamOffset + 0x20), 0.1f); + } + viewParamOffset = getViewParamOffset.Invoke(playerCameraAddr + 0x1380, 0, 0xCA); + if (viewParamOffset != 0x0) + { + ImGui.DragFloat3("Far", ref MemoryUtil.GetRef(viewParamOffset + 0x20), 0.1f); + } + } + } + } if (camera == vCamera) { if (!usedByFreeCamera) { ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); } + ImGui.Text("Angle"); // If our camera hooks aren't being run, these values won't be updated. ImGui.DragFloat("Yaw", ref cameraYaw, 0.2f); ImGui.DragFloat("Pitch", ref cameraPitch, 0.2f); @@ -3219,7 +3815,7 @@ namespace NewCamera { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, ImGui.GetStyle().Alpha * 0.5f); } - ImGui.Text("Offsets"); + ImGui.Text("Move"); float offsetForward = 0.0f; if (ImGui.DragFloat("Forward", ref offsetForward, 0.425f)) { @@ -3270,7 +3866,7 @@ namespace NewCamera } if (debug) { - ImGui.Text($"ActionController: {actionController.Instance:X}"); + ImGui.Text($"ActionController: 0x{actionController.Instance:X}"); ImGui.Text($" Current: {currentAction} {currentActionInfo}"); if (currentAction != null) { @@ -3283,16 +3879,16 @@ namespace NewCamera AnimationLayerComponent? animationLayer = entity.AnimationLayer; if (animationLayer != null) { - ImGui.Text(debug ? $"AnimationLayer: {animationLayer.Instance:X}" : "Animation:"); - ImGui.Text($" Current: {currentAnimation}"); + ImGui.Text(debug ? $"AnimationLayer: 0x{animationLayer.Instance:X}" : "Animation"); if (debug) { + ImGui.Text($" Current: {currentAnimation}"); ImGui.Text($" Frame: {animationLayer.CurrentFrame:0.000}/{animationLayer.MaxFrame:0.000}"); - return; } else { + ImGui.Text($" Current: {currentAnimation.Lmt}.{currentAnimation.Id}, Action: {(currentAction != null ? currentAction.Name : "None")}"); ImGui.SetNextItemWidth(width * 0.8f); ImGui.SliderFloat("Frame", ref animationLayer.CurrentFrame, 0.0f, animationLayer.MaxFrame, "%.3f"); } @@ -3302,15 +3898,14 @@ namespace NewCamera animationLayer.Paused = animationPaused; } ImGui.SameLine(); - /* float? lockedSpeed = animationLayer.LockedSpeed; + float speed = lockedSpeed ?? animationLayer.Speed; bool animationLocked = lockedSpeed != null; if (ImGui.Checkbox("Set", ref animationLocked)) { if (animationLocked) { - lockedSpeed = animationLayer.Speed; - animationLayer.LockSpeed((float)lockedSpeed); + animationLayer.LockSpeed(speed); } else { @@ -3318,14 +3913,11 @@ namespace NewCamera } } ImGui.SameLine(); - ImGui.PushItemWidth(width * 0.35f); - float speed = animationLocked ? (float)lockedSpeed! : animationLayer.Speed; + ImGui.SetNextItemWidth(width * 0.35f); if (ImGui.DragFloat($"Speed", ref speed, 0.01f, 0.0f, 0.0f, "%.3f")) { if (animationLocked) animationLayer.LockSpeed(speed); } - */ - ImGui.PopItemWidth(); } } @@ -3394,6 +3986,10 @@ namespace NewCamera { jmpOverHotSpringsSteam.Disable(); } + if (ikForcedOff) + { + forceDisableIK.Disable(); + } } private void tryToEnableMod() @@ -3418,6 +4014,10 @@ namespace NewCamera { jmpOverHotSpringsSteam.Enable(); } + if (ikForcedOff) + { + forceDisableIK.Enable(); + } } private void drawPlayerInfo(Player player, float width) @@ -3425,10 +4025,11 @@ namespace NewCamera nint playerSettings = getPlayerSettings(); ImGui.Text($"{Marshal.PtrToStringAnsi(playerSettings + 0x50)}"); - ImGui.Text($"Settings: {playerSettings:X}"); ImGui.Checkbox("Hide Weapon", ref hideWeapon); + ImGui.SameLine(); ImGui.Checkbox("Hide Knife", ref hideKnife); + ImGui.SameLine(); ImGui.Checkbox("Hide Slinger", ref hideSlinger); ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); ImGui.Text("Head Armor Display"); @@ -3456,6 +4057,7 @@ namespace NewCamera ImGui.Separator(); + /* ref byte ikDisabledB = ref MemoryUtil.GetRef(MemoryUtil.Read(player.Instance + 0x990) + 0x5C); bool ikDisabled = ikDisabledB == 0x0; if (ImGui.Checkbox("Disable IK", ref ikDisabled)) @@ -3468,7 +4070,8 @@ namespace NewCamera ImGui.EndTooltip(); } ImGui.SameLine(); - if (ImGui.Checkbox("Force Disable IK", ref ikForcedOff)) + */ + if (ImGui.Checkbox("Disable IK", ref ikForcedOff)) { if (ikForcedOff) { @@ -3479,46 +4082,94 @@ namespace NewCamera forceDisableIK.Disable(); } } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text("Forcefully disable inverse kinematics."); + ImGui.EndTooltip(); + } - if (ImGui.CollapsingHeader("Armor Parts")) + ImGui.PushID("PartsAndJoints"); + if (ImGui.CollapsingHeader("Armor Parts & Joints")) { - dropArmorState(); - if (!collectArmorAndJoints(player)) + refreshArmorState(player); + ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(0.0f, 6.0f)); +#if QUARANTINED_FEATURES + ImGui.Text($"Joint Offsets: {jointOffsets.Count}, IK Offsets: {ikOffsets.Count}"); +#else + ImGui.Text($"Joint Offsets: {jointOffsets.Count}"); +#endif + ImGui.SameLine(); + ImGui.SetCursorPos(ImGui.GetCursorPos() - new Vector2(0.0f, 4.0f)); + if (ImGui.Button("Clear")) { dropJointOffsets(); } - ImGui.Text($"Offset Count: {jointOffsets.Count}, IK Offset Count: {ikOffsets.Count}"); - if (ImGui.CollapsingHeader($"Body (id: 0x{MemoryUtil.Read(player.Instance + 0x13740):X})")) + if (ImGui.CollapsingHeader("Joints")) { - drawArmorParts(playerArmor[Armor.Body]); + drawJoints(width); + ImGui.Separator(); } - if (ImGui.CollapsingHeader($"Helmet (id: 0x{MemoryUtil.Read(player.Instance + 0x1373C):X})")) + bool helmetExpaned = ImGui.CollapsingHeader("Helmet"); + ImGui.SameLine(); + ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x1373C):X})"); + if (helmetExpaned) { drawArmorParts(playerArmor[Armor.Helmet]); + ImGui.Separator(); } - if (ImGui.CollapsingHeader($"Arms (id: 0x{MemoryUtil.Read(player.Instance + 0x13744):X})")) + bool bodyExpaned = ImGui.CollapsingHeader("Body"); + ImGui.SameLine(); + ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13740):X})"); + if (bodyExpaned) + { + drawArmorParts(playerArmor[Armor.Body]); + ImGui.Separator(); + } + bool armsExpaned = ImGui.CollapsingHeader("Arms"); + ImGui.SameLine(); + ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13744):X})"); + if (armsExpaned) { drawArmorParts(playerArmor[Armor.Arm]); + ImGui.Separator(); } - if (ImGui.CollapsingHeader($"Waist (id: 0x{MemoryUtil.Read(player.Instance + 0x13748):X})")) + bool waistExpaned = ImGui.CollapsingHeader("Waist"); + ImGui.SameLine(); + ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x13748):X})"); + if (waistExpaned) { drawArmorParts(playerArmor[Armor.Waist]); + ImGui.Separator(); } - if (ImGui.CollapsingHeader($"Legs (id: 0x{MemoryUtil.Read(player.Instance + 0x1374C):X})")) + bool legsExpaned = ImGui.CollapsingHeader("Legs"); + ImGui.SameLine(); + ImGui.Text($"(id: 0x{MemoryUtil.Read(player.Instance + 0x1374C):X})"); + if (legsExpaned) { drawArmorParts(playerArmor[Armor.Leg]); + ImGui.Separator(); } - ImGui.Text($"Slinger: {MemoryUtil.Read(player.Instance + 0x13D8C):X}_{MemoryUtil.Read(player.Instance + 0x13D90):X}"); + ImGui.Text($"Slinger: 0x{MemoryUtil.Read(player.Instance + 0x13D8C):X}, 0x{MemoryUtil.Read(player.Instance + 0x13D90):X}"); /* - ImGui.Text($"Last Equipped: {lastEquipedId:X}"); + ImGui.Text($"Last Equipped: 0x{lastEquipedId:X}"); */ - /* if (ImGui.CollapsingHeader("Face")) { drawArmorParts(playerArmor[Armor.Face]); + ImGui.Separator(); } - */ + if (ImGui.CollapsingHeader("Eye Lens")) + { + drawArmorParts(playerArmor[Armor.EyeLens]); + ImGui.Separator(); + } + if (ImGui.CollapsingHeader("Hair")) + { + drawArmorParts(playerArmor[Armor.Hair]); + } + ImGui.Separator(); } + ImGui.PopID(); nint controlsAddr = MemoryUtil.Read(player.Instance + 0x12608); nint zoneStateAddr = MemoryUtil.Read(0x1451C42B8); @@ -3540,7 +4191,9 @@ namespace NewCamera } bool combatControls = MemoryUtil.Read(controlsAddr + 0xB18) == 0x80; zoneState = combatControls ? ZoneState.Combat : ZoneState.Hub; -#if QUARANTINED_FEATURES +#if !QUARANTINED_FEATURES + ImGui.Text($"Current Zone State: {((MemoryUtil.GetRef(zoneStateAddr + 0xD2EA) == 0x1) ? "Hub" : "Combat")}"); +#else if (ImGui.Checkbox("Combat Controls", ref combatControls)) { passiveFlag = ByteFlag(!combatControls); @@ -3720,16 +4373,19 @@ namespace NewCamera playerOpacityOverride = playerOpacity; } + ImGui.PushID("Wetness"); if (ImGui.CollapsingHeader("Wetness")) { nint wetnessAddr = player.Instance + 0x13BD0; - ImGui.PushItemWidth(width * 0.25f); + ImGui.PushItemWidth(width * 0.15f); ImGui.DragFloat("Head", ref MemoryUtil.GetRef(wetnessAddr), 0.005f); + ImGui.SameLine(); ImGui.DragFloat("Body", ref MemoryUtil.GetRef(wetnessAddr + 0x28), 0.005f); ImGui.DragFloat("Waist", ref MemoryUtil.GetRef(wetnessAddr + 0x50), 0.005f); + ImGui.SameLine(); ImGui.DragFloat("Legs", ref MemoryUtil.GetRef(wetnessAddr + 0x78), 0.005f); ImGui.PopItemWidth(); - ImGui.PushItemWidth(width * 0.35f); + ImGui.SetNextItemWidth(width * 0.35f); if (ImGui.DragFloat("Whole Body", ref wholeBodyWetness, 0.005f)) { if (overridePlayerWetness) @@ -3737,7 +4393,6 @@ namespace NewCamera writePlayerWholeBodyWetness(wetnessAddr); } } - ImGui.PopItemWidth(); if (ImGui.Button("Reset")) { wholeBodyWetness = 0.0f; @@ -3756,16 +4411,22 @@ namespace NewCamera overridePlayerWetnessDisable(); } } + ImGui.Separator(); } + ImGui.PopID(); - ImGui.PushItemWidth(width * 0.8f); + ImGui.PushItemWidth(width * 0.75f); ImGui.DragFloat3("Position", ref player.Position, 0.5f); Vector3 forward = new Vector3(player.Forward.X, player.Forward.Y, player.Forward.Z); ImGui.DragFloat3("Forward", ref forward, 0.0f); Vector4 rotation = new Vector4(player.Rotation.X, player.Rotation.Y, player.Rotation.Z, player.Rotation.W); - if (ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f)) + ImGui.SliderFloat4("Rotation", ref rotation, -1.0f, 1.0f); + Vector3 rotationOffset = new Vector3(); + if (ImGui.DragFloat3("Rotation Offset", ref rotationOffset, 0.0025f)) { - player.Rotation = new MtQuaternion(rotation.X, rotation.Y, rotation.Z, rotation.W); + Quaternion qRotation = new Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W); + qRotation *= Quaternion.CreateFromYawPitchRoll(rotationOffset.X, rotationOffset.Y, rotationOffset.Z); + player.Rotation = new MtQuaternion(qRotation.X, qRotation.Y, qRotation.Z, qRotation.W); } ImGui.PopItemWidth(); if (ImGui.Button("Reset")) @@ -3892,7 +4553,6 @@ namespace NewCamera ImGui.PopItemFlag(); ImGui.PopStyleVar(); } - drawAnimationInfo(player, width, false); } @@ -4201,6 +4861,7 @@ namespace NewCamera vCamera.NearClip = alternateNearClip; } } + ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Save")) { @@ -4209,7 +4870,6 @@ namespace NewCamera config.Camera = camera; ConfigManager.SaveConfig(this); } - ImGui.PopItemWidth(); } ImGui.Separator(); @@ -4260,7 +4920,7 @@ namespace NewCamera { ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0000FF); } - ImGui.PushItemWidth(width * 0.15f); + ImGui.SetNextItemWidth(width * 0.15f); ImGui.InputText("##Toggle Free Camera", ref typedCombo, 12); if (freeCameraCombo == null) { @@ -4271,7 +4931,6 @@ namespace NewCamera ImGui.Text("Form: RT+LB, R3+L2, A+LStick, Up+RT, Cross+Triangle, etc."); ImGui.EndTooltip(); } - ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Save")) { @@ -4396,6 +5055,7 @@ namespace NewCamera ImGui.TableSetColumnIndex(1); ImGui.Text("Open Poses Menu"); + /* ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text(" + Press B"); @@ -4407,6 +5067,7 @@ namespace NewCamera ImGui.Text(" + Press A"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle SSAO"); + */ ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); @@ -4484,12 +5145,12 @@ namespace NewCamera config.Binds = binds; ConfigManager.SaveConfig(this); } + ImGui.PopItemWidth(); if (ImGui.BeginItemTooltip()) { ImGui.Text("Value that gets sent as a simulated joystick movement. Range: [0, 32767]."); ImGui.EndTooltip(); } - ImGui.PopItemWidth(); if (ImGui.BeginTable("Keyboard Binds", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { ImGui.TableNextRow(); @@ -4540,11 +5201,13 @@ namespace NewCamera ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle UI"); + /* ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); ImGui.Text("Num /"); ImGui.TableSetColumnIndex(1); ImGui.Text("Toggle Depth of Field"); + */ ImGui.EndTable(); } @@ -4595,8 +5258,8 @@ namespace NewCamera } } - ImGui.PushItemWidth(width * 0.125f); ref float gameSpeed = ref MemoryUtil.GetRef(sMain.Instance + 0xA4); + ImGui.SetNextItemWidth(width * 0.125f); if (ImGui.DragFloat("Game Speed", ref gameSpeed, 0.005f, 0.0f, Single.MaxValue)) { if (gameSpeed == 1.0f) @@ -4614,7 +5277,6 @@ namespace NewCamera { advanceFrame++; } - ImGui.PopItemWidth(); ImGui.Checkbox("Decouple Camera Speed from Game Speed", ref decoupleDtFromGameTime); if (ImGui.BeginItemTooltip()) { @@ -4659,16 +5321,16 @@ namespace NewCamera { if (vCamera != null || pCamera != null) { - ImGui.Text("Camera:"); + ImGui.Text("Camera"); if (vCamera != null) { - ImGui.Text($"Visible Camera: {vCamera.Instance:X}"); + ImGui.Text($"Visible Camera: 0x{vCamera.Instance:X}"); ImGui.Text($"freeCameraFallback: {freeCameraFallback}"); - //ImGui.Text($"viewModeObject: {psuedoViewModeObject:X}"); + //ImGui.Text($"viewModeObject: 0x{psuedoViewModeObject:X}"); } if (pCamera != null) { - ImGui.Text($"Player Camera: {pCamera.Instance:X}"); + ImGui.Text($"Player Camera: 0x{pCamera.Instance:X}"); ImGui.Text($"Applying Offset: {applyPerspective}"); ImGui.Text($"previousCameraAnimState: {previousCameraAnimState}"); ImGui.PushItemFlag(ImGuiItemFlags.Disabled, true); @@ -4679,11 +5341,14 @@ namespace NewCamera } ImGui.PushID("Viewports"); - ImGui.Text("Viewports:"); + ImGui.Text("Viewports"); for (int i = 0; i < 8; i++) { ImGui.PushID($"Viewport{i}"); - if (ImGui.CollapsingHeader($"Viewport #{i} ({((i == vCameraViewportIndex) ? "visible" : "inactive")})")) + bool viewportExpanded = ImGui.CollapsingHeader($"Viewport #{i}"); + ImGui.SameLine(); + ImGui.Text($"({((i == vCameraViewportIndex) ? "visible" : "inactive")})"); + if (viewportExpanded) { drawViewportInfo(i, width, config, true); } @@ -4694,11 +5359,12 @@ namespace NewCamera ImGui.Separator(); ImGui.PushID("Player"); - ImGui.Text("Player:"); - ImGui.Text($"sMhPlayer: {sPlayer.Instance:X}"); + ImGui.Text("Player"); + ImGui.Text($"sMhPlayer: 0x{sPlayer.Instance:X}"); if (player != null) { - ImGui.Text($"Address: {player.Instance:X}"); + ImGui.Text($"Address: 0x{player.Instance:X}"); + ImGui.Text($"Settings: 0x{getPlayerSettings():X}"); drawAnimationInfo(player, width, true); @@ -4719,21 +5385,34 @@ namespace NewCamera ImGui.PopID(); ImGui.PushID("Palico"); - ImGui.Text("Palico/Otomo:"); - ImGui.Text($"sOtomo: {sOtomo.Instance:X}"); + ImGui.Text("Palico/Otomo"); + ImGui.Text($"sOtomo: 0x{sOtomo.Instance:X}"); ImGui.PopID(); ImGui.Separator(); - Monster[] monsters = Monster.GetAllMonsters(); - if (ImGui.CollapsingHeader("Monsters")) + if (ImGui.CollapsingHeader($"Monsters")) { + Monster[] monsters = Monster.GetAllMonsters(); + ImGui.Text($"Count: {monsters.Length}"); + ImGui.Checkbox("Sort by distance from camera", ref sortMonsters); + if (sortMonsters && vCamera != null) + { + Array.Sort(monsters, delegate(Monster x, Monster y) + { + float distX = Vector3.Distance(vCamera.Position, x.Position); + float distY = Vector3.Distance(vCamera.Position, y.Position); + if (distX < distY) return 1; + else if (distX > distY) return -1; + return 0; + }); + } for (int i = monsters.Length - 1; i >= 0; i--) { Monster monster = monsters[i]; ImGui.PushID(monster.Instance); ImGui.Text($"{monster.Name}:"); - ImGui.Text($" Address: {monster.Instance:X}"); + ImGui.Text($" Address: 0x{monster.Instance:X}"); ImGui.DragFloat3("Position", ref monster.Position, 0.5f); drawAnimationInfo(monster, width, true); ImGui.PopID(); @@ -4741,15 +5420,28 @@ namespace NewCamera } } - Animal[] animals = Animal.GetAllAnimals(); - if (ImGui.CollapsingHeader("Animals")) + if (ImGui.CollapsingHeader($"Animals")) { + Animal[] animals = Animal.GetAllAnimals(); + ImGui.Text($"Count: {animals.Length}"); + ImGui.Checkbox("Sort by distance from camera", ref sortAnimals); + if (sortAnimals && vCamera != null) + { + Array.Sort(animals, delegate(Animal x, Animal y) + { + float distX = Vector3.Distance(vCamera.Position, x.Position); + float distY = Vector3.Distance(vCamera.Position, y.Position); + if (distX < distY) return 1; + else if (distX > distY) return -1; + return 0; + }); + } for (int i = animals.Length - 1; i >= 0; i--) { Animal animal = animals[i]; ImGui.PushID(animal.Instance); - ImGui.Text($"{animal.Id:X} ({animal.OtherId:X}):"); - ImGui.Text($" Address: {animal.Instance:X}"); + ImGui.Text($"0x{animal.Id:X} (0x{animal.OtherId:X}):"); + ImGui.Text($" Address: 0x{animal.Instance:X}"); ImGui.DragFloat3("Position", ref animal.Position, 0.5f); // Freeze: +0x1AFC = 0xFFFFFFFC if (ImGui.Button("Remove")) @@ -4761,18 +5453,111 @@ namespace NewCamera } } + ImGui.Separator(); + + if (ImGui.CollapsingHeader("Loaded Models") && player != null) + { + ImGui.Text("Filter"); + bool updateRegex = false; + ImGui.SetNextItemWidth(width * 0.6f); + if (ImGui.InputText("##Filter", ref modelFilter, 256)) + { + if (modelFilterIsRegex) + { + updateRegex = true; + } + } + ImGui.SameLine(); + if (ImGui.Checkbox("Regex", ref modelFilterIsRegex)) + { + if (modelFilterIsRegex) + { + updateRegex = true; + } + } + if (updateRegex) + { + if (String.IsNullOrEmpty(modelFilter)) + { + modelRegex = null; + } + else + { + try + { + modelRegex = new Regex(modelFilter); + } + catch (ArgumentException) + { + modelRegex = null; + } + } + } + nint bodyArmorParts = MemoryUtil.Read(player.Instance + 0x2A0); + if (bodyArmorParts != 0x0) + { + nint next = bodyArmorParts - 0x40; + nint head = next; + nint prev = MemoryUtil.Read(next + 0x10); + for (;next != 0x0;) + { + ImGui.PushID(next); + nint partsAddr = next + 0x40; + nint vtable = MemoryUtil.Read(partsAddr); + if (vtable == 0x143507A18) + { + string fullString = Marshal.PtrToStringAnsi(partsAddr + 0xC)!; + bool filterMatch = false; + if (modelFilterIsRegex) + { + filterMatch = modelRegex == null || modelRegex.Match(fullString).Success; + } + else + { + filterMatch = String.IsNullOrEmpty(modelFilter) || fullString.StartsWith(modelFilter); + } + if (filterMatch) + { + drawArmorParts(0x0, partsAddr); + } + } + ImGui.PopID(); + if (head == prev) + { + next = MemoryUtil.Read(next + 0x10); + } + else + { + next = MemoryUtil.Read(next + 0x18); + if (next == 0x0) + { + head = prev; + next = prev; + } + } + } + } + } + if (ImGui.BeginItemTooltip()) + { + ImGui.Text($"Part toggling only applies to LOD0."); + ImGui.EndTooltip(); + } + + ImGui.Separator(); + #if MOUSE_AND_KEYBOARD_LAYER ImGui.PushID("Mouse/Keyboard"); - ImGui.Text("Mouse:"); - ImGui.Text($"Address: {sMhMouse.Instance:X}"); - ImGui.Text("Keyboard:"); - ImGui.Text($"Address: {sMhKeyboard.Instance:X}"); + ImGui.Text("Mouse"); + ImGui.Text($"Address: 0x{sMhMouse.Instance:X}"); + ImGui.Text("Keyboard"); + ImGui.Text($"Address: 0x{sMhKeyboard.Instance:X}"); ImGui.PopID(); #endif ImGui.PushID("Pad"); - ImGui.Text("Pad:"); - ImGui.Text($"Address: {sMhController.Instance:X}"); + ImGui.Text("Pad"); + ImGui.Text($"Address: 0x{sMhController.Instance:X}"); int Rx = MemoryUtil.Read(sMhController.Instance + 0x1B0); int Ry = MemoryUtil.Read(sMhController.Instance + 0x1B4); int Lx = MemoryUtil.Read(sMhController.Instance + 0x1B8); @@ -4791,6 +5576,7 @@ namespace NewCamera ImGui.DragFloat("+Right", ref plusRight, 0.01f); ImGui.SameLine(); ImGui.DragFloat("+Forward", ref plusForward, 0.01f); + ImGui.PopItemWidth(); ImGui.SameLine(); if (ImGui.Button("Reset")) { @@ -4809,13 +5595,12 @@ namespace NewCamera plusForward = -plusForward; } } - ImGui.PopItemWidth(); ImGui.PopID(); ImGui.Separator(); ImGui.PushID("Orbit"); - ImGui.Text("Orbital Camera:"); + ImGui.Text("Orbital Camera"); ImGui.PushItemWidth(width * 0.15f); ImGui.DragFloat("Distance", ref orbitDistance, 1.0f); ImGui.SameLine(); @@ -4823,6 +5608,7 @@ namespace NewCamera ImGui.SameLine(); ImGui.DragFloat("Target Right", ref orbitRight, 1.0f); ImGui.DragFloat("Movement Rotation", ref orbitMovementRotation, 1.0f); + ImGui.InputInt("Target Joint", ref orbitJoint); ImGui.PopItemWidth(); ImGui.PopID(); @@ -4837,6 +5623,7 @@ namespace NewCamera ImGui.TextWrapped("Otis_Inf: Initial LOD and object fading adjustment locations, time of day and game speed."); ImGui.TextWrapped("Andoryuuta: MHW-ClassPropDump/MHW-DTI-Dumps."); ImGui.TextWrapped("MonsterHunterWorldModding/wiki Authors."); + ImGui.Separator(); } ImGui.PopID(); } -- cgit v1.2.3-101-g0448